diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index a5cf513..2ccca07 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -1,4 +1,4 @@ -name: Deploy to GitHub Pages +name: Build and Deploy on: push: @@ -7,100 +7,694 @@ on: - development - testing +permissions: + contents: write + +concurrency: + group: deploy-gh-pages + cancel-in-progress: false + +env: + NODE_VERSION: 24 + jobs: - deploy: + prepare-env: runs-on: ubuntu-latest + outputs: + build_env: ${{ steps.set-env.outputs.build_env }} + path: ${{ steps.set-env.outputs.path }} + page_root: ${{ steps.set-env.outputs.page_root }} + build_prefix: ${{ steps.set-env.outputs.build_prefix }} steps: - name: Set environment variables id: set-env run: | - echo "::set-output name=build_env::$(if [ '${{ github.ref }}' = 'refs/heads/release' ]; then echo 'production'; else echo 'development'; fi)" - echo "::set-output name=path::$(if [ '${{ github.ref }}' = 'refs/heads/release' ]; then echo 'app'; elif [ '${{ github.ref }}' = 'refs/heads/testing' ]; then echo 'test'; else echo 'development'; fi)" - echo "::set-output name=page_root::$(if [ '${{ github.ref }}' = 'refs/heads/release' ]; then echo '/CheemsBonkGame/app/'; elif [ '${{ github.ref }}' = 'refs/heads/testing' ]; then echo '/CheemsBonkGame/test/'; else echo '/CheemsBonkGame/development/'; fi)" - echo "::set-output name=build_prefix::$(if [ '${{ github.ref }}' = 'refs/heads/release' ]; then echo 'prod'; elif [ '${{ github.ref }}' = 'refs/heads/testing' ]; then echo 'test'; else echo 'dev'; fi)" - - name: Checkout code - uses: actions/checkout@v3 + if [ '${{ github.ref }}' = 'refs/heads/release' ]; then + echo "build_env=production" >> $GITHUB_OUTPUT + echo "path=app" >> $GITHUB_OUTPUT + echo "page_root=/CheemsBonkGame/app/" >> $GITHUB_OUTPUT + echo "build_prefix=prod" >> $GITHUB_OUTPUT + elif [ '${{ github.ref }}' = 'refs/heads/testing' ]; then + echo "build_env=development" >> $GITHUB_OUTPUT + echo "path=test" >> $GITHUB_OUTPUT + echo "page_root=/CheemsBonkGame/test/" >> $GITHUB_OUTPUT + echo "build_prefix=test" >> $GITHUB_OUTPUT + else + echo "build_env=development" >> $GITHUB_OUTPUT + echo "path=dev" >> $GITHUB_OUTPUT + echo "page_root=/CheemsBonkGame/dev/" >> $GITHUB_OUTPUT + echo "build_prefix=dev" >> $GITHUB_OUTPUT + fi - - name: Set up Node.js - uses: actions/setup-node@v3 + compile-web: + needs: prepare-env + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 with: - node-version: latest - - - name: Install Angular CLI - run: npm install -g @angular/cli + node-version: ${{ env.NODE_VERSION }} + - name: Install Dependencies + env: + NODE_TLS_REJECT_UNAUTHORIZED: 0 + run: | + # Try installing globals up to 3 times to handle random network drops + for i in 1 2 3; do + npm install -g @angular/cli @capacitor/cli @capacitor/assets png-to-ico && break || sleep 5 + done + + # Use 'npm ci' for reliable CI builds (falls back to 'npm install' if no lockfile exists) + npm ci || npm install - - name: Install dependencies - run: npm install + - name: Setup PWA env: - build_prefix: ${{ steps.set-env.outputs.build_prefix }} + build_prefix: ${{ needs.prepare-env.outputs.build_prefix }} run: | rm -rf public/img/icons/pwa mkdir -p public/img/icons/pwa cp .pwa/icons-$build_prefix/pwa/* public/img/icons/pwa - rm public/img/favicon.ico + rm -f public/img/favicon.ico cp .pwa/favicon-$build_prefix.ico public/img/favicon.ico - rm public/manifest.webmanifest + rm -f public/manifest.webmanifest cp .pwa/manifest-$build_prefix.webmanifest public/manifest.webmanifest - cp .pwa/styles-$build_prefix.css src/styles.css - - name: Build the application + - name: Build Web env: - build_env: ${{ steps.set-env.outputs.build_env }} - page_root: ${{ steps.set-env.outputs.page_root }} - run: npm run build -- --configuration="$build_env" --base-href="$page_root" + build_env: ${{ needs.prepare-env.outputs.build_env }} + run: npm run build -- --configuration="$build_env" - - name: Set up SSH Key + - name: Upload Web Artifact + uses: actions/upload-artifact@v4 + with: + name: web-app-${{ needs.prepare-env.outputs.build_prefix }} + path: dist/ + + - name: Deploy to gh-pages env: - DEPLOY_KEY: ${{ secrets.DEPLOY_KEY }} + GH_PAT: ${{ secrets.GH_PAT }} + path: ${{ needs.prepare-env.outputs.path }} + build_env: ${{ needs.prepare-env.outputs.build_env }} + page_root: ${{ needs.prepare-env.outputs.page_root }} run: | - mkdir -p ~/.ssh - echo "$DEPLOY_KEY" > ~/.ssh/deploy_key - chmod 600 ~/.ssh/deploy_key - ssh-keyscan github.com >> ~/.ssh/known_hosts - eval "$(ssh-agent -s)" - ssh-add ~/.ssh/deploy_key - git config --global user.name "GitHub Actions" - git config --global user.email "actions@github.com" + git config --global user.name "github-actions[bot]" + git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com" + if [ -n "$GH_PAT" ]; then + REPO_URL="https://x-access-token:${GH_PAT}@github.com/${{ github.repository }}.git" + else + REPO_URL="https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}.git" + fi + if git clone --branch gh-pages --single-branch "$REPO_URL" deploy-folder 2>/dev/null; then + echo "Cloned existing gh-pages branch." + else + echo "gh-pages branch does not exist yet. Creating orphan branch." + mkdir deploy-folder + cd deploy-folder + git init + git remote add origin "$REPO_URL" + git checkout --orphan gh-pages + cd .. + fi + target_dir="deploy-folder/$path" + rm -rf "$target_dir" + mkdir -p "$target_dir" + cp -r dist/cheems-angular/browser/* "$target_dir/" + + sed -i 's|||g' "$target_dir/index.html" + + cp README.md .gitignore "$target_dir/" 2>/dev/null || true + mkdir -p "$target_dir/game" + cp "$target_dir/index.html" "$target_dir/game/index.html" + mkdir -p "$target_dir/minigames/block-breaker" + cp "$target_dir/index.html" "$target_dir/minigames/block-breaker/index.html" + cp "$target_dir/index.html" "$target_dir/404.html" + if [ "$build_env" = "production" ]; then + cp .pwa/index.html "deploy-folder/" 2>/dev/null || true + cp README.md .gitignore "deploy-folder/" 2>/dev/null || true + cp .pwa/index.html "deploy-folder/404.html" 2>/dev/null || true + fi + cd deploy-folder + git add . + if ! git diff --cached --quiet; then + git commit -m "Deploy #${{ github.run_number }} from ${{ github.ref }} branch - $build_env" + git push origin HEAD:gh-pages + fi - - name: Prepare Git Worktree for gh-pages + build-android-linux: + needs: [prepare-env, compile-web] + runs-on: ubuntu-latest + strategy: + matrix: + app_type: [bundled, pwa] + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: ${{ env.NODE_VERSION }} + - uses: actions/setup-java@v5 + with: + distribution: 'zulu' + java-version: '21' + + - name: Install Dependencies + env: + NODE_TLS_REJECT_UNAUTHORIZED: 0 run: | - git fetch origin gh-pages - git worktree add deploy-folder gh-pages + # Try installing globals up to 3 times to handle random network drops + for i in 1 2 3; do + npm install -g @angular/cli @capacitor/cli @capacitor/assets png-to-ico && break || sleep 5 + done + + # Use 'npm ci' for reliable CI builds (falls back to 'npm install' if no lockfile exists) + npm ci || npm install + - - name: Clean Deployment Directory + - name: Apply Environment Configs env: - path: ${{ steps.set-env.outputs.path }} + build_prefix: ${{ needs.prepare-env.outputs.build_prefix }} + page_root: ${{ needs.prepare-env.outputs.page_root }} + app_type: ${{ matrix.app_type }} run: | - target_dir="deploy-folder/$path" - mkdir -p "$target_dir" - find "$target_dir" -mindepth 1 -not -name '.git' -exec rm -rf {} + + node -e " + const fs = require('fs'); + let cap = fs.readFileSync('capacitor.config.ts', 'utf8'); + let elec = fs.readFileSync('electron/electron-builder.config.json', 'utf8'); + const isPwa = process.env.app_type === 'pwa'; + const prefix = process.env.build_prefix; + const repoOwner = '${{ github.repository_owner }}'.toLowerCase() || 'luna115-oncode'; + const pageRoot = process.env.page_root; + + // Parse the electron config as JSON first to validate + let elecObj = JSON.parse(elec); + + // Update appId in the parsed object + if (elecObj.appId) { + elecObj.appId = isPwa ? 'com.cheems.pwa.' + prefix : 'com.cheems.app.' + prefix; + } + + // Update name for PWA variants + if (isPwa && elecObj.productName) { + elecObj.productName = 'Cheems Bonk Game (PWA)'; + } + if (isPwa && elecObj.executableName) { + elecObj.executableName = 'CheemsBonkGamePWA'; + } + + // Write back as valid JSON + elec = JSON.stringify(elecObj, null, 2); + + // Update capacitor config + cap = cap.replace('com.cheems.app', isPwa ? 'com.cheems.pwa.' + prefix : 'com.cheems.app.' + prefix); + if (isPwa) { + cap = cap.replace('Cheems Bonk Game', 'Cheems Bonk Game (PWA)'); + const url = 'https://' + repoOwner + '.github.io' + pageRoot; + cap = cap.replace('webDir: \\'dist/cheems-angular/browser\\'', 'webDir: \\'dist/cheems-angular/browser\\',\\n server: { url: \\'' + url + '\\' }'); + } + + fs.writeFileSync('capacitor.config.ts', cap); + fs.writeFileSync('electron/electron-builder.config.json', elec); + " + mkdir -p assets electron/assets + cp .pwa/icons-$build_prefix/pwa/icon-512x512.png assets/icon-only.png + cp .pwa/icons-$build_prefix/pwa/icon-512x512.png assets/icon-foreground.png + cp .pwa/icons-$build_prefix/pwa/icon-512x512.png assets/icon-background.png + cp .pwa/icons-$build_prefix/pwa/icon-512x512.png assets/splash.png + cp .pwa/icons-$build_prefix/pwa/icon-512x512.png electron/assets/icon.png - - name: Copy New Files to Deploy Folder + - name: Download Web Artifact + uses: actions/download-artifact@v4 + with: + name: web-app-${{ needs.prepare-env.outputs.build_prefix }} + path: dist/ + + - name: Optimize PWA Size for Wrappers + if: matrix.app_type == 'pwa' + shell: bash + run: | + rm -rf dist/cheems-angular/browser/* + echo "Cheems Bonk Game

Loading PWA...

" > dist/cheems-angular/browser/index.html + + - name: Build Android + run: | + npx cap add android + npx @capacitor/assets generate --android + npx cap sync android + + cd android + ./gradlew assembleDebug + ./gradlew bundleDebug + + - name: Build Linux (Bundled Electron + Portable) + if: matrix.app_type == 'bundled' env: - path: ${{ steps.set-env.outputs.path }} - build_env: ${{ steps.set-env.outputs.build_env }} + build_prefix: ${{ needs.prepare-env.outputs.build_prefix }} run: | - target_dir="deploy-folder/$path" - mkdir -p "$target_dir" - cp -r dist/cheems-angular/browser/* "$target_dir" - cp README.md .gitignore "$target_dir" - if [ "$build_env" = "production" ]; then - cp .pwa/index.html "deploy-folder/" - cp README.md .gitignore "deploy-folder/" - fi + npx cap copy @capacitor-community/electron + cd electron + npm install + npm run electron:make - - name: Commit and Deploy to GitHub Pages - working-directory: deploy-folder + - name: Build Linux (Native PWA .deb and .rpm) + if: matrix.app_type == 'pwa' + shell: bash + env: + page_root: ${{ needs.prepare-env.outputs.page_root }} + build_prefix: ${{ needs.prepare-env.outputs.build_prefix }} run: | - git add . - if git diff --cached --quiet; then - echo "No changes to commit. Skipping deployment." + OWNER="${{ github.repository_owner }}" + if [ -z "$OWNER" ]; then OWNER="luna115-oncode"; fi + MANIFEST_URL="https://${OWNER,,}.github.io${page_root}" + APP_NAME="cheems-bonk-pwa-${build_prefix}" + + mkdir -p deb-package/DEBIAN + mkdir -p deb-package/usr/bin + mkdir -p deb-package/usr/share/applications + mkdir -p deb-package/usr/share/icons/hicolor/512x512/apps + + sed -e "s|\${AppName}|$APP_NAME|g" .pwa/linux-control > deb-package/DEBIAN/control + + sed -e "s|\${ManifestUrl}|$MANIFEST_URL|g" .pwa/linux-launcher.sh > deb-package/usr/bin/$APP_NAME + chmod +x deb-package/usr/bin/$APP_NAME + + sed -e "s|\${AppName}|$APP_NAME|g" .pwa/linux.desktop > deb-package/usr/share/applications/$APP_NAME.desktop + + cp .pwa/icons-${build_prefix}/pwa/icon-512x512.png deb-package/usr/share/icons/hicolor/512x512/apps/$APP_NAME.png + + dpkg-deb --build deb-package ${APP_NAME}.deb + + sudo apt-get update && sudo apt-get install -y rpm + mkdir -p rpmbuild/{BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS} + sed -e "s|\${AppName}|$APP_NAME|g" -e "s|\${Workspace}|$GITHUB_WORKSPACE|g" .pwa/linux.spec > rpmbuild/SPECS/pwa.spec + + rpmbuild -bb --define "_topdir $GITHUB_WORKSPACE/rpmbuild" rpmbuild/SPECS/pwa.spec + cp rpmbuild/RPMS/noarch/*.rpm . + + + + - name: Upload Android Artifacts + uses: actions/upload-artifact@v4 + with: + name: ${{ matrix.app_type == 'bundled' && 'android-app-' || 'android-pwa-' }}${{ needs.prepare-env.outputs.build_prefix }} + path: | + android/app/build/outputs/apk/debug/app-debug.apk + android/app/build/outputs/bundle/debug/app-debug.aab + + - name: Upload Linux Bundled Artifacts + if: matrix.app_type == 'bundled' + uses: actions/upload-artifact@v4 + with: + name: linux-app-${{ needs.prepare-env.outputs.build_prefix }} + path: | + electron/dist/*.deb + electron/dist/*.rpm + electron/dist/*.AppImage + + - name: Upload Linux PWA Artifacts + if: matrix.app_type == 'pwa' + uses: actions/upload-artifact@v4 + with: + name: linux-pwa-${{ needs.prepare-env.outputs.build_prefix }} + path: | + *.deb + *.rpm + + build-windows-xbox: + needs: [prepare-env, compile-web] + runs-on: windows-latest + strategy: + matrix: + app_type: [bundled, pwa] + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: ${{ env.NODE_VERSION }} + + - name: Install Dependencies + env: + NODE_TLS_REJECT_UNAUTHORIZED: 0 + run: | + foreach ($i in 1..3) { + npm install -g @angular/cli @capacitor/cli @capacitor/assets png-to-ico + if ($LASTEXITCODE -eq 0) { break } + Start-Sleep -Seconds 5 + } + if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } + + npm ci + if ($LASTEXITCODE -ne 0) { npm install } + + - name: Apply Environment Configs + shell: bash + env: + build_prefix: ${{ needs.prepare-env.outputs.build_prefix }} + page_root: ${{ needs.prepare-env.outputs.page_root }} + app_type: ${{ matrix.app_type }} + run: | + # Create directories and copy the source PNG + mkdir -p electron/assets assets + cp .pwa/icons-$build_prefix/pwa/icon-512x512.png electron/assets/icon.png + + # Install the converter locally so Node can require() it + npm install png-to-ico --no-save + + node -e " + const fs = require('fs'); + + // Safely handle both ESM and CommonJS exports for the png-to-ico package + const imported = require('png-to-ico'); + const pngToIco = imported.default || imported; + + let cap = fs.readFileSync('capacitor.config.ts', 'utf8'); + let elec = JSON.parse(fs.readFileSync('electron/electron-builder.config.json', 'utf8')); + const isPwa = process.env.app_type === 'pwa'; + const prefix = process.env.build_prefix; + const repoOwner = '${{ github.repository_owner }}'.toLowerCase() || 'luna115-oncode'; + const pageRoot = process.env.page_root; + const appId = isPwa ? 'com.cheems.pwa.' + prefix : 'com.cheems.app.' + prefix; + + elec.appId = appId; + if (isPwa) { + elec.productName = 'Cheems Bonk Game (PWA)'; + elec.executableName = 'CheemsBonkGamePWA'; + if (elec.nsis) elec.nsis.shortcutName = 'Cheems Bonk Game (PWA)'; + } + + // Point Windows specifically to the .ico file + if (elec.win) elec.win.icon = 'assets/icon.ico'; + + cap = cap.replace('com.cheems.app', appId); + if (isPwa) { + cap = cap.replace('Cheems Bonk Game', 'Cheems Bonk Game (PWA)'); + const url = 'https://' + repoOwner + '.github.io' + pageRoot; + cap = cap.replace('webDir: \'dist/cheems-angular/browser\'', 'webDir: \'dist/cheems-angular/browser\',\n server: { url: \'' + url + '\' }'); + } + + // Generate the ICO file using raw binary buffers (avoids shell redirection corruption) + pngToIco('electron/assets/icon.png').then(buf => { + fs.writeFileSync('electron/assets/icon.ico', buf); + fs.writeFileSync('capacitor.config.ts', cap); + fs.writeFileSync('electron/electron-builder.config.json', JSON.stringify(elec, null, 2)); + }).catch(err => { + console.error('Failed to convert icon:', err); + process.exit(1); + }); + " + + + - name: Download Web Artifact + uses: actions/download-artifact@v4 + with: + name: web-app-${{ needs.prepare-env.outputs.build_prefix }} + path: dist/ + + - name: Optimize PWA Size for Wrappers + if: matrix.app_type == 'pwa' + shell: bash + run: | + rm -rf dist/cheems-angular/browser/* + echo "Cheems Bonk Game

Loading PWA...

" > dist/cheems-angular/browser/index.html + + - name: Build Windows Desktop (Electron Bundled + Portable) + if: matrix.app_type == 'bundled' + shell: bash + run: | + npx cap copy @capacitor-community/electron + cd electron + npm install + npm run electron:make + + - name: Build Windows & Xbox (Native MSIX Bundled Offline) + if: matrix.app_type == 'bundled' + shell: pwsh + env: + build_prefix: ${{ needs.prepare-env.outputs.build_prefix }} + run: | + $Prefix = $env:build_prefix + $AppDir = "windows-bundled-src" + New-Item -ItemType Directory -Path "$AppDir\Assets" -Force + Copy-Item -Path "dist\cheems-angular\browser\*" -Destination $AppDir -Recurse + $IconSrc = ".pwa/icons-$Prefix/pwa/icon-512x512.png" + Copy-Item $IconSrc "$AppDir\Assets\StoreLogo.png" + Copy-Item $IconSrc "$AppDir\Assets\Square150x150Logo.png" + Copy-Item $IconSrc "$AppDir\Assets\Square44x44Logo.png" + Copy-Item $IconSrc "$AppDir\Assets\SplashScreen.png" + + $ManifestContent = Get-Content -Path ".pwa/windows-bundled.appxmanifest.xml" -Raw + $ManifestContent = $ManifestContent -replace '\$\{Prefix\}', $Prefix + Set-Content -Path "$AppDir\AppxManifest.xml" -Value $ManifestContent + + $MakeAppx = (Get-ChildItem -Path "C:\Program Files (x86)\Windows Kits\10\bin\*\x64\makeappx.exe" -ErrorAction SilentlyContinue | Sort-Object FullName -Descending | Select-Object -First 1).FullName + $SignTool = (Get-ChildItem -Path "C:\Program Files (x86)\Windows Kits\10\bin\*\x64\signtool.exe" -ErrorAction SilentlyContinue | Sort-Object FullName -Descending | Select-Object -First 1).FullName + & $MakeAppx pack /d $AppDir /p cheems-bundled-$Prefix.msix + $Cert = New-SelfSignedCertificate -Type Custom -Subject "CN=Cheems" -KeyUsage DigitalSignature -FriendlyName "Cheems App Cert" -CertStoreLocation "Cert:\CurrentUser\My" -TextExtension @("2.5.29.37={text}1.3.6.1.5.5.7.3.3", "2.5.29.19={text}") + $Password = ConvertTo-SecureString -String "password" -Force -AsPlainText + Export-PfxCertificate -Cert "Cert:\CurrentUser\My\$($Cert.Thumbprint)" -FilePath "cheems.pfx" -Password $Password + + & $SignTool sign /fd SHA256 /a /f cheems.pfx /p password cheems-bundled-$Prefix.msix + + mkdir -p windows-bundled + mv cheems-bundled-$Prefix.msix windows-bundled/ + + - name: Build Windows & Xbox (Native MSIX PWA) + if: matrix.app_type == 'pwa' + shell: pwsh + env: + page_root: ${{ needs.prepare-env.outputs.page_root }} + build_prefix: ${{ needs.prepare-env.outputs.build_prefix }} + run: | + $Owner = "${{ github.repository_owner }}" + if ([string]::IsNullOrWhiteSpace($Owner)) { $Owner = "luna115-oncode" } + $Owner = $Owner.ToLower() + $ManifestUrl = "https://$Owner.github.io${env:page_root}" + $Prefix = $env:build_prefix + $AppDir = "windows-pwa-src" + New-Item -ItemType Directory -Path "$AppDir\Assets" -Force + $IconSrc = ".pwa/icons-$Prefix/pwa/icon-512x512.png" + Copy-Item $IconSrc "$AppDir\Assets\StoreLogo.png" + Copy-Item $IconSrc "$AppDir\Assets\Square150x150Logo.png" + Copy-Item $IconSrc "$AppDir\Assets\Square44x44Logo.png" + Copy-Item $IconSrc "$AppDir\Assets\SplashScreen.png" + + $ManifestContent = Get-Content -Path ".pwa/windows-pwa.appxmanifest.xml" -Raw + $ManifestContent = $ManifestContent -replace '\$\{Prefix\}', $Prefix -replace '\$\{ManifestUrl\}', $ManifestUrl + Set-Content -Path "$AppDir\AppxManifest.xml" -Value $ManifestContent + + $MakeAppx = (Get-ChildItem -Path "C:\Program Files (x86)\Windows Kits\10\bin\*\x64\makeappx.exe" -ErrorAction SilentlyContinue | Sort-Object FullName -Descending | Select-Object -First 1).FullName + $SignTool = (Get-ChildItem -Path "C:\Program Files (x86)\Windows Kits\10\bin\*\x64\signtool.exe" -ErrorAction SilentlyContinue | Sort-Object FullName -Descending | Select-Object -First 1).FullName + & $MakeAppx pack /d $AppDir /p cheems-pwa-$Prefix.msix + $Cert = New-SelfSignedCertificate -Type Custom -Subject "CN=Cheems" -KeyUsage DigitalSignature -FriendlyName "Cheems PWA Cert" -CertStoreLocation "Cert:\CurrentUser\My" -TextExtension @("2.5.29.37={text}1.3.6.1.5.5.7.3.3", "2.5.29.19={text}") + $Password = ConvertTo-SecureString -String "password" -Force -AsPlainText + Export-PfxCertificate -Cert "Cert:\CurrentUser\My\$($Cert.Thumbprint)" -FilePath "cheems.pfx" -Password $Password + + & $SignTool sign /fd SHA256 /a /f cheems.pfx /p password cheems-pwa-$Prefix.msix + + mkdir -p windows-pwa + mv cheems-pwa-$Prefix.msix windows-pwa/ + + - name: Upload Windows Bundled Artifacts + if: matrix.app_type == 'bundled' + uses: actions/upload-artifact@v4 + with: + name: windows-app-${{ needs.prepare-env.outputs.build_prefix }} + path: | + electron/dist/*.exe + electron/dist/*.msi + windows-bundled/*.msix + + - name: Upload Windows PWA Artifacts + if: matrix.app_type == 'pwa' + uses: actions/upload-artifact@v4 + with: + name: windows-pwa-${{ needs.prepare-env.outputs.build_prefix }} + path: windows-pwa/*.msix + + build-macos-ios: + needs: [prepare-env, compile-web] + runs-on: macos-latest + strategy: + matrix: + app_type: [bundled, pwa] + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: ${{ env.NODE_VERSION }} + + - name: Install Dependencies + env: + NODE_TLS_REJECT_UNAUTHORIZED: 0 + run: | + # Try installing globals up to 3 times to handle random network drops + for i in 1 2 3; do + npm install -g @angular/cli @capacitor/cli @capacitor/assets png-to-ico && break || sleep 5 + done + + # Use 'npm ci' for reliable CI builds (falls back to 'npm install' if no lockfile exists) + npm ci || npm install + + + - name: Apply Environment Configs + env: + build_prefix: ${{ needs.prepare-env.outputs.build_prefix }} + page_root: ${{ needs.prepare-env.outputs.page_root }} + app_type: ${{ matrix.app_type }} + run: | + node -e " + const fs = require('fs'); + let cap = fs.readFileSync('capacitor.config.ts', 'utf8'); + let elec = JSON.parse(fs.readFileSync('electron/electron-builder.config.json', 'utf8')); + const isPwa = process.env.app_type === 'pwa'; + const prefix = process.env.build_prefix; + const repoOwner = '${{ github.repository_owner }}'.toLowerCase() || 'luna115-oncode'; + const pageRoot = process.env.page_root; + const appId = isPwa ? 'com.cheems.pwa.' + prefix : 'com.cheems.app.' + prefix; + + // Update electron config as JSON object + elec.appId = appId; + if (isPwa) { + elec.productName = 'Cheems Bonk Game (PWA)'; + elec.executableName = 'CheemsBonkGamePWA'; + } + + // Update capacitor config + cap = cap.replace('com.cheems.app', appId); + if (isPwa) { + cap = cap.replace('Cheems Bonk Game', 'Cheems Bonk Game (PWA)'); + const url = 'https://' + repoOwner + '.github.io' + pageRoot; + cap = cap.replace('webDir: \\'dist/cheems-angular/browser\\'', 'webDir: \\'dist/cheems-angular/browser\\',\\n server: { url: \\'' + url + '\\' }'); + } + + fs.writeFileSync('capacitor.config.ts', cap); + fs.writeFileSync('electron/electron-builder.config.json', JSON.stringify(elec, null, 2)); + " + mkdir -p assets electron/assets + cp .pwa/icons-$build_prefix/pwa/icon-512x512.png assets/icon-only.png + cp .pwa/icons-$build_prefix/pwa/icon-512x512.png assets/icon-foreground.png + cp .pwa/icons-$build_prefix/pwa/icon-512x512.png assets/icon-background.png + cp .pwa/icons-$build_prefix/pwa/icon-512x512.png assets/splash.png + cp .pwa/icons-$build_prefix/pwa/icon-512x512.png electron/assets/icon.png + + - name: Download Web Artifact + uses: actions/download-artifact@v4 + with: + name: web-app-${{ needs.prepare-env.outputs.build_prefix }} + path: dist/ + + - name: Optimize PWA Size for Wrappers + if: matrix.app_type == 'pwa' + shell: bash + run: | + rm -rf dist/cheems-angular/browser/* + echo "Cheems Bonk Game

Loading PWA...

" > dist/cheems-angular/browser/index.html + + - name: Build Mac (Electron Intel & Apple Silicon) + if: matrix.app_type != 'pwa' + run: | + npx cap copy @capacitor-community/electron + cd electron + npm install + # Kill any processes that might be holding onto the disk + lsof | grep -i /dev/disk | awk '{print $2}' | xargs kill -9 2>/dev/null || true + # Give the system a moment to clean up + sleep 2 + # Retry the build + npm run electron:make || { + # If it fails, force unmount any remaining disk images + diskutil list | grep -i APFS | awk '{print $NF}' | xargs -I {} diskutil unmountDisk force /dev/{} 2>/dev/null || true + exit 1 + } + + - name: Build iOS + run: | + npx cap add ios + npx @capacitor/assets generate --ios + npx cap sync ios + cd ios/App + xcodebuild -project App.xcodeproj -scheme App -configuration Debug -sdk iphonesimulator -derivedDataPath build + xcodebuild archive -project App.xcodeproj -scheme App -configuration Release -archivePath build/App.xcarchive CODE_SIGNING_ALLOWED=NO || true + xcodebuild -exportArchive -archivePath build/App.xcarchive -exportPath build/Export -exportOptionsPlist App/Info.plist CODE_SIGNING_ALLOWED=NO || true + + - name: Upload Mac Artifacts + if: matrix.app_type != 'pwa' + uses: actions/upload-artifact@v4 + with: + name: ${{ matrix.app_type == 'bundled' && 'macos-app-' || 'macos-pwa-' }}${{ needs.prepare-env.outputs.build_prefix }} + path: | + electron/dist/*.dmg + electron/dist/*.zip + electron/dist/**/*.app + + - name: Upload iOS Artifacts + uses: actions/upload-artifact@v4 + with: + name: ${{ matrix.app_type == 'bundled' && 'ios-app-' || 'ios-pwa-' }}${{ needs.prepare-env.outputs.build_prefix }} + path: | + ios/App/build/Build/Products/Debug-iphonesimulator/*.app + ios/App/build/Export/*.ipa + + build-extensions: + needs: [prepare-env, compile-web] + runs-on: ubuntu-latest + strategy: + matrix: + app_type: [bundled, pwa] + steps: + - uses: actions/checkout@v4 + + - name: Download Web Artifact + uses: actions/download-artifact@v4 + with: + name: web-app-${{ needs.prepare-env.outputs.build_prefix }} + path: dist/ + + - name: Build Chromium and Firefox Extensions + env: + app_type: ${{ matrix.app_type }} + build_prefix: ${{ needs.prepare-env.outputs.build_prefix }} + page_root: ${{ needs.prepare-env.outputs.page_root }} + run: | + mkdir -p ext-chromium ext-firefox + + # Setup routing logic based on PWA or Bundled + OWNER="${{ github.repository_owner }}" + if [ -z "$OWNER" ]; then OWNER="luna115-oncode"; fi + MANIFEST_URL="https://${OWNER,,}.github.io${page_root}" + if [ "$app_type" = "bundled" ]; then + # Copy all game files into the extension for offline play + cp -r dist/cheems-angular/browser/* ext-chromium/ + cp -r dist/cheems-angular/browser/* ext-firefox/ + TARGET_URL="index.html" + APP_NAME="Cheems Bonk Game" else - git commit -m "Deploy #${{ github.run_number }} from ${{ github.ref }} branch - ${{ steps.set-env.outputs.build_env }}" - GIT_SSH_COMMAND="ssh -i ~/.ssh/deploy_key -o UserKnownHostsFile=~/.ssh/known_hosts" git push git@github.com:${{ github.repository }} gh-pages --force + # Light PWA: Only opens the remote URL + TARGET_URL="$MANIFEST_URL" + APP_NAME="Cheems Bonk Game (PWA)" fi - - - name: Clean Up Worktree - run: git worktree remove deploy-folder --force + + # Copy extension icons + cp .pwa/icons-$build_prefix/pwa/icon-512x512.png ext-chromium/icon.png + cp .pwa/icons-$build_prefix/pwa/icon-512x512.png ext-firefox/icon.png + + # 1. Chromium Extension (Chrome, Edge, Brave, Opera, ChromeOS) + sed -e "s|\${AppName}|$APP_NAME|g" .pwa/chromium-manifest.json > ext-chromium/manifest.json + sed -e "s|\${TargetUrl}|$TARGET_URL|g" .pwa/extension-background.js > ext-chromium/background.js + + # 2. Firefox Extension + sed -e "s|\${AppName}|$APP_NAME|g" -e "s|\${Prefix}|$build_prefix|g" .pwa/firefox-manifest.json > ext-firefox/manifest.json + sed -e "s|\${TargetUrl}|$TARGET_URL|g" .pwa/extension-background.js > ext-firefox/background.js + + # Zip the extensions (Ready for Chrome Web Store & Mozilla Add-ons) + cd ext-chromium + zip -r ../chromium-extension-$build_prefix.zip * + cd ../ext-firefox + zip -r ../firefox-extension-$build_prefix.zip * + cd .. + + - name: Upload Extension Artifacts + uses: actions/upload-artifact@v4 + with: + name: ${{ matrix.app_type == 'bundled' && 'browser-extensions-bundled-' || 'browser-extensions-pwa-' }}${{ needs.prepare-env.outputs.build_prefix }} + path: | + *.zip diff --git a/.pwa/chromium-manifest.json b/.pwa/chromium-manifest.json new file mode 100644 index 0000000..524da32 --- /dev/null +++ b/.pwa/chromium-manifest.json @@ -0,0 +1,13 @@ +{ + "manifest_version": 3, + "name": "${AppName}", + "version": "1.0.0", + "description": "Play Cheems Bonk Game", + "action": {}, + "background": { + "service_worker": "background.js" + }, + "icons": { + "128": "icon.png" + } +} diff --git a/.pwa/extension-background.js b/.pwa/extension-background.js new file mode 100644 index 0000000..9da995f --- /dev/null +++ b/.pwa/extension-background.js @@ -0,0 +1,3 @@ +chrome.action.onClicked.addListener(() => { + chrome.tabs.create({ url: '${TargetUrl}' }); +}); diff --git a/.pwa/firefox-manifest.json b/.pwa/firefox-manifest.json new file mode 100644 index 0000000..7a86182 --- /dev/null +++ b/.pwa/firefox-manifest.json @@ -0,0 +1,18 @@ +{ + "manifest_version": 3, + "name": "${AppName}", + "version": "1.0.0", + "description": "Play Cheems Bonk Game", + "action": {}, + "background": { + "scripts": ["background.js"] + }, + "icons": { + "128": "icon.png" + }, + "browser_specific_settings": { + "gecko": { + "id": "cheemsbonk-${Prefix}@cheems.com" + } + } +} diff --git a/.pwa/linux-control b/.pwa/linux-control new file mode 100644 index 0000000..80ebc5e --- /dev/null +++ b/.pwa/linux-control @@ -0,0 +1,8 @@ +Package: ${AppName} +Version: 1.0.0 +Section: games +Priority: optional +Architecture: all +Maintainer: Action +Description: Cheems Bonk Game (PWA) + A lightweight Linux native wrapper for the Cheems Bonk PWA. diff --git a/.pwa/linux-launcher.sh b/.pwa/linux-launcher.sh new file mode 100644 index 0000000..2e324c5 --- /dev/null +++ b/.pwa/linux-launcher.sh @@ -0,0 +1,3 @@ +#!/bin/bash +URL="${ManifestUrl}" +if command -v google-chrome &> /dev/null; then exec google-chrome --app="$URL"; elif command -v chromium &> /dev/null; then exec chromium --app="$URL"; else exec xdg-open "$URL"; fi diff --git a/.pwa/linux.desktop b/.pwa/linux.desktop new file mode 100644 index 0000000..acba3a6 --- /dev/null +++ b/.pwa/linux.desktop @@ -0,0 +1,7 @@ +[Desktop Entry] +Type=Application +Name=Cheems Bonk Game (PWA) +Exec=${AppName} +Icon=${AppName} +Terminal=false +Categories=Game; diff --git a/.pwa/linux.spec b/.pwa/linux.spec new file mode 100644 index 0000000..cc9b3f5 --- /dev/null +++ b/.pwa/linux.spec @@ -0,0 +1,20 @@ +Name: ${AppName} +Version: 1.0.0 +Release: 1 +Summary: Cheems Bonk Game (PWA) +License: MIT +BuildArch: noarch + +%description +A lightweight Linux native wrapper for the Cheems Bonk PWA. + +%prep +%build +%install +mkdir -p %{buildroot} +cp -a ${Workspace}/deb-package/usr %{buildroot}/ + +%files +/usr/bin/${AppName} +/usr/share/applications/${AppName}.desktop +/usr/share/icons/hicolor/512x512/apps/${AppName}.png diff --git a/.pwa/manifest-dev.webmanifest b/.pwa/manifest-dev.webmanifest index a3bc7c7..cf07b27 100644 --- a/.pwa/manifest-dev.webmanifest +++ b/.pwa/manifest-dev.webmanifest @@ -3,29 +3,29 @@ "short_name": "Cheems Bonk Game (Development Environment)", "description": "A fun and interactive game featuring Cheems Bonk.\nThis is the Development environment version.", "display": "standalone", - "scope": "/CheemsBonkGame/development/", - "start_url": "/CheemsBonkGame/development/", + "scope": "/CheemsBonkGame/dev/", + "start_url": "/CheemsBonkGame/dev/", "icons": [ { - "src": "/CheemsBonkGame/development/img/icons/pwa/icon-72x72.png", + "src": "/CheemsBonkGame/dev/img/icons/pwa/icon-72x72.png", "sizes": "72x72", "type": "image/png", "purpose": "maskable any" }, { - "src": "/CheemsBonkGame/development/img/icons/pwa/icon-144x144.png", + "src": "/CheemsBonkGame/dev/img/icons/pwa/icon-144x144.png", "sizes": "144x144", "type": "image/png", "purpose": "maskable any" }, { - "src": "/CheemsBonkGame/development/img/icons/pwa/icon-192x192.png", + "src": "/CheemsBonkGame/dev/img/icons/pwa/icon-192x192.png", "sizes": "192x192", "type": "image/png", "purpose": "maskable any" }, { - "src": "/CheemsBonkGame/development/img/icons/pwa/icon-512x512.png", + "src": "/CheemsBonkGame/dev/img/icons/pwa/icon-512x512.png", "sizes": "512x512", "type": "image/png", "purpose": "maskable any" diff --git a/.pwa/styles-dev.css b/.pwa/styles-dev.css deleted file mode 100644 index e12e583..0000000 --- a/.pwa/styles-dev.css +++ /dev/null @@ -1,42 +0,0 @@ -/*Fonts*/ -@font-face { - font-family: 'Kalam'; - src: url('/CheemsBonkGame/development/fonts/Kalam-Regular.ttf') format('truetype'); -} - -/*App*/ -html { - user-select: none; - font-family: Kalam, Arial, Helvetica, sans-serif; -} -.icon { - height: 100%; - width: auto; -} - -/*Accesibility*/ -.text-normal { - font-size: 14pt; -} -.text-big { - font-size: 18pt; -} -.text-bigger { - font-size: 24pt; -} -.text-small { - font-size: 12pt; -} -.text-smaller { - font-size: 8pt; -} - -.color-text.theme-contrast { - color: rgb(255, 255, 0); -} -.color-text.theme-dark { - color: rgb(145, 145, 72); -} -.color-text.theme-light { - color: rgb(194, 194, 72); -} diff --git a/.pwa/styles-prod.css b/.pwa/styles-prod.css deleted file mode 100644 index 233421c..0000000 --- a/.pwa/styles-prod.css +++ /dev/null @@ -1,42 +0,0 @@ -/*Fonts*/ -@font-face { - font-family: 'Kalam'; - src: url('/CheemsBonkGame/app/fonts/Kalam-Regular.ttf') format('truetype'); -} - -/*App*/ -html { - user-select: none; - font-family: Kalam, Arial, Helvetica, sans-serif; -} -.icon { - height: 100%; - width: auto; -} - -/*Accesibility*/ -.text-normal { - font-size: 14pt; -} -.text-big { - font-size: 18pt; -} -.text-bigger { - font-size: 24pt; -} -.text-small { - font-size: 12pt; -} -.text-smaller { - font-size: 8pt; -} - -.color-text.theme-contrast { - color: rgb(255, 255, 0); -} -.color-text.theme-dark { - color: rgb(145, 145, 72); -} -.color-text.theme-light { - color: rgb(194, 194, 72); -} diff --git a/.pwa/styles-test.css b/.pwa/styles-test.css deleted file mode 100644 index 6df9346..0000000 --- a/.pwa/styles-test.css +++ /dev/null @@ -1,42 +0,0 @@ -/*Fonts*/ -@font-face { - font-family: 'Kalam'; - src: url('/CheemsBonkGame/test/fonts/Kalam-Regular.ttf') format('truetype'); -} - -/*App*/ -html { - user-select: none; - font-family: Kalam, Arial, Helvetica, sans-serif; -} -.icon { - height: 100%; - width: auto; -} - -/*Accesibility*/ -.text-normal { - font-size: 14pt; -} -.text-big { - font-size: 18pt; -} -.text-bigger { - font-size: 24pt; -} -.text-small { - font-size: 12pt; -} -.text-smaller { - font-size: 8pt; -} - -.color-text.theme-contrast { - color: rgb(255, 255, 0); -} -.color-text.theme-dark { - color: rgb(145, 145, 72); -} -.color-text.theme-light { - color: rgb(194, 194, 72); -} diff --git a/.pwa/windows-bundled.appxmanifest.xml b/.pwa/windows-bundled.appxmanifest.xml new file mode 100644 index 0000000..b16f13a --- /dev/null +++ b/.pwa/windows-bundled.appxmanifest.xml @@ -0,0 +1,23 @@ + + + + + Cheems Bonk Game + Cheems + Assets\StoreLogo.png + + + + + + + + + + + + + + + + diff --git a/.pwa/windows-pwa.appxmanifest.xml b/.pwa/windows-pwa.appxmanifest.xml new file mode 100644 index 0000000..f2291f2 --- /dev/null +++ b/.pwa/windows-pwa.appxmanifest.xml @@ -0,0 +1,26 @@ + + + + + Cheems Bonk Game (PWA) + Cheems + Assets\StoreLogo.png + + + + + + + + + + + + + + + + + + + diff --git a/angular.json b/angular.json index 4e4708d..e7f319a 100644 --- a/angular.json +++ b/angular.json @@ -36,13 +36,13 @@ "budgets": [ { "type": "initial", - "maximumWarning": "500kB", - "maximumError": "1MB" + "maximumWarning": "1MB", + "maximumError": "3MB" }, { "type": "anyComponentStyle", - "maximumWarning": "2kB", - "maximumError": "4kB" + "maximumWarning": "20kB", + "maximumError": "50kB" } ], "outputHashing": "all", @@ -51,7 +51,8 @@ "development": { "optimization": false, "extractLicenses": false, - "sourceMap": true + "sourceMap": true, + "serviceWorker": "ngsw-config.json" } }, "defaultConfiguration": "production" diff --git a/capacitor.config.ts b/capacitor.config.ts new file mode 100644 index 0000000..e6d5008 --- /dev/null +++ b/capacitor.config.ts @@ -0,0 +1,9 @@ +import type { CapacitorConfig } from '@capacitor/cli'; + +const config: CapacitorConfig = { + appId: 'com.cheems.app', + appName: 'Cheems Bonk Game', + webDir: 'dist/cheems-angular/browser' +}; + +export default config; diff --git a/electron/.gitignore b/electron/.gitignore new file mode 100644 index 0000000..c340937 --- /dev/null +++ b/electron/.gitignore @@ -0,0 +1,8 @@ +# NPM renames .gitignore to .npmignore +# In order to prevent that, we remove the initial "." +# And the CLI then renames it +app +node_modules +build +dist +logs diff --git a/electron/capacitor.config.ts b/electron/capacitor.config.ts new file mode 100644 index 0000000..ee88259 --- /dev/null +++ b/electron/capacitor.config.ts @@ -0,0 +1,9 @@ +import type { CapacitorConfig } from '@capacitor/cli'; + +const config: CapacitorConfig = { + appId: 'com.cheems.angular', + appName: 'CheemsAngular', + webDir: 'dist/cheems-angular/browser' +}; + +export default config; diff --git a/electron/electron-builder.config.json b/electron/electron-builder.config.json new file mode 100644 index 0000000..ccebe17 --- /dev/null +++ b/electron/electron-builder.config.json @@ -0,0 +1,70 @@ +{ + "appId": "com.cheems.app", + "productName": "Cheems Bonk Game", + "executableName": "CheemsBonkGame", + "directories": { + "output": "dist", + "buildResources": "assets" + }, + "files": [ + "build/**/*", + "node_modules/**/*", + "package.json" + ], + "extraMetadata": { + "main": "build/src/index.js" + }, + "win": { + "target": [ + { + "target": "nsis", + "arch": ["x64"] + }, + { + "target": "msi", + "arch": ["x64"] + } + ], + "icon": "assets/icon.png", + "certificateFile": null, + "certificatePassword": null, + "signingHashAlgorithms": ["sha256"] + }, + "nsis": { + "oneClick": false, + "allowToChangeInstallationDirectory": true, + "createDesktopShortcut": true, + "createStartMenuShortcut": true, + "shortcutName": "Cheems Bonk Game" + }, + "msi": { + "oneClick": false, + "createDesktopShortcut": true, + "createStartMenuShortcut": true, + "shortcutName": "Cheems Bonk Game" + }, + "linux": { + "target": ["deb", "rpm", "AppImage"], + "category": "Game" + }, + "mac": { + "target": [ + { + "target": "dmg", + "arch": ["x64"] + }, + { + "target": "dmg", + "arch": ["arm64"] + }, + { + "target": "zip", + "arch": ["x64"] + }, + { + "target": "zip", + "arch": ["arm64"] + } + ] + } +} \ No newline at end of file diff --git a/electron/live-runner.js b/electron/live-runner.js new file mode 100644 index 0000000..84c3ea7 --- /dev/null +++ b/electron/live-runner.js @@ -0,0 +1,75 @@ +/* eslint-disable no-undef */ +/* eslint-disable @typescript-eslint/no-var-requires */ +const cp = require('child_process'); +const chokidar = require('chokidar'); +const electron = require('electron'); + +let child = null; +const npmCmd = process.platform === 'win32' ? 'npm.cmd' : 'npm'; +const reloadWatcher = { + debouncer: null, + ready: false, + watcher: null, + restarting: false, +}; + +///* +function runBuild() { + return new Promise((resolve, _reject) => { + let tempChild = cp.spawn(npmCmd, ['run', 'build']); + tempChild.once('exit', () => { + resolve(); + }); + tempChild.stdout.pipe(process.stdout); + }); +} +//*/ + +async function spawnElectron() { + if (child !== null) { + child.stdin.pause(); + child.kill(); + child = null; + await runBuild(); + } + child = cp.spawn(electron, ['--inspect=5858', './']); + child.on('exit', () => { + if (!reloadWatcher.restarting) { + process.exit(0); + } + }); + child.stdout.pipe(process.stdout); +} + +function setupReloadWatcher() { + reloadWatcher.watcher = chokidar + .watch('./src/**/*', { + ignored: /[/\\]\./, + persistent: true, + }) + .on('ready', () => { + reloadWatcher.ready = true; + }) + .on('all', (_event, _path) => { + if (reloadWatcher.ready) { + clearTimeout(reloadWatcher.debouncer); + reloadWatcher.debouncer = setTimeout(async () => { + console.log('Restarting'); + reloadWatcher.restarting = true; + await spawnElectron(); + reloadWatcher.restarting = false; + reloadWatcher.ready = false; + clearTimeout(reloadWatcher.debouncer); + reloadWatcher.debouncer = null; + reloadWatcher.watcher = null; + setupReloadWatcher(); + }, 500); + } + }); +} + +(async () => { + await runBuild(); + await spawnElectron(); + setupReloadWatcher(); +})(); diff --git a/electron/package-lock.json b/electron/package-lock.json new file mode 100644 index 0000000..0ce2147 --- /dev/null +++ b/electron/package-lock.json @@ -0,0 +1,5582 @@ +{ + "name": "CheemsAngular", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "CheemsAngular", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "@capacitor-community/electron": "^5.0.0", + "chokidar": "~3.5.3", + "electron-is-dev": "~2.0.0", + "electron-serve": "~1.1.0", + "electron-unhandled": "~4.0.1", + "electron-updater": "^5.3.0", + "electron-window-state": "^5.0.3" + }, + "devDependencies": { + "electron": "^26.2.2", + "electron-builder": "~23.6.0", + "electron-rebuild": "^3.2.9", + "typescript": "^5.0.4" + } + }, + "node_modules/@capacitor-community/electron": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@capacitor-community/electron/-/electron-5.0.1.tgz", + "integrity": "sha512-4/x12ycTq0Kq8JIn/BmIBdFVP5Cqw8iA6SU6YfFjmONfjW3OELwsB3zwLxOwAjLxnjyCMOBHl4ci9E5jLgZgAQ==", + "license": "MIT", + "dependencies": { + "@capacitor/cli": ">=5.4.0", + "@capacitor/core": ">=5.4.0", + "@ionic/utils-fs": "~3.1.6", + "chalk": "^4.1.2", + "electron-is-dev": "~2.0.0", + "events": "~3.3.0", + "fs-extra": "~11.1.1", + "keyv": "^4.5.2", + "mime-types": "~2.1.35", + "ora": "^5.4.1" + } + }, + "node_modules/@capacitor/cli": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@capacitor/cli/-/cli-8.5.0.tgz", + "integrity": "sha512-rLdzMUM5QV4WITcqoWv04p32i14BXgUH2diqEH6MWQlWaJfiyNrvOyt/+d5vHAfOxOm1klBu637VDEobctlwBA==", + "license": "MIT", + "dependencies": { + "@ionic/cli-framework-output": "^2.2.8", + "@ionic/utils-subprocess": "^3.0.1", + "@ionic/utils-terminal": "^2.3.5", + "commander": "^12.1.0", + "debug": "^4.4.0", + "env-paths": "^2.2.0", + "fs-extra": "^11.2.0", + "kleur": "^4.1.5", + "native-run": "^2.0.3", + "open": "^8.4.0", + "plist": "^3.1.0", + "prompts": "^2.4.2", + "rimraf": "^6.0.1", + "semver": "^7.6.3", + "tar": "^7.5.3", + "tslib": "^2.8.1", + "xcode": "^3.0.1", + "xml2js": "^0.6.2" + }, + "bin": { + "cap": "bin/capacitor", + "capacitor": "bin/capacitor" + }, + "engines": { + "node": ">=22.0.0" + } + }, + "node_modules/@capacitor/cli/node_modules/fs-extra": { + "version": "11.4.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.4.0.tgz", + "integrity": "sha512-EQsFzMUJkCKGr1ePqlYADkIUmHW1s3ZXr5Yqy6wbGrfUCphpl2maM/kyOIRA2HpP3AaFQTZXD4ldjek+nccddA==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/@capacitor/cli/node_modules/jsonfile": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz", + "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/@capacitor/core": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@capacitor/core/-/core-8.5.0.tgz", + "integrity": "sha512-Ca4krtqH1hothjtBIwf2J2TW7IhYq1ujp8QeItTiJohNsqij8ja2DYYH3DU0l8RmxCWaBAFTGA2TgOgOMCSNsQ==", + "license": "MIT", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@develar/schema-utils": { + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/@develar/schema-utils/-/schema-utils-2.6.5.tgz", + "integrity": "sha512-0cp4PsWQ/9avqTVMCtZ+GirikIA36ikvjtHweU4/j8yLtgObI0+JUPhYFScgwlteveGB1rt3Cm8UhN04XayDig==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.0", + "ajv-keywords": "^3.4.1" + }, + "engines": { + "node": ">= 8.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/@electron/get": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@electron/get/-/get-2.0.3.tgz", + "integrity": "sha512-Qkzpg2s9GnVV2I2BjRksUi43U5e6+zaQMcjoJy0C+C5oxaKl+fmckGDQFtRpZpZV0NQekuZZ+tGz7EA9TVnQtQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.1.1", + "env-paths": "^2.2.0", + "fs-extra": "^8.1.0", + "got": "^11.8.5", + "progress": "^2.0.3", + "semver": "^6.2.0", + "sumchecker": "^3.0.1" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "global-agent": "^3.0.0" + } + }, + "node_modules/@electron/get/node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/@electron/get/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@electron/get/node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/@electron/universal": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@electron/universal/-/universal-1.2.1.tgz", + "integrity": "sha512-7323HyMh7KBAl/nPDppdLsC87G6RwRU02dy5FPeGB1eS7rUePh55+WNWiDPLhFQqqVPHzh77M69uhmoT8XnwMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@malept/cross-spawn-promise": "^1.1.0", + "asar": "^3.1.0", + "debug": "^4.3.1", + "dir-compare": "^2.4.0", + "fs-extra": "^9.0.1", + "minimatch": "^3.0.4", + "plist": "^3.0.4" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/@electron/universal/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@electron/universal/node_modules/jsonfile": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz", + "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/@gar/promisify": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", + "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@ionic/cli-framework-output": { + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/@ionic/cli-framework-output/-/cli-framework-output-2.2.8.tgz", + "integrity": "sha512-TshtaFQsovB4NWRBydbNFawql6yul7d5bMiW1WYYf17hd99V6xdDdk3vtF51bw6sLkxON3bDQpWsnUc9/hVo3g==", + "license": "MIT", + "dependencies": { + "@ionic/utils-terminal": "2.3.5", + "debug": "^4.0.0", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@ionic/utils-array": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@ionic/utils-array/-/utils-array-2.1.6.tgz", + "integrity": "sha512-0JZ1Zkp3wURnv8oq6Qt7fMPo5MpjbLoUoa9Bu2Q4PJuSDWM8H8gwF3dQO7VTeUj3/0o1IB1wGkFWZZYgUXZMUg==", + "license": "MIT", + "dependencies": { + "debug": "^4.0.0", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@ionic/utils-fs": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/@ionic/utils-fs/-/utils-fs-3.1.7.tgz", + "integrity": "sha512-2EknRvMVfhnyhL1VhFkSLa5gOcycK91VnjfrTB0kbqkTFCOXyXgVLI5whzq7SLrgD9t1aqos3lMMQyVzaQ5gVA==", + "license": "MIT", + "dependencies": { + "@types/fs-extra": "^8.0.0", + "debug": "^4.0.0", + "fs-extra": "^9.0.0", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@ionic/utils-fs/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "license": "MIT", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@ionic/utils-fs/node_modules/jsonfile": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz", + "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/@ionic/utils-object": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@ionic/utils-object/-/utils-object-2.1.6.tgz", + "integrity": "sha512-vCl7sl6JjBHFw99CuAqHljYJpcE88YaH2ZW4ELiC/Zwxl5tiwn4kbdP/gxi2OT3MQb1vOtgAmSNRtusvgxI8ww==", + "license": "MIT", + "dependencies": { + "debug": "^4.0.0", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@ionic/utils-process": { + "version": "2.1.12", + "resolved": "https://registry.npmjs.org/@ionic/utils-process/-/utils-process-2.1.12.tgz", + "integrity": "sha512-Jqkgyq7zBs/v/J3YvKtQQiIcxfJyplPgECMWgdO0E1fKrrH8EF0QGHNJ9mJCn6PYe2UtHNS8JJf5G21e09DfYg==", + "license": "MIT", + "dependencies": { + "@ionic/utils-object": "2.1.6", + "@ionic/utils-terminal": "2.3.5", + "debug": "^4.0.0", + "signal-exit": "^3.0.3", + "tree-kill": "^1.2.2", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@ionic/utils-stream": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/@ionic/utils-stream/-/utils-stream-3.1.7.tgz", + "integrity": "sha512-eSELBE7NWNFIHTbTC2jiMvh1ABKGIpGdUIvARsNPMNQhxJB3wpwdiVnoBoTYp+5a6UUIww4Kpg7v6S7iTctH1w==", + "license": "MIT", + "dependencies": { + "debug": "^4.0.0", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@ionic/utils-subprocess": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@ionic/utils-subprocess/-/utils-subprocess-3.0.1.tgz", + "integrity": "sha512-cT4te3AQQPeIM9WCwIg8ohroJ8TjsYaMb2G4ZEgv9YzeDqHZ4JpeIKqG2SoaA3GmVQ3sOfhPM6Ox9sxphV/d1A==", + "license": "MIT", + "dependencies": { + "@ionic/utils-array": "2.1.6", + "@ionic/utils-fs": "3.1.7", + "@ionic/utils-process": "2.1.12", + "@ionic/utils-stream": "3.1.7", + "@ionic/utils-terminal": "2.3.5", + "cross-spawn": "^7.0.3", + "debug": "^4.0.0", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@ionic/utils-terminal": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@ionic/utils-terminal/-/utils-terminal-2.3.5.tgz", + "integrity": "sha512-3cKScz9Jx2/Pr9ijj1OzGlBDfcmx7OMVBt4+P1uRR0SSW4cm1/y3Mo4OY3lfkuaYifMNBW8Wz6lQHbs1bihr7A==", + "license": "MIT", + "dependencies": { + "@types/slice-ansi": "^4.0.0", + "debug": "^4.0.0", + "signal-exit": "^3.0.3", + "slice-ansi": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "tslib": "^2.0.1", + "untildify": "^4.0.0", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@isaacs/fs-minipass": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", + "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", + "license": "ISC", + "dependencies": { + "minipass": "^7.0.4" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@isaacs/fs-minipass/node_modules/minipass": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/@malept/cross-spawn-promise": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@malept/cross-spawn-promise/-/cross-spawn-promise-1.1.1.tgz", + "integrity": "sha512-RTBGWL5FWQcg9orDOCcp4LvItNzUPcyEU9bwaeJX0rJ1IQxzucC48Y0/sQLp/g6t99IQgAlGIaesJS+gTn7tVQ==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/malept" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/subscription/pkg/npm-.malept-cross-spawn-promise?utm_medium=referral&utm_source=npm_fund" + } + ], + "license": "Apache-2.0", + "dependencies": { + "cross-spawn": "^7.0.1" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@malept/flatpak-bundler": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@malept/flatpak-bundler/-/flatpak-bundler-0.4.0.tgz", + "integrity": "sha512-9QOtNffcOF/c1seMCDnjckb3R9WHcG34tky+FHpNKKCW0wc/scYLwMtO+ptyGUfMW0/b/n4qRiALlaFHc9Oj7Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.1.1", + "fs-extra": "^9.0.0", + "lodash": "^4.17.15", + "tmp-promise": "^3.0.2" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@malept/flatpak-bundler/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@malept/flatpak-bundler/node_modules/jsonfile": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz", + "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/@npmcli/fs": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-2.1.2.tgz", + "integrity": "sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "@gar/promisify": "^1.1.3", + "semver": "^7.3.5" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/@npmcli/move-file": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-2.0.1.tgz", + "integrity": "sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==", + "deprecated": "This functionality has been moved to @npmcli/fs", + "dev": true, + "license": "MIT", + "dependencies": { + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/@npmcli/move-file/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@npmcli/move-file/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@sindresorhus/is": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", + "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "node_modules/@szmarczak/http-timer": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", + "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", + "dev": true, + "license": "MIT", + "dependencies": { + "defer-to-connect": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@tootallnate/once": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.1.tgz", + "integrity": "sha512-HqmEUIGRJ5fSXchkVgR5F7qn48bDBzv0kWj/Kfu5e6uci4UlEeng4331LnBkWffb++Ei3FOVLxo8JJWMFBDMeQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/@types/cacheable-request": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", + "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/http-cache-semantics": "*", + "@types/keyv": "^3.1.4", + "@types/node": "*", + "@types/responselike": "^1.0.0" + } + }, + "node_modules/@types/debug": { + "version": "4.1.13", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.13.tgz", + "integrity": "sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/ms": "*" + } + }, + "node_modules/@types/fs-extra": { + "version": "8.1.5", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-8.1.5.tgz", + "integrity": "sha512-0dzKcwO+S8s2kuF5Z9oUWatQJj5Uq/iqphEtE3GQJVRRYm/tD1LglU2UnXi2A8jLq5umkGouOXOR9y0n613ZwQ==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@types/minimatch": "*", + "@types/node": "*" + } + }, + "node_modules/@types/http-cache-semantics": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", + "integrity": "sha512-L3LgimLHXtGkWikKnsPg0/VFx9OGZaC+eN1u4r+OB1XRqH3meBIAVC2zr1WdMH+RHmnRkqliQAOHNJ/E0j/e0Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/keyv": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", + "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/minimatch": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", + "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/@types/ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "26.2.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-26.2.0.tgz", + "integrity": "sha512-5IviulTZeRNp2vAJ514cc/HUlY5nZ9fCbq9DMyC52BrhFZACo3nI0R7qBxhQmo/d27NFe96ur/b7Wwxklda+kg==", + "license": "MIT", + "dependencies": { + "undici-types": "~8.3.0" + } + }, + "node_modules/@types/plist": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/plist/-/plist-3.0.5.tgz", + "integrity": "sha512-E6OCaRmAe4WDmWNsL/9RMqdkkzDCY1etutkflWk4c+AcjDU07Pcz1fQwTX0TQz+Pxqn9i4L1TU3UFpjnrcDgxA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@types/node": "*", + "xmlbuilder": ">=11.0.1" + } + }, + "node_modules/@types/responselike": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.3.tgz", + "integrity": "sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/semver": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.8.0.tgz", + "integrity": "sha512-1mAINjtQCXXeLkJ9ehXkwOcBpqtLxiVtKhpUf83DdRNdQKV0iXZpaHYqRr7nj+wvxuJzoAmAwXI+sCNMv1CzLQ==", + "license": "MIT" + }, + "node_modules/@types/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-+OpjSaq85gvlZAYINyzKpLeiFkSC4EsC6IIiT6v6TLSU5k5U83fHGj9Lel8oKEXM0HqgrMVCjXPDPVICtxF7EQ==", + "license": "MIT" + }, + "node_modules/@types/verror": { + "version": "1.10.11", + "resolved": "https://registry.npmjs.org/@types/verror/-/verror-1.10.11.tgz", + "integrity": "sha512-RlDm9K7+o5stv0Co8i8ZRGxDbrTxhJtgjqjFyVh/tXQyl/rYtTKlnTvZ88oSTeYREWurwx20Js4kTuKCsFkUtg==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/@types/yargs": { + "version": "17.0.35", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.35.tgz", + "integrity": "sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/yauzl": { + "version": "2.10.3", + "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", + "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@xmldom/xmldom": { + "version": "0.9.10", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.9.10.tgz", + "integrity": "sha512-A9gOqLdi6cV4ibazAjcQufGj0B1y/vDqYrcuP6d/6x8P27gRS8643Dj9o1dEKtB6O7fwxb2FgBmJS2mX7gpvdw==", + "license": "MIT", + "engines": { + "node": ">=14.6" + } + }, + "node_modules/7zip-bin": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/7zip-bin/-/7zip-bin-5.1.1.tgz", + "integrity": "sha512-sAP4LldeWNz0lNzmTird3uWfFDWWTeg6V/MsmyyLR9X1idwKBWIgt/ZvinqQldJm3LecKEs1emkbquO6PCiLVQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true, + "license": "ISC" + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/agentkeepalive": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.6.0.tgz", + "integrity": "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "humanize-ms": "^1.2.1" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ajv": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/app-builder-bin": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/app-builder-bin/-/app-builder-bin-4.0.0.tgz", + "integrity": "sha512-xwdG0FJPQMe0M0UA4Tz0zEB8rBJTRA5a476ZawAqiBkMv16GRK5xpXThOjMaEOFnZ6zabejjG4J3da0SXG63KA==", + "dev": true, + "license": "MIT" + }, + "node_modules/app-builder-lib": { + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-23.6.0.tgz", + "integrity": "sha512-dQYDuqm/rmy8GSCE6Xl/3ShJg6Ab4bZJMT8KaTKGzT436gl1DN4REP3FCWfXoh75qGTJ+u+WsdnnpO9Jl8nyMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@develar/schema-utils": "~2.6.5", + "@electron/universal": "1.2.1", + "@malept/flatpak-bundler": "^0.4.0", + "7zip-bin": "~5.1.1", + "async-exit-hook": "^2.0.1", + "bluebird-lst": "^1.0.9", + "builder-util": "23.6.0", + "builder-util-runtime": "9.1.1", + "chromium-pickle-js": "^0.2.0", + "debug": "^4.3.4", + "ejs": "^3.1.7", + "electron-osx-sign": "^0.6.0", + "electron-publish": "23.6.0", + "form-data": "^4.0.0", + "fs-extra": "^10.1.0", + "hosted-git-info": "^4.1.0", + "is-ci": "^3.0.0", + "isbinaryfile": "^4.0.10", + "js-yaml": "^4.1.0", + "lazy-val": "^1.0.5", + "minimatch": "^3.1.2", + "read-config-file": "6.2.0", + "sanitize-filename": "^1.6.3", + "semver": "^7.3.7", + "tar": "^6.1.11", + "temp-file": "^3.4.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/app-builder-lib/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/app-builder-lib/node_modules/jsonfile": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz", + "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/app-builder-lib/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=8" + } + }, + "node_modules/app-builder-lib/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/app-builder-lib/node_modules/tar": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "deprecated": "Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/aproba": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.1.0.tgz", + "integrity": "sha512-tLIEcj5GuR2RSTnxNKdkK0dJ/GrC7P38sUkiDmDuHfsHmbagTFAxDVIBltoklXEVIQ/f14IL8IMJ5pn9Hez1Ew==", + "dev": true, + "license": "ISC" + }, + "node_modules/are-we-there-yet": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", + "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", + "deprecated": "This package is no longer supported.", + "dev": true, + "license": "ISC", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "license": "Python-2.0" + }, + "node_modules/asar": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/asar/-/asar-3.2.0.tgz", + "integrity": "sha512-COdw2ZQvKdFGFxXwX3oYh2/sOsJWJegrdJCGxnN4MZ7IULgRBp9P6665aqj9z1v9VwP4oP1hRBojRDQ//IGgAg==", + "deprecated": "Please use @electron/asar moving forward. There is no API change, just a package name change", + "dev": true, + "license": "MIT", + "dependencies": { + "chromium-pickle-js": "^0.2.0", + "commander": "^5.0.0", + "glob": "^7.1.6", + "minimatch": "^3.0.4" + }, + "bin": { + "asar": "bin/asar.js" + }, + "engines": { + "node": ">=10.12.0" + }, + "optionalDependencies": { + "@types/glob": "^7.1.1" + } + }, + "node_modules/asar/node_modules/commander": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", + "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "dev": true, + "license": "MIT" + }, + "node_modules/async-exit-hook": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/async-exit-hook/-/async-exit-hook-2.0.1.tgz", + "integrity": "sha512-NW2cX8m1Q7KPA7a5M2ULQeZ2wR5qI5PAbw5L0UOMxdioVk9PMZ0h1TmyZEkPYrCvYjDlFICusOu1dlEKAAeXBw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "license": "ISC", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/big-integer": { + "version": "1.6.52", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz", + "integrity": "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==", + "license": "Unlicense", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "license": "MIT", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true, + "license": "MIT" + }, + "node_modules/bluebird-lst": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/bluebird-lst/-/bluebird-lst-1.0.9.tgz", + "integrity": "sha512-7B1Rtx82hjnSD4PGLAjVWeYH3tHAcVUmChh85a3lltKQm6FresXh9ErQo6oAv6CqxttczC3/kEg8SY5NluPuUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "bluebird": "^3.5.5" + } + }, + "node_modules/boolean": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", + "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/bplist-creator": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/bplist-creator/-/bplist-creator-0.1.0.tgz", + "integrity": "sha512-sXaHZicyEEmY86WyueLTQesbeoH/mquvarJaQNbjuOQO+7gbFcDEWqKmcWA4cOTLzFlfgvkiVxolk1k5bBIpmg==", + "license": "MIT", + "dependencies": { + "stream-buffers": "2.2.x" + } + }, + "node_modules/bplist-parser": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.3.2.tgz", + "integrity": "sha512-apC2+fspHGI3mMKj+dGevkGo/tCqVB8jMb6i+OX+E29p0Iposz07fABkRIfVUPNd5A5VbuOz1bZbnmkKLYF+wQ==", + "license": "MIT", + "dependencies": { + "big-integer": "1.6.x" + }, + "engines": { + "node": ">= 5.10.0" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.18", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", + "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-alloc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", + "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-alloc-unsafe": "^1.1.0", + "buffer-fill": "^1.0.0" + } + }, + "node_modules/buffer-alloc-unsafe": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", + "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==", + "dev": true, + "license": "MIT" + }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/buffer-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz", + "integrity": "sha512-tcBWO2Dl4e7Asr9hTGcpVrCe+F7DubpmqWCTbj4FHLmjqO2hIaC383acQubWtRJhdceqs5uBHs6Es+Sk//RKiQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/buffer-fill": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", + "integrity": "sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/builder-util": { + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/builder-util/-/builder-util-23.6.0.tgz", + "integrity": "sha512-QiQHweYsh8o+U/KNCZFSvISRnvRctb8m/2rB2I1JdByzvNKxPeFLlHFRPQRXab6aYeXc18j9LpsDLJ3sGQmWTQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/debug": "^4.1.6", + "@types/fs-extra": "^9.0.11", + "7zip-bin": "~5.1.1", + "app-builder-bin": "4.0.0", + "bluebird-lst": "^1.0.9", + "builder-util-runtime": "9.1.1", + "chalk": "^4.1.1", + "cross-spawn": "^7.0.3", + "debug": "^4.3.4", + "fs-extra": "^10.0.0", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "is-ci": "^3.0.0", + "js-yaml": "^4.1.0", + "source-map-support": "^0.5.19", + "stat-mode": "^1.0.0", + "temp-file": "^3.4.0" + } + }, + "node_modules/builder-util-runtime": { + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.1.1.tgz", + "integrity": "sha512-azRhYLEoDvRDR8Dhis4JatELC/jUvYjm4cVSj7n9dauGTOM2eeNn9KS0z6YA6oDsjI1xphjNbY6PZZeHPzzqaw==", + "license": "MIT", + "dependencies": { + "debug": "^4.3.4", + "sax": "^1.2.4" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/builder-util/node_modules/@types/fs-extra": { + "version": "9.0.13", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.13.tgz", + "integrity": "sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/builder-util/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/builder-util/node_modules/jsonfile": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz", + "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/cacache": { + "version": "16.1.3", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.1.3.tgz", + "integrity": "sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "@npmcli/fs": "^2.1.0", + "@npmcli/move-file": "^2.0.0", + "chownr": "^2.0.0", + "fs-minipass": "^2.1.0", + "glob": "^8.0.1", + "infer-owner": "^1.0.4", + "lru-cache": "^7.7.1", + "minipass": "^3.1.6", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "mkdirp": "^1.0.4", + "p-map": "^4.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^3.0.2", + "ssri": "^9.0.0", + "tar": "^6.1.11", + "unique-filename": "^2.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/cacache/node_modules/brace-expansion": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.4.tgz", + "integrity": "sha512-hGfVzPxthbf3+2yjg/RBs60cB0FhqBS/zvdV/4wn4/BmN0bNMMHPc4V/BbFieqf1TKAGGAHnY4eSjajCl0f2Xg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/cacache/node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/cacache/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/cacache/node_modules/minimatch": { + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz", + "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cacache/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cacache/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/cacache/node_modules/rimraf/node_modules/brace-expansion": { + "version": "1.1.18", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", + "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/cacache/node_modules/rimraf/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/cacache/node_modules/rimraf/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/cacache/node_modules/tar": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "deprecated": "Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cacache/node_modules/tar/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=8" + } + }, + "node_modules/cacheable-lookup": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", + "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.6.0" + } + }, + "node_modules/cacheable-request": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.4.tgz", + "integrity": "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==", + "dev": true, + "license": "MIT", + "dependencies": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^4.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^6.0.1", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/chromium-pickle-js": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/chromium-pickle-js/-/chromium-pickle-js-0.2.0.tgz", + "integrity": "sha512-1R5Fho+jBq0DDydt+/vHWj5KJNJCKdARKOCwZUen84I5BreWoLqRLANH1U87eJy1tiASPtMnGqJJq0ZsLoRPOw==", + "dev": true, + "license": "MIT" + }, + "node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "license": "MIT", + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-spinners": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", + "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "slice-ansi": "^3.0.0", + "string-width": "^4.2.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate/node_modules/slice-ansi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", + "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "license": "MIT", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/clone-response": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", + "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-response": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "dev": true, + "license": "ISC", + "bin": { + "color-support": "bin.js" + } + }, + "node_modules/colors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", + "integrity": "sha512-pFGrxThWcWQ2MsAz6RtgeWe4NK2kUE1WfsrvvlctdII745EW9I0yflqhe7++M5LEc7bV2c/9/5zc8sFcpL0Drw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/compare-version": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/compare-version/-/compare-version-0.1.2.tgz", + "integrity": "sha512-pJDh5/4wrEnXX/VWRZvruAGHkzKdr46z11OlTPN+VrATlWWhSKewNCJ1futCO5C7eJB3nPMFZA1LeYtcFboZ2A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/crc": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.8.0.tgz", + "integrity": "sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "buffer": "^5.1.0" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decompress-response/node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/defaults": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", + "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", + "license": "MIT", + "dependencies": { + "clone": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/defer-to-connect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/detect-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/dir-compare": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/dir-compare/-/dir-compare-2.4.0.tgz", + "integrity": "sha512-l9hmu8x/rjVC9Z2zmGzkhOEowZvW7pmYws5CWHutg8u1JgvsKWMx7Q/UODeu4djLZ4FgW5besw5yvMQnBHzuCA==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-equal": "1.0.0", + "colors": "1.0.3", + "commander": "2.9.0", + "minimatch": "3.0.4" + }, + "bin": { + "dircompare": "src/cli/dircompare.js" + } + }, + "node_modules/dir-compare/node_modules/commander": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", + "integrity": "sha512-bmkUukX8wAOjHdN26xj5c4ctEV22TQ7dQYhSmuckKhToXrkUn0iIaolHdIxYYqD55nhpSPA9zPQ1yP57GdXP2A==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-readlink": ">= 1.0.0" + }, + "engines": { + "node": ">= 0.6.x" + } + }, + "node_modules/dir-compare/node_modules/minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/dmg-builder": { + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/dmg-builder/-/dmg-builder-23.6.0.tgz", + "integrity": "sha512-jFZvY1JohyHarIAlTbfQOk+HnceGjjAdFjVn3n8xlDWKsYNqbO4muca6qXEZTfGXeQMG7TYim6CeS5XKSfSsGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "app-builder-lib": "23.6.0", + "builder-util": "23.6.0", + "builder-util-runtime": "9.1.1", + "fs-extra": "^10.0.0", + "iconv-lite": "^0.6.2", + "js-yaml": "^4.1.0" + }, + "optionalDependencies": { + "dmg-license": "^1.0.11" + } + }, + "node_modules/dmg-builder/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/dmg-builder/node_modules/jsonfile": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz", + "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/dmg-license": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/dmg-license/-/dmg-license-1.0.11.tgz", + "integrity": "sha512-ZdzmqwKmECOWJpqefloC5OJy1+WZBBse5+MR88z9g9Zn4VY+WYUkAyojmhzJckH5YbbZGcYIuGAkY5/Ys5OM2Q==", + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "dependencies": { + "@types/plist": "^3.0.1", + "@types/verror": "^1.10.3", + "ajv": "^6.10.0", + "crc": "^3.8.0", + "iconv-corefoundation": "^1.1.7", + "plist": "^3.0.4", + "smart-buffer": "^4.0.2", + "verror": "^1.10.0" + }, + "bin": { + "dmg-license": "bin/dmg-license.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dotenv": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-9.0.2.tgz", + "integrity": "sha512-I9OvvrHp4pIARv4+x9iuewrWycX6CcZtoAu1XrzPxc5UygMJXJZYmBsynku8IkrJwgypE5DGNjDPmPRhDCptUg==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=10" + } + }, + "node_modules/dotenv-expand": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz", + "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ejs": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", + "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "jake": "^10.8.5" + }, + "bin": { + "ejs": "bin/cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/electron": { + "version": "26.6.10", + "resolved": "https://registry.npmjs.org/electron/-/electron-26.6.10.tgz", + "integrity": "sha512-pV2SD0RXzAiNRb/2yZrsVmVkBOMrf+DVsPulIgRjlL0+My9BL5spFuhHVMQO9yHl9tFpWtuRpQv0ofM/i9P8xg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "@electron/get": "^2.0.0", + "@types/node": "^18.11.18", + "extract-zip": "^2.0.1" + }, + "bin": { + "electron": "cli.js" + }, + "engines": { + "node": ">= 12.20.55" + } + }, + "node_modules/electron-builder": { + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/electron-builder/-/electron-builder-23.6.0.tgz", + "integrity": "sha512-y8D4zO+HXGCNxFBV/JlyhFnoQ0Y0K7/sFH+XwIbj47pqaW8S6PGYQbjoObolKBR1ddQFPt4rwp4CnwMJrW3HAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/yargs": "^17.0.1", + "app-builder-lib": "23.6.0", + "builder-util": "23.6.0", + "builder-util-runtime": "9.1.1", + "chalk": "^4.1.1", + "dmg-builder": "23.6.0", + "fs-extra": "^10.0.0", + "is-ci": "^3.0.0", + "lazy-val": "^1.0.5", + "read-config-file": "6.2.0", + "simple-update-notifier": "^1.0.7", + "yargs": "^17.5.1" + }, + "bin": { + "electron-builder": "cli.js", + "install-app-deps": "install-app-deps.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/electron-builder/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/electron-builder/node_modules/jsonfile": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz", + "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/electron-is-dev": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/electron-is-dev/-/electron-is-dev-2.0.0.tgz", + "integrity": "sha512-3X99K852Yoqu9AcW50qz3ibYBWY79/pBhlMCab8ToEWS48R0T9tyxRiQhwylE7zQdXrMnx2JKqUJyMPmt5FBqA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/electron-osx-sign": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/electron-osx-sign/-/electron-osx-sign-0.6.0.tgz", + "integrity": "sha512-+hiIEb2Xxk6eDKJ2FFlpofCnemCbjbT5jz+BKGpVBrRNT3kWTGs4DfNX6IzGwgi33hUcXF+kFs9JW+r6Wc1LRg==", + "deprecated": "Please use @electron/osx-sign moving forward. Be aware the API is slightly different", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "bluebird": "^3.5.0", + "compare-version": "^0.1.2", + "debug": "^2.6.8", + "isbinaryfile": "^3.0.2", + "minimist": "^1.2.0", + "plist": "^3.0.1" + }, + "bin": { + "electron-osx-flat": "bin/electron-osx-flat.js", + "electron-osx-sign": "bin/electron-osx-sign.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/electron-osx-sign/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/electron-osx-sign/node_modules/isbinaryfile": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-3.0.3.tgz", + "integrity": "sha512-8cJBL5tTd2OS0dM4jz07wQd5g0dCCqIhUxPIGtZfa5L6hWlvV5MHTITy/DBAsF+Oe2LS1X3krBUhNwaGUWpWxw==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-alloc": "^1.2.0" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/electron-osx-sign/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "license": "MIT" + }, + "node_modules/electron-publish": { + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-23.6.0.tgz", + "integrity": "sha512-jPj3y+eIZQJF/+t5SLvsI5eS4mazCbNYqatv5JihbqOstIM13k0d1Z3vAWntvtt13Itl61SO6seicWdioOU5dg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/fs-extra": "^9.0.11", + "builder-util": "23.6.0", + "builder-util-runtime": "9.1.1", + "chalk": "^4.1.1", + "fs-extra": "^10.0.0", + "lazy-val": "^1.0.5", + "mime": "^2.5.2" + } + }, + "node_modules/electron-publish/node_modules/@types/fs-extra": { + "version": "9.0.13", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.13.tgz", + "integrity": "sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/electron-publish/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/electron-publish/node_modules/jsonfile": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz", + "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/electron-rebuild": { + "version": "3.2.9", + "resolved": "https://registry.npmjs.org/electron-rebuild/-/electron-rebuild-3.2.9.tgz", + "integrity": "sha512-FkEZNFViUem3P0RLYbZkUjC8LUFIK+wKq09GHoOITSJjfDAVQv964hwaNseTTWt58sITQX3/5fHNYcTefqaCWw==", + "deprecated": "Please use @electron/rebuild moving forward. There is no API change, just a package name change", + "dev": true, + "license": "MIT", + "dependencies": { + "@malept/cross-spawn-promise": "^2.0.0", + "chalk": "^4.0.0", + "debug": "^4.1.1", + "detect-libc": "^2.0.1", + "fs-extra": "^10.0.0", + "got": "^11.7.0", + "lzma-native": "^8.0.5", + "node-abi": "^3.0.0", + "node-api-version": "^0.1.4", + "node-gyp": "^9.0.0", + "ora": "^5.1.0", + "semver": "^7.3.5", + "tar": "^6.0.5", + "yargs": "^17.0.1" + }, + "bin": { + "electron-rebuild": "lib/src/cli.js" + }, + "engines": { + "node": ">=12.13.0" + } + }, + "node_modules/electron-rebuild/node_modules/@malept/cross-spawn-promise": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@malept/cross-spawn-promise/-/cross-spawn-promise-2.0.0.tgz", + "integrity": "sha512-1DpKU0Z5ThltBwjNySMC14g0CkbyhCaz9FkhxqNsZI6uAPJXFS8cMXlBKo26FJ8ZuW6S9GCMcR9IO5k2X5/9Fg==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/malept" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/subscription/pkg/npm-.malept-cross-spawn-promise?utm_medium=referral&utm_source=npm_fund" + } + ], + "license": "Apache-2.0", + "dependencies": { + "cross-spawn": "^7.0.1" + }, + "engines": { + "node": ">= 12.13.0" + } + }, + "node_modules/electron-rebuild/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/electron-rebuild/node_modules/jsonfile": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz", + "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/electron-rebuild/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=8" + } + }, + "node_modules/electron-rebuild/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/electron-rebuild/node_modules/tar": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "deprecated": "Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/electron-serve": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/electron-serve/-/electron-serve-1.1.0.tgz", + "integrity": "sha512-tQJBCbXKoKCfkBC143QCqnEtT1s8dNE2V+b/82NF6lxnGO/2Q3a3GSLHtKl3iEDQgdzTf9pH7p418xq2rXbz1Q==", + "license": "MIT" + }, + "node_modules/electron-unhandled": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/electron-unhandled/-/electron-unhandled-4.0.1.tgz", + "integrity": "sha512-6BsLnBg+i96eUnbaIFZyYdyfNX3f80/Nlfqy34YEMxXT9JP3ddNsNnUeiOF8ezN4+et4t4D37gjghKTP0V3jyw==", + "license": "MIT", + "dependencies": { + "clean-stack": "^2.1.0", + "electron-is-dev": "^2.0.0", + "ensure-error": "^2.0.0", + "lodash.debounce": "^4.0.8", + "serialize-error": "^8.1.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/electron-updater": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/electron-updater/-/electron-updater-5.3.0.tgz", + "integrity": "sha512-iKEr7yQBcvnQUPnSDYGSWC9t0eF2YbZWeYYYZzYxdl+HiRejXFENjYMnYjoOm2zxyD6Cr2JTHZhp9pqxiXuCOw==", + "license": "MIT", + "dependencies": { + "@types/semver": "^7.3.6", + "builder-util-runtime": "9.1.1", + "fs-extra": "^10.0.0", + "js-yaml": "^4.1.0", + "lazy-val": "^1.0.5", + "lodash.escaperegexp": "^4.1.2", + "lodash.isequal": "^4.5.0", + "semver": "^7.3.5", + "typed-emitter": "^2.1.0" + } + }, + "node_modules/electron-updater/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/electron-updater/node_modules/jsonfile": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz", + "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/electron-window-state": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/electron-window-state/-/electron-window-state-5.0.3.tgz", + "integrity": "sha512-1mNTwCfkolXl3kMf50yW3vE2lZj0y92P/HYWFBrb+v2S/pCka5mdwN3cagKm458A7NjndSwijynXgcLWRodsVg==", + "license": "MIT", + "dependencies": { + "jsonfile": "^4.0.0", + "mkdirp": "^0.5.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/electron/node_modules/@types/node": { + "version": "18.19.130", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.130.tgz", + "integrity": "sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/electron/node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true, + "license": "MIT" + }, + "node_modules/elementtree": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/elementtree/-/elementtree-0.1.7.tgz", + "integrity": "sha512-wkgGT6kugeQk/P6VZ/f4T+4HB41BVgNBq5CDIZVbQ02nvTVqAiVTbskxxu3eA/X96lMlfYOwnLQpN2v5E1zDEg==", + "license": "Apache-2.0", + "dependencies": { + "sax": "1.1.4" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/elementtree/node_modules/sax": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.1.4.tgz", + "integrity": "sha512-5f3k2PbGGp+YtKJjOItpg3P99IMD84E4HOvcfleTb5joCHNXYLsR9yWFPOYGgaeMPDubQILTCMdsFb2OMeOjtg==", + "license": "ISC" + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "iconv-lite": "^0.6.2" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/ensure-error": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ensure-error/-/ensure-error-2.1.0.tgz", + "integrity": "sha512-+BMSJHw9gxiJAAp2ZR1E0TNcL09dD3lOvkl7WVm4+Y6xnes/pMetP/TzCHiDduh8ihNDjbGfuYxl7l4PA1xZ8A==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/err-code": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", + "dev": true, + "license": "MIT" + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", + "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es6-error": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", + "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "license": "MIT", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/exponential-backoff": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.3.tgz", + "integrity": "sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/extract-zip": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", + "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "debug": "^4.1.1", + "get-stream": "^5.1.0", + "yauzl": "^2.10.0" + }, + "bin": { + "extract-zip": "cli.js" + }, + "engines": { + "node": ">= 10.17.0" + }, + "optionalDependencies": { + "@types/yauzl": "^2.9.1" + } + }, + "node_modules/extsprintf": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.4.1.tgz", + "integrity": "sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA==", + "dev": true, + "engines": [ + "node >=0.6.0" + ], + "license": "MIT", + "optional": true + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", + "license": "MIT", + "dependencies": { + "pend": "~1.2.0" + } + }, + "node_modules/filelist": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.6.tgz", + "integrity": "sha512-5giy2PkLYY1cP39p17Ech+2xlpTRL9HLspOfEgm0L6CwBXBTgsK5ou0JtzYuepxkaQ/tvhCFIJ5uXo0OrM2DxA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "minimatch": "^5.0.1" + } + }, + "node_modules/filelist/node_modules/brace-expansion": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.4.tgz", + "integrity": "sha512-hGfVzPxthbf3+2yjg/RBs60cB0FhqBS/zvdV/4wn4/BmN0bNMMHPc4V/BbFieqf1TKAGGAHnY4eSjajCl0f2Xg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/filelist/node_modules/minimatch": { + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz", + "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/form-data": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz", + "integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.4", + "mime-types": "^2.1.35" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fs-extra": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.1.tgz", + "integrity": "sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/fs-extra/node_modules/jsonfile": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz", + "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true, + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gauge": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", + "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", + "deprecated": "This package is no longer supported.", + "dev": true, + "license": "ISC", + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.3", + "console-control-strings": "^1.1.0", + "has-unicode": "^2.0.1", + "signal-exit": "^3.0.7", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.5" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "license": "MIT", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/global-agent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-3.0.0.tgz", + "integrity": "sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==", + "dev": true, + "license": "BSD-3-Clause", + "optional": true, + "dependencies": { + "boolean": "^3.0.1", + "es6-error": "^4.1.1", + "matcher": "^3.0.0", + "roarr": "^2.15.3", + "semver": "^7.3.2", + "serialize-error": "^7.0.1" + }, + "engines": { + "node": ">=10.0" + } + }, + "node_modules/global-agent/node_modules/serialize-error": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", + "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "type-fest": "^0.13.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/global-agent/node_modules/type-fest": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", + "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "optional": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/got": { + "version": "11.8.6", + "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", + "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sindresorhus/is": "^4.0.0", + "@szmarczak/http-timer": "^4.0.5", + "@types/cacheable-request": "^6.0.1", + "@types/responselike": "^1.0.0", + "cacheable-lookup": "^5.0.3", + "cacheable-request": "^7.0.2", + "decompress-response": "^6.0.0", + "http2-wrapper": "^1.0.0-beta.5.2", + "lowercase-keys": "^2.0.0", + "p-cancelable": "^2.0.0", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=10.19.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/got?sponsor=1" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "license": "ISC" + }, + "node_modules/graceful-readlink": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", + "integrity": "sha512-8tLu60LgxF6XpdbK8OW3FA+IfTNBn1ZHGHKF4KQbEeSkajYw5PlYJcKluntgegDPTg8UkHjpet1T82vk6TQ68w==", + "dev": true, + "license": "MIT" + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/hasown": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hosted-git-info": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", + "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/http-cache-semantics": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", + "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/http2-wrapper": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", + "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.0.0" + }, + "engines": { + "node": ">=10.19.0" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.0.0" + } + }, + "node_modules/iconv-corefoundation": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/iconv-corefoundation/-/iconv-corefoundation-1.1.7.tgz", + "integrity": "sha512-T10qvkw0zz4wnm560lOEg0PovVqUXuOFhhHAkixw8/sycy7TJt7v/RrkEKEQnAw2viPSJu6iAkErxnzR0g8PpQ==", + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "dependencies": { + "cli-truncate": "^2.1.0", + "node-addon-api": "^1.6.3" + }, + "engines": { + "node": "^8.11.2 || >=10" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", + "dev": true, + "license": "ISC" + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/ini": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.3.tgz", + "integrity": "sha512-X7rqawQBvfdjS10YU1y1YVreA3SsLrW9dX2CewP2EbBJM4ypVNLDkO5y04gejPwKIY9lR+7r9gn3rFPt/kmWFg==", + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/ip-address": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.4.0.tgz", + "integrity": "sha512-oSK96Grm3aP6OrS263xVxbNDGVL7rzBtYdpGqlDG8iQdoenDoTs/nkki+DflYbAEE8Xl6o5YxhxlrKvI3nqKXQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-ci": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz", + "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ci-info": "^3.2.0" + }, + "bin": { + "is-ci": "bin.js" + } + }, + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-lambda": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", + "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "license": "MIT", + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/isbinaryfile": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.10.tgz", + "integrity": "sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/gjtorikian/" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "license": "ISC" + }, + "node_modules/jake": { + "version": "10.9.4", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.4.tgz", + "integrity": "sha512-wpHYzhxiVQL+IV05BLE2Xn34zW1S223hvjtqk0+gsPrwd/8JNLXJgZZM/iPFsYc1xyphF+6M6EvdE5E9MBGkDA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "async": "^3.2.6", + "filelist": "^1.0.4", + "picocolors": "^1.1.1" + }, + "bin": { + "jake": "bin/cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/js-yaml": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.1.tgz", + "integrity": "sha512-CY6crGq313MX8GkwvB7tzgp99vjQxY1++5y10/BKN/GUfHqWaOGQMNZkBvqSzsZKWk/ijwHlWzzkLulsGHhjWQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "dev": true, + "license": "ISC", + "optional": true + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "license": "MIT", + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/kleur": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", + "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/lazy-val": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/lazy-val/-/lazy-val-1.0.5.tgz", + "integrity": "sha512-0/BnGCCfyUMkBpeDgWihanIAF9JmZhHBgUhEqzvf+adhNGLoP6TaiI5oF8oyb3I45P+PcnrqihSf01M0l0G5+Q==", + "license": "MIT" + }, + "node_modules/lodash": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", + "license": "MIT" + }, + "node_modules/lodash.escaperegexp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz", + "integrity": "sha512-TM9YBvyC84ZxE3rgfefxUWiQKLilstD6k7PTGt6wfbtXF8ixIJLOL3VYyV/z+ZiPLsVxAsKAFVwWlWeb2Y8Yyw==", + "license": "MIT" + }, + "node_modules/lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==", + "deprecated": "This package is deprecated. Use require('node:util').isDeepStrictEqual instead.", + "license": "MIT" + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "license": "MIT", + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/lzma-native": { + "version": "8.0.6", + "resolved": "https://registry.npmjs.org/lzma-native/-/lzma-native-8.0.6.tgz", + "integrity": "sha512-09xfg67mkL2Lz20PrrDeNYZxzeW7ADtpYFbwSQh9U8+76RIzx5QsJBMy8qikv3hbUPfpy6hqwxt6FcGK81g9AA==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "node-addon-api": "^3.1.0", + "node-gyp-build": "^4.2.1", + "readable-stream": "^3.6.0" + }, + "bin": { + "lzmajs": "bin/lzmajs" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/lzma-native/node_modules/node-addon-api": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", + "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==", + "dev": true, + "license": "MIT" + }, + "node_modules/make-fetch-happen": { + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-10.2.1.tgz", + "integrity": "sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==", + "dev": true, + "license": "ISC", + "dependencies": { + "agentkeepalive": "^4.2.1", + "cacache": "^16.1.0", + "http-cache-semantics": "^4.1.0", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^7.7.1", + "minipass": "^3.1.6", + "minipass-collect": "^1.0.2", + "minipass-fetch": "^2.0.3", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^7.0.0", + "ssri": "^9.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/make-fetch-happen/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/matcher": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz", + "integrity": "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "escape-string-regexp": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "dev": true, + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-collect": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", + "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-fetch": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-2.1.2.tgz", + "integrity": "sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==", + "dev": true, + "license": "MIT", + "dependencies": { + "minipass": "^3.1.6", + "minipass-sized": "^1.0.3", + "minizlib": "^2.1.2" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + }, + "optionalDependencies": { + "encoding": "^0.1.13" + } + }, + "node_modules/minipass-flush": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.7.tgz", + "integrity": "sha512-TbqTz9cUwWyHS2Dy89P3ocAGUGxKjjLuR9z8w4WUTGAVgEj17/4nhgo2Du56i0Fm3Pm30g4iA8Lcqctc76jCzA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-pipeline": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-sized": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", + "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "license": "MIT", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/native-run": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/native-run/-/native-run-2.0.3.tgz", + "integrity": "sha512-U1PllBuzW5d1gfan+88L+Hky2eZx+9gv3Pf6rNBxKbORxi7boHzqiA6QFGSnqMem4j0A9tZ08NMIs5+0m/VS1Q==", + "license": "MIT", + "dependencies": { + "@ionic/utils-fs": "^3.1.7", + "@ionic/utils-terminal": "^2.3.4", + "bplist-parser": "^0.3.2", + "debug": "^4.3.4", + "elementtree": "^0.1.7", + "ini": "^4.1.1", + "plist": "^3.1.0", + "split2": "^4.2.0", + "through2": "^4.0.2", + "tslib": "^2.6.2", + "yauzl": "^2.10.0" + }, + "bin": { + "native-run": "bin/native-run" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/negotiator": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", + "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/node-abi": { + "version": "3.94.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.94.0.tgz", + "integrity": "sha512-W5ZNO5KRPB5TkYmGVD9F6YqhsglXJzE6etpbmT+f6EQElhiX/UTG551cnsRGvLG3fyZEg9HwaDmNmj5nwJ4z9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-addon-api": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-1.7.2.tgz", + "integrity": "sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/node-api-version": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/node-api-version/-/node-api-version-0.1.4.tgz", + "integrity": "sha512-KGXihXdUChwJAOHO53bv9/vXcLmdUsZ6jIptbvYvkpKfth+r7jw44JkVxQFA3kX5nQjzjmGu1uAu/xNNLNlI5g==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.3.5" + } + }, + "node_modules/node-gyp": { + "version": "9.4.1", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-9.4.1.tgz", + "integrity": "sha512-OQkWKbjQKbGkMf/xqI1jjy3oCTgMKJac58G2+bjZb3fza6gW2YrCSdMQYaoTb70crvE//Gngr4f0AgVHmqHvBQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "env-paths": "^2.2.0", + "exponential-backoff": "^3.1.1", + "glob": "^7.1.4", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^10.0.3", + "nopt": "^6.0.0", + "npmlog": "^6.0.0", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.2", + "which": "^2.0.2" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" + }, + "engines": { + "node": "^12.13 || ^14.13 || >=16" + } + }, + "node_modules/node-gyp-build": { + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz", + "integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==", + "dev": true, + "license": "MIT", + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, + "node_modules/node-gyp/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=8" + } + }, + "node_modules/node-gyp/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-gyp/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/node-gyp/node_modules/tar": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "deprecated": "Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/nopt": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz", + "integrity": "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==", + "dev": true, + "license": "ISC", + "dependencies": { + "abbrev": "^1.0.0" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-url": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npmlog": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", + "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", + "deprecated": "This package is no longer supported.", + "dev": true, + "license": "ISC", + "dependencies": { + "are-we-there-yet": "^3.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^4.0.3", + "set-blocking": "^2.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "license": "MIT", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/open": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", + "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", + "license": "MIT", + "dependencies": { + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "license": "MIT", + "dependencies": { + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-cancelable": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", + "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "license": "BlueOak-1.0.0" + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-scurry": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.2.tgz", + "integrity": "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==", + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "11.5.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.2.tgz", + "integrity": "sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g==", + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/path-scurry/node_modules/minipass": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/plist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/plist/-/plist-3.1.1.tgz", + "integrity": "sha512-ZIfcLJC+7E7FBFnDxm9MPmt7D+DidyQ26lewieO75AdhA2ayMtsJSES0iWzqJQbcVRSrTufQoy0DR94xHue0oA==", + "license": "MIT", + "dependencies": { + "@xmldom/xmldom": "^0.9.10", + "base64-js": "^1.5.1", + "xmlbuilder": "^15.1.1" + }, + "engines": { + "node": ">=10.4.0" + } + }, + "node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", + "dev": true, + "license": "ISC" + }, + "node_modules/promise-retry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "license": "MIT", + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/prompts/node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/pump": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.4.tgz", + "integrity": "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-config-file": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/read-config-file/-/read-config-file-6.2.0.tgz", + "integrity": "sha512-gx7Pgr5I56JtYz+WuqEbQHj/xWo+5Vwua2jhb1VwM4Wid5PqYmZ4i00ZB0YEGIfkVBsCv9UrjgyqCiQfS/Oosg==", + "dev": true, + "license": "MIT", + "dependencies": { + "dotenv": "^9.0.2", + "dotenv-expand": "^5.1.0", + "js-yaml": "^4.1.0", + "json5": "^2.2.0", + "lazy-val": "^1.0.4" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve-alpn": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", + "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", + "dev": true, + "license": "MIT" + }, + "node_modules/responselike": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", + "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", + "dev": true, + "license": "MIT", + "dependencies": { + "lowercase-keys": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "license": "MIT", + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/rimraf": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.1.3.tgz", + "integrity": "sha512-LKg+Cr2ZF61fkcaK1UdkH2yEBBKnYjTyWzTJT6KNPcSPaiT7HSdhtMXQuN5wkTX0Xu72KQ1l8S42rlmexS2hSA==", + "license": "BlueOak-1.0.0", + "dependencies": { + "glob": "^13.0.3", + "package-json-from-dist": "^1.0.1" + }, + "bin": { + "rimraf": "dist/esm/bin.mjs" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/rimraf/node_modules/brace-expansion": { + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz", + "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==", + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/rimraf/node_modules/glob": { + "version": "13.0.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.6.tgz", + "integrity": "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==", + "license": "BlueOak-1.0.0", + "dependencies": { + "minimatch": "^10.2.2", + "minipass": "^7.1.3", + "path-scurry": "^2.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/minimatch": { + "version": "10.2.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.6.tgz", + "integrity": "sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==", + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.8" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/minipass": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/roarr": { + "version": "2.15.4", + "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz", + "integrity": "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==", + "dev": true, + "license": "BSD-3-Clause", + "optional": true, + "dependencies": { + "boolean": "^3.0.1", + "detect-node": "^2.0.4", + "globalthis": "^1.0.1", + "json-stringify-safe": "^5.0.1", + "semver-compare": "^1.0.0", + "sprintf-js": "^1.1.2" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/rxjs": { + "version": "7.8.2", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", + "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true, + "license": "MIT" + }, + "node_modules/sanitize-filename": { + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/sanitize-filename/-/sanitize-filename-1.6.4.tgz", + "integrity": "sha512-9ZyI08PsvdQl2r/bBIGubpVdR3RR9sY6RDiWFPreA21C/EFlQhmgo20UZlNjZMMZNubusLhAQozkA0Od5J21Eg==", + "dev": true, + "license": "WTFPL OR ISC", + "dependencies": { + "truncate-utf8-bytes": "^1.0.0" + } + }, + "node_modules/sax": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.6.1.tgz", + "integrity": "sha512-42tBVwLWnaQvW5zc4HbZrTuWccECCZfBi92FDuwtqxasH+JbPB3/FOKb1m222K42R4WxuxzzMsTswfzgtSu64Q==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=11.0.0" + } + }, + "node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", + "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/serialize-error": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-8.1.0.tgz", + "integrity": "sha512-3NnuWfM6vBYoy5gZFvHiYsVbafvI9vZv/+jlIigFn4oP4zjNPK3LhcY0xSCgeb1a5L8jO71Mit9LlNoi2UfDDQ==", + "license": "MIT", + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "dev": true, + "license": "ISC" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "license": "ISC" + }, + "node_modules/simple-plist": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/simple-plist/-/simple-plist-1.3.1.tgz", + "integrity": "sha512-iMSw5i0XseMnrhtIzRb7XpQEXepa9xhWxGUojHBL43SIpQuDQkh3Wpy67ZbDzZVr6EKxvwVChnVpdl8hEVLDiw==", + "license": "MIT", + "dependencies": { + "bplist-creator": "0.1.0", + "bplist-parser": "0.3.1", + "plist": "^3.0.5" + } + }, + "node_modules/simple-plist/node_modules/bplist-parser": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.3.1.tgz", + "integrity": "sha512-PyJxiNtA5T2PlLIeBot4lbp7rj4OadzjnMZD/G5zuBNt8ei/yCU7+wW0h2bag9vr8c+/WuRWmSxbqAl9hL1rBA==", + "license": "MIT", + "dependencies": { + "big-integer": "1.6.x" + }, + "engines": { + "node": ">= 5.10.0" + } + }, + "node_modules/simple-update-notifier": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-1.1.0.tgz", + "integrity": "sha512-VpsrsJSUcJEseSbMHkrsrAVSdvVS5I96Qo1QAQ4FxQ9wXFcB+pjj7FB7/us9+GcgfW4ziHtYMc1J0PLczb55mg==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "~7.0.0" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/simple-update-notifier/node_modules/semver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", + "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "license": "MIT" + }, + "node_modules/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.9.tgz", + "integrity": "sha512-LJhUYUvItdQ0LkJTmPeaEObWXAqFyfmP85x0tch/ez9cahmhlBBLbIqDFnvBnUJGagb0JbIQrkBs1wJ+yRYpEw==", + "dev": true, + "license": "MIT", + "dependencies": { + "ip-address": "^10.1.1", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz", + "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^6.0.2", + "debug": "^4.3.3", + "socks": "^2.6.2" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "license": "ISC", + "engines": { + "node": ">= 10.x" + } + }, + "node_modules/sprintf-js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", + "dev": true, + "license": "BSD-3-Clause", + "optional": true + }, + "node_modules/ssri": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-9.0.1.tgz", + "integrity": "sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^3.1.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/stat-mode": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stat-mode/-/stat-mode-1.0.0.tgz", + "integrity": "sha512-jH9EhtKIjuXZ2cWxmXS8ZP80XyC3iasQxMDV8jzhNJpfDb7VbQLVW4Wvsxz9QZvzV+G4YoSfBUVKDOyxLzi/sg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/stream-buffers": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/stream-buffers/-/stream-buffers-2.2.0.tgz", + "integrity": "sha512-uyQK/mx5QjHun80FLJTfaWE7JtwfRMKBLkMne6udYOmvH0CawotVa7TfgYHzAnpphn4+TweIx1QKMnRIbipmUg==", + "license": "Unlicense", + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/sumchecker": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.1.tgz", + "integrity": "sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "debug": "^4.1.0" + }, + "engines": { + "node": ">= 8.0" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tar": { + "version": "7.5.22", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.22.tgz", + "integrity": "sha512-MFO/QzvtAOmJbkhOaCTvbGcFN9L9b+JunIsDwaKljSOdcLMea3NJ1k9Usz/rjdfSXTq4dfzfeS7W4p4YOAAHeA==", + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", + "minipass": "^7.1.2", + "minizlib": "^3.1.0", + "yallist": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/tar/node_modules/chownr": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", + "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/tar/node_modules/minipass": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/tar/node_modules/minizlib": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.1.0.tgz", + "integrity": "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==", + "license": "MIT", + "dependencies": { + "minipass": "^7.1.2" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/tar/node_modules/yallist": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", + "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/temp-file": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/temp-file/-/temp-file-3.4.0.tgz", + "integrity": "sha512-C5tjlC/HCtVUOi3KWVokd4vHVViOmGjtLwIh4MuzPo/nMYTV/p1urt3RnMz2IWXDdKEGJH3k5+KPxtqRsUYGtg==", + "dev": true, + "license": "MIT", + "dependencies": { + "async-exit-hook": "^2.0.1", + "fs-extra": "^10.0.0" + } + }, + "node_modules/temp-file/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/temp-file/node_modules/jsonfile": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz", + "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/through2": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", + "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", + "license": "MIT", + "dependencies": { + "readable-stream": "3" + } + }, + "node_modules/tmp": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.7.tgz", + "integrity": "sha512-e0votIpp4Uo2AJYSzVHV6xCcawuiez3DzqDAbrTc3YxBkplN6e+dM13ZeIcZnDg/QpSuU2zfZ3rzwY8ukEnaXw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.14" + } + }, + "node_modules/tmp-promise": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/tmp-promise/-/tmp-promise-3.0.3.tgz", + "integrity": "sha512-RwM7MoPojPxsOBYnyd2hy0bxtIlVrihNs9pj5SUvY8Zz1sQcQG2tG1hSr8PDxfgEB8RNKDhqbIlroIarSNDNsQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "tmp": "^0.2.0" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "license": "MIT", + "bin": { + "tree-kill": "cli.js" + } + }, + "node_modules/truncate-utf8-bytes": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz", + "integrity": "sha512-95Pu1QXQvruGEhv62XCMO3Mm90GscOCClvrIUwCM0PYOXK3kaF3l3sIHxx71ThJfcbM2O5Au6SO3AWCSEfW4mQ==", + "dev": true, + "license": "WTFPL", + "dependencies": { + "utf8-byte-length": "^1.0.1" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typed-emitter": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/typed-emitter/-/typed-emitter-2.1.0.tgz", + "integrity": "sha512-g/KzbYKbH5C2vPkaXGu8DJlHrGKHLsM25Zg9WuC9pMGfuvT+X25tZQWo5fK1BjBm8+UrVE9LDCvaY0CQk+fXDA==", + "license": "MIT", + "optionalDependencies": { + "rxjs": "*" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-8.3.0.tgz", + "integrity": "sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ==", + "license": "MIT" + }, + "node_modules/unique-filename": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-2.0.1.tgz", + "integrity": "sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==", + "dev": true, + "license": "ISC", + "dependencies": { + "unique-slug": "^3.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/unique-slug": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-3.0.0.tgz", + "integrity": "sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/untildify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", + "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/utf8-byte-length": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.5.tgz", + "integrity": "sha512-Xn0w3MtiQ6zoz2vFyUVruaCL53O/DwUvkEeOvj+uulMm0BkUGYWmBYVyElqZaSLhY6ZD0ulfU3aBra2aVT4xfA==", + "dev": true, + "license": "(WTFPL OR MIT)" + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, + "node_modules/uuid": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.3.tgz", + "integrity": "sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg==", + "deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).", + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/verror": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.1.tgz", + "integrity": "sha512-veufcmxri4e3XSrT0xwfUR7kguIkaxBeosDg00yDWhk49wdwkSUrvvsm7nc75e1PUyvIeZj6nS8VQRYz2/S4Xg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", + "license": "MIT", + "dependencies": { + "defaults": "^1.0.3" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/xcode": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/xcode/-/xcode-3.0.1.tgz", + "integrity": "sha512-kCz5k7J7XbJtjABOvkc5lJmkiDh8VhjVCGNiqdKCscmVpdVUpEAyXv1xmCLkQJ5dsHqx3IPO4XW+NTDhU/fatA==", + "license": "Apache-2.0", + "dependencies": { + "simple-plist": "^1.1.0", + "uuid": "^7.0.3" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/xml2js": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.6.2.tgz", + "integrity": "sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==", + "license": "MIT", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/xml2js/node_modules/xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "license": "MIT", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/xmlbuilder": { + "version": "15.1.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz", + "integrity": "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==", + "license": "MIT", + "engines": { + "node": ">=8.0" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "license": "ISC" + }, + "node_modules/yargs": { + "version": "17.7.3", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.3.tgz", + "integrity": "sha512-GZtjxm/J/4TSxuL3FNYjCmLktBTnIw/rVmKSIyKeYAZpmJB2ig9VauCC5xsa82GNKVKDAqpOn3KVzNt0zmrU0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", + "license": "MIT", + "dependencies": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + } + } +} diff --git a/electron/package.json b/electron/package.json new file mode 100644 index 0000000..1faca10 --- /dev/null +++ b/electron/package.json @@ -0,0 +1,41 @@ +{ + "name": "CheemsAngular", + "version": "1.0.0", + "description": "An Amazing Capacitor App", + "author": { + "name": "Cheems", + "email": "cheems@example.com" + }, + "repository": { + "type": "git", + "url": "https://github.com/Luna115-onCode/CheemsBonkGame.git" + }, + "license": "MIT", + "main": "build/src/index.js", + "scripts": { + "build": "tsc && electron-rebuild", + "electron:start-live": "node ./live-runner.js", + "electron:start": "npm run build && electron --inspect=5858 ./", + "electron:pack": "npm run build && electron-builder build --dir -c ./electron-builder.config.json", + "electron:make": "npm run build && electron-builder build -c ./electron-builder.config.json --publish never" + }, + "dependencies": { + "@capacitor-community/electron": "^5.0.0", + "chokidar": "~3.5.3", + "electron-is-dev": "~2.0.0", + "electron-serve": "~1.1.0", + "electron-unhandled": "~4.0.1", + "electron-updater": "^5.3.0", + "electron-window-state": "^5.0.3" + }, + "devDependencies": { + "electron": "^26.2.2", + "electron-builder": "~23.6.0", + "electron-rebuild": "^3.2.9", + "typescript": "^5.0.4" + }, + "keywords": [ + "capacitor", + "electron" + ] +} diff --git a/electron/resources/electron-publisher-custom.js b/electron/resources/electron-publisher-custom.js new file mode 100644 index 0000000..6e0821e --- /dev/null +++ b/electron/resources/electron-publisher-custom.js @@ -0,0 +1,10 @@ +/* eslint-disable no-undef */ +/* eslint-disable @typescript-eslint/no-var-requires */ +const electronPublish = require('electron-publish'); + +class Publisher extends electronPublish.Publisher { + async upload(task) { + console.log('electron-publisher-custom', task.file); + } +} +module.exports = Publisher; diff --git a/electron/src/index.ts b/electron/src/index.ts new file mode 100644 index 0000000..1d48128 --- /dev/null +++ b/electron/src/index.ts @@ -0,0 +1,68 @@ +import type { CapacitorElectronConfig } from '@capacitor-community/electron'; +import { getCapacitorElectronConfig, setupElectronDeepLinking } from '@capacitor-community/electron'; +import type { MenuItemConstructorOptions } from 'electron'; +import { app, MenuItem } from 'electron'; +import electronIsDev from 'electron-is-dev'; +import unhandled from 'electron-unhandled'; +import { autoUpdater } from 'electron-updater'; + +import { ElectronCapacitorApp, setupContentSecurityPolicy, setupReloadWatcher } from './setup'; + +// Graceful handling of unhandled errors. +unhandled(); + +// Define our menu templates (these are optional) +const trayMenuTemplate: (MenuItemConstructorOptions | MenuItem)[] = [new MenuItem({ label: 'Quit App', role: 'quit' })]; +const appMenuBarMenuTemplate: (MenuItemConstructorOptions | MenuItem)[] = [ + { role: process.platform === 'darwin' ? 'appMenu' : 'fileMenu' }, + { role: 'viewMenu' }, +]; + +// Get Config options from capacitor.config +const capacitorFileConfig: CapacitorElectronConfig = getCapacitorElectronConfig(); + +// Initialize our app. You can pass menu templates into the app here. +// const myCapacitorApp = new ElectronCapacitorApp(capacitorFileConfig); +const myCapacitorApp = new ElectronCapacitorApp(capacitorFileConfig, trayMenuTemplate, appMenuBarMenuTemplate); + +// If deeplinking is enabled then we will set it up here. +if (capacitorFileConfig.electron?.deepLinkingEnabled) { + setupElectronDeepLinking(myCapacitorApp, { + customProtocol: capacitorFileConfig.electron.deepLinkingCustomProtocol ?? 'mycapacitorapp', + }); +} + +// If we are in Dev mode, use the file watcher components. +if (electronIsDev) { + setupReloadWatcher(myCapacitorApp); +} + +// Run Application +(async () => { + // Wait for electron app to be ready. + await app.whenReady(); + // Security - Set Content-Security-Policy based on whether or not we are in dev mode. + setupContentSecurityPolicy(myCapacitorApp.getCustomURLScheme()); + // Initialize our app, build windows, and load content. + await myCapacitorApp.init(); +})(); + +// Handle when all of our windows are close (platforms have their own expectations). +app.on('window-all-closed', function () { + // On OS X it is common for applications and their menu bar + // to stay active until the user quits explicitly with Cmd + Q + if (process.platform !== 'darwin') { + app.quit(); + } +}); + +// When the dock icon is clicked. +app.on('activate', async function () { + // On OS X it's common to re-create a window in the app when the + // dock icon is clicked and there are no other windows open. + if (myCapacitorApp.getMainWindow().isDestroyed()) { + await myCapacitorApp.init(); + } +}); + +// Place all ipc or other electron api calls and custom functionality under this line diff --git a/electron/src/preload.ts b/electron/src/preload.ts new file mode 100644 index 0000000..c817d3b --- /dev/null +++ b/electron/src/preload.ts @@ -0,0 +1,4 @@ +require('./rt/electron-rt'); +////////////////////////////// +// User Defined Preload scripts below +console.log('User Preload!'); diff --git a/electron/src/rt/electron-plugins.js b/electron/src/rt/electron-plugins.js new file mode 100644 index 0000000..b33b282 --- /dev/null +++ b/electron/src/rt/electron-plugins.js @@ -0,0 +1,4 @@ +/* eslint-disable @typescript-eslint/no-var-requires */ + +module.exports = { +} \ No newline at end of file diff --git a/electron/src/rt/electron-rt.ts b/electron/src/rt/electron-rt.ts new file mode 100644 index 0000000..55d67c3 --- /dev/null +++ b/electron/src/rt/electron-rt.ts @@ -0,0 +1,88 @@ +import { randomBytes } from 'crypto'; +import { ipcRenderer, contextBridge } from 'electron'; +import { EventEmitter } from 'events'; + +//////////////////////////////////////////////////////// +// eslint-disable-next-line @typescript-eslint/no-var-requires +const plugins = require('./electron-plugins'); + +const randomId = (length = 5) => randomBytes(length).toString('hex'); + +const contextApi: { + [plugin: string]: { [functionName: string]: () => Promise }; +} = {}; + +Object.keys(plugins).forEach((pluginKey) => { + Object.keys(plugins[pluginKey]) + .filter((className) => className !== 'default') + .forEach((classKey) => { + const functionList = Object.getOwnPropertyNames(plugins[pluginKey][classKey].prototype).filter( + (v) => v !== 'constructor' + ); + + if (!contextApi[classKey]) { + contextApi[classKey] = {}; + } + + functionList.forEach((functionName) => { + if (!contextApi[classKey][functionName]) { + contextApi[classKey][functionName] = (...args) => ipcRenderer.invoke(`${classKey}-${functionName}`, ...args); + } + }); + + // Events + if (plugins[pluginKey][classKey].prototype instanceof EventEmitter) { + const listeners: { [key: string]: { type: string; listener: (...args: any[]) => void } } = {}; + const listenersOfTypeExist = (type) => + !!Object.values(listeners).find((listenerObj) => listenerObj.type === type); + + Object.assign(contextApi[classKey], { + addListener(type: string, callback: (...args) => void) { + const id = randomId(); + + // Deduplicate events + if (!listenersOfTypeExist(type)) { + ipcRenderer.send(`event-add-${classKey}`, type); + } + + const eventHandler = (_, ...args) => callback(...args); + + ipcRenderer.addListener(`event-${classKey}-${type}`, eventHandler); + listeners[id] = { type, listener: eventHandler }; + + return id; + }, + removeListener(id: string) { + if (!listeners[id]) { + throw new Error('Invalid id'); + } + + const { type, listener } = listeners[id]; + + ipcRenderer.removeListener(`event-${classKey}-${type}`, listener); + + delete listeners[id]; + + if (!listenersOfTypeExist(type)) { + ipcRenderer.send(`event-remove-${classKey}-${type}`); + } + }, + removeAllListeners(type: string) { + Object.entries(listeners).forEach(([id, listenerObj]) => { + if (!type || listenerObj.type === type) { + ipcRenderer.removeListener(`event-${classKey}-${listenerObj.type}`, listenerObj.listener); + ipcRenderer.send(`event-remove-${classKey}-${listenerObj.type}`); + delete listeners[id]; + } + }); + }, + }); + } + }); +}); + +contextBridge.exposeInMainWorld('CapacitorCustomPlatform', { + name: 'electron', + plugins: contextApi, +}); +//////////////////////////////////////////////////////// diff --git a/electron/src/setup.ts b/electron/src/setup.ts new file mode 100644 index 0000000..e7c957b --- /dev/null +++ b/electron/src/setup.ts @@ -0,0 +1,233 @@ +import type { CapacitorElectronConfig } from '@capacitor-community/electron'; +import { + CapElectronEventEmitter, + CapacitorSplashScreen, + setupCapacitorElectronPlugins, +} from '@capacitor-community/electron'; +import chokidar from 'chokidar'; +import type { MenuItemConstructorOptions } from 'electron'; +import { app, BrowserWindow, Menu, MenuItem, nativeImage, Tray, session } from 'electron'; +import electronIsDev from 'electron-is-dev'; +import electronServe from 'electron-serve'; +import windowStateKeeper from 'electron-window-state'; +import { join } from 'path'; + +// Define components for a watcher to detect when the webapp is changed so we can reload in Dev mode. +const reloadWatcher = { + debouncer: null, + ready: false, + watcher: null, +}; +export function setupReloadWatcher(electronCapacitorApp: ElectronCapacitorApp): void { + reloadWatcher.watcher = chokidar + .watch(join(app.getAppPath(), 'app'), { + ignored: /[/\\]\./, + persistent: true, + }) + .on('ready', () => { + reloadWatcher.ready = true; + }) + .on('all', (_event, _path) => { + if (reloadWatcher.ready) { + clearTimeout(reloadWatcher.debouncer); + reloadWatcher.debouncer = setTimeout(async () => { + electronCapacitorApp.getMainWindow().webContents.reload(); + reloadWatcher.ready = false; + clearTimeout(reloadWatcher.debouncer); + reloadWatcher.debouncer = null; + reloadWatcher.watcher = null; + setupReloadWatcher(electronCapacitorApp); + }, 1500); + } + }); +} + +// Define our class to manage our app. +export class ElectronCapacitorApp { + private MainWindow: BrowserWindow | null = null; + private SplashScreen: CapacitorSplashScreen | null = null; + private TrayIcon: Tray | null = null; + private CapacitorFileConfig: CapacitorElectronConfig; + private TrayMenuTemplate: (MenuItem | MenuItemConstructorOptions)[] = [ + new MenuItem({ label: 'Quit App', role: 'quit' }), + ]; + private AppMenuBarMenuTemplate: (MenuItem | MenuItemConstructorOptions)[] = [ + { role: process.platform === 'darwin' ? 'appMenu' : 'fileMenu' }, + { role: 'viewMenu' }, + ]; + private mainWindowState; + private loadWebApp; + private customScheme: string; + + constructor( + capacitorFileConfig: CapacitorElectronConfig, + trayMenuTemplate?: (MenuItemConstructorOptions | MenuItem)[], + appMenuBarMenuTemplate?: (MenuItemConstructorOptions | MenuItem)[] + ) { + this.CapacitorFileConfig = capacitorFileConfig; + + this.customScheme = this.CapacitorFileConfig.electron?.customUrlScheme ?? 'capacitor-electron'; + + if (trayMenuTemplate) { + this.TrayMenuTemplate = trayMenuTemplate; + } + + if (appMenuBarMenuTemplate) { + this.AppMenuBarMenuTemplate = appMenuBarMenuTemplate; + } + + // Setup our web app loader, this lets us load apps like react, vue, and angular without changing their build chains. + this.loadWebApp = electronServe({ + directory: join(app.getAppPath(), 'app'), + scheme: this.customScheme, + }); + } + + // Helper function to load in the app. + private async loadMainWindow(thisRef: any) { + await thisRef.loadWebApp(thisRef.MainWindow); + } + + // Expose the mainWindow ref for use outside of the class. + getMainWindow(): BrowserWindow { + return this.MainWindow; + } + + getCustomURLScheme(): string { + return this.customScheme; + } + + async init(): Promise { + const icon = nativeImage.createFromPath( + join(app.getAppPath(), 'assets', process.platform === 'win32' ? 'appIcon.ico' : 'appIcon.png') + ); + this.mainWindowState = windowStateKeeper({ + defaultWidth: 1000, + defaultHeight: 800, + }); + // Setup preload script path and construct our main window. + const preloadPath = join(app.getAppPath(), 'build', 'src', 'preload.js'); + this.MainWindow = new BrowserWindow({ + icon, + show: false, + x: this.mainWindowState.x, + y: this.mainWindowState.y, + width: this.mainWindowState.width, + height: this.mainWindowState.height, + webPreferences: { + nodeIntegration: true, + contextIsolation: true, + // Use preload to inject the electron varriant overrides for capacitor plugins. + // preload: join(app.getAppPath(), "node_modules", "@capacitor-community", "electron", "dist", "runtime", "electron-rt.js"), + preload: preloadPath, + }, + }); + this.mainWindowState.manage(this.MainWindow); + + if (this.CapacitorFileConfig.backgroundColor) { + this.MainWindow.setBackgroundColor(this.CapacitorFileConfig.electron.backgroundColor); + } + + // If we close the main window with the splashscreen enabled we need to destory the ref. + this.MainWindow.on('closed', () => { + if (this.SplashScreen?.getSplashWindow() && !this.SplashScreen.getSplashWindow().isDestroyed()) { + this.SplashScreen.getSplashWindow().close(); + } + }); + + // When the tray icon is enabled, setup the options. + if (this.CapacitorFileConfig.electron?.trayIconAndMenuEnabled) { + this.TrayIcon = new Tray(icon); + this.TrayIcon.on('double-click', () => { + if (this.MainWindow) { + if (this.MainWindow.isVisible()) { + this.MainWindow.hide(); + } else { + this.MainWindow.show(); + this.MainWindow.focus(); + } + } + }); + this.TrayIcon.on('click', () => { + if (this.MainWindow) { + if (this.MainWindow.isVisible()) { + this.MainWindow.hide(); + } else { + this.MainWindow.show(); + this.MainWindow.focus(); + } + } + }); + this.TrayIcon.setToolTip(app.getName()); + this.TrayIcon.setContextMenu(Menu.buildFromTemplate(this.TrayMenuTemplate)); + } + + // Setup the main manu bar at the top of our window. + Menu.setApplicationMenu(Menu.buildFromTemplate(this.AppMenuBarMenuTemplate)); + + // If the splashscreen is enabled, show it first while the main window loads then switch it out for the main window, or just load the main window from the start. + if (this.CapacitorFileConfig.electron?.splashScreenEnabled) { + this.SplashScreen = new CapacitorSplashScreen({ + imageFilePath: join( + app.getAppPath(), + 'assets', + this.CapacitorFileConfig.electron?.splashScreenImageName ?? 'splash.png' + ), + windowWidth: 400, + windowHeight: 400, + }); + this.SplashScreen.init(this.loadMainWindow, this); + } else { + this.loadMainWindow(this); + } + + // Security + this.MainWindow.webContents.setWindowOpenHandler((details) => { + if (!details.url.includes(this.customScheme)) { + return { action: 'deny' }; + } else { + return { action: 'allow' }; + } + }); + this.MainWindow.webContents.on('will-navigate', (event, _newURL) => { + if (!this.MainWindow.webContents.getURL().includes(this.customScheme)) { + event.preventDefault(); + } + }); + + // Link electron plugins into the system. + setupCapacitorElectronPlugins(); + + // When the web app is loaded we hide the splashscreen if needed and show the mainwindow. + this.MainWindow.webContents.on('dom-ready', () => { + if (this.CapacitorFileConfig.electron?.splashScreenEnabled) { + this.SplashScreen.getSplashWindow().hide(); + } + if (!this.CapacitorFileConfig.electron?.hideMainWindowOnLaunch) { + this.MainWindow.show(); + } + setTimeout(() => { + if (electronIsDev) { + this.MainWindow.webContents.openDevTools(); + } + CapElectronEventEmitter.emit('CAPELECTRON_DeeplinkListenerInitialized', ''); + }, 400); + }); + } +} + +// Set a CSP up for our application based on the custom scheme +export function setupContentSecurityPolicy(customScheme: string): void { + session.defaultSession.webRequest.onHeadersReceived((details, callback) => { + callback({ + responseHeaders: { + ...details.responseHeaders, + 'Content-Security-Policy': [ + electronIsDev + ? `default-src ${customScheme}://* 'unsafe-inline' devtools://* 'unsafe-eval' data:` + : `default-src ${customScheme}://* 'unsafe-inline' data:`, + ], + }, + }); + }); +} diff --git a/electron/tsconfig.json b/electron/tsconfig.json new file mode 100644 index 0000000..848a65f --- /dev/null +++ b/electron/tsconfig.json @@ -0,0 +1,16 @@ +{ + "compileOnSave": true, + "include": ["./src/**/*", "./capacitor.config.ts", "./capacitor.config.js"], + "compilerOptions": { + "outDir": "./build", + "importHelpers": true, + "target": "ES2017", + "module": "CommonJS", + "moduleResolution": "node", + "esModuleInterop": true, + "typeRoots": ["./node_modules/@types"], + "allowJs": true, + "skipLibCheck": true, + "rootDir": "." + } +} diff --git a/legacy_js/closet.html b/legacy_js/closet.html deleted file mode 100644 index e777956..0000000 --- a/legacy_js/closet.html +++ /dev/null @@ -1,94 +0,0 @@ - - - - - - - Tienda - - - - - - -


-
-
-

- Cheems (Skins) -

-
- - - -
-
- - - -
-
- - - -
-
-
-

- Sonidos -

-
- - - -
-
- - - -
-
- - - -
-
- - - -
-
-
-

- Música de fondo -

-
- - - -
-
- - - -
-
-
- - - - - diff --git a/legacy_js/comming_soon.html b/legacy_js/comming_soon.html deleted file mode 100644 index 700d3ce..0000000 --- a/legacy_js/comming_soon.html +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - Menu - - - - - - -


-
-
-
- -

Esta página está en desarrollo aún

-
-
-
- - - - - \ No newline at end of file diff --git a/legacy_js/css/index.css b/legacy_js/css/index.css deleted file mode 100644 index 9ea3833..0000000 --- a/legacy_js/css/index.css +++ /dev/null @@ -1,122 +0,0 @@ - - -/*Light theme*/ -body.theme-light { - background-color: aliceblue; - color: black; -} -.group.theme-light { - background-color: antiquewhite; - border: solid black; -} - -.selected-cheems.theme-light { - background-color: rgba(230, 186, 128, 0.699); -} - - - -/*Dark theme*/ -body.theme-dark { - background-color: rgb(54, 54, 54); - color: rgb(211, 211, 211); -} -.group.theme-dark { - background-color: rgb(82, 75, 67); - border: solid black; -} - -.selected-cheems.theme-dark { - background-color: rgba(59, 37, 7, 0.699); -} - - -/*High contrast theme*/ -body.theme-contrast { - background-color: rgb(0, 0, 0); - color: rgb(255, 0, 255); -} -.group.theme-contrast { - background-color: rgb(0, 0, 255); - border: solid rgb(255, 0, 255); -} - - -.selected-cheems.theme-contrast { - background-color: rgba(255, 0, 0, 0.699); -} - - - - - -/*Utilities*/ -.color-text { - font-family: "Kalam"; -} -.hidden { - display: none; -} - - -/*General group*/ -.container { - width: 100%; - height: 100%; - max-width: 100%; - max-height: 100%; - min-width: 100%; - min-height: 100%; - user-select: none; -} -.flex-right { - display: flex; - flex-direction: row; - flex-wrap: wrap; - align-content: center; - justify-content: space-between; - align-items: center; - width: 95%; -} -.flex-right.center { - justify-content: center; -} -.go-down { - flex-direction: column; -} -.group { - display: flex; - flex-direction: column; - flex-wrap: wrap; - align-content: center; - justify-content: center; - align-items: center; - width: 100%; - height: 100%; - margin-top: 3%; -} -.container.shop { - display: flex; - flex-direction: column; - flex-wrap: wrap; - align-content: center; - justify-content: center; - align-items: center; -} -.container.shop img { - width: 10%; - height: 100%; -} -.container.shop div img { - width: 10%; - height: 100%; -} - - -.selected-cheems { - border-radius: 50%; - transform: scale(115%); -} - - - diff --git a/legacy_js/dev.html b/legacy_js/dev.html deleted file mode 100644 index 8c0830c..0000000 --- a/legacy_js/dev.html +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - Menu - - - - - - -


-
-
-
-

Reset to zero

-
-
-

Unlock All

-
-
-
- - - - - \ No newline at end of file diff --git a/legacy_js/download-repos.html b/legacy_js/download-repos.html deleted file mode 100644 index 0c3d07c..0000000 --- a/legacy_js/download-repos.html +++ /dev/null @@ -1,103 +0,0 @@ - - - - - - - Download Files - - - - - - -


-
-
-
-

- Si los archivos ya estabán descargados, se actualizarán con el servidor, si estás sin - conexión, se cargarán desde caché. -

-

- Realizar esto es importante para poder mejorar la velocidad de carga y usar la aplicación - en el modo Offline (Sin conexión). -

-

- Nota: Se pueden descargar hasta 118 MB, revisa el peso de la descarga antes de descargar con - redes móviles, tu proovedor de red móvil podría aplicar cargos de conexión. -

-
-
-
-
-

- Descarga de Scripts. -

-
-
-

- Peso estimado: 506 KB -

-
-
- -

Descargar Scripts

-
-
-
Contenedor de scripts...
-
-
-
-
-

- Descarga de imagenes. -

-
-
-

- Peso estimado: 9.98 MB -

-
-
- -

Descargar Imagenes

- -
-
-
-
-

- Descarga de efectos de sonido. -

-
-
-

- Peso estimado: 305 KB -

-
-
- -
-

Descargar Efectos de sonido.

- -
-
-
-
- - - - - - \ No newline at end of file diff --git a/legacy_js/game.html b/legacy_js/game.html deleted file mode 100644 index 14d53cd..0000000 --- a/legacy_js/game.html +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - Cheems Bonk Game - - - - - - -
- - -
- - - - - - - \ No newline at end of file diff --git a/legacy_js/index.html b/legacy_js/index.html deleted file mode 100644 index 9a6f8b7..0000000 --- a/legacy_js/index.html +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - Cheems Bonk Game - - - - - - -
-
- High Score de toques:
0
- Toques totales:
0
- Toques de esta sesión:
0
-
-
- -
-
- - - - - - - \ No newline at end of file diff --git a/legacy_js/js/SoundDefinitions.js b/legacy_js/js/SoundDefinitions.js deleted file mode 100644 index d0ce0ba..0000000 --- a/legacy_js/js/SoundDefinitions.js +++ /dev/null @@ -1,223 +0,0 @@ -var sound = new Audio(); -var music = new Audio(); -var effVol = 100, musVol = 50; - -function PlaySound(a) { - let Random; - switch (a) - { - case '1': - sound = new Audio('./sound/hit.ogg'); - break; - case '2': - sound = new Audio('./sound/hurt-minecraft.ogg'); - break; - case '3': - sound = new Audio('./sound/hurt-roblox.ogg'); - break; - case '4': - Random = Math.floor(Math.random()*5)+1; - if (Random == 4) - { - sound = new Audio('./sound/levelup2.ogg'); - } else { - sound = new Audio('./sound/levelup1.ogg'); - } - break; - case '5': - Random = Math.floor(Math.random()*3)+1; - if (Random == 1) - { - sound = new Audio('./sound/discord-connect.ogg'); - } else if (Random == 2) { - sound = new Audio('./sound/discord-disconnect.ogg'); - } else if (Random == 3) { - sound = new Audio('./sound/discord-msg.ogg'); - } - break; - case '6': - sound = new Audio('./sound/hello.ogg') - break; - case '7': - sound = new Audio('./sound/hit-minecraft.ogg') - break; - case '8': - sound = new Audio('./sound/no.ogg') - break; - case '9': - sound = new Audio('./sound/pato.ogg') - break; - case '10': - sound = new Audio('./sound/peluche.ogg') - break; - case '11': - sound = new Audio('./sound/splat.ogg') - break; - case '12': - sound = new Audio('./sound/windows-error.ogg') - break; - } - sound.volume = effVol/100; - sound.play(); -} - -function PlayMusic(a, t) { - switch (a) { - case 0: - music.src = null; - break; - case 1: - music.src = "./sound/music/A_Jazz_Piano.ogg"; - break; - case 2: - music.src = "./sound/music/Jack_Bootleg.ogg"; - break; - case 3: - music.src = "./sound/music/Magic_night.ogg"; - break; - case 4: - music.src = "./sound/music/Minimalism_No9.ogg"; - break; - case 5: - music.src = "./sound/music/Minimalism_No10.ogg"; - break; - case 6: - music.src = "./sound/music/When_you_smile.ogg"; - break; - } - music.currentTime = t; - music.volume = musVol/100; - music.loop = true; - music.play(); -} - -function SetVolumeEffect() { - let a = parseInt(document.getElementById("effect-volume").value); - effVol = a; - sound.volume = effVol/100; - PlaySound(SelSound); - console.log(effVol); - localStorage.setItem("CheemsAppLiEffectsVolume", effVol); - UpdateVolIcon("effects"); -} - -function LoadEffectsVolume(b) { - let a = parseInt(localStorage.getItem("CheemsAppLiEffectsVolume")); - effVol = a; - if (isNaN(effVol)) { - effVol = 100; - sound.volume = effVol/100; - localStorage.setItem("CheemsAppLiEffectsVolume", effVol); - } - sound.volume = effVol/100; - if (b) { - document.getElementById("effect-volume").value = effVol; - UpdateVolIcon("effects"); - } -} - -function SetVolumeMusic() { - let a = parseInt(document.getElementById("music-volume").value); - musVol = a; - music.volume = musVol/100; - localStorage.setItem("CheemsAppLiMusicVolume", musVol); - UpdateVolIcon("music"); -} - -function LoadMusicVolume(b) { - let a = parseInt(localStorage.getItem("CheemsAppLiMusicVolume")); - musVol = a; - if (isNaN(musVol)) { - musVol = 50; - music.volume = musVol/100; - localStorage.setItem("CheemsAppLiMusicVolume", musVol); - } - music.volume = musVol/100; - if (b) { - document.getElementById("music-volume").value = musVol; - UpdateVolIcon("music"); - } -} - -function setVolCont(choose) { - switch (choose) { - case "music": - if (musVol == 0) { - musVol = 100; - music.volume = musVol/100; - localStorage.setItem("CheemsAppLiMusicVolume", musVol); - } else { - musVol = 0; - music.volume = musVol/100; - localStorage.setItem("CheemsAppLiMusicVolume", musVol); - } - document.getElementById("music-volume").value = musVol; - console.log(musVol); - UpdateVolIcon("music"); - break; - case "effects": - if (effVol == 0) { - effVol = 100; - sound.volume = effVol/100; - localStorage.setItem("CheemsAppLiEffectsVolume", effVol); - } else { - effVol = 0; - sound.volume = effVol/100; - localStorage.setItem("CheemsAppLiEffectsVolume", effVol); - } - PlaySound(SelSound); - document.getElementById("effect-volume").value = effVol; - console.log(effVol); - UpdateVolIcon("effects"); - break; - } -} - -function UpdateVolIcon(choose) { - switch (choose) { - case "music": - if (musVol == 0) { - document.getElementById("music-vol-icon").setAttribute("src", "img/icons/volume-cross-svgrepo-com.svg"); - } else if (musVol > 50) { - document.getElementById("music-vol-icon").setAttribute("src", "img/icons/volume-loud-svgrepo-com.svg"); - } else if (musVol <= 50) { - document.getElementById("music-vol-icon").setAttribute("src", "img/icons/volume-small-svgrepo-com.svg"); - } - console.log("music icon"); - break; - case "effects": - if (effVol == 0) { - document.getElementById("effects-vol-icon").setAttribute("src", "img/icons/volume-cross-svgrepo-com.svg"); - } else if (effVol > 50) { - document.getElementById("effects-vol-icon").setAttribute("src", "img/icons/volume-loud-svgrepo-com.svg"); - } else if (effVol <= 50) { - document.getElementById("effects-vol-icon").setAttribute("src", "img/icons/volume-small-svgrepo-com.svg"); - } - console.log("effects icon"); - break; - } -} - -function ReplaySong() { - music.pause(); - music.currentTime = 0; - musicTime = 0; - KeepMusic(); - PlayMusic(SelMusic, musicTime); -} - -function KeepMusic() { - musicTime = music.currentTime; - localStorage.setItem("CheemsAppLiMusicTime", musicTime); -} - -//startSimulation and pauseSimulation defined elsewhere -function handleVisibilityChange() { - if (document.hidden) { - music.pause(); - } else { - music.play(); - } - } - - document.addEventListener("visibilitychange", handleVisibilityChange, false); \ No newline at end of file diff --git a/legacy_js/js/buttons.js b/legacy_js/js/buttons.js deleted file mode 100644 index 93593b8..0000000 --- a/legacy_js/js/buttons.js +++ /dev/null @@ -1,9 +0,0 @@ -document.addEventListener('keyup', (e) => { - if (e.code == 'Space') - { - ClickCheems(); - setTimeout(() => { - NoClick(); - }, 1000) - } -}); \ No newline at end of file diff --git a/legacy_js/js/functions.js b/legacy_js/js/functions.js deleted file mode 100644 index cc4506b..0000000 --- a/legacy_js/js/functions.js +++ /dev/null @@ -1,995 +0,0 @@ -navigator.serviceWorker.register("./sw.js"); -navigator.serviceWorker.register("./pwabuilder-adv-sw.js"); - -function RemoveSelectedCheems() -{ - BC1.classList.remove('selected-cheems', "light-theme", "dark-theme", "contrast-theme"); - BC2.classList.remove('selected-cheems', "light-theme", "dark-theme", "contrast-theme"); - BC3.classList.remove('selected-cheems', "light-theme", "dark-theme", "contrast-theme"); - BC4.classList.remove('selected-cheems', "light-theme", "dark-theme", "contrast-theme"); - BC5.classList.remove('selected-cheems', "light-theme", "dark-theme", "contrast-theme"); - BC6.classList.remove('selected-cheems', "light-theme", "dark-theme", "contrast-theme"); - BC7.classList.remove('selected-cheems', "light-theme", "dark-theme", "contrast-theme"); - BC8.classList.remove('selected-cheems', "light-theme", "dark-theme", "contrast-theme"); - BC9.classList.remove('selected-cheems', "light-theme", "dark-theme", "contrast-theme"); -} -function RemoveSelectedSound() -{ - BS1.classList.remove('selected-cheems', "light-theme", "dark-theme", "contrast-theme"); - BS2.classList.remove('selected-cheems', "light-theme", "dark-theme", "contrast-theme"); - BS3.classList.remove('selected-cheems', "light-theme", "dark-theme", "contrast-theme"); - BS4.classList.remove('selected-cheems', "light-theme", "dark-theme", "contrast-theme"); - BS5.classList.remove('selected-cheems', "light-theme", "dark-theme", "contrast-theme"); - BS6.classList.remove('selected-cheems', "light-theme", "dark-theme", "contrast-theme"); - BS7.classList.remove('selected-cheems', "light-theme", "dark-theme", "contrast-theme"); - BS8.classList.remove('selected-cheems', "light-theme", "dark-theme", "contrast-theme"); - BS9.classList.remove('selected-cheems', "light-theme", "dark-theme", "contrast-theme"); - BS10.classList.remove('selected-cheems', "light-theme", "dark-theme", "contrast-theme"); - BS11.classList.remove('selected-cheems', "light-theme", "dark-theme", "contrast-theme"); - BS12.classList.remove('selected-cheems', "light-theme", "dark-theme", "contrast-theme"); -} -function RemoveSelectedSong() -{ - BM1.classList.remove('selected-cheems', "light-theme", "dark-theme", "contrast-theme"); - BM2.classList.remove('selected-cheems', "light-theme", "dark-theme", "contrast-theme"); - BM3.classList.remove('selected-cheems', "light-theme", "dark-theme", "contrast-theme"); - BM4.classList.remove('selected-cheems', "light-theme", "dark-theme", "contrast-theme"); - BM5.classList.remove('selected-cheems', "light-theme", "dark-theme", "contrast-theme"); - BM6.classList.remove('selected-cheems', "light-theme", "dark-theme", "contrast-theme"); -} - -function LoadFirst() { - musicTime = 0; - localStorage.setItem("CheemsAppLiMusicTime", musicTime); - points = 0; - localStorage.setItem("CheemsAppLiActPoints", points); - LoadTheme(); - LoadAccesibility(); -} - -function LoadAll() -{ - Selcheems = localStorage.getItem("CheemsAppLiSelCheems"); - SelSound = localStorage.getItem("CheemsAppLiSelSound"); - SelMusic = parseInt(localStorage.getItem("CheemsAppLiSelMusic")); - musicTime = parseFloat(localStorage.getItem("CheemsAppLiMusicTime")); - totalCount = parseInt(localStorage.getItem("CheemsAppLiTotalCounter")); - maxCount = parseInt(localStorage.getItem("CheemsAppLiMaxCounter")); - points = parseInt(localStorage.getItem("CheemsAppLiPoints")); - dogeCoins = parseInt(localStorage.getItem("CheemsAppLiDogecoins")); - clickable = localStorage.getItem("CheemsAppLiClickable"); - thisCount = parseInt(localStorage.getItem("CheemsAppLiActPoints")); - if (isNaN(totalCount)) - { - totalCount = 0; - let totalCountP = JSON.stringify(totalCount); - localStorage.setItem("CheemsAppLiTotalCounter", totalCountP); - } - if (isNaN(maxCount)) - { - maxCount = 0; - let maxCountP = JSON.stringify(maxCount); - localStorage.setItem("CheemsAppLiMaxCounter", maxCountP); - } - if (isNaN(points)) - { - points = 0; - let pointsP = JSON.stringify(points); - localStorage.setItem("CheemsAppLiPoints", pointsP); - } - if (isNaN(dogeCoins)) - { - dogeCoins = 0; - let dogeCoinsP = JSON.stringify(dogeCoins); - localStorage.setItem("CheemsAppLiDogecoins", dogeCoinsP); - } - if (Selcheems == '[object Undefined]' || Selcheems == null || Selcheems == "undefined") - { - Selcheems = "normal"; - let SelCheemsP = JSON.stringify(Selcheems); - localStorage.setItem("CheemsAppLiSelCheems", SelCheemsP); - } else { - Selcheems = Selcheems.replace('"',''); - Selcheems = Selcheems.replace('"',''); - } - if (SelSound == '[object Undefined]' || SelSound == null || SelSound == "undefined") - { - SelSound = 1; - let SelSoundP = JSON.stringify(SelSound); - localStorage.setItem("CheemsAppLiSelSound", SelSoundP); - } - if (clickable == '[object Undefined]' || clickable == null || clickable == "undefined") - { - clickable = "true"; - localStorage.setItem("CheemsAppLiClickable", clickable); - } else { - clickable = "true"; - localStorage.setItem("CheemsAppLiClickable", clickable); - } - if (isNaN(SelMusic) || SelMusic == null) { - SelMusic = 1; - localStorage.setItem("CheemsAppLiSelMusic", SelMusic); - } - if (isNaN(musicTime) || musicTime == null) { - musicTime = 0; - localStorage.setItem("CheemsAppLiMusicTime", musicTime); - } - LoadMusicVolume(false); - LoadEffectsVolume(false); - PlayMusic(SelMusic, musicTime); - LoadAccesibility(); - LoadTheme(); - PrintChanges(); -} - -function LoadCloset() -{ - Selcheems = localStorage.getItem("CheemsAppLiSelCheems"); - Selcheems = Selcheems.replace('"',''); - Selcheems = Selcheems.replace('"',''); - SelSound = localStorage.getItem("CheemsAppLiSelSound"); - SelMusic = parseInt(localStorage.getItem("CheemsAppLiSelMusic")); - musicTime = parseFloat(localStorage.getItem("CheemsAppLiMusicTime")); - points = parseInt(localStorage.getItem("CheemsAppLiPoints")) + 1 - 1; - dogeCoins = parseInt(localStorage.getItem("CheemsAppLiDogecoins")) + 1 - 1; - LoadMusicVolume(false); - LoadEffectsVolume(false); - PlayMusic(SelMusic, musicTime); - LoadTheme(); - LoadAccesibility(); - PrintChangesS(); - CheckPurchases(); - LoadSelection(); -} - -function LoadSelection() { - CheckSound(); - CheckSong(); - CheckSelected(); - LoadAccesibility(); - CheckPurchases(); - PrintChangesS(); -} - -function LoadMenu() { - SelSound = localStorage.getItem("CheemsAppLiSelSound"); - SelMusic = parseInt(localStorage.getItem("CheemsAppLiSelMusic")); - musicTime = parseFloat(localStorage.getItem("CheemsAppLiMusicTime")); - devMenu = localStorage.getItem("CheemsAppLiDevMenu"); - if (devMenu == null || devMenu == "[object Undefined]") { - devMenu = "false"; - localStorage.setItem("CheemsAppLiDevMenu", devMenu); - } else if (devMenu == "true") { - document.getElementById("dev-menu").classList.remove("hidden"); - } else { - document.getElementById("dev-menu").classList.add("hidden"); - } - LoadMusicVolume(false); - LoadEffectsVolume(false); - LoadTheme(); - LoadAccesibility(); - PlayMusic(SelMusic, musicTime); -} - -function LoadGeneral() { - SelSound = localStorage.getItem("CheemsAppLiSelSound"); - SelMusic = parseInt(localStorage.getItem("CheemsAppLiSelMusic")); - musicTime = parseFloat(localStorage.getItem("CheemsAppLiMusicTime")); - LoadMusicVolume(false); - LoadEffectsVolume(false); - LoadTheme(); - LoadAccesibility(); - PlayMusic(SelMusic, musicTime); -} - -function LoadSettings() { - SelSound = localStorage.getItem("CheemsAppLiSelSound"); - SelMusic = parseInt(localStorage.getItem("CheemsAppLiSelMusic")); - musicTime = parseFloat(localStorage.getItem("CheemsAppLiMusicTime")); - LoadMusicVolume(true); - LoadEffectsVolume(true); - LoadTheme(); - LoadAccesibility(); - PlayMusic(SelMusic, musicTime); -} - -function ResetToZero() -{ - let SelCheems; - maxCount = 0; - totalCount = 0; - thisCount = 0; - points = 0; - dogeCoins = 0; - SelSound = 1; - SelMusic = 1; - effVol = 100; - musVol = 50; - musicTime = 0; - Selcheems = "normal"; - theme = 0; - let a = JSON.stringify(false); - let b = JSON.stringify(true); - localStorage.setItem('c1', b); - localStorage.setItem('c2', a); - localStorage.setItem('c3', a); - localStorage.setItem('c4', a); - localStorage.setItem('c5', a); - localStorage.setItem('c6', a); - localStorage.setItem('c7', a); - localStorage.setItem('c8', a); - localStorage.setItem('c9', a); - localStorage.setItem("s1", b); - localStorage.setItem("s2", a); - localStorage.setItem("s3", a); - localStorage.setItem("s4", a); - localStorage.setItem("s5", a); - localStorage.setItem("s6", a); - localStorage.setItem("s7", a); - localStorage.setItem("s8", a); - localStorage.setItem("s9", a); - localStorage.setItem("s10", a); - localStorage.setItem("s11", a); - localStorage.setItem("s12", a); - localStorage.setItem("CheemsAppLiM1", b); - localStorage.setItem("CheemsAppLiM2", a); - localStorage.setItem("CheemsAppLiM3", a); - localStorage.setItem("CheemsAppLiM4", a); - localStorage.setItem("CheemsAppLiM5", a); - localStorage.setItem("CheemsAppLiM6", a); - localStorage.setItem("CheemsAppLiMaxCounter", maxCount); - localStorage.setItem("CheemsAppLiPoints", points); - localStorage.setItem("CheemsAppLiTotalCounter", totalCount); - localStorage.setItem("CheemsAppLiDogecoins", dogeCoins); - localStorage.setItem("CheemsAppLiSelCheems", SelCheems); - localStorage.setItem("CheemsAppLiClickable", clickable); - localStorage.setItem("CheemsAppLiSelSound", SelSound); - localStorage.setItem("CheemsAppLiSelMusic", SelMusic); - localStorage.setItem("CheemsAppLiMusicVolume", musVol); - localStorage.setItem("CheemsAppLiEffectsVolume", effVol); - localStorage.setItem("CheemsAppLiMusicTime", musicTime); - localStorage.setItem("CheemsAppLiActTheme", theme); - Redirect("index.html"); -} - -function UnlockAll() { - let SelCheems; - maxCount = 999999; - totalCount = 999999; - thisCount = 0; - points = 999999; - dogeCoins = 999999; - SelSound = 1; - SelMusic = 1; - effVol = 100; - musVol = 50; - musicTime = 0; - Selcheems = "normal"; - theme = 1; - let a = JSON.stringify(true); - let b = JSON.stringify(true); - localStorage.setItem('c1', b); - localStorage.setItem('c2', a); - localStorage.setItem('c3', a); - localStorage.setItem('c4', a); - localStorage.setItem('c5', a); - localStorage.setItem('c6', a); - localStorage.setItem('c7', a); - localStorage.setItem('c8', a); - localStorage.setItem('c9', a); - localStorage.setItem("s1", b); - localStorage.setItem("s2", a); - localStorage.setItem("s3", a); - localStorage.setItem("s4", a); - localStorage.setItem("s5", a); - localStorage.setItem("s6", a); - localStorage.setItem("s7", a); - localStorage.setItem("s8", a); - localStorage.setItem("s9", a); - localStorage.setItem("s10", a); - localStorage.setItem("s11", a); - localStorage.setItem("s12", a); - localStorage.setItem("CheemsAppLiM1", b); - localStorage.setItem("CheemsAppLiM2", a); - localStorage.setItem("CheemsAppLiM3", a); - localStorage.setItem("CheemsAppLiM4", a); - localStorage.setItem("CheemsAppLiM5", a); - localStorage.setItem("CheemsAppLiM6", a); - localStorage.setItem("CheemsAppLiMaxCounter", maxCount); - localStorage.setItem("CheemsAppLiPoints", points); - localStorage.setItem("CheemsAppLiTotalCounter", totalCount); - localStorage.setItem("CheemsAppLiDogecoins", dogeCoins); - localStorage.setItem("CheemsAppLiSelCheems", SelCheems); - localStorage.setItem("CheemsAppLiClickable", clickable); - localStorage.setItem("CheemsAppLiSelSound", SelSound); - localStorage.setItem("CheemsAppLiSelMusic", SelMusic); - localStorage.setItem("CheemsAppLiMusicVolume", musVol); - localStorage.setItem("CheemsAppLiEffectsVolume", effVol); - localStorage.setItem("CheemsAppLiMusicTime", musicTime); - localStorage.setItem("CheemsAppLiActTheme", theme); - Redirect("index.html"); -} - -function SaveCountChanges() -{ - let sum = 1; - thisCount += sum; - if (maxCount < thisCount) - { - maxCount = thisCount; - let maxCountP = JSON.stringify(maxCount); - localStorage.setItem("CheemsAppLiMaxCounter", maxCountP); - } - totalCount += sum; - let totalCountP = JSON.stringify(totalCount); - localStorage.setItem("CheemsAppLiTotalCounter", totalCountP); - points += sum; - let pointsP = JSON.stringify(points); - localStorage.setItem("CheemsAppLiPoints", pointsP); - localStorage.setItem("CheemsAppLiActPoints", thisCount); -} - -function BuyDogeCoins() -{ - PlaySound(SelSound); - if (points >= DGC) - { - points -= DGC; - dogeCoins += 1; - let pointsP = JSON.stringify(points); - let dogeCoinsP = JSON.stringify(dogeCoins); - localStorage.setItem("CheemsAppLiPoints", pointsP); - localStorage.setItem("CheemsAppLiDogecoins", dogeCoinsP); - shopTextS.innerHTML = 'Compraste 1 DogeCoin'; - setTimeout(() => { - shopTextS.innerHTML = 'Tienda'; - }, (STTimer+=3000)); - LoadShop(); - } else { - shopTextS.innerHTML = '¡NECESITAS ' + String(DGC - points) + ' pts. MÁS!'; - setTimeout(() => { - shopTextS.innerHTML = 'Tienda'; - }, (STTimer+=3000)); - } -} - -function BuyCheems(a) -{ - PlaySound(SelSound); - switch (a) - { - case "normal": - BuyAnyCheems(0, a, c1, 1); - break; - case "little": - BuyAnyCheems(1, a, c2, 2); - break; - case "adult": - BuyAnyCheems(2, a, c3, 3); - break; - case "kid": - BuyAnyCheems(3, a, c4, 4); - break; - case "mamado": - BuyAnyCheems(5, a, c5, 5); - break; - case "pixelart": - BuyAnyCheems(12, a, c6, 6); - break; - case "elegant": - BuyAnyCheems(13, a, c7, 7); - break; - case "3d": - BuyAnyCheems(7, a, c8, 8); - break; - case "black": - BuyAnyCheems(10, a, c9, 9); - break; - } - LoadShop(); -} - -function BuySound(a) -{ - switch (a) - { - case 1: - BuyAnySound(s1, 1, '"Hit"', 0); - break; - case 2: - BuyAnySound(s2, 2, '"Hurt Minecraft"', 7); - break; - case 3: - BuyAnySound(s3, 3, '"Hurt Roblox"', 6); - break; - case 4: - BuyAnySound(s4, 4, '"Level Up Minecraft"', 8); - break; - case 5: - BuyAnySound(s5, 5, '"Discord"', 8); - break; - case 6: - BuyAnySound(s6, 6, '"Hello FNAF"', 6); - break; - case 7: - BuyAnySound(s7, 7, '"Hit Minecraft"', 4); - break; - case 8: - BuyAnySound(s8, 8, '"NO"', 11); - break; - case 9: - BuyAnySound(s9, 9, '"Duck"', 3); - break; - case 10: - BuyAnySound(s10, 10, '"Toy"', 3); - break; - case 11: - BuyAnySound(s11, 11, '"Splat"', 3); - break; - case 12: - BuyAnySound(s12, 12, '"Error Windows"', 5); - break; - } - setTimeout(() => { - PlaySound(SelSound); - }, 50); - LoadShop(); -} - -function CheckPurchases() -{ - c2 = localStorage.getItem('c2'); - c3 = localStorage.getItem('c3'); - c4 = localStorage.getItem('c4'); - c5 = localStorage.getItem('c5'); - c6 = localStorage.getItem('c6'); - c7 = localStorage.getItem('c7'); - c8 = localStorage.getItem('c8'); - c9 = localStorage.getItem('c9'); - s1 = localStorage.getItem('s1'); - s2 = localStorage.getItem('s2'); - s3 = localStorage.getItem('s3'); - s4 = localStorage.getItem('s4'); - s5 = localStorage.getItem('s5'); - s6 = localStorage.getItem('s6'); - s7 = localStorage.getItem('s7'); - s8 = localStorage.getItem('s8'); - s9 = localStorage.getItem('s9'); - s10 = localStorage.getItem('s10'); - s11 = localStorage.getItem('s11'); - s12 = localStorage.getItem('s12'); - m1 = localStorage.getItem("CheemsAppLiM1"); - m2 = localStorage.getItem("CheemsAppLiM2"); - m3 = localStorage.getItem("CheemsAppLiM3"); - m4 = localStorage.getItem("CheemsAppLiM4"); - m5 = localStorage.getItem("CheemsAppLiM5"); - m6 = localStorage.getItem("CheemsAppLiM6"); - let a = JSON.stringify(false); - let b = JSON.stringify(true); - - if (c1 == '[object Undefined]' || c1 == null) - { - localStorage.setItem('c1', b); - c1 = localStorage.getItem('c1'); - } - if (c2 == '[object Undefined]' || c2 == null) - { - localStorage.setItem('c2', a); - c2 = localStorage.getItem('c2'); - } - if (c3 == '[object Undefined]' || c3 == null) - { - localStorage.setItem('c3', a); - c3 = localStorage.getItem('c3'); - } - if (c4 == '[object Undefined]' || c4 == null) - { - localStorage.setItem('c4', a); - c4 = localStorage.getItem('c4'); - } - if (c5 == '[object Undefined]' || c5 == null) - { - localStorage.setItem('c5', a); - c5 = localStorage.getItem('c5'); - } - if (c6 == '[object Undefined]' || c6 == null) - { - localStorage.setItem('c6', a); - c6 = localStorage.getItem('c6'); - } - if (c7 == '[object Undefined]' || c7 == null) - { - localStorage.setItem('c7', a); - c7 = localStorage.getItem('c7'); - } - if (c8 == '[object Undefined]' || c8 == null) - { - localStorage.setItem('c8', a); - c8 = localStorage.getItem('c8'); - } - if (c9 == '[object Undefined]' || c9 == null) - { - localStorage.setItem('c9', a); - c9 = localStorage.getItem('c9'); - } - if (s1 == '[object Undefined]' || s1 == null) - { - localStorage.setItem('s1', b); - s1 = localStorage.getItem('s1'); - } - if (s2 == '[object Undefined]' || s2 == null) - { - localStorage.setItem('s2', a); - s2 = localStorage.getItem('s2'); - } - if (s3 == '[object Undefined]' || s3 == null) - { - localStorage.setItem('s3', a); - s3 = localStorage.getItem('s3'); - } - if (s4 == '[object Undefined]' || s4 == null) - { - localStorage.setItem('s4', a); - s4 = localStorage.getItem('s4'); - } - if (s5 == '[object Undefined]' || s5 == null) - { - localStorage.setItem('s5', a); - s5 = localStorage.getItem('s5'); - } - if (s6 == '[object Undefined]' || s6 == null) - { - localStorage.setItem('s6', a); - s6 = localStorage.getItem('s6'); - } - if (s7 == '[object Undefined]' || s7 == null) - { - localStorage.setItem('s7', a); - s7 = localStorage.getItem('s7'); - } - if (s8 == '[object Undefined]' || s8 == null) - { - localStorage.setItem('s8', a); - s8 = localStorage.getItem('s8'); - } - if (s9 == '[object Undefined]' || s9 == null) - { - localStorage.setItem('s9', a); - s9 = localStorage.getItem('s9'); - } - if (s10 == '[object Undefined]' || s10 == null) - { - localStorage.setItem('s10', a); - s10 = localStorage.getItem('s10'); - } - if (s11 == '[object Undefined]' || s11 == null) - { - localStorage.setItem('s11', a); - s11 = localStorage.getItem('s11'); - } - if (s12 == '[object Undefined]' || s12 == null) - { - localStorage.setItem('s12', a); - s12 = localStorage.getItem('s12'); - } - if (m1 == '[object Undefined]' || m1 == null) { - m1 = "true"; - localStorage.setItem("CheemsAppLiM1", m1); - } - if (m2 == '[object Undefined]' || m2 == null) { - m2 = "false"; - localStorage.setItem("CheemsAppLiM2", m2); - } - if (m3 == '[object Undefined]' || m3 == null) { - m3 = "false"; - localStorage.setItem("CheemsAppLiM3", m3); - } - if (m4 == '[object Undefined]' || m4 == null) { - m4 = "false"; - localStorage.setItem("CheemsAppLiM4", m4); - } - if (m5 == '[object Undefined]' || m5 == null) { - m5 = "false"; - localStorage.setItem("CheemsAppLiM5", m5); - } - if (m6 == '[object Undefined]' || m6 == null) { - m6 = "false"; - localStorage.setItem("CheemsAppLiM6", m6); - } - CheckSound(); - CheckSelected(); - CheckSong(); -} - -function BuyAnySound(sound, nSound, string, cost) -{ - let fv = JSON.stringify(true); - if (sound == 'true') - { - SelSound = nSound; - SSP = JSON.stringify(SelSound); - localStorage.setItem("CheemsAppLiSelSound", SSP); - shopTextS.innerHTML = 'Sonido ' + string + ' Seleccionado'; - setTimeout(() => { - shopTextS.innerHTML = 'Tienda'; - }, (STTimer+=3000)); - } else { - if (dogeCoins >= cost) - { - dogeCoins -= cost; - let dogeCoinsP = JSON.stringify(dogeCoins); - localStorage.setItem("CheemsAppLiDogecoins", dogeCoinsP); - localStorage.setItem('s'+String(nSound), fv); - sound = localStorage.getItem('s'+String(nSound)); - SelSound = nSound; - let SSP = JSON.stringify(SelSound); - localStorage.setItem("CheemsAppLiSelSound", SSP); - shopTextS.innerHTML = 'Sonido ' + string + ' Comprado'; - setTimeout(() => { - shopTextS.innerHTML = 'Tienda'; - }, (STTimer+=3000)); - } else { - shopTextS.innerHTML = '¡Necesitas ' + String(cost - dogeCoins) + ' DogeCoins Más!'; - setTimeout(() => { - shopTextS.innerHTML = 'Tienda'; - }, (STTimer+=3000)); - } - } -} - -function BuyAnyCheems(cost, nCheems, cheems, num) -{ - let b = JSON.stringify(true); - if (cheems == 'true') - { - Selcheems = nCheems; - let SelCheemsP = JSON.stringify(Selcheems); - localStorage.setItem("CheemsAppLiSelCheems", SelCheemsP); - shopTextS.innerHTML = 'Cheems ' + nCheems + ' Seleccionado'; - setTimeout(() => { - shopTextS.innerHTML = 'Tienda'; - }, (STTimer+=3000)); - } else { - if (dogeCoins >= cost) - { - dogeCoins -= cost; - let dogeCoinsP = JSON.stringify(dogeCoins); - localStorage.setItem("CheemsAppLiDogecoins", dogeCoinsP); - localStorage.setItem('c'+String(num), b); - cheems = localStorage.getItem('c'+String(num)); - Selcheems = nCheems; - let SelCheemsP = JSON.stringify(Selcheems); - localStorage.setItem("CheemsAppLiSelCheems", SelCheemsP); - shopTextS.innerHTML = 'Cheems ' + nCheems + ' Comprado'; - setTimeout(() => { - shopTextS.innerHTML = 'Tienda'; - }, (STTimer+=3000)); - } else { - shopTextS.innerHTML = '¡Necesitas ' + String(cost - dogeCoins) + ' DogeCoins Más!'; - setTimeout(() => { - shopTextS.innerHTML = 'Tienda'; - }, (STTimer+=3000)); - } - } -} - -function CheckSelected() -{ - if (c1 == 'false') - { - BC1.setAttribute('src', 'img/locked-cheems.png'); - } else { - BC1.setAttribute('src', 'img/cheems/normal.png'); - } - if (c2 == 'false') - { - BC2.setAttribute('src', 'img/locked-cheems.png'); - } else { - BC2.setAttribute('src', 'img/cheems/little.png'); - } - if (c3 == 'false') - { - BC3.setAttribute('src', 'img/locked-cheems.png'); - } else { - BC3.setAttribute('src', 'img/cheems/adult.png'); - } - if (c4 == 'false') - { - BC4.setAttribute('src', 'img/locked-cheems.png'); - } else { - BC4.setAttribute('src', 'img/cheems/kid.png'); - } - if (c5 == 'false') - { - BC5.setAttribute('src', 'img/locked-cheems.png'); - } else { - BC5.setAttribute('src', 'img/cheems/mamado.png'); - } - if (c6 == 'false') - { - BC6.setAttribute('src', 'img/locked-cheems.png'); - } else { - BC6.setAttribute('src', 'img/cheems/pixelart.png'); - } - if (c7 == 'false') - { - BC7.setAttribute('src', 'img/locked-cheems.png'); - } else { - BC7.setAttribute('src', 'img/cheems/elegant.png'); - } - if (c8 == 'false') - { - BC8.setAttribute('src', 'img/locked-cheems.png'); - } else { - BC8.setAttribute('src', 'img/cheems/3d.png'); - } - if (c9 == 'false') - { - BC9.setAttribute('src', 'img/locked-cheems.png'); - } else { - BC9.setAttribute('src', 'img/cheems/black.png'); - } - - RemoveSelectedCheems(); - switch (Selcheems) - { - case 'normal': - BC1.classList.add('selected-cheems', ChooseByTheme()); - break; - case 'little': - BC2.classList.add('selected-cheems', ChooseByTheme()); - break; - case 'adult': - BC3.classList.add('selected-cheems', ChooseByTheme()); - break; - case 'kid': - BC4.classList.add('selected-cheems', ChooseByTheme()); - break; - case 'mamado': - BC5.classList.add('selected-cheems', ChooseByTheme()); - break; - case 'pixelart': - BC6.classList.add('selected-cheems', ChooseByTheme()); - break; - case 'elegant': - BC7.classList.add('selected-cheems', ChooseByTheme()); - break; - case '3d': - BC8.classList.add('selected-cheems', ChooseByTheme()); - break; - case 'black': - BC9.classList.add('selected-cheems', ChooseByTheme()); - break; - } -} - -function CheckSound() -{ - if (s1 == 'false') - { - BS1.setAttribute('src', 'img/icons/volume-cross-svgrepo-com.svg'); - } else { - BS1.setAttribute('src', 'img/icons/volume-loud-svgrepo-com.svg'); - } - if (s2 == 'false') - { - BS2.setAttribute('src', 'img/icons/volume-cross-svgrepo-com.svg'); - } else { - BS2.setAttribute('src', 'img/icons/volume-loud-svgrepo-com.svg'); - } - if (s3 == 'false') - { - BS3.setAttribute('src', 'img/icons/volume-cross-svgrepo-com.svg'); - } else { - BS3.setAttribute('src', 'img/icons/volume-loud-svgrepo-com.svg'); - } - if (s4 == 'false') - { - BS4.setAttribute('src', 'img/icons/volume-cross-svgrepo-com.svg'); - } else { - BS4.setAttribute('src', 'img/icons/volume-loud-svgrepo-com.svg'); - } - if (s5 == 'false') - { - BS5.setAttribute('src', 'img/icons/volume-cross-svgrepo-com.svg'); - } else { - BS5.setAttribute('src', 'img/icons/volume-loud-svgrepo-com.svg'); - } - if (s6 == 'false') - { - BS6.setAttribute('src', 'img/icons/volume-cross-svgrepo-com.svg'); - } else { - BS6.setAttribute('src', 'img/icons/volume-loud-svgrepo-com.svg'); - } - if (s7 == 'false') - { - BS7.setAttribute('src', 'img/icons/volume-cross-svgrepo-com.svg'); - } else { - BS7.setAttribute('src', 'img/icons/volume-loud-svgrepo-com.svg'); - } - if (s8 == 'false') - { - BS8.setAttribute('src', 'img/icons/volume-cross-svgrepo-com.svg'); - } else { - BS8.setAttribute('src', 'img/icons/volume-loud-svgrepo-com.svg'); - } - if (s9 == 'false') - { - BS9.setAttribute('src', 'img/icons/volume-cross-svgrepo-com.svg'); - } else { - BS9.setAttribute('src', 'img/icons/volume-loud-svgrepo-com.svg'); - } - if (s10 == 'false') - { - BS10.setAttribute('src', 'img/icons/volume-cross-svgrepo-com.svg'); - } else { - BS10.setAttribute('src', 'img/icons/volume-loud-svgrepo-com.svg'); - } - if (s11 == 'false') - { - BS11.setAttribute('src', 'img/icons/volume-cross-svgrepo-com.svg'); - } else { - BS11.setAttribute('src', 'img/icons/volume-loud-svgrepo-com.svg'); - } - if (s12 == 'false') - { - BS12.setAttribute('src', 'img/icons/volume-cross-svgrepo-com.svg'); - } else { - BS12.setAttribute('src', 'img/icons/volume-loud-svgrepo-com.svg'); - } - - RemoveSelectedSound(); - switch (SelSound) - { - case '1': - BS1.classList.add('selected-cheems', ChooseByTheme()); - break; - case '2': - BS2.classList.add('selected-cheems', ChooseByTheme()); - break; - case '3': - BS3.classList.add('selected-cheems', ChooseByTheme()); - break; - case '4': - BS4.classList.add('selected-cheems', ChooseByTheme()); - break; - case '5': - BS5.classList.add('selected-cheems', ChooseByTheme()); - break; - case '6': - BS6.classList.add('selected-cheems', ChooseByTheme()); - break; - case '7': - BS7.classList.add('selected-cheems', ChooseByTheme()); - break; - case '8': - BS8.classList.add('selected-cheems', ChooseByTheme()); - break; - case '9': - BS9.classList.add('selected-cheems', ChooseByTheme()); - break; - case '10': - BS10.classList.add('selected-cheems', ChooseByTheme()); - break; - case '11': - BS11.classList.add('selected-cheems', ChooseByTheme()); - break; - case '12': - BS12.classList.add('selected-cheems', ChooseByTheme()); - break; - } -} - -function CheckSong() -{ - if (m1 == 'false') - { - BM1.setAttribute('src', 'img/icons/black-music-svgrepo-com.svg'); - } else { - BM1.setAttribute('src', 'img/icons/music-svgrepo-com.svg'); - } - if (m2 == 'false') - { - BM2.setAttribute('src', 'img/icons/black-music-svgrepo-com.svg'); - } else { - BM2.setAttribute('src', 'img/icons/music-svgrepo-com.svg'); - } - if (m3 == 'false') - { - BM3.setAttribute('src', 'img/icons/black-music-svgrepo-com.svg'); - } else { - BM3.setAttribute('src', 'img/icons/music-svgrepo-com.svg'); - } - if (m4 == 'false') - { - BM4.setAttribute('src', 'img/icons/black-music-svgrepo-com.svg'); - } else { - BM4.setAttribute('src', 'img/icons/music-svgrepo-com.svg'); - } - if (m5 == 'false') - { - BM5.setAttribute('src', 'img/icons/black-music-svgrepo-com.svg'); - } else { - BM5.setAttribute('src', 'img/icons/music-svgrepo-com.svg'); - } - if (m6 == 'false') - { - BM6.setAttribute('src', 'img/icons/black-music-svgrepo-com.svg'); - } else { - BM6.setAttribute('src', 'img/icons/music-svgrepo-com.svg'); - } - - RemoveSelectedSong(); - switch (SelMusic) - { - case 1: - BM1.classList.add('selected-cheems', ChooseByTheme()); - break; - case 2: - BM2.classList.add('selected-cheems', ChooseByTheme()); - break; - case 3: - BM3.classList.add('selected-cheems', ChooseByTheme()); - break; - case 4: - BM4.classList.add('selected-cheems', ChooseByTheme()); - break; - case 5: - BM5.classList.add('selected-cheems', ChooseByTheme()); - break; - case 6: - BM6.classList.add('selected-cheems', ChooseByTheme()); - break; - } -} - -function ChangeCheems(a, b) { - let canChange = false; - if (b == 'true') { - canChange = true; - } - if (canChange) { - Selcheems = a; - localStorage.setItem("CheemsAppLiSelCheems", a); - } - PlaySound(SelSound); - LoadSelection(); -} - -function ChangeSound(a, b) { - let canChange = false; - if (b == 'true') { - canChange = true; - } - if (canChange) { - SelSound = a; - localStorage.setItem("CheemsAppLiSelSound", a); - } - PlaySound(SelSound); - LoadSelection(); -} - -function ChangeSong(a, b) { - let canChange = false; - if (b == 'true') { - canChange = true; - } - if (canChange) { - SelMusic = a; - localStorage.setItem("CheemsAppLiSelMusic", a); - ReplaySong(); - } - PlaySound(SelSound); - LoadSelection(); -} - -function EnableDevOptions() { - if (devMenu == "true") { - devMenu = "false"; - document.getElementById("dev-menu").classList.add("hidden"); - } else { - devMenu = "true"; - document.getElementById("dev-menu").classList.remove("hidden"); - } - localStorage.setItem("CheemsAppLiDevMenu", devMenu); -} \ No newline at end of file diff --git a/legacy_js/js/index.js b/legacy_js/js/index.js deleted file mode 100644 index 5c58d8e..0000000 --- a/legacy_js/js/index.js +++ /dev/null @@ -1,217 +0,0 @@ -const img = document.getElementById('cheems-img'), shopTextS = document.getElementById('shop-text'); -const generalCounter = document.getElementById('general-count'), maxCounter = document.getElementById('max-count'), thisCounter = document.getElementById('this-count'); -const pointsS = document.getElementById('pts-count'), dogeCoinsS = document.getElementById('dg-count'); -const BC1 = document.getElementById('BuyCheems1'), BC2 = document.getElementById('BuyCheems2'), BC3 = document.getElementById('BuyCheems3'); -const BC4 = document.getElementById('BuyCheems4'), BC5 = document.getElementById('BuyCheems5'), BC6 = document.getElementById('BuyCheems6'); -const BC7 = document.getElementById('BuyCheems7'), BC8 = document.getElementById('BuyCheems8'), BC9 = document.getElementById('BuyCheems9'); -const ClickCheemsB = document.getElementById('ClickCheems'), dgc = document.getElementById('dgc'); -const BS1 = document.getElementById('BS1'), BS2 = document.getElementById('BS2'), BS3 = document.getElementById('BS3'); -const BS4 = document.getElementById('BS4'), BS5 = document.getElementById('BS5'), BS6 = document.getElementById('BS6'); -const BS7 = document.getElementById('BS7'), BS8 = document.getElementById('BS8'), BS9 = document.getElementById('BS9'); -const BS10 = document.getElementById('BS10'), BS11 = document.getElementById('BS11'), BS12 = document.getElementById('BS12'); -const BM1 = document.getElementById('BM1'), BM2 = document.getElementById('BM2'), BM3 = document.getElementById('BM3'); -const BM4 = document.getElementById('BM4'), BM5 = document.getElementById('BM5'), BM6 = document.getElementById('BM6'); - - -var DGC = Math.floor(Math.random()*100) + 51, SelSound = 1; -var Selcheems = "normal", totalCount = 0, maxCount = 0, thisCount = 0, points = 0, dogeCoins = 0, STTimer = 0; -var c1 = 'true', c2 = 'false', c3 = 'false', c5 = 'false', c6 = 'false', c7 = 'false', c8 = 'false', c9 = 'false'; -var s1 = 'true', s2 = 'false', s3 = 'false', s4 = 'false', s5 = 'false', s6 = 'false', s7 = 'false', s8 = 'false'; -var s9 = 'false', s10 = 'false', s11 = 'false', s12 = 'false', m1 = 'true', m2 = 'false', m3 = 'false', m4 = 'false'; -var m5 = 'false', m6 = 'false', devMenu = 'false'; -var clickable = "false", SelMusic = 1, musicTime = 0, theme = 0, FontSize = 2; - -var body = document.getElementById("body"), navbar = document.getElementById("navbar"), group = document.getElementById("group"); -var group1 = document.getElementById("group1"), group2 = document.getElementById("group2"), uppcont = document.getElementById("upper-container"); - -// descomentar al desplegar -//document.oncontextmenu = function(){return false} -//document.ondragstart = function(){return false} -//document.onselectstart = function(){return false} -//document.onmousedown = function() {return false} - - -function PrintChanges() -{ - pointsS.innerHTML = points + ' pts.'; - dogeCoinsS.innerHTML = dogeCoins; - generalCounter.innerHTML = totalCount; - maxCounter.innerHTML = maxCount; - thisCounter.innerHTML = thisCount; -} - -function PrintChangesS() -{ - pointsS.innerHTML = points + ' pts.'; - dogeCoinsS.innerHTML = dogeCoins; -} - -function ClickCheems() -{ - if (clickable == "true") { - PlaySound(SelSound); - img.classList.add('full-size'); - img.setAttribute('src', 'img/hit/'+Selcheems+'.png'); - SaveCountChanges(); - PrintChanges(); - } -} - -function NoClick() { - return; -} - -function LoadTheme() { - theme = parseInt(localStorage.getItem("CheemsAppLiActTheme")); - switch (theme) { - case 0: - body.classList.remove("dark-theme"); - body.classList.add("light-theme"); - navbar.classList.remove("dark-theme"); - navbar.classList.add("light-theme"); - try { - uppcont.classList.remove("dark-theme"); - uppcont.classList.add("light-theme"); - } catch (error) {} - try { - group.classList.remove("dark-theme"); - group.classList.add("light-theme"); - } catch (error) {} - try { - group1.classList.remove("dark-theme"); - group1.classList.add("light-theme"); - } catch (error) {} - try { - group2.classList.remove("dark-theme"); - group2.classList.add("light-theme"); - } catch (error) {} - break; - case 1: - break; - case 2: - body.classList.remove("dark-theme"); - body.classList.add("contrast-theme"); - navbar.classList.remove("dark-theme"); - navbar.classList.add("contrast-theme"); - try { - uppcont.classList.remove("dark-theme"); - uppcont.classList.add("contrast-theme"); - } catch (error) {} - try { - group.classList.remove("dark-theme"); - group.classList.add("contrast-theme"); - } catch (error) {} - try { - group1.classList.remove("dark-theme"); - group1.classList.add("contrast-theme"); - } catch (error) {} - try { - group2.classList.remove("dark-theme"); - group2.classList.add("contrast-theme"); - } catch (error) {} - break; - default: - theme = 0; - localStorage.setItem("CheemsAppLiActTheme", theme); - Redirect("index.html"); - break; - } -} - -function SwitchTheme(themeI) { - theme = themeI; - localStorage.setItem("CheemsAppLiActTheme", theme); - Redirect("settings.html"); -} - -function LoadAccesibility() { - FontSize = parseInt(localStorage.getItem("CheemsAppLiFontSize")); - switch (FontSize) { - case 0: - body.classList.remove("text-smaller", "text-small", "text-normal", "text-big", "text-max"); - body.classList.add("text-smaller"); - try { - pointsS.classList.remove("text-smaller", "text-small", "text-normal", "text-big", "text-max"); - pointsS.classList.add("text-smaller"); - } catch (error) {} - try { - dogeCoinsS.classList.remove("text-smaller", "text-small", "text-normal", "text-big", "text-max"); - dogeCoinsS.classList.add("text-smaller"); - } catch (error) {} - break; - case 1: - body.classList.remove("text-smaller", "text-small", "text-normal", "text-big", "text-max"); - body.classList.add("text-small"); - try { - pointsS.classList.remove("text-smaller", "text-small", "text-normal", "text-big", "text-max"); - pointsS.classList.add("text-small"); - } catch (error) {} - try { - dogeCoinsS.classList.remove("text-smaller", "text-small", "text-normal", "text-big", "text-max"); - dogeCoinsS.classList.add("text-small"); - } catch (error) {} - break; - case 2: - body.classList.remove("text-smaller", "text-small", "text-normal", "text-big", "text-max"); - body.classList.add("text-normal"); - try { - pointsS.classList.remove("text-smaller", "text-small", "text-normal", "text-big", "text-max"); - pointsS.classList.add("text-normal"); - } catch (error) {} - try { - dogeCoinsS.classList.remove("text-smaller", "text-small", "text-normal", "text-big", "text-max"); - dogeCoinsS.classList.add("text-normal"); - } catch (error) {} - break; - case 3: - body.classList.remove("text-smaller", "text-small", "text-normal", "text-big", "text-max"); - body.classList.add("text-big"); - try { - pointsS.classList.remove("text-smaller", "text-small", "text-normal", "text-big", "text-max"); - pointsS.classList.add("text-big"); - } catch (error) {} - try { - dogeCoinsS.classList.remove("text-smaller", "text-small", "text-normal", "text-big", "text-max"); - dogeCoinsS.classList.add("text-big"); - } catch (error) {} - break; - case 4: - body.classList.remove("text-smaller", "text-small", "text-normal", "text-big", "text-max"); - body.classList.add("text-max"); - try { - pointsS.classList.remove("text-smaller", "text-small", "text-normal", "text-big", "text-max"); - pointsS.classList.add("text-max"); - } catch (error) {} - try { - dogeCoinsS.classList.remove("text-smaller", "text-small", "text-normal", "text-big", "text-max"); - dogeCoinsS.classList.add("text-max"); - } catch (error) {} - break; - default: - FontSize = 2; - localStorage.setItem("CheemsAppLiFontSize", FontSize); - Redirect("index.html"); - } -} - -function SetAccesibility(size) { - FontSize = size; - localStorage.setItem("CheemsAppLiFontSize", FontSize); - Redirect("settings.html"); -} - -function Redirect(url) { - KeepMusic(); - window.location.href = url; -} - -function ChooseByTheme() { - switch (theme) { - case 0: - return "light-theme"; - case 1: - return "dark-theme"; - case 2: - return "contrast-theme"; - } -} \ No newline at end of file diff --git a/legacy_js/js/main.js b/legacy_js/js/main.js deleted file mode 100644 index ddf6f94..0000000 --- a/legacy_js/js/main.js +++ /dev/null @@ -1,10 +0,0 @@ -setInterval(() => { - if (img.classList.contains('full-size')) - { - img.classList.remove('full-size'); - } - if (img.getAttribute('src') == ('img/hit/'+Selcheems+'.png') || img.getAttribute('src') == 'img/locked-cheems.png') - { - img.setAttribute('src', 'img/cheems/'+Selcheems+'.png'); - } -}, 1500); \ No newline at end of file diff --git a/legacy_js/js/offlineMode.js b/legacy_js/js/offlineMode.js deleted file mode 100644 index 66a0326..0000000 --- a/legacy_js/js/offlineMode.js +++ /dev/null @@ -1,159 +0,0 @@ -function sleep(ms) { - return new Promise(resolve => setTimeout(resolve, ms)); -} - -async function DownloadImages() { - IMG = document.getElementById("loadableIMG"); - IMGLabel = document.getElementById("process-images"); - images = [ - "img/cheems/3d.png", - "img/cheems/adult.png", - "img/cheems/black.png", - "img/cheems/elegant.png", - "img/cheems/kid.png", - "img/cheems/little.png", - "img/cheems/mamado.png", - "img/cheems/normal.png", - "img/cheems/pixelart.png", - "img/hit/3d.png", - "img/hit/adult.png", - "img/hit/black.png", - "img/hit/elegant.png", - "img/hit/kid.png", - "img/hit/little.png", - "img/hit/mamado.png", - "img/hit/normal.png", - "img/hit/pixelart.png", - "img/dogecoin-min.png", - "img/dogecoin.png", - "img/locked-cheems.png", - "img/icons/application-svgrepo-com.svg", - "img/icons/back.png", - "img/icons/black-music-svgrepo-com.svg", - "img/icons/cart.png", - "img/icons/earphone-svgrepo-com.svg", - "img/icons/front-page-svgrepo-com.svg", - "img/icons/link-svgrepo-com.svg", - "img/icons/lock-keyhole-minimalistic-svgrepo-com.svg", - "img/icons/lock-keyhole-minimalistic-unlocked-svgrepo-com.svg", - "img/icons/menu-svgrepo-com.svg", - "img/icons/music-svgrepo-com.svg", - "img/icons/personal-svgrepo-com.svg", - "img/icons/picture-svgrepo-com.svg", - "img/icons/play-svgrepo-com.svg", - "img/icons/report-svgrepo-com.svg", - "img/icons/set-up-svgrepo-com.svg", - "img/icons/shopping-svgrepo-com.svg", - "img/icons/sound-svgrepo-com.svg", - "img/icons/the-internet-svgrepo-com.svg", - "img/icons/trophy-svgrepo-com.svg", - "img/icons/volume-cross-svgrepo-com.svg", - "img/icons/volume-loud-svgrepo-com.svg", - "img/icons/volume-small-svgrepo-com.svg" - ]; - IMGLabel.innerHTML = "Descargando Imagenes..."; - for (i = 0; i < images.length; i++) { - IMG.src = images[i]; - console.log(images[i]); - await sleep(250); - } - IMGLabel.innerHTML = "Imagenes Descargadas!!!"; - IMG.src = "img/locked-cheems.png"; -} - -async function DownloadScripts() { - const resources = [ - "index.html", - "game.html", - "closet.html", - "comming_soon.html", - "dev.html", - "download-repos.html", - "menu.html", - "settings.html", - "js/buttons.js", - "js/functions.js", - "index.js", - "main.js", - "offlineMode.js", - "SoundDefinitions.js", - "css/index.css", - "licences/electro-electro-summer-positive-party-141081-license.txt", - "licences/futuro-bajo-titanium-170190-license.txt", - "licences/futuro-bajo-trap-future-bass-royalty-free-music-167020-license.txt", - "licences/guitarra-solista-separation-185196-license.txt" - ]; - const container = document.getElementById("resource-container"); - const label = document.getElementById("process-resources"); - - label.innerHTML = "Descargando recursos..."; - - const resourceMap = {}; - - for (let i = 0; i < resources.length; i++) { - const resourceUrl = resources[i]; - const extension = resourceUrl.split('.').pop(); - let element; - - switch (extension) { - case 'css': - element = resourceMap['css'] || document.createElement('link'); - element.rel = 'stylesheet'; - element.href = resourceUrl; - resourceMap['css'] = element; - break; - case 'js': - element = resourceMap['js'] || document.createElement('script'); - element.src = resourceUrl; - resourceMap['js'] = element; - break; - case 'html': - case 'txt': - element = resourceMap['html'] || document.createElement('object'); - element.data = resourceUrl; - resourceMap['html'] = element; - break; - default: - console.error(`Tipo de archivo no soportado: ${extension}`); - continue; - } - container.innerHTML = ''; - container.appendChild(element); - container.innerHTML = `

${resourceUrl}

`+container.innerHTML; - - console.log(`Descargando ${resourceUrl}`); - await sleep(250); - } - container.innerHTML = 'Contenedor de scripts...'; - label.innerHTML = "Recursos descargados!"; -} - -async function DownloadSounds() { - SND = document.getElementById("loadableSound"); - SNDLabel = document.getElementById("process-sounds"); - sounds = [ - "sound/discord-connect.ogg", - "sound/discord-disconnect.ogg", - "sound/discord-msg.ogg", - "sound/hello.ogg", - "sound/hit-minecraft.ogg", - "sound/hit.ogg", - "sound/hurt-minecraft.ogg", - "sound/hurt-roblox.ogg", - "sound/levelup1.ogg", - "sound/levelup2.ogg", - "sound/no.ogg", - "sound/pato.ogg", - "sound/peluche.ogg", - "sound/splat.ogg", - "sound/windows-error.ogg" - ]; - SNDLabel.innerHTML = "Descargando Efectos de sonido..."; - for (i = 0; i < sounds.length; i++) { - SND.src = sounds[i]; - console.log(sounds[i]); - await sleep(250); - } - SNDLabel.innerHTML = "Efectos de sonido Descargados!!!"; - SND.src = ""; -} \ No newline at end of file diff --git a/legacy_js/manifest.json b/legacy_js/manifest.json deleted file mode 100644 index eb26abb..0000000 --- a/legacy_js/manifest.json +++ /dev/null @@ -1,64 +0,0 @@ -{ -"name": "CheemsAppLi", -"short_name": "Cheems App Li", -"start_url": "/", -"display": "standalone", -"description": "Cheems Bonk Game", -"lang": "es", -"dir": "auto", -"theme_color": "#f7ce45", -"background_color": "#8a4c06", -"orientation": "any", -"icons": [ - { - "src": "/img/icon-512x512.png", - "sizes": "512x512", - "type": "image/png", - "purpose": "maskable" - }, - { - "src": "/img/icon-192x192.png", - "sizes": "192x192", - "type": "image/png", - "purpose": "any" - } -], -"screenshots": [ - { - "src": "/img/capture1.png", - "sizes": "680x685", - "type": "image/png", - "description": "A screenshot of the main game" - }, - { - "src": "/img/capture2.png", - "sizes": "680x684", - "type": "image/png", - "description": "A screenshot of the main game hitting to cheems" - }, - { - "src": "/img/capture3.png", - "sizes": "680x685", - "type": "image/png", - "description": "A screenshot of the closet menu" - } -], -"related_applications": [ - { - "platform":"windows", - "url": "/" - }, - { - "platform":"android", - "url": "/" - } -], -"prefer_related_applications": false, -"shortcuts": [ - { - "name":"The name you would like to be displayed for your shortcut", - "url":"The url you would like to open when the user chooses this shortcut. This must be a URL local to your PWA. For example: If my start_url is /, this URL must be something like /shortcut", - "description":"A description of the functionality of this shortcut" - } -] -} \ No newline at end of file diff --git a/legacy_js/menu.html b/legacy_js/menu.html deleted file mode 100644 index adaed78..0000000 --- a/legacy_js/menu.html +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - Menu - - - - - - -


-
-
-
- -

Ajustes

-
-
- -

Descarga de recursos (Modo offline)

-
-
- -

Tienda

-
-
- -

Personalización

-
-
- -

Estadisticas

-
-
- -

Licencias

-
- -
-
- - - - - \ No newline at end of file diff --git a/legacy_js/pwabuilder-adv-sw.js b/legacy_js/pwabuilder-adv-sw.js deleted file mode 100644 index 8a684cf..0000000 --- a/legacy_js/pwabuilder-adv-sw.js +++ /dev/null @@ -1,3 +0,0 @@ - - import { precacheAndRoute } from 'workbox-precaching/precacheAndRoute'; - precacheAndRoute([{"revision":"ef6543bdb0cf2dd8795f3cf1a7d3976d","url":"closet.html"},{"revision":"efc3e963d181a74e0e25c38788e3f46a","url":"comming_soon.html"},{"revision":"72fd1f431ce9e991a916140c27f5542f","url":"css/index.css"},{"revision":"6830c3b71e63e8a213a627fd61d06673","url":"dev.html"},{"revision":"b3f792d325415b2e3668aa07339146a4","url":"game.html"},{"revision":"2c2c35b1eec0bbce33cdca4611b871e6","url":"index.html"},{"revision":"ad2e6a036904d2e87311269535301c2b","url":"js/buttons.js"},{"revision":"314b55ccdea0cae64c1ff13f18626382","url":"js/functions.js"},{"revision":"92aaf644de44e9a13d16cce2b15f2326","url":"js/index.js"},{"revision":"26f24de9ab6e2d64c6f3c755ab8e2fe9","url":"js/main.js"},{"revision":"ec123b77066b3235d861afa28ca5460a","url":"js/SoundDefinitions.js"},{"revision":"5f79509418774d8baad55eacc25339f2","url":"menu.html"},{"revision":"228f41e118888ecc0359da31e8d49af6","url":"settings.html"},{"revision":"ff5da0b292612186186be55009060875","url":"sw.js"}]); diff --git a/legacy_js/settings.html b/legacy_js/settings.html deleted file mode 100644 index a33b6f3..0000000 --- a/legacy_js/settings.html +++ /dev/null @@ -1,82 +0,0 @@ - - - - - - - Ajustes - - - - - - -


-
-
-
- -

Volumen de la música

-
-
- -
-
- -

Volumen de los efectos

-
-
- -
-
- Tema de la app (colores): -
-
-
- Modo claro -
-
- Modo Oscuro -
-

- Modo Alto contraste -

-
-
- Tamaño de la fuente: -
-
-
- Small -
-
- Small -
-
- Normal -
-
- Big -
-
- Biggest -
-
-
-
- - - - - - \ No newline at end of file diff --git a/legacy_js/sw.js b/legacy_js/sw.js deleted file mode 100644 index a95d236..0000000 --- a/legacy_js/sw.js +++ /dev/null @@ -1,93 +0,0 @@ - - // Based off of https://github.com/pwa-builder/PWABuilder/blob/main/docs/sw.js - - /* - Welcome to our basic Service Worker! This Service Worker offers a basic offline experience - while also being easily customizeable. You can add in your own code to implement the capabilities - listed below, or change anything else you would like. - - - Need an introduction to Service Workers? Check our docs here: https://docs.pwabuilder.com/#/home/sw-intro - Want to learn more about how our Service Worker generation works? Check our docs here: https://docs.pwabuilder.com/#/studio/existing-app?id=add-a-service-worker - - Did you know that Service Workers offer many more capabilities than just offline? - - Background Sync: https://microsoft.github.io/win-student-devs/#/30DaysOfPWA/advanced-capabilities/06 - - Periodic Background Sync: https://web.dev/periodic-background-sync/ - - Push Notifications: https://microsoft.github.io/win-student-devs/#/30DaysOfPWA/advanced-capabilities/07?id=push-notifications-on-the-web - - Badges: https://microsoft.github.io/win-student-devs/#/30DaysOfPWA/advanced-capabilities/07?id=application-badges - */ - - const HOSTNAME_WHITELIST = [ - self.location.hostname, - 'fonts.gstatic.com', - 'fonts.googleapis.com', - 'cdn.jsdelivr.net' - ] - - // The Util Function to hack URLs of intercepted requests - const getFixedUrl = (req) => { - var now = Date.now() - var url = new URL(req.url) - - // 1. fixed http URL - // Just keep syncing with location.protocol - // fetch(httpURL) belongs to active mixed content. - // And fetch(httpRequest) is not supported yet. - url.protocol = self.location.protocol - - // 2. add query for caching-busting. - // Github Pages served with Cache-Control: max-age=600 - // max-age on mutable content is error-prone, with SW life of bugs can even extend. - // Until cache mode of Fetch API landed, we have to workaround cache-busting with query string. - // Cache-Control-Bug: https://bugs.chromium.org/p/chromium/issues/detail?id=453190 - if (url.hostname === self.location.hostname) { - url.search += (url.search ? '&' : '?') + 'cache-bust=' + now - } - return url.href - } - - /** - * @Lifecycle Activate - * New one activated when old isnt being used. - * - * waitUntil(): activating ====> activated - */ - self.addEventListener('activate', event => { - event.waitUntil(self.clients.claim()) - }) - - /** - * @Functional Fetch - * All network requests are being intercepted here. - * - * void respondWith(Promise r) - */ - self.addEventListener('fetch', event => { - // Skip some of cross-origin requests, like those for Google Analytics. - if (HOSTNAME_WHITELIST.indexOf(new URL(event.request.url).hostname) > -1) { - // Stale-while-revalidate - // similar to HTTP's stale-while-revalidate: https://www.mnot.net/blog/2007/12/12/stale - // Upgrade from Jake's to Surma's: https://gist.github.com/surma/eb441223daaedf880801ad80006389f1 - const cached = caches.match(event.request) - const fixedUrl = getFixedUrl(event.request) - const fetched = fetch(fixedUrl, { cache: 'no-store' }) - const fetchedCopy = fetched.then(resp => resp.clone()) - - // Call respondWith() with whatever we get first. - // If the fetch fails (e.g disconnected), wait for the cache. - // If there’s nothing in cache, wait for the fetch. - // If neither yields a response, return offline pages. - event.respondWith( - Promise.race([fetched.catch(_ => cached), cached]) - .then(resp => resp || fetched) - .catch(_ => { /* eat any errors */ }) - ) - - // Update the cache with the version we fetched (only for ok status) - event.waitUntil( - Promise.all([fetchedCopy, caches.open("pwa-cache")]) - .then(([response, cache]) => response.ok && cache.put(event.request, response)) - .catch(_ => { /* eat any errors */ }) - ) - } - }) diff --git a/ngsw-config.json b/ngsw-config.json index 1ac894a..98b3a6a 100644 --- a/ngsw-config.json +++ b/ngsw-config.json @@ -18,11 +18,17 @@ }, { "name": "assets", - "installMode": "lazy", + "installMode": "prefetch", "updateMode": "prefetch", "resources": { "files": [ - "/**/*.(svg|cur|jpg|jpeg|png|apng|webp|avif|gif|otf|ttf|woff|woff2|txt|json|xml|csv|ico)" + "/**/*.(svg|cur|jpg|jpeg|png|apng|webp|avif|gif|otf|ttf|woff|woff2|txt|json|xml|csv|ico|ogg|mp3|wav|m4a|lang)", + "/closet.json", + "/items/*.json", + "/lang/*.lang", + "/sound/**/*", + "/img/**/*", + "/games/**/*" ] } } diff --git a/package.json b/package.json index bd85e19..8c08fed 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,9 @@ "ng": "ng", "start": "ng serve", "build": "ng build", + "build:mobile": "ng build && npx cap sync", + "build:desktop": "ng build && npx cap copy @capacitor-community/electron", + "electron:start": "npx cap open @capacitor-community/electron", "watch": "ng build --watch --configuration development", "test": "ng test" }, @@ -19,7 +22,12 @@ "@angular/platform-browser-dynamic": "^19.2.14", "@angular/router": "^19.2.14", "@angular/service-worker": "^19.2.14", + "@capacitor/core": "^8.5.0", + "@types/matter-js": "^0.20.2", + "@types/three": "^0.185.1", + "matter-js": "^0.20.0", "rxjs": "~7.8.0", + "three": "^0.185.1", "tslib": "^2.3.0", "zone.js": "~0.15.1" }, @@ -27,6 +35,10 @@ "@angular-devkit/build-angular": "^19.2.14", "@angular/cli": "^19.2.14", "@angular/compiler-cli": "^19.2.14", + "@capacitor-community/electron": "^5.0.1", + "@capacitor/android": "^8.5.0", + "@capacitor/cli": "^8.5.0", + "@capacitor/ios": "^8.5.0", "@types/jasmine": "~5.1.0", "jasmine-core": "~5.1.0", "karma": "~6.4.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..e57b8e3 --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,10272 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + '@angular/animations': + specifier: ^19.2.14 + version: 19.2.25(@angular/common@19.2.25(@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1)) + '@angular/common': + specifier: ^19.2.14 + version: 19.2.25(@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) + '@angular/compiler': + specifier: ^19.2.14 + version: 19.2.25 + '@angular/core': + specifier: ^19.2.14 + version: 19.2.25(rxjs@7.8.2)(zone.js@0.15.1) + '@angular/forms': + specifier: ^19.2.14 + version: 19.2.25(@angular/common@19.2.25(@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@19.2.25(@angular/animations@19.2.25(@angular/common@19.2.25(@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@19.2.25(@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2) + '@angular/platform-browser': + specifier: ^19.2.14 + version: 19.2.25(@angular/animations@19.2.25(@angular/common@19.2.25(@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@19.2.25(@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1)) + '@angular/platform-browser-dynamic': + specifier: ^19.2.14 + version: 19.2.25(@angular/common@19.2.25(@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/compiler@19.2.25)(@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@19.2.25(@angular/animations@19.2.25(@angular/common@19.2.25(@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@19.2.25(@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1))) + '@angular/router': + specifier: ^19.2.14 + version: 19.2.25(@angular/common@19.2.25(@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@19.2.25(@angular/animations@19.2.25(@angular/common@19.2.25(@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@19.2.25(@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2) + '@angular/service-worker': + specifier: ^19.2.14 + version: 19.2.25(@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) + '@capacitor/core': + specifier: ^8.5.0 + version: 8.5.0 + '@types/matter-js': + specifier: ^0.20.2 + version: 0.20.2 + '@types/three': + specifier: ^0.185.1 + version: 0.185.1 + matter-js: + specifier: ^0.20.0 + version: 0.20.0 + rxjs: + specifier: ~7.8.0 + version: 7.8.2 + three: + specifier: ^0.185.1 + version: 0.185.1 + tslib: + specifier: ^2.3.0 + version: 2.8.1 + zone.js: + specifier: ~0.15.1 + version: 0.15.1 + devDependencies: + '@angular-devkit/build-angular': + specifier: ^19.2.14 + version: 19.2.27(@angular/compiler-cli@19.2.25(@angular/compiler@19.2.25)(supports-color@8.1.1)(typescript@5.5.4))(@angular/compiler@19.2.25)(@angular/service-worker@19.2.25(@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@types/node@26.1.2)(chokidar@4.0.3)(debug@4.4.3(supports-color@8.1.1))(jiti@1.21.7)(karma@6.4.4(debug@4.4.3(supports-color@8.1.1))(supports-color@8.1.1))(supports-color@8.1.1)(typescript@5.5.4)(vite@6.4.2(@types/node@26.1.2)(jiti@1.21.7)(less@4.2.2)(sass@1.85.0)(terser@5.39.0)) + '@angular/cli': + specifier: ^19.2.14 + version: 19.2.27(@types/node@26.1.2)(chokidar@4.0.3)(supports-color@8.1.1) + '@angular/compiler-cli': + specifier: ^19.2.14 + version: 19.2.25(@angular/compiler@19.2.25)(supports-color@8.1.1)(typescript@5.5.4) + '@capacitor-community/electron': + specifier: ^5.0.1 + version: 5.0.1(supports-color@8.1.1) + '@capacitor/android': + specifier: ^8.5.0 + version: 8.5.0(@capacitor/core@8.5.0) + '@capacitor/cli': + specifier: ^8.5.0 + version: 8.5.0(supports-color@8.1.1) + '@capacitor/ios': + specifier: ^8.5.0 + version: 8.5.0(@capacitor/core@8.5.0) + '@types/jasmine': + specifier: ~5.1.0 + version: 5.1.15 + jasmine-core: + specifier: ~5.1.0 + version: 5.1.2 + karma: + specifier: ~6.4.0 + version: 6.4.4(debug@4.4.3(supports-color@8.1.1))(supports-color@8.1.1) + karma-chrome-launcher: + specifier: ~3.2.0 + version: 3.2.0 + karma-coverage: + specifier: ~2.2.0 + version: 2.2.1(supports-color@8.1.1) + karma-jasmine: + specifier: ~5.1.0 + version: 5.1.0(karma@6.4.4(debug@4.4.3(supports-color@8.1.1))(supports-color@8.1.1)) + karma-jasmine-html-reporter: + specifier: ~2.1.0 + version: 2.1.0(jasmine-core@5.1.2)(karma-jasmine@5.1.0(karma@6.4.4(debug@4.4.3(supports-color@8.1.1))(supports-color@8.1.1)))(karma@6.4.4(debug@4.4.3(supports-color@8.1.1))(supports-color@8.1.1)) + typescript: + specifier: ~5.5.2 + version: 5.5.4 + +packages: + + '@ampproject/remapping@2.3.0': + resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} + engines: {node: '>=6.0.0'} + + '@angular-devkit/architect@0.1902.27': + resolution: {integrity: sha512-I2YW4Zn1818toEGKPPcbv8qqglegNnWT4A4GM28LPRg4rOYwPkZzy3PAB7EIJEwZIDQgz2I+Oy0pc56BWcFVUw==} + engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} + + '@angular-devkit/build-angular@19.2.27': + resolution: {integrity: sha512-63dLzZeRAZiDOWegZHDG1L3Su4m7tfh2n4uV4fXhJYQeyblAQIrmz/dsyjn2cwR021neDbteLCn7MeysKj47/g==} + engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} + peerDependencies: + '@angular/compiler-cli': ^19.0.0 || ^19.2.0-next.0 + '@angular/localize': ^19.0.0 || ^19.2.0-next.0 + '@angular/platform-server': ^19.0.0 || ^19.2.0-next.0 + '@angular/service-worker': ^19.0.0 || ^19.2.0-next.0 + '@angular/ssr': ^19.2.27 + '@web/test-runner': ^0.20.0 + browser-sync: ^3.0.2 + jest: ^29.5.0 + jest-environment-jsdom: ^29.5.0 + karma: ^6.3.0 + ng-packagr: ^19.0.0 || ^19.2.0-next.0 + protractor: ^7.0.0 + tailwindcss: ^2.0.0 || ^3.0.0 || ^4.0.0 + typescript: '>=5.5 <5.9' + peerDependenciesMeta: + '@angular/localize': + optional: true + '@angular/platform-server': + optional: true + '@angular/service-worker': + optional: true + '@angular/ssr': + optional: true + '@web/test-runner': + optional: true + browser-sync: + optional: true + jest: + optional: true + jest-environment-jsdom: + optional: true + karma: + optional: true + ng-packagr: + optional: true + protractor: + optional: true + tailwindcss: + optional: true + + '@angular-devkit/build-webpack@0.1902.27': + resolution: {integrity: sha512-O3v9/x2+yJrXJIBG0x7o/EMSjRjJqWcJb8u5lHFKut9qCpQJ6oDeoxqGM5SWXIk4RGr3qbAsOragkR2Lsq0cRQ==} + engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} + peerDependencies: + webpack: ^5.30.0 + webpack-dev-server: ^5.0.2 + + '@angular-devkit/core@19.2.27': + resolution: {integrity: sha512-3amNzoCVSKd7ah6l6lBQL4onwwJvqvam7FMoQBILrxtW5LB5ezh8gMSPuA4zJjKjoRzf9uoWdlzqv/84I52xZA==} + engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} + peerDependencies: + chokidar: ^4.0.0 + peerDependenciesMeta: + chokidar: + optional: true + + '@angular-devkit/schematics@19.2.27': + resolution: {integrity: sha512-/PZmyAlb2NGWPikRRuiWLdfHQd8Wrx6lX4HqvTcaDhlU43M3T0ud4PH2T3QDp7BzHYY92xtD8iPxX2asg67G1A==} + engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} + + '@angular/animations@19.2.25': + resolution: {integrity: sha512-1IE7wuC3ecAumb7ZQHCugV1jsSl93j0omX7BAWwwmM8C7Xo//fZcO/ad/IFfn0zV/VCBAhOAFBUKUIVAGpsylw==} + engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0} + peerDependencies: + '@angular/common': 19.2.25 + '@angular/core': 19.2.25 + + '@angular/build@19.2.27': + resolution: {integrity: sha512-kMcuTUxDcnTa+JF9SaxdY+b6pkGjtefxGp/VYblSbvlzQ1rVX4wH4V9LHHyXsTOxRRNGqRJ01g0Enhq1iA19mQ==} + engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} + peerDependencies: + '@angular/compiler': ^19.0.0 || ^19.2.0-next.0 + '@angular/compiler-cli': ^19.0.0 || ^19.2.0-next.0 + '@angular/localize': ^19.0.0 || ^19.2.0-next.0 + '@angular/platform-server': ^19.0.0 || ^19.2.0-next.0 + '@angular/service-worker': ^19.0.0 || ^19.2.0-next.0 + '@angular/ssr': ^19.2.27 + karma: ^6.4.0 + less: ^4.2.0 + ng-packagr: ^19.0.0 || ^19.2.0-next.0 + postcss: ^8.4.0 + tailwindcss: ^2.0.0 || ^3.0.0 || ^4.0.0 + typescript: '>=5.5 <5.9' + peerDependenciesMeta: + '@angular/localize': + optional: true + '@angular/platform-server': + optional: true + '@angular/service-worker': + optional: true + '@angular/ssr': + optional: true + karma: + optional: true + less: + optional: true + ng-packagr: + optional: true + postcss: + optional: true + tailwindcss: + optional: true + + '@angular/cli@19.2.27': + resolution: {integrity: sha512-npqpoV7Y49ggwUysXbRUDDmFRmwQdZ92nljtxX1yjakmwR93WdEq7NwqHEGODOAXo5NtPoEeBNc3InPtrLmh5g==} + engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} + hasBin: true + + '@angular/common@19.2.25': + resolution: {integrity: sha512-WteFLyfDPvilzpSGHk64bqowa4NnHdbjNl1xXeGr038fgTjp0l0NdiUPqeDtYT4pf5lWl6477pPoQN7o//NyyQ==} + engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0} + peerDependencies: + '@angular/core': 19.2.25 + rxjs: ^6.5.3 || ^7.4.0 + + '@angular/compiler-cli@19.2.25': + resolution: {integrity: sha512-IBBKRz6ua+y6bdcaUIpOPq7G/S4biJfcT1TCMD7wi+48wiKKSXj4J/8BN5fSjt+UozlHwya3B8z0XqnwO2ywZw==} + engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0} + hasBin: true + peerDependencies: + '@angular/compiler': 19.2.25 + typescript: '>=5.5 <5.9' + + '@angular/compiler@19.2.25': + resolution: {integrity: sha512-GGEeTTd/DV71E07K0u5753bxXozc6Z7iWaCZJDW7xiA7hdHCwrYBMz1PVUJAtXcxf4wTdiXQR48kw8/YHYnDAw==} + engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0} + + '@angular/core@19.2.25': + resolution: {integrity: sha512-j7/irbbdO4rmZfRXS+sphCerzgcRlpGFwxHc/76Ual+ckwJG0MPsNFkllz2SIEZzE1EZkmIunGrHbjeRBJjyvg==} + engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0} + peerDependencies: + rxjs: ^6.5.3 || ^7.4.0 + zone.js: ~0.15.0 + + '@angular/forms@19.2.25': + resolution: {integrity: sha512-lbuhZiuNKy8vcIHFSP7sOW5kfHSVDiVsXh2/+rWjqGklscfUG5cTK9F9d+k60CH24OhK0NgRKoCHiAK5zPQi2g==} + engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0} + peerDependencies: + '@angular/common': 19.2.25 + '@angular/core': 19.2.25 + '@angular/platform-browser': 19.2.25 + rxjs: ^6.5.3 || ^7.4.0 + + '@angular/platform-browser-dynamic@19.2.25': + resolution: {integrity: sha512-T6LK+NH6VR0bNKepN6urSHPE86OxbIMvgm855W06YjXvK7cMotPCC+N10zv7M8zQRZtQ7WBkY0EGpC8qLrao0g==} + engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0} + peerDependencies: + '@angular/common': 19.2.25 + '@angular/compiler': 19.2.25 + '@angular/core': 19.2.25 + '@angular/platform-browser': 19.2.25 + + '@angular/platform-browser@19.2.25': + resolution: {integrity: sha512-UF7cyBnMF3puA/cGy3MXbiPB2Rlw0Umf78XH664Iwqsb37A+TxqzOPaByXsNTIbpV6/h28yO3dMvDVFT3aOvOA==} + engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0} + peerDependencies: + '@angular/animations': 19.2.25 + '@angular/common': 19.2.25 + '@angular/core': 19.2.25 + peerDependenciesMeta: + '@angular/animations': + optional: true + + '@angular/router@19.2.25': + resolution: {integrity: sha512-IddC2vPiagB2jAsUrNuAr74p+OirWaroouvPkUjzPmyQ+12/0EsygHamsgUbsCVLXJKh72oqnD+xViN0AMguOA==} + engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0} + peerDependencies: + '@angular/common': 19.2.25 + '@angular/core': 19.2.25 + '@angular/platform-browser': 19.2.25 + rxjs: ^6.5.3 || ^7.4.0 + + '@angular/service-worker@19.2.25': + resolution: {integrity: sha512-NB4g5bA+f5Jx6UsLmEdrHUXLOQDtAjQqeM7JHRl7qXg/xESnNubNqM0VMKO1P5oqAjQ++5Vc1G3s59uOgHKnPw==} + engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0} + hasBin: true + peerDependencies: + '@angular/core': 19.2.25 + rxjs: ^6.5.3 || ^7.4.0 + + '@babel/code-frame@7.29.7': + resolution: {integrity: sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==} + engines: {node: '>=6.9.0'} + + '@babel/compat-data@7.29.7': + resolution: {integrity: sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==} + engines: {node: '>=6.9.0'} + + '@babel/core@7.26.10': + resolution: {integrity: sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==} + engines: {node: '>=6.9.0'} + + '@babel/core@7.26.9': + resolution: {integrity: sha512-lWBYIrF7qK5+GjY5Uy+/hEgp8OJWOD/rpy74GplYRhEauvbHDeFB8t5hPOZxCZ0Oxf4Cc36tK51/l3ymJysrKw==} + engines: {node: '>=6.9.0'} + + '@babel/core@7.29.7': + resolution: {integrity: sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==} + engines: {node: '>=6.9.0'} + + '@babel/generator@7.26.10': + resolution: {integrity: sha512-rRHT8siFIXQrAYOYqZQVsAr8vJ+cBNqcVAY6m5V8/4QqzaPl+zDBe6cLEPRDuNOUf3ww8RfJVlOyQMoSI+5Ang==} + engines: {node: '>=6.9.0'} + + '@babel/generator@7.29.7': + resolution: {integrity: sha512-DkXD5OJQaAQIdZ1bt3UZdEnHAn9Imd3IVBdX03UFe+ony9Ojw5pzr9YVKGDY1jt+Gcn/FnGkNf8r+Vj5NOJWtQ==} + engines: {node: '>=6.9.0'} + + '@babel/helper-annotate-as-pure@7.25.9': + resolution: {integrity: sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==} + engines: {node: '>=6.9.0'} + + '@babel/helper-annotate-as-pure@7.29.7': + resolution: {integrity: sha512-OoK6239jHPuSQOoS0kfTVKn0b/rVTk0seKq4Gd2UMLtmOVLjDC0ki3e+c90Trqv2gMfvJFqkiljrr568+qddiw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-compilation-targets@7.29.7': + resolution: {integrity: sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==} + engines: {node: '>=6.9.0'} + + '@babel/helper-create-class-features-plugin@7.29.7': + resolution: {integrity: sha512-IY3ZD9Tmooqr3TUhc3DUWxiuo8xx1DWLhd5M7hQ+ZWJamqM2BbalrBJb2MisSLoYorOj75U03qULCxQTY9r3hg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-create-regexp-features-plugin@7.29.7': + resolution: {integrity: sha512-907Uymvqgg1dwUA+7IGwFAOSYzQOuzPXKNJ1yxzwPffzkYFg2q2eHi1fIOs6sXkG9NbIUMunnUlkYsfRFNvomg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-define-polyfill-provider@0.6.8': + resolution: {integrity: sha512-47UwBLPpQi1NoWzLuHNjRoHlYXMwIJoBf7MFou6viC/sIHWYygpvr0B6IAyh5sBdA2nr2LPIRww8lfaUVQINBA==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + + '@babel/helper-globals@7.29.7': + resolution: {integrity: sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-member-expression-to-functions@7.29.7': + resolution: {integrity: sha512-j+7JYmk1JYDtACIGj0QJqqWZjoUpMoEikQGADMaHgCMCSDqd2+P32rfcibUNrGOMWrlzK1WJBdxrB3JJQZwWtg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-imports@7.29.7': + resolution: {integrity: sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-transforms@7.29.7': + resolution: {integrity: sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-optimise-call-expression@7.29.7': + resolution: {integrity: sha512-+kmGVjcT9RGYzoDwdwEqEvGgKe3BYq+O1iGzjFubaNgZHwYHP6lsF2Yghf4kEuv9BV7tYDZ913aBW9am6YKong==} + engines: {node: '>=6.9.0'} + + '@babel/helper-plugin-utils@7.29.7': + resolution: {integrity: sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-remap-async-to-generator@7.29.7': + resolution: {integrity: sha512-16AMiW26DbXWBbr3B8wNozKM0ydMLB892vaOaJW/fPJdnT8vJk5sdkQcU/isqUxyCE0cEoa8wZOcbgDuC4b6Og==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-replace-supers@7.29.7': + resolution: {integrity: sha512-atfGXWSeCiF4DnKZIfmJfQRkSw9b9gNNXR1kqKjbhG4pGYCOnkp8OcTB8E3NXjBu8NpheSnOeNKz8KT7UNFTmQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-skip-transparent-expression-wrappers@7.29.7': + resolution: {integrity: sha512-brcMGQaVzIeUb+6/bs1Av0f8YuNNjKY2JyvfRCsFuFsdKccEQ5Ges2y74D74NZ1Rz8lKJ9ksJkfqwQFJ/iNEyQ==} + engines: {node: '>=6.9.0'} + + '@babel/helper-split-export-declaration@7.24.7': + resolution: {integrity: sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-string-parser@7.29.7': + resolution: {integrity: sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.29.7': + resolution: {integrity: sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-option@7.29.7': + resolution: {integrity: sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-wrap-function@7.29.7': + resolution: {integrity: sha512-iES0Skag9ERIF68aXadpO6dbXa03mNWK3sEqJaMnLNs/eC3l0lkImdfoy6Y09/SfkpawdAB4RjQ7PVA7TcVGdw==} + engines: {node: '>=6.9.0'} + + '@babel/helpers@7.29.7': + resolution: {integrity: sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==} + engines: {node: '>=6.9.0'} + + '@babel/parser@7.29.7': + resolution: {integrity: sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.29.7': + resolution: {integrity: sha512-j8SrR0zLZrRsC09DlszEx8FpMiwukKffYXMK0d5LmOglO7vGG6sz/BR/20yHqWH+Lnn31JTt2PE3hIWNgM2J6w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-bugfix-safari-class-field-initializer-scope@7.29.7': + resolution: {integrity: sha512-r8j8escF+U2FUHo0KOhPUdMzUO+jp9fInva6+ACVAF3Y97Ev+5iNZwiqTghmzNeWwDkOPlYuTcfb1vDaoZKmAQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.29.7': + resolution: {integrity: sha512-GE1TFSiuFeGsCxmYXZl8HwoPrVlwe4rHPFE8weieGKZqnDORK+Ar3vgWMgW+AOxQ6/2TgLSKx9p6W7O4rC6qgQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.29.7': + resolution: {integrity: sha512-QQt9qKHZ2sg/kivaLr7lnQr8HVrQDdBNSfCsTjiDxRuX/K5ORyKq+Bu8Xr0cDE3Dfkv0cw28Ve0EKyKMvulkOw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.13.0 + + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.29.7': + resolution: {integrity: sha512-pn6QacGLgvCcwc+syUhKE/qSjV2D1IHDB84RNxWYSt1mW3K/SCtjinZ2p0cETJxAWBjPy3K/1lHwG5BjjPxNlw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2': + resolution: {integrity: sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-import-assertions@7.29.7': + resolution: {integrity: sha512-/An1OCBN93thpBAGyfsK2pcf0jvju1SAtKkL2Ny++B5Sy6sqgzXDQH1cZxWbF96Wuk+bn41MDA9bLd4VVAw6rw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-import-attributes@7.26.0': + resolution: {integrity: sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-import-attributes@7.29.7': + resolution: {integrity: sha512-zGYcYfq/WmZ4V+kBIXQon9dSSc8ircGZqw9ZaNhhGj9nZkeBu1jHLBDQqYYi5WA9uawvA2sIMbry2nCFhf5Djg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-unicode-sets-regex@7.18.6': + resolution: {integrity: sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-transform-arrow-functions@7.29.7': + resolution: {integrity: sha512-N7zArUXWzAMzm+/N0uPBeVB3Fam5lMxtUwMmDK5f/IBBS7a7p1qeUoxd/6CckXoxUdgsntq1Dh8xNW06maZbDQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-async-generator-functions@7.26.8': + resolution: {integrity: sha512-He9Ej2X7tNf2zdKMAGOsmg2MrFc+hfoAhd3po4cWfo/NWjzEAKa0oQruj1ROVUdl0e6fb6/kE/G3SSxE0lRJOg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-async-to-generator@7.25.9': + resolution: {integrity: sha512-NT7Ejn7Z/LjUH0Gv5KsBCxh7BH3fbLTV0ptHvpeMvrt3cPThHfJfst9Wrb7S8EvJ7vRTFI7z+VAvFVEQn/m5zQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-block-scoped-functions@7.29.7': + resolution: {integrity: sha512-cUSmjh72N+rN4PrkFlN1dJwNCwjVp5d38/CQrEsFggkD10UiFlBFgdH3tv5dNsLuHY+3S8db2xCHjhZcv5WgvA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-block-scoping@7.29.7': + resolution: {integrity: sha512-ONyr4+AZhKh8yKWInVxU9AXA9EbsyeLcL6V0dJy6M2/62vuvpGm29zzuymbTpdc451GEpDIdAyPLP3r+P61yKQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-class-properties@7.29.7': + resolution: {integrity: sha512-GtcpjFvanPfzNQi3eTitsCqtRRmmqzpy/A+yhTR1HaZo1Ly3EA8ZXxlPyHdR8/IuRMYc3E4wdGBewB2QKQjAaA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-class-static-block@7.29.7': + resolution: {integrity: sha512-kibJgmEdX2iMwsHY2tSZNDgj8PwIlCQz7FK9KuGKO8zsuoUwSEhoNnNVp/emKWrbY4HeO6kkXfdMqRKKKXBm2A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.12.0 + + '@babel/plugin-transform-classes@7.29.7': + resolution: {integrity: sha512-qV0OGGBVacduzQHE649JyCneOFI/maT+YKsO+K4Yi3xv2wTPNjM/W2o2gdzMwEAZz7fXNTHAe0NcSg30bIN69g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-computed-properties@7.29.7': + resolution: {integrity: sha512-RK7/IyU5phpuCdBAuig5VkzG/EnbDaui5SQGdU9BFrHdV+mV4cUjLMQ9lJDjLNtWHsqtiefpGZUXQP2BiTYMsA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-destructuring@7.29.7': + resolution: {integrity: sha512-iPX8aD6H9zV5s7ZsqTdNocPN/MGQ5sSMnElKrktxjJRMnB2jN/1p2+R7GkfD6CAYoVFqy5A4XnSIUeGgJzIWpg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-dotall-regex@7.29.7': + resolution: {integrity: sha512-3qc18hsD2RdZiyJNDNc7HQpv6xbncwh8FYtxNFFzclSyh/trPD9KkVR9BDECUjDLvb7yJVF15GfYUuC+LMkkiQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-duplicate-keys@7.29.7': + resolution: {integrity: sha512-6IvRRriEMqnBwD6chtxdLpMYCHWEzN+oL5cyQtjykya19UgzbmKhxmhZgKC/LHxS2nYr9Q/qYPZ5Lr6jOL9+yQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.29.7': + resolution: {integrity: sha512-2wiIyo2BjtgU7HufSeDnL9L2O7zr8jmhFKuSr65VpRkUiRKRNpb0mdlk56+XPPKoIrfHqzbMuglDvZun0RISsA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-transform-dynamic-import@7.29.7': + resolution: {integrity: sha512-giOlEm/EFjfjr+te9NsdjkUo2v4f8rS/SXPumRVHAtbNcyNlvtREkU1dZzaIDclNpnaVhlCqRdFKhJBjBikzLg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-exponentiation-operator@7.29.7': + resolution: {integrity: sha512-zFpMOTLZBdW5LfObqcSbL6kefg4R4eLdmvS0wbN9M6D5Mym/sKm9toOoWyVOa+xDjvCnuWcHls2YonXwHvH3CQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-export-namespace-from@7.29.7': + resolution: {integrity: sha512-24B2nOy2TeJSMheqwPD4DDQOV/elLSIlKxjZt4i05H5AgdPdWR3n18HnNrcJ+j76WJd9gbwb9jPjNYUy6RautA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-for-of@7.29.7': + resolution: {integrity: sha512-zeSIHh0+E1Um1WJRXCFlHQYu2ieJNdivLLjlBEp+dIBu3S51n+SZZmIXjxnItw6pz56Cn+KvK68BIBVsxq2JiQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-function-name@7.29.7': + resolution: {integrity: sha512-otRWaHXE6fbAGkePvaj/kvs3HsqXfPhlnzwSOlnFgbqCPMd975dW+4wZ00WFBt+/YlBGcJwNrARQTOJOb4ZrIg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-json-strings@7.29.7': + resolution: {integrity: sha512-RRnE2+eon1rJAq8MnoF1b5kTpY1vU88twHcvcKMrsqP/jxIRqDVs9iJB5fqPuqyeFAW0wJo4MlUIPpQCq/aRsg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-literals@7.29.7': + resolution: {integrity: sha512-DZ/oLP21ZuWx1vKqnoNv6/tvEK48AQOBRai40CX9dTjGluvT/YZCyY3rryDtyUqCEoyNroy5KKPwX2iQCiRvyw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-logical-assignment-operators@7.29.7': + resolution: {integrity: sha512-A0H91hh6W8MFRkp5TqJmMr39jzGD1A1E1Ysiv2O06Sfbhkapm+XyIzxWCEh5kqwOZ1/8QZ0dY3SeQ7XBqfJd5Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-member-expression-literals@7.29.7': + resolution: {integrity: sha512-hl1kwFZCCiDyfH25Xmco9jTrkPgnS9pmOzSG7W5I4SaGbLeqKv417hcU2RKmaxoPEgsoJh7ZPOrnPGq99bHoUg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-modules-amd@7.29.7': + resolution: {integrity: sha512-fxtQoH3m5ywUSIfaH0FGCzWu4McsYon5bD3K4XnskC7f+OyQMj7rsOMi4NvvmJ83WwBAg4UCe+ov4VZlqEvyew==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-modules-commonjs@7.29.7': + resolution: {integrity: sha512-j0vCldybPC5b5dwCQOJ21uKtHzt7hxLygJTg9eF1ScfaikEDNfzn94XoW5Fi+seBR0nCyL23xaBFFkq7dTM8XQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-modules-systemjs@7.29.7': + resolution: {integrity: sha512-TM2ZcQLoG2/y4HODiStCo10DibYhWhGWAwVv+EQKmG/7GFl0N+AAmUiXOMKM+aiJ9XBJ9AHVZBvTzMnJ2sM3cQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-modules-umd@7.29.7': + resolution: {integrity: sha512-B4UkaTK3QpgCwJnrxKfMPKdo92CN7OKXAlpAAnM3UPu0Q0lCCk57ylA9AJbRy2v8dDKOPAAWcoR6CMyeoHwRCA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-named-capturing-groups-regex@7.29.7': + resolution: {integrity: sha512-vuFoLwr4qnv2xbZ16SQd6uPcH5FNrLHhk/Jzo++0XJFcaDsr4gjJVg6j398oMHiC+83k/GiBzviwF5KBJkPUtQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-transform-new-target@7.29.7': + resolution: {integrity: sha512-fEo41GmsOUhOBlw8ioo6zvjX5Xc2Lqkzlyfqbpsk3eB6TReV18uhxZ0esfEokVbY2+PVJAQHNKxER6lGrzNd3A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-nullish-coalescing-operator@7.29.7': + resolution: {integrity: sha512-idmp1dFaekP9GbcMvG24Kvw2BfhFZjHnNJCkV4WuIY4PskJzwI3f1N5OdgYke38T7rftO6ERulFRn2cFeZwRkg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-numeric-separator@7.29.7': + resolution: {integrity: sha512-zR7fv/z14OjgHl4AgRtkDBvBMhIzCxqV/qN/2BCRC7LjFwvuzjYe7gDWxC4Wl/SNsLM6SE1IWvRPYMgSJaUvNw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-object-rest-spread@7.29.7': + resolution: {integrity: sha512-Ld98jn4c0smUywL57m7SgsHq3OpThOa6LqZJif3G6jYOovPleoFhVrBJ1WegRApSFB2wu4+RelAj9AC9G08Z4A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-object-super@7.29.7': + resolution: {integrity: sha512-Ea/diGcw0twB5IlZPO5sgET6fJsLJqPABqTuFWIR+iMPGPZJkATEIWx0wa+aEQ5UY1CBQyP/gkAiLEqn1vBiQA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-optional-catch-binding@7.29.7': + resolution: {integrity: sha512-sLsyndxK2VwX6yNUOakMb7Sh553ZTe/vVM1XJ+9Z5aW1ytsc8xOIwmyk05NNjN60vkc5/KqoTH6hB4V41LJhng==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-optional-chaining@7.29.7': + resolution: {integrity: sha512-6GM1dhvK3gNODkXcEcMCOLEDCLSoZ/sBbro2Ax8HURyasQ4NshagQixkRFdh5niI6E4gmA/jYI/4aT7rRos3ZQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-parameters@7.29.7': + resolution: {integrity: sha512-ZDOBqV/qLYJI0YElr8DcENEyARsFQeESqWXH6gZlghYXuPPjvweuDhP4VyEi4BlUBlLRFZVjxoZDMjxhLW766g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-private-methods@7.29.7': + resolution: {integrity: sha512-/6Rz4DK1ETDEM/bWHsPHcaEe7ZaT1EqSXjtSP/L0DijOYuaUhiRiOKcwpZ8P7zR4xXEHc2ITdiCgBm9Tpyv9ug==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-private-property-in-object@7.29.7': + resolution: {integrity: sha512-+BNo06dnrzdNNqCm1X6YUaVv0DKk8Q+JYcoZfOkLhYWNCXzlwTSRq8zGWayT1csjcpNXV9CQTBRRbmTLZac5cA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-property-literals@7.29.7': + resolution: {integrity: sha512-bOMRLQuI0A5ZqHq3OWJ89/rXpJ/NJrbVhXiP4zwPGMs6kpcVsuTUNjwoE30K0Qm3mf48a/TnRYYD6vPNqcg6jA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-regenerator@7.29.7': + resolution: {integrity: sha512-rNNFV0DBAJp988xW2DOntfDoYn1eR8GGF5AT5vYc+rjyfaQkM242c9tZUHHPe7KYaiJizXPWhQTzzdbXySyhBw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-regexp-modifiers@7.29.7': + resolution: {integrity: sha512-mB5Fs0VWrJ42ZCmc8114v60qetdaUVNkj9PmSZRmanCZM3S9hm0CFRLjRmYIsuXav14l2jvZ+4T8iiCGnhj3nQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-transform-reserved-words@7.29.7': + resolution: {integrity: sha512-5+YhdpVgmfSmwZyLMftfaiffLRMHjzIRHFHHLdibcSyJm2pasMrKHrO3Ptrt2DRshjvpgjEJJ1zVW14WPq/6QA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-runtime@7.26.10': + resolution: {integrity: sha512-NWaL2qG6HRpONTnj4JvDU6th4jYeZOJgu3QhmFTCihib0ermtOJqktA5BduGm3suhhVe9EMP9c9+mfJ/I9slqw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-shorthand-properties@7.29.7': + resolution: {integrity: sha512-I+WYbGBAiCn7nA6xBrlgPH+MB7HWb4u8pv5S0Pv7OtwNvIFvCCb24YlttKEeUFVurfBCEaOTnuhlqsb7f0Z5Dg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-spread@7.29.7': + resolution: {integrity: sha512-/u5K1QWada7tbYNqTjMh96718g9NTwh9tfPJMsSmVsQwGT447FskV+KcfeXkXq2GWki4EM/MuTdmBec+hOuVTQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-sticky-regex@7.29.7': + resolution: {integrity: sha512-BCHzNYJGe9l7EpwwDBN/ztlL2NYFFq8hp9ddjtUEM9f2O7S7kKV/lL6Fwo7IF7NSkYhPK2vO+86nIGltA90MsA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-template-literals@7.29.7': + resolution: {integrity: sha512-NCSEJ4sLFU2gqAub45HYh4fus2yQ36rr6ei6vpU7NdoJqCpxvEG8E6eJpscGyXP3VHD2Ny+fSXr04k1hoUrFqA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-typeof-symbol@7.29.7': + resolution: {integrity: sha512-223mNGoTkBiTEWFoK+Q6Go3tueMRclO8vxxxxquNCYuNI4jWOofFKJRRDu6SDrB8Sgo1UEGW9T4GAQ8ZyRso1A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-unicode-escapes@7.29.7': + resolution: {integrity: sha512-jCfXxSjf94lf4E0hKE0AByxF6F3/pVFqRdUUNkDJhsY0m1ZKjnN6ZYyMeHNpzflxb/0q5b7t3p+BE+SLF1WOtA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-unicode-property-regex@7.29.7': + resolution: {integrity: sha512-OgZ+zoAJgZLUCunsTRQ5LAjOywDv5zzZ2/hQ5aMw1pGXyY2rtE8/chXYUmu3AlVHKpm10KEdG9aMwbI/K76ZGw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-unicode-regex@7.29.7': + resolution: {integrity: sha512-7D/x/23/d/3VqZ0QA+LGbZMlGwZjztBygSWWWsfTPoQ1oQ6Q1P6Mr3d0kk42XabyUVw+fha3LqdRsFqeKqvCyA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-unicode-sets-regex@7.29.7': + resolution: {integrity: sha512-BLOhLht9DOJwIxlmp91wHvkXv1lguuHS3/FwUO8HL1H0u8s4hR1gASVFyilu9iGtcTRYqjTZmlsFFeQletntEg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/preset-env@7.26.9': + resolution: {integrity: sha512-vX3qPGE8sEKEAZCWk05k3cpTAE3/nOYca++JA+Rd0z2NCNzabmYvEiSShKzm10zdquOIAVXsy2Ei/DTW34KlKQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/preset-modules@0.1.6-no-external-plugins': + resolution: {integrity: sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==} + peerDependencies: + '@babel/core': ^7.0.0-0 || ^8.0.0-0 <8.0.0 + + '@babel/runtime@7.26.10': + resolution: {integrity: sha512-2WJMeRQPHKSPemqk/awGrAiuFfzBmOIPXKizAsVhWH9YJqLZ0H+HS4c8loHGgW6utJ3E/ejXQUsiGaQy2NZ9Fw==} + engines: {node: '>=6.9.0'} + + '@babel/template@7.29.7': + resolution: {integrity: sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==} + engines: {node: '>=6.9.0'} + + '@babel/traverse@7.29.7': + resolution: {integrity: sha512-EhlfNQtZ+NK22w5BM61ciuiq1m58ed33Wr1Xan//ZRTy6hgjnwyCffRYwzsGXdASJSUJ1guZILsErh1eQcl+zw==} + engines: {node: '>=6.9.0'} + + '@babel/types@7.29.7': + resolution: {integrity: sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==} + engines: {node: '>=6.9.0'} + + '@capacitor-community/electron@5.0.1': + resolution: {integrity: sha512-4/x12ycTq0Kq8JIn/BmIBdFVP5Cqw8iA6SU6YfFjmONfjW3OELwsB3zwLxOwAjLxnjyCMOBHl4ci9E5jLgZgAQ==} + + '@capacitor/android@8.5.0': + resolution: {integrity: sha512-Rb3prJeQiTp0pQhSSOReJuG9VgibOGMG4ECs+UhMwr6TCCHZ3NCZO811bDA0HxD0xrT/gCrJAsY5yfEATu84JQ==} + peerDependencies: + '@capacitor/core': ^8.5.0 + + '@capacitor/cli@8.5.0': + resolution: {integrity: sha512-rLdzMUM5QV4WITcqoWv04p32i14BXgUH2diqEH6MWQlWaJfiyNrvOyt/+d5vHAfOxOm1klBu637VDEobctlwBA==} + engines: {node: '>=22.0.0'} + hasBin: true + + '@capacitor/core@8.5.0': + resolution: {integrity: sha512-Ca4krtqH1hothjtBIwf2J2TW7IhYq1ujp8QeItTiJohNsqij8ja2DYYH3DU0l8RmxCWaBAFTGA2TgOgOMCSNsQ==} + + '@capacitor/ios@8.5.0': + resolution: {integrity: sha512-7k1TfohJu5BzRXc1F3g04Q8QQ0fyQgms6h1AvhnHb04VaNr9EdHOx03hL8O+OigEKMQnyJd1ZOjTPPNHCqL5Yw==} + peerDependencies: + '@capacitor/core': ^8.5.0 + + '@colors/colors@1.5.0': + resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==} + engines: {node: '>=0.1.90'} + + '@dimforge/rapier3d-compat@0.12.0': + resolution: {integrity: sha512-uekIGetywIgopfD97oDL5PfeezkFpNhwlzlaEYNOA0N6ghdsOvh/HYjSMek5Q2O1PYvRSDFcqFVJl4r4ZBwOow==} + + '@discoveryjs/json-ext@0.6.3': + resolution: {integrity: sha512-4B4OijXeVNOPZlYA2oEwWOTkzyltLao+xbotHQeqN++Rv27Y6s818+n2Qkp8q+Fxhn0t/5lA5X1Mxktud8eayQ==} + engines: {node: '>=14.17.0'} + + '@esbuild/aix-ppc64@0.25.12': + resolution: {integrity: sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + + '@esbuild/aix-ppc64@0.28.0': + resolution: {integrity: sha512-lhRUCeuOyJQURhTxl4WkpFTjIsbDayJHih5kZC1giwE+MhIzAb7mEsQMqMf18rHLsrb5qI1tafG20mLxEWcWlA==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.25.12': + resolution: {integrity: sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm64@0.28.0': + resolution: {integrity: sha512-+WzIXQOSaGs33tLEgYPYe/yQHf0WTU0X42Jca3y8NWMbUVhp7rUnw+vAsRC/QiDrdD31IszMrZy+qwPOPjd+rw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.25.12': + resolution: {integrity: sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + + '@esbuild/android-arm@0.28.0': + resolution: {integrity: sha512-wqh0ByljabXLKHeWXYLqoJ5jKC4XBaw6Hk08OfMrCRd2nP2ZQ5eleDZC41XHyCNgktBGYMbqnrJKq/K/lzPMSQ==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.25.12': + resolution: {integrity: sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + + '@esbuild/android-x64@0.28.0': + resolution: {integrity: sha512-+VJggoaKhk2VNNqVL7f6S189UzShHC/mR9EE8rDdSkdpN0KflSwWY/gWjDrNxxisg8Fp1ZCD9jLMo4m0OUfeUA==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.25.12': + resolution: {integrity: sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-arm64@0.28.0': + resolution: {integrity: sha512-0T+A9WZm+bZ84nZBtk1ckYsOvyA3x7e2Acj1KdVfV4/2tdG4fzUp91YHx+GArWLtwqp77pBXVCPn2We7Letr0Q==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.25.12': + resolution: {integrity: sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@esbuild/darwin-x64@0.28.0': + resolution: {integrity: sha512-fyzLm/DLDl/84OCfp2f/XQ4flmORsjU7VKt8HLjvIXChJoFFOIL6pLJPH4Yhd1n1gGFF9mPwtlN5Wf82DZs+LQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.25.12': + resolution: {integrity: sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-arm64@0.28.0': + resolution: {integrity: sha512-l9GeW5UZBT9k9brBYI+0WDffcRxgHQD8ShN2Ur4xWq/NFzUKm3k5lsH4PdaRgb2w7mI9u61nr2gI2mLI27Nh3Q==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.25.12': + resolution: {integrity: sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.28.0': + resolution: {integrity: sha512-BXoQai/A0wPO6Es3yFJ7APCiKGc1tdAEOgeTNy3SsB491S3aHn4S4r3e976eUnPdU+NbdtmBuLncYir2tMU9Nw==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.25.12': + resolution: {integrity: sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm64@0.28.0': + resolution: {integrity: sha512-RVyzfb3FWsGA55n6WY0MEIEPURL1FcbhFE6BffZEMEekfCzCIMtB5yyDcFnVbTnwk+CLAgTujmV/Lgvih56W+A==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.25.12': + resolution: {integrity: sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-arm@0.28.0': + resolution: {integrity: sha512-CjaaREJagqJp7iTaNQjjidaNbCKYcd4IDkzbwwxtSvjI7NZm79qiHc8HqciMddQ6CKvJT6aBd8lO9kN/ZudLlw==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.25.12': + resolution: {integrity: sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-ia32@0.28.0': + resolution: {integrity: sha512-KBnSTt1kxl9x70q+ydterVdl+Cn0H18ngRMRCEQfrbqdUuntQQ0LoMZv47uB97NljZFzY6HcfqEZ2SAyIUTQBQ==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.25.12': + resolution: {integrity: sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-loong64@0.28.0': + resolution: {integrity: sha512-zpSlUce1mnxzgBADvxKXX5sl8aYQHo2ezvMNI8I0lbblJtp8V4odlm3Yzlj7gPyt3T8ReksE6bK+pT3WD+aJRg==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.25.12': + resolution: {integrity: sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-mips64el@0.28.0': + resolution: {integrity: sha512-2jIfP6mmjkdmeTlsX/9vmdmhBmKADrWqN7zcdtHIeNSCH1SqIoNI63cYsjQR8J+wGa4Y5izRcSHSm8K3QWmk3w==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.25.12': + resolution: {integrity: sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-ppc64@0.28.0': + resolution: {integrity: sha512-bc0FE9wWeC0WBm49IQMPSPILRocGTQt3j5KPCA8os6VprfuJ7KD+5PzESSrJ6GmPIPJK965ZJHTUlSA6GNYEhg==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.25.12': + resolution: {integrity: sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-riscv64@0.28.0': + resolution: {integrity: sha512-SQPZOwoTTT/HXFXQJG/vBX8sOFagGqvZyXcgLA3NhIqcBv1BJU1d46c0rGcrij2B56Z2rNiSLaZOYW5cUk7yLQ==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.25.12': + resolution: {integrity: sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-s390x@0.28.0': + resolution: {integrity: sha512-SCfR0HN8CEEjnYnySJTd2cw0k9OHB/YFzt5zgJEwa+wL/T/raGWYMBqwDNAC6dqFKmJYZoQBRfHjgwLHGSrn3Q==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.25.12': + resolution: {integrity: sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/linux-x64@0.28.0': + resolution: {integrity: sha512-us0dSb9iFxIi8srnpl931Nvs65it/Jd2a2K3qs7fz2WfGPHqzfzZTfec7oxZJRNPXPnNYZtanmRc4AL/JwVzHQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-arm64@0.25.12': + resolution: {integrity: sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + + '@esbuild/netbsd-arm64@0.28.0': + resolution: {integrity: sha512-CR/RYotgtCKwtftMwJlUU7xCVNg3lMYZ0RzTmAHSfLCXw3NtZtNpswLEj/Kkf6kEL3Gw+BpOekRX0BYCtklhUw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.25.12': + resolution: {integrity: sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.28.0': + resolution: {integrity: sha512-nU1yhmYutL+fQ71Kxnhg8uEOdC0pwEW9entHykTgEbna2pw2dkbFSMeqjjyHZoCmt8SBkOSvV+yNmm94aUrrqw==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-arm64@0.25.12': + resolution: {integrity: sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-arm64@0.28.0': + resolution: {integrity: sha512-cXb5vApOsRsxsEl4mcZ1XY3D4DzcoMxR/nnc4IyqYs0rTI8ZKmW6kyyg+11Z8yvgMfAEldKzP7AdP64HnSC/6g==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.25.12': + resolution: {integrity: sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.28.0': + resolution: {integrity: sha512-8wZM2qqtv9UP3mzy7HiGYNH/zjTA355mpeuA+859TyR+e+Tc08IHYpLJuMsfpDJwoLo1ikIJI8jC3GFjnRClzA==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/openharmony-arm64@0.25.12': + resolution: {integrity: sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + + '@esbuild/openharmony-arm64@0.28.0': + resolution: {integrity: sha512-FLGfyizszcef5C3YtoyQDACyg95+dndv79i2EekILBofh5wpCa1KuBqOWKrEHZg3zrL3t5ouE5jgr94vA+Wb2w==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + + '@esbuild/sunos-x64@0.25.12': + resolution: {integrity: sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + + '@esbuild/sunos-x64@0.28.0': + resolution: {integrity: sha512-1ZgjUoEdHZZl/YlV76TSCz9Hqj9h9YmMGAgAPYd+q4SicWNX3G5GCyx9uhQWSLcbvPW8Ni7lj4gDa1T40akdlw==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.25.12': + resolution: {integrity: sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-arm64@0.28.0': + resolution: {integrity: sha512-Q9StnDmQ/enxnpxCCLSg0oo4+34B9TdXpuyPeTedN/6+iXBJ4J+zwfQI28u/Jl40nOYAxGoNi7mFP40RUtkmUA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.25.12': + resolution: {integrity: sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-ia32@0.28.0': + resolution: {integrity: sha512-zF3ag/gfiCe6U2iczcRzSYJKH1DCI+ByzSENHlM2FcDbEeo5Zd2C86Aq0tKUYAJJ1obRP84ymxIAksZUcdztHA==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.25.12': + resolution: {integrity: sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + + '@esbuild/win32-x64@0.28.0': + resolution: {integrity: sha512-pEl1bO9mfAmIC+tW5btTmrKaujg3zGtUmWNdCw/xs70FBjwAL3o9OEKNHvNmnyylD6ubxUERiEhdsL0xBQ9efw==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + + '@inquirer/ansi@1.0.2': + resolution: {integrity: sha512-S8qNSZiYzFd0wAcyG5AXCvUHC5Sr7xpZ9wZ2py9XR88jUz8wooStVx5M6dRzczbBWjic9NP7+rY0Xi7qqK/aMQ==} + engines: {node: '>=18'} + + '@inquirer/checkbox@4.3.2': + resolution: {integrity: sha512-VXukHf0RR1doGe6Sm4F0Em7SWYLTHSsbGfJdS9Ja2bX5/D5uwVOEjr07cncLROdBvmnvCATYEWlHqYmXv2IlQA==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/confirm@5.1.21': + resolution: {integrity: sha512-KR8edRkIsUayMXV+o3Gv+q4jlhENF9nMYUZs9PA2HzrXeHI8M5uDag70U7RJn9yyiMZSbtF5/UexBtAVtZGSbQ==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/confirm@5.1.6': + resolution: {integrity: sha512-6ZXYK3M1XmaVBZX6FCfChgtponnL0R6I7k8Nu+kaoNkT828FVZTcca1MqmWQipaW2oNREQl5AaPCUOOCVNdRMw==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/core@10.3.2': + resolution: {integrity: sha512-43RTuEbfP8MbKzedNqBrlhhNKVwoK//vUFNW3Q3vZ88BLcrs4kYpGg+B2mm5p2K/HfygoCxuKwJJiv8PbGmE0A==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/editor@4.2.23': + resolution: {integrity: sha512-aLSROkEwirotxZ1pBaP8tugXRFCxW94gwrQLxXfrZsKkfjOYC1aRvAZuhpJOb5cu4IBTJdsCigUlf2iCOu4ZDQ==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/expand@4.0.23': + resolution: {integrity: sha512-nRzdOyFYnpeYTTR2qFwEVmIWypzdAx/sIkCMeTNTcflFOovfqUk+HcFhQQVBftAh9gmGrpFj6QcGEqrDMDOiew==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/external-editor@1.0.3': + resolution: {integrity: sha512-RWbSrDiYmO4LbejWY7ttpxczuwQyZLBUyygsA9Nsv95hpzUWwnNTVQmAq3xuh7vNwCp07UTmE5i11XAEExx4RA==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/figures@1.0.15': + resolution: {integrity: sha512-t2IEY+unGHOzAaVM5Xx6DEWKeXlDDcNPeDyUpsRc6CUhBfU3VQOEl+Vssh7VNp1dR8MdUJBWhuObjXCsVpjN5g==} + engines: {node: '>=18'} + + '@inquirer/input@4.3.1': + resolution: {integrity: sha512-kN0pAM4yPrLjJ1XJBjDxyfDduXOuQHrBB8aLDMueuwUGn+vNpF7Gq7TvyVxx8u4SHlFFj4trmj+a2cbpG4Jn1g==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/number@3.0.23': + resolution: {integrity: sha512-5Smv0OK7K0KUzUfYUXDXQc9jrf8OHo4ktlEayFlelCjwMXz0299Y8OrI+lj7i4gCBY15UObk76q0QtxjzFcFcg==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/password@4.0.23': + resolution: {integrity: sha512-zREJHjhT5vJBMZX/IUbyI9zVtVfOLiTO66MrF/3GFZYZ7T4YILW5MSkEYHceSii/KtRk+4i3RE7E1CUXA2jHcA==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/prompts@7.3.2': + resolution: {integrity: sha512-G1ytyOoHh5BphmEBxSwALin3n1KGNYB6yImbICcRQdzXfOGbuJ9Jske/Of5Sebk339NSGGNfUshnzK8YWkTPsQ==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/rawlist@4.1.11': + resolution: {integrity: sha512-+LLQB8XGr3I5LZN/GuAHo+GpDJegQwuPARLChlMICNdwW7OwV2izlCSCxN6cqpL0sMXmbKbFcItJgdQq5EBXTw==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/search@3.2.2': + resolution: {integrity: sha512-p2bvRfENXCZdWF/U2BXvnSI9h+tuA8iNqtUKb9UWbmLYCRQxd8WkvwWvYn+3NgYaNwdUkHytJMGG4MMLucI1kA==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/select@4.4.2': + resolution: {integrity: sha512-l4xMuJo55MAe+N7Qr4rX90vypFwCajSakx59qe/tMaC1aEHWLyw68wF4o0A4SLAY4E0nd+Vt+EyskeDIqu1M6w==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/type@1.5.5': + resolution: {integrity: sha512-MzICLu4yS7V8AA61sANROZ9vT1H3ooca5dSmI1FjZkzq7o/koMsRfQSzRtFo+F3Ao4Sf1C0bpLKejpKB/+j6MA==} + engines: {node: '>=18'} + + '@inquirer/type@3.0.10': + resolution: {integrity: sha512-BvziSRxfz5Ov8ch0z/n3oijRSEcEsHnhggm4xFZe93DHcUCTlutlq9Ox4SVENAfcRD22UQq7T/atg9Wr3k09eA==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@ionic/cli-framework-output@2.2.8': + resolution: {integrity: sha512-TshtaFQsovB4NWRBydbNFawql6yul7d5bMiW1WYYf17hd99V6xdDdk3vtF51bw6sLkxON3bDQpWsnUc9/hVo3g==} + engines: {node: '>=16.0.0'} + + '@ionic/utils-array@2.1.6': + resolution: {integrity: sha512-0JZ1Zkp3wURnv8oq6Qt7fMPo5MpjbLoUoa9Bu2Q4PJuSDWM8H8gwF3dQO7VTeUj3/0o1IB1wGkFWZZYgUXZMUg==} + engines: {node: '>=16.0.0'} + + '@ionic/utils-fs@3.1.7': + resolution: {integrity: sha512-2EknRvMVfhnyhL1VhFkSLa5gOcycK91VnjfrTB0kbqkTFCOXyXgVLI5whzq7SLrgD9t1aqos3lMMQyVzaQ5gVA==} + engines: {node: '>=16.0.0'} + + '@ionic/utils-object@2.1.6': + resolution: {integrity: sha512-vCl7sl6JjBHFw99CuAqHljYJpcE88YaH2ZW4ELiC/Zwxl5tiwn4kbdP/gxi2OT3MQb1vOtgAmSNRtusvgxI8ww==} + engines: {node: '>=16.0.0'} + + '@ionic/utils-process@2.1.12': + resolution: {integrity: sha512-Jqkgyq7zBs/v/J3YvKtQQiIcxfJyplPgECMWgdO0E1fKrrH8EF0QGHNJ9mJCn6PYe2UtHNS8JJf5G21e09DfYg==} + engines: {node: '>=16.0.0'} + + '@ionic/utils-stream@3.1.7': + resolution: {integrity: sha512-eSELBE7NWNFIHTbTC2jiMvh1ABKGIpGdUIvARsNPMNQhxJB3wpwdiVnoBoTYp+5a6UUIww4Kpg7v6S7iTctH1w==} + engines: {node: '>=16.0.0'} + + '@ionic/utils-subprocess@3.0.1': + resolution: {integrity: sha512-cT4te3AQQPeIM9WCwIg8ohroJ8TjsYaMb2G4ZEgv9YzeDqHZ4JpeIKqG2SoaA3GmVQ3sOfhPM6Ox9sxphV/d1A==} + engines: {node: '>=16.0.0'} + + '@ionic/utils-terminal@2.3.5': + resolution: {integrity: sha512-3cKScz9Jx2/Pr9ijj1OzGlBDfcmx7OMVBt4+P1uRR0SSW4cm1/y3Mo4OY3lfkuaYifMNBW8Wz6lQHbs1bihr7A==} + engines: {node: '>=16.0.0'} + + '@isaacs/cliui@8.0.2': + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} + engines: {node: '>=12'} + + '@isaacs/fs-minipass@4.0.1': + resolution: {integrity: sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==} + engines: {node: '>=18.0.0'} + + '@istanbuljs/schema@0.1.6': + resolution: {integrity: sha512-+Sg6GCR/wy1oSmQDFq4LQDAhm3ETKnorxN+y5nbLULOR3P0c14f2Wurzj3/xqPXtasLFfHd5iRFQ7AJt4KH2cw==} + engines: {node: '>=8'} + + '@jridgewell/gen-mapping@0.3.13': + resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} + + '@jridgewell/remapping@2.3.5': + resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==} + + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + + '@jridgewell/source-map@0.3.11': + resolution: {integrity: sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==} + + '@jridgewell/sourcemap-codec@1.5.5': + resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} + + '@jridgewell/trace-mapping@0.3.31': + resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} + + '@jsonjoy.com/base64@1.1.2': + resolution: {integrity: sha512-q6XAnWQDIMA3+FTiOYajoYqySkO+JSat0ytXGSuRdq9uXE7o92gzuQwQM14xaCRlBLGq3v5miDGC4vkVTn54xA==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/base64@17.67.0': + resolution: {integrity: sha512-5SEsJGsm15aP8TQGkDfJvz9axgPwAEm98S5DxOuYe8e1EbfajcDmgeXXzccEjh+mLnjqEKrkBdjHWS5vFNwDdw==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/buffers@1.2.1': + resolution: {integrity: sha512-12cdlDwX4RUM3QxmUbVJWqZ/mrK6dFQH4Zxq6+r1YXKXYBNgZXndx2qbCJwh3+WWkCSn67IjnlG3XYTvmvYtgA==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/buffers@17.67.0': + resolution: {integrity: sha512-tfExRpYxBvi32vPs9ZHaTjSP4fHAfzSmcahOfNxtvGHcyJel+aibkPlGeBB+7AoC6hL7lXIE++8okecBxx7lcw==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/codegen@1.0.0': + resolution: {integrity: sha512-E8Oy+08cmCf0EK/NMxpaJZmOxPqM+6iSe2S4nlSBrPZOORoDJILxtbSUEDKQyTamm/BVAhIGllOBNU79/dwf0g==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/codegen@17.67.0': + resolution: {integrity: sha512-idnkUplROpdBOV0HMcwhsCUS5TRUi9poagdGs70A6S4ux9+/aPuKbh8+UYRTLYQHtXvAdNfQWXDqZEx5k4Dj2Q==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/fs-core@4.64.0': + resolution: {integrity: sha512-zs2TAq7Six5jgMuoMNjpspAvOP3mhtgq/k1UyQodEzCtQi/N83y2/y+zcvnZSGp/Rxq96DBN+bValOBQAyn/ew==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/fs-fsa@4.64.0': + resolution: {integrity: sha512-nMWOVbkLFyEgmXZih3wyvxA9XpgyyqyfrINMHvEFqhi7uqfRl7c9ERJt6yX7vgMPrB9Uo+OJO+Spa0cFzPD01w==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/fs-node-builtins@4.64.0': + resolution: {integrity: sha512-/o7WRFhUWaM/fOrslwLZGnzn4RmRILykn+lAL+mNObqqRNw+CQSiij6hpCeZ+C7buhdoVo7go/OYqzaSUfDYmA==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/fs-node-to-fsa@4.64.0': + resolution: {integrity: sha512-WDD9WVs0hb7UAEKTgZW2f66WDrbj7gIIWwpP3spbLyXa0rghtUaFTB8L4gdR3ZCWwiKIsj38/CNijpVmpnuPUw==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/fs-node-utils@4.64.0': + resolution: {integrity: sha512-k5Indsx9hWW9xSF7Y6oSKKwtCUNhzZxadub3owhIlitc+iMRVlPPdX2duTKQWBL3qNWpXya8jykgaaWpheeS4w==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/fs-node@4.64.0': + resolution: {integrity: sha512-dO+NNkODbUli4uV42bcNrrLvq5rE7SNpdZ5TNd0dtbLsAaNK3MDiIC9lUi+brboGoIjW6vd2fB1qao60nrk5xA==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/fs-print@4.64.0': + resolution: {integrity: sha512-PHZFccchvkhWrwPWHjmVAhbC3vSHCtyZvlZfJJ3ho2bnzl450hXri6/8e6pbkWdH+SkmLXNml0sV8e5HDAfxKw==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/fs-snapshot@4.64.0': + resolution: {integrity: sha512-oM7UDeL83q6NBzzsfKAsYKXKVXlykKFqqOLh4xZZKAzzROTlInkPbc6LTDGThEOnPiFiUzA7tYziHG9xavd76Q==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/json-pack@1.21.0': + resolution: {integrity: sha512-+AKG+R2cfZMShzrF2uQw34v3zbeDYUqnQ+jg7ORic3BGtfw9p/+N6RJbq/kkV8JmYZaINknaEQ2m0/f693ZPpg==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/json-pack@17.67.0': + resolution: {integrity: sha512-t0ejURcGaZsn1ClbJ/3kFqSOjlryd92eQY465IYrezsXmPcfHPE/av4twRSxf6WE+TkZgLY+71vCZbiIiFKA/w==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/json-pointer@1.0.2': + resolution: {integrity: sha512-Fsn6wM2zlDzY1U+v4Nc8bo3bVqgfNTGcn6dMgs6FjrEnt4ZCe60o6ByKRjOGlI2gow0aE/Q41QOigdTqkyK5fg==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/json-pointer@17.67.0': + resolution: {integrity: sha512-+iqOFInH+QZGmSuaybBUNdh7yvNrXvqR+h3wjXm0N/3JK1EyyFAeGJvqnmQL61d1ARLlk/wJdFKSL+LHJ1eaUA==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/util@1.9.0': + resolution: {integrity: sha512-pLuQo+VPRnN8hfPqUTLTHk126wuYdXVxE6aDmjSeV4NCAgyxWbiOIeNJVtID3h1Vzpoi9m4jXezf73I6LgabgQ==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/util@17.67.0': + resolution: {integrity: sha512-6+8xBaz1rLSohlGh68D1pdw3AwDi9xydm8QNlAFkvnavCJYSze+pxoW2VKP8p308jtlMRLs5NTHfPlZLd4w7ew==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@leichtgewicht/ip-codec@2.0.5': + resolution: {integrity: sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==} + + '@listr2/prompt-adapter-inquirer@2.0.18': + resolution: {integrity: sha512-0hz44rAcrphyXcA8IS7EJ2SCoaBZD2u5goE8S/e+q/DL+dOGpqpcLidVOFeLG3VgML62SXmfRLAhWt0zL1oW4Q==} + engines: {node: '>=18.0.0'} + peerDependencies: + '@inquirer/prompts': '>= 3 < 8' + + '@lmdb/lmdb-darwin-arm64@3.2.6': + resolution: {integrity: sha512-yF/ih9EJJZc72psFQbwnn8mExIWfTnzWJg+N02hnpXtDPETYLmQswIMBn7+V88lfCaFrMozJsUvcEQIkEPU0Gg==} + cpu: [arm64] + os: [darwin] + + '@lmdb/lmdb-darwin-x64@3.2.6': + resolution: {integrity: sha512-5BbCumsFLbCi586Bb1lTWQFkekdQUw8/t8cy++Uq251cl3hbDIGEwD9HAwh8H6IS2F6QA9KdKmO136LmipRNkg==} + cpu: [x64] + os: [darwin] + + '@lmdb/lmdb-linux-arm64@3.2.6': + resolution: {integrity: sha512-l5VmJamJ3nyMmeD1ANBQCQqy7do1ESaJQfKPSm2IG9/ADZryptTyCj8N6QaYgIWewqNUrcbdMkJajRQAt5Qjfg==} + cpu: [arm64] + os: [linux] + + '@lmdb/lmdb-linux-arm@3.2.6': + resolution: {integrity: sha512-+6XgLpMb7HBoWxXj+bLbiiB4s0mRRcDPElnRS3LpWRzdYSe+gFk5MT/4RrVNqd2MESUDmb53NUXw1+BP69bjiQ==} + cpu: [arm] + os: [linux] + + '@lmdb/lmdb-linux-x64@3.2.6': + resolution: {integrity: sha512-nDYT8qN9si5+onHYYaI4DiauDMx24OAiuZAUsEqrDy+ja/3EbpXPX/VAkMV8AEaQhy3xc4dRC+KcYIvOFefJ4Q==} + cpu: [x64] + os: [linux] + + '@lmdb/lmdb-win32-x64@3.2.6': + resolution: {integrity: sha512-XlqVtILonQnG+9fH2N3Aytria7P/1fwDgDhl29rde96uH2sLB8CHORIf2PfuLVzFQJ7Uqp8py9AYwr3ZUCFfWg==} + cpu: [x64] + os: [win32] + + '@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.4': + resolution: {integrity: sha512-LCkGo6JDfaBhgST7UpPWgNgLINpcpabaHfyz5OBx75nUYxBsaEPxjnyNjWpeb/xBup/682QnBfRBy2/LvPutZQ==} + cpu: [arm64] + os: [darwin] + + '@msgpackr-extract/msgpackr-extract-darwin-x64@3.0.4': + resolution: {integrity: sha512-zExlW9zUJKZH/tOtVMttwjKa4Xm/3KcNjnE3dPN92uCktwavMxpgCA3MoJK/DOnTWsQgo224OaST27/mPNAf+w==} + cpu: [x64] + os: [darwin] + + '@msgpackr-extract/msgpackr-extract-linux-arm64@3.0.4': + resolution: {integrity: sha512-dgX0P/9wGPJeHFBG+ZmhgE6bmtMt7NP5CRBGyyktpopdk/mW4POnrpQsSLtKI1dwpc+pPLuXHDh6vvskyQE/sw==} + cpu: [arm64] + os: [linux] + + '@msgpackr-extract/msgpackr-extract-linux-arm@3.0.4': + resolution: {integrity: sha512-Tg3yX65f5GbtXLkrYEHE5oibZG9epyYWas7FogTTEJeDEF9JlXJzKgXaNhT3UXlTOeA+AfZpYZYZ0uPj7Cfquw==} + cpu: [arm] + os: [linux] + + '@msgpackr-extract/msgpackr-extract-linux-x64@3.0.4': + resolution: {integrity: sha512-8TNXMEjJc3QEy7R/x1INhgiU+XakDAFUzBhaz7+Rbrs8NH5UQeHQxxmzsSBJGyV6I1jW79undiQm8tOI+D+8FQ==} + cpu: [x64] + os: [linux] + + '@msgpackr-extract/msgpackr-extract-win32-x64@3.0.4': + resolution: {integrity: sha512-CmCXPQrkbwExx3j946/PtHWHbYJiCRBRDl4BlkRQcJB/YOwQxJRTpoo7aTsortjgoJ1x7opzTSxn7C+ASSLVjQ==} + cpu: [x64] + os: [win32] + + '@napi-rs/nice-android-arm-eabi@1.1.1': + resolution: {integrity: sha512-kjirL3N6TnRPv5iuHw36wnucNqXAO46dzK9oPb0wj076R5Xm8PfUVA9nAFB5ZNMmfJQJVKACAPd/Z2KYMppthw==} + engines: {node: '>= 10'} + cpu: [arm] + os: [android] + + '@napi-rs/nice-android-arm64@1.1.1': + resolution: {integrity: sha512-blG0i7dXgbInN5urONoUCNf+DUEAavRffrO7fZSeoRMJc5qD+BJeNcpr54msPF6qfDD6kzs9AQJogZvT2KD5nw==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [android] + + '@napi-rs/nice-darwin-arm64@1.1.1': + resolution: {integrity: sha512-s/E7w45NaLqTGuOjC2p96pct4jRfo61xb9bU1unM/MJ/RFkKlJyJDx7OJI/O0ll/hrfpqKopuAFDV8yo0hfT7A==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [darwin] + + '@napi-rs/nice-darwin-x64@1.1.1': + resolution: {integrity: sha512-dGoEBnVpsdcC+oHHmW1LRK5eiyzLwdgNQq3BmZIav+9/5WTZwBYX7r5ZkQC07Nxd3KHOCkgbHSh4wPkH1N1LiQ==} + engines: {node: '>= 10'} + cpu: [x64] + os: [darwin] + + '@napi-rs/nice-freebsd-x64@1.1.1': + resolution: {integrity: sha512-kHv4kEHAylMYmlNwcQcDtXjklYp4FCf0b05E+0h6nDHsZ+F0bDe04U/tXNOqrx5CmIAth4vwfkjjUmp4c4JktQ==} + engines: {node: '>= 10'} + cpu: [x64] + os: [freebsd] + + '@napi-rs/nice-linux-arm-gnueabihf@1.1.1': + resolution: {integrity: sha512-E1t7K0efyKXZDoZg1LzCOLxgolxV58HCkaEkEvIYQx12ht2pa8hoBo+4OB3qh7e+QiBlp1SRf+voWUZFxyhyqg==} + engines: {node: '>= 10'} + cpu: [arm] + os: [linux] + + '@napi-rs/nice-linux-arm64-gnu@1.1.1': + resolution: {integrity: sha512-CIKLA12DTIZlmTaaKhQP88R3Xao+gyJxNWEn04wZwC2wmRapNnxCUZkVwggInMJvtVElA+D4ZzOU5sX4jV+SmQ==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@napi-rs/nice-linux-arm64-musl@1.1.1': + resolution: {integrity: sha512-+2Rzdb3nTIYZ0YJF43qf2twhqOCkiSrHx2Pg6DJaCPYhhaxbLcdlV8hCRMHghQ+EtZQWGNcS2xF4KxBhSGeutg==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@napi-rs/nice-linux-ppc64-gnu@1.1.1': + resolution: {integrity: sha512-4FS8oc0GeHpwvv4tKciKkw3Y4jKsL7FRhaOeiPei0X9T4Jd619wHNe4xCLmN2EMgZoeGg+Q7GY7BsvwKpL22Tg==} + engines: {node: '>= 10'} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@napi-rs/nice-linux-riscv64-gnu@1.1.1': + resolution: {integrity: sha512-HU0nw9uD4FO/oGCCk409tCi5IzIZpH2agE6nN4fqpwVlCn5BOq0MS1dXGjXaG17JaAvrlpV5ZeyZwSon10XOXw==} + engines: {node: '>= 10'} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@napi-rs/nice-linux-s390x-gnu@1.1.1': + resolution: {integrity: sha512-2YqKJWWl24EwrX0DzCQgPLKQBxYDdBxOHot1KWEq7aY2uYeX+Uvtv4I8xFVVygJDgf6/92h9N3Y43WPx8+PAgQ==} + engines: {node: '>= 10'} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@napi-rs/nice-linux-x64-gnu@1.1.1': + resolution: {integrity: sha512-/gaNz3R92t+dcrfCw/96pDopcmec7oCcAQ3l/M+Zxr82KT4DljD37CpgrnXV+pJC263JkW572pdbP3hP+KjcIg==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@napi-rs/nice-linux-x64-musl@1.1.1': + resolution: {integrity: sha512-xScCGnyj/oppsNPMnevsBe3pvNaoK7FGvMjT35riz9YdhB2WtTG47ZlbxtOLpjeO9SqqQ2J2igCmz6IJOD5JYw==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + libc: [musl] + + '@napi-rs/nice-openharmony-arm64@1.1.1': + resolution: {integrity: sha512-6uJPRVwVCLDeoOaNyeiW0gp2kFIM4r7PL2MczdZQHkFi9gVlgm+Vn+V6nTWRcu856mJ2WjYJiumEajfSm7arPQ==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [openharmony] + + '@napi-rs/nice-win32-arm64-msvc@1.1.1': + resolution: {integrity: sha512-uoTb4eAvM5B2aj/z8j+Nv8OttPf2m+HVx3UjA5jcFxASvNhQriyCQF1OB1lHL43ZhW+VwZlgvjmP5qF3+59atA==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [win32] + + '@napi-rs/nice-win32-ia32-msvc@1.1.1': + resolution: {integrity: sha512-CNQqlQT9MwuCsg1Vd/oKXiuH+TcsSPJmlAFc5frFyX/KkOh0UpBLEj7aoY656d5UKZQMQFP7vJNa1DNUNORvug==} + engines: {node: '>= 10'} + cpu: [ia32] + os: [win32] + + '@napi-rs/nice-win32-x64-msvc@1.1.1': + resolution: {integrity: sha512-vB+4G/jBQCAh0jelMTY3+kgFy00Hlx2f2/1zjMoH821IbplbWZOkLiTYXQkygNTzQJTq5cvwBDgn2ppHD+bglQ==} + engines: {node: '>= 10'} + cpu: [x64] + os: [win32] + + '@napi-rs/nice@1.1.1': + resolution: {integrity: sha512-xJIPs+bYuc9ASBl+cvGsKbGrJmS6fAKaSZCnT0lhahT5rhA2VVy9/EcIgd2JhtEuFOJNx7UHNn/qiTPTY4nrQw==} + engines: {node: '>= 10'} + + '@ngtools/webpack@19.2.27': + resolution: {integrity: sha512-nuKxH4WaRILjlje4143T8XeDWVi5AIDlCMu/SPSKsYtyGxX7AC3sEu0UatFG7rrJkS/SB+fZngtuydoprhvYkQ==} + engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} + peerDependencies: + '@angular/compiler-cli': ^19.0.0 || ^19.2.0-next.0 + typescript: '>=5.5 <5.9' + webpack: ^5.54.0 + + '@nodelib/fs.scandir@2.1.5': + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + + '@nodelib/fs.stat@2.0.5': + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + + '@nodelib/fs.walk@1.2.8': + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + + '@npmcli/agent@3.0.0': + resolution: {integrity: sha512-S79NdEgDQd/NGCay6TCoVzXSj74skRZIKJcpJjC5lOq34SZzyI6MqtiiWoiVWoVrTcGjNeC4ipbh1VIHlpfF5Q==} + engines: {node: ^18.17.0 || >=20.5.0} + + '@npmcli/fs@4.0.0': + resolution: {integrity: sha512-/xGlezI6xfGO9NwuJlnwz/K14qD1kCSAGtacBHnGzeAIuJGazcp45KP5NuyARXoKb7cwulAGWVsbeSxdG/cb0Q==} + engines: {node: ^18.17.0 || >=20.5.0} + + '@npmcli/git@6.0.3': + resolution: {integrity: sha512-GUYESQlxZRAdhs3UhbB6pVRNUELQOHXwK9ruDkwmCv2aZ5y0SApQzUJCg02p3A7Ue2J5hxvlk1YI53c00NmRyQ==} + engines: {node: ^18.17.0 || >=20.5.0} + + '@npmcli/installed-package-contents@3.0.0': + resolution: {integrity: sha512-fkxoPuFGvxyrH+OQzyTkX2LUEamrF4jZSmxjAtPPHHGO0dqsQ8tTKjnIS8SAnPHdk2I03BDtSMR5K/4loKg79Q==} + engines: {node: ^18.17.0 || >=20.5.0} + hasBin: true + + '@npmcli/node-gyp@4.0.0': + resolution: {integrity: sha512-+t5DZ6mO/QFh78PByMq1fGSAub/agLJZDRfJRMeOSNCt8s9YVlTjmGpIPwPhvXTGUIJk+WszlT0rQa1W33yzNA==} + engines: {node: ^18.17.0 || >=20.5.0} + + '@npmcli/package-json@6.2.0': + resolution: {integrity: sha512-rCNLSB/JzNvot0SEyXqWZ7tX2B5dD2a1br2Dp0vSYVo5jh8Z0EZ7lS9TsZ1UtziddB1UfNUaMCc538/HztnJGA==} + engines: {node: ^18.17.0 || >=20.5.0} + + '@npmcli/promise-spawn@8.0.3': + resolution: {integrity: sha512-Yb00SWaL4F8w+K8YGhQ55+xE4RUNdMHV43WZGsiTM92gS+lC0mGsn7I4hLug7pbao035S6bj3Y3w0cUNGLfmkg==} + engines: {node: ^18.17.0 || >=20.5.0} + + '@npmcli/redact@3.2.2': + resolution: {integrity: sha512-7VmYAmk4csGv08QzrDKScdzn11jHPFGyqJW39FyPgPuAp3zIaUmuCo1yxw9aGs+NEJuTGQ9Gwqpt93vtJubucg==} + engines: {node: ^18.17.0 || >=20.5.0} + + '@npmcli/run-script@9.1.0': + resolution: {integrity: sha512-aoNSbxtkePXUlbZB+anS1LqsJdctG5n3UVhfU47+CDdwMi6uNTBMF9gPcQRnqghQd2FGzcwwIFBruFMxjhBewg==} + engines: {node: ^18.17.0 || >=20.5.0} + + '@parcel/watcher-android-arm64@2.6.0': + resolution: {integrity: sha512-trgpLSCKRC/huFjXX/Smh+0sWe4+YtKfktIToiMl59ghz7z+qkH6kMvNnUbLyRs9N11t8l4svSCs1+5B3rOAhA==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [android] + + '@parcel/watcher-darwin-arm64@2.6.0': + resolution: {integrity: sha512-Y3QV0gl7Q1zbfueunkWIERICbEojQFCgpyG7YqOGNFLsckXyI1xu9mAIUpKY9QBYzBtSkN8dBPwd3yiAO9ovMw==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [darwin] + + '@parcel/watcher-darwin-x64@2.6.0': + resolution: {integrity: sha512-Ohv6OpzhUfKYD7Beb8kDvG0jbIxORCYY1JRdZnaBtnjjkJxgD7ZVL0nw2sCYd0yTMKTvz3nnTnOF3cDifK+kvw==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [darwin] + + '@parcel/watcher-freebsd-x64@2.6.0': + resolution: {integrity: sha512-5HmXvDgs8VK+74jF9y9/2FE3/OnlcKmc56tjmSrEuZjpSZOGL+fvAu+HKJBdPs9uwoP2hE6TlSUpXZ/C5jUFmQ==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [freebsd] + + '@parcel/watcher-linux-arm-glibc@2.6.0': + resolution: {integrity: sha512-Ps/hui3A+vMbjdqlqAowK2ZL8+BO8dBjxeWXj6npTBs3jx4wWmbPpaLuqwrQrSqIVMCnpWo238bJ1U37GhQOYg==} + engines: {node: '>= 10.0.0'} + cpu: [arm] + os: [linux] + libc: [glibc] + + '@parcel/watcher-linux-arm-musl@2.6.0': + resolution: {integrity: sha512-9c6AUHgHoG+IY88MRIHupztQiQnrbqHYQjkM2btA+Bf/wQnQMuiD0Wfk1EVv3TlNT3x41uU71rn6E4xh/+zvkw==} + engines: {node: '>= 10.0.0'} + cpu: [arm] + os: [linux] + libc: [musl] + + '@parcel/watcher-linux-arm64-glibc@2.6.0': + resolution: {integrity: sha512-yHRqS2owEXe6Hic9z6Mh1ECsCd+ODVOGvZDyciqRd21+v+o+DnXMOrw50DSpIG2sb8GPEaPPmfeCAWKPJdq46g==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@parcel/watcher-linux-arm64-musl@2.6.0': + resolution: {integrity: sha512-WhB2e/V7rqdHHWZusBSPuy5Ei8S6lSz6FE5TKKQz5h3a0O+C+mhY7vxU9b/stqvMb8beLnPY82ZrFTLKs+SrKA==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@parcel/watcher-linux-x64-glibc@2.6.0': + resolution: {integrity: sha512-ulGE6x6Oz6iAwg75T8YQSoguBWasniIbX+QWpaYPcCnDOpdWX3k+4xbEYPZVLxOuoJI+svJJPD3sEj8G7lrQ3A==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@parcel/watcher-linux-x64-musl@2.6.0': + resolution: {integrity: sha512-tkBYKt7YQrjIJWYDnto2YgO8MRkjlMTSNoRHzsXinBqbLdeOM3L32wPZJvIZxqaLMfSlS/4sUjH/6STVP/XDLw==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [linux] + libc: [musl] + + '@parcel/watcher-win32-arm64@2.6.0': + resolution: {integrity: sha512-gIZAP23jaHjGWasY/TY6yL7NHFClf0Ga7FN+iINvk+KN94rhm94lYZhFsbYFNcA04/onvGD9kKmiJLJB2HbNwQ==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [win32] + + '@parcel/watcher-win32-x64@2.6.0': + resolution: {integrity: sha512-cA+/pXV2YkfxlIcXOQ5fSWqAzzPyD78/x5qbK/I0vUkrlYHA8TIz+MXjAbGouguKVSI4bOmkTSJ1/poVSsgt+A==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [win32] + + '@parcel/watcher@2.6.0': + resolution: {integrity: sha512-7FNeNl8NCE7aINx7WXiKQrPYZWC/hvrTsmk6zmxbI7LTXE7hVek/n8AfVgpe2y82zl3w0HvCHN0bVKMBoJcC0w==} + engines: {node: '>= 10.0.0'} + + '@pkgjs/parseargs@0.11.0': + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} + engines: {node: '>=14'} + + '@rollup/rollup-android-arm-eabi@4.59.0': + resolution: {integrity: sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==} + cpu: [arm] + os: [android] + + '@rollup/rollup-android-arm-eabi@4.62.3': + resolution: {integrity: sha512-c0wdcekXtQvvn5Tsrk/+op/gUArrbWaFduBnTLP2l1cKLSQs4diMWjJw3m6A0DdzT8dAAX95KpkJ3qynCePbmw==} + cpu: [arm] + os: [android] + + '@rollup/rollup-android-arm64@4.59.0': + resolution: {integrity: sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q==} + cpu: [arm64] + os: [android] + + '@rollup/rollup-android-arm64@4.62.3': + resolution: {integrity: sha512-3YjElDdWN+qXAFbJ/CzPV+0wspLqh54k/I6GfdYtEJRqg7buSgc1yPM3B+93j1M4neobtkATHZTmxK2AMVGfnA==} + cpu: [arm64] + os: [android] + + '@rollup/rollup-darwin-arm64@4.59.0': + resolution: {integrity: sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg==} + cpu: [arm64] + os: [darwin] + + '@rollup/rollup-darwin-arm64@4.62.3': + resolution: {integrity: sha512-Pch2pFNOxxz1hTjypIdPyRTR6riiwRl84+VcN9djS680fw+Co1nAJINrdpqp7KV0NvyuU8ilZXZCjd7ykJl1GQ==} + cpu: [arm64] + os: [darwin] + + '@rollup/rollup-darwin-x64@4.59.0': + resolution: {integrity: sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w==} + cpu: [x64] + os: [darwin] + + '@rollup/rollup-darwin-x64@4.62.3': + resolution: {integrity: sha512-LEuncFUHFiF8t4yZVZvvZA1wk0pjAscRnsrn1EfTEmN4HXotBi2YtcnLRyaK6UbuczW7xZS5ES+81Rdz8Z0T6g==} + cpu: [x64] + os: [darwin] + + '@rollup/rollup-freebsd-arm64@4.59.0': + resolution: {integrity: sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA==} + cpu: [arm64] + os: [freebsd] + + '@rollup/rollup-freebsd-arm64@4.62.3': + resolution: {integrity: sha512-zvBUvsQUpOWALdDsk6qbS8bXf2VxmPisuudNDrY7x0p0jBdsoZl8HsHczIOgkQiZldmcacMKtBzpoGVNeIe2bQ==} + cpu: [arm64] + os: [freebsd] + + '@rollup/rollup-freebsd-x64@4.59.0': + resolution: {integrity: sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg==} + cpu: [x64] + os: [freebsd] + + '@rollup/rollup-freebsd-x64@4.62.3': + resolution: {integrity: sha512-C2KmNrcSem/AMg984H/dev+si0lieQGdXdR/lYGJnuumXnFb9Y7QdiI62obFdLlxRYLBv4P0eUVIDbD4c1vVvw==} + cpu: [x64] + os: [freebsd] + + '@rollup/rollup-linux-arm-gnueabihf@4.59.0': + resolution: {integrity: sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==} + cpu: [arm] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-arm-gnueabihf@4.62.3': + resolution: {integrity: sha512-ggXnsTAEzNQx74XpunRsiZ9aBZDsI7XIa0hm2nzR9f4WzH5/f/d73ZSDaC5ejJ8YLY4NW+V3wr0tjOaeCq8hqA==} + cpu: [arm] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-arm-musleabihf@4.59.0': + resolution: {integrity: sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==} + cpu: [arm] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-arm-musleabihf@4.62.3': + resolution: {integrity: sha512-2vng+FlzNUhKZxtej3IUqJgbZoQk2M/dwQM20+ULV0R/E/8tr9/P6uEf2iiGIk4HL0zMKh5Jry7mUHdUOvyGgA==} + cpu: [arm] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-arm64-gnu@4.59.0': + resolution: {integrity: sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-arm64-gnu@4.62.3': + resolution: {integrity: sha512-LLLFZKt4/Nraf9rxDkhiU8QVgLF4WmCkfr0L4fj0fPfIZFBib0DeiFk1hhaYKd03LFAFJcxHslhDFlNJLylf5Q==} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-arm64-musl@4.59.0': + resolution: {integrity: sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-arm64-musl@4.62.3': + resolution: {integrity: sha512-WJkdQCvS9sWNOUBJZfQRKpZGFBztRzcowI+nndmflKgU4XY+3a420FgTOSKTsVqJbnzSxeT4vaJalpOaPo2YCQ==} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-loong64-gnu@4.59.0': + resolution: {integrity: sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==} + cpu: [loong64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-loong64-gnu@4.62.3': + resolution: {integrity: sha512-PwHXCCS2n64/1Ot6rP1YEYA02MGYBcQlr8CSZZyrUG2O7NH6NklYmvr9v3Jy+5e/eDeNchc/ukmKJi9LuflMIQ==} + cpu: [loong64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-loong64-musl@4.59.0': + resolution: {integrity: sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==} + cpu: [loong64] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-loong64-musl@4.62.3': + resolution: {integrity: sha512-vUjxINQu3RC8NZS3ykk1gN65gIz8pAopOq2HXuZhiIxHdx7TFvDG+jgrdSgInu1Eza4/Rfi2VzZgyIgEH4WOaw==} + cpu: [loong64] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-ppc64-gnu@4.59.0': + resolution: {integrity: sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-ppc64-gnu@4.62.3': + resolution: {integrity: sha512-wzko4aJ13+0G3kGnviCg5gnXFKd40izKsrf2uOw12US4XqprkDrmwOpeW14aSNa37V8bfPcz5Fkob6LZ3BAPmA==} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-ppc64-musl@4.59.0': + resolution: {integrity: sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==} + cpu: [ppc64] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-ppc64-musl@4.62.3': + resolution: {integrity: sha512-8120ue0JUMSwy11stlwnfdX3pPd+WZYGCDBwEHWtIHi6pOpZmsEF5QKB7a/UN+XFdqvobxz98kv8RTqikyCEBw==} + cpu: [ppc64] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-riscv64-gnu@4.59.0': + resolution: {integrity: sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-riscv64-gnu@4.62.3': + resolution: {integrity: sha512-XLFHnR3tXMjbOCh2vtVJHmxt+995uJsTERQyseFDRA0xxMxyTZPLa3OIUlyFaO4mF/Lu0FjmWHCuPXJT1n/IOg==} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-riscv64-musl@4.59.0': + resolution: {integrity: sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==} + cpu: [riscv64] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-riscv64-musl@4.62.3': + resolution: {integrity: sha512-se6yXvNGMIl0f+RQzyh7XAmia8/9kplQx424wnG2w0C1oi6XgO6Y8otKhdXFHbHs88Ihavzmvh1NWjuovE76BQ==} + cpu: [riscv64] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-s390x-gnu@4.59.0': + resolution: {integrity: sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-s390x-gnu@4.62.3': + resolution: {integrity: sha512-gNoxRefktVIiGflpONuxWWXZAzIQG++z9qHO3xKwk4WdDMuQja3JHGfE1u0i3PfPDyvhypdk+WrgIJqLhGG7sg==} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-x64-gnu@4.59.0': + resolution: {integrity: sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-x64-gnu@4.62.3': + resolution: {integrity: sha512-V4KtWtQfAFMU7+9/A/VDps/VI8CHd3cYz0L8sgJzz8qK7eY7wI4ruFD82UYIYvW9Z4DtlTfhQcsl4XyPHW5uSg==} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-x64-musl@4.59.0': + resolution: {integrity: sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==} + cpu: [x64] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-x64-musl@4.62.3': + resolution: {integrity: sha512-LBx9LYXvj2CBkMkjLdNAWLwH0MLMin7do2VcVo9kVPibGLkY0BQQut2fv7NVqkXqZ/CrAu9LqDHVV1xHCMpCPw==} + cpu: [x64] + os: [linux] + libc: [musl] + + '@rollup/rollup-openbsd-x64@4.59.0': + resolution: {integrity: sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==} + cpu: [x64] + os: [openbsd] + + '@rollup/rollup-openbsd-x64@4.62.3': + resolution: {integrity: sha512-ABVf3Q0RCu7NcyCCOZQI0pJ3GuSdfSl8EXcy88QtdceIMIoCUdfhsJChZ64L9zVM2aJHjde1Bhn5uqSRcX9ySA==} + cpu: [x64] + os: [openbsd] + + '@rollup/rollup-openharmony-arm64@4.59.0': + resolution: {integrity: sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA==} + cpu: [arm64] + os: [openharmony] + + '@rollup/rollup-openharmony-arm64@4.62.3': + resolution: {integrity: sha512-+2Cy/ldweGBLlPIKsQLF8U5N44a0KDdbrk1rAjHOM9M2K+kGdIVjHLmmrZIcx+9Ny3ke/1JomCsDI1ocb11+sg==} + cpu: [arm64] + os: [openharmony] + + '@rollup/rollup-win32-arm64-msvc@4.59.0': + resolution: {integrity: sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A==} + cpu: [arm64] + os: [win32] + + '@rollup/rollup-win32-arm64-msvc@4.62.3': + resolution: {integrity: sha512-dtZvzc8BedpSaFNy75x6uiWwAGTH+aZHDtdrqP6qk+WcLJrfti6sGje1ZJ9UxyzDLF23d/mV+PaMwuC0hL7UVA==} + cpu: [arm64] + os: [win32] + + '@rollup/rollup-win32-ia32-msvc@4.59.0': + resolution: {integrity: sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA==} + cpu: [ia32] + os: [win32] + + '@rollup/rollup-win32-ia32-msvc@4.62.3': + resolution: {integrity: sha512-Rj8Ra4noo+aYy7sKBggCx0407mws34kAb1ySyWuq5DAtFBQdkSwnsjCgPrhPe9cvgBKZIukpE+CVHvORCS93kQ==} + cpu: [ia32] + os: [win32] + + '@rollup/rollup-win32-x64-gnu@4.59.0': + resolution: {integrity: sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA==} + cpu: [x64] + os: [win32] + + '@rollup/rollup-win32-x64-gnu@4.62.3': + resolution: {integrity: sha512-vp7N084ew/odXn2gi/mzm9mUkQu9l6AiN6dt4IeUM2Uvm9o+cVmP+YkqbMOteLbiGgqBBlJZjIMYVCfOOIVbVQ==} + cpu: [x64] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.59.0': + resolution: {integrity: sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA==} + cpu: [x64] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.62.3': + resolution: {integrity: sha512-MOG/3gTOn4Fwf574RVOaY61I5o6P90legkFADiTyn1hyjNydT+cerU2rLUwPdZkKKyJ+iT+K9p7WXK4LM1Ka6g==} + cpu: [x64] + os: [win32] + + '@schematics/angular@19.2.27': + resolution: {integrity: sha512-kJX5nyDjwo6iHQ+g/AJa+4SyHRSQyGgutpqXUIuYY2htGWVS1HUQlHfwAER5btjSNKe/iHgh4pzYGZfvJ2V6/A==} + engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} + + '@sigstore/bundle@3.1.0': + resolution: {integrity: sha512-Mm1E3/CmDDCz3nDhFKTuYdB47EdRFRQMOE/EAbiG1MJW77/w1b3P7Qx7JSrVJs8PfwOLOVcKQCHErIwCTyPbag==} + engines: {node: ^18.17.0 || >=20.5.0} + + '@sigstore/core@2.0.0': + resolution: {integrity: sha512-nYxaSb/MtlSI+JWcwTHQxyNmWeWrUXJJ/G4liLrGG7+tS4vAz6LF3xRXqLH6wPIVUoZQel2Fs4ddLx4NCpiIYg==} + engines: {node: ^18.17.0 || >=20.5.0} + + '@sigstore/protobuf-specs@0.4.3': + resolution: {integrity: sha512-fk2zjD9117RL9BjqEwF7fwv7Q/P9yGsMV4MUJZ/DocaQJ6+3pKr+syBq1owU5Q5qGw5CUbXzm+4yJ2JVRDQeSA==} + engines: {node: ^18.17.0 || >=20.5.0} + + '@sigstore/sign@3.1.0': + resolution: {integrity: sha512-knzjmaOHOov1Ur7N/z4B1oPqZ0QX5geUfhrVaqVlu+hl0EAoL4o+l0MSULINcD5GCWe3Z0+YJO8ues6vFlW0Yw==} + engines: {node: ^18.17.0 || >=20.5.0} + + '@sigstore/tuf@3.1.1': + resolution: {integrity: sha512-eFFvlcBIoGwVkkwmTi/vEQFSva3xs5Ot3WmBcjgjVdiaoelBLQaQ/ZBfhlG0MnG0cmTYScPpk7eDdGDWUcFUmg==} + engines: {node: ^18.17.0 || >=20.5.0} + + '@sigstore/verify@2.1.1': + resolution: {integrity: sha512-hVJD77oT67aowHxwT4+M6PGOp+E2LtLdTK3+FC0lBO9T7sYwItDMXZ7Z07IDCvR1M717a4axbIWckrW67KMP/w==} + engines: {node: ^18.17.0 || >=20.5.0} + + '@sindresorhus/merge-streams@2.3.0': + resolution: {integrity: sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==} + engines: {node: '>=18'} + + '@socket.io/component-emitter@3.1.2': + resolution: {integrity: sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==} + + '@tufjs/canonical-json@2.0.0': + resolution: {integrity: sha512-yVtV8zsdo8qFHe+/3kw81dSLyF7D576A5cCFCi4X7B39tWT7SekaEFUnvnWJHz+9qO7qJTah1JbrDjWKqFtdWA==} + engines: {node: ^16.14.0 || >=18.0.0} + + '@tufjs/models@3.0.1': + resolution: {integrity: sha512-UUYHISyhCU3ZgN8yaear3cGATHb3SMuKHsQ/nVbHXcmnBf+LzQ/cQfhNG+rfaSHgqGKNEm2cOCLVLELStUQ1JA==} + engines: {node: ^18.17.0 || >=20.5.0} + + '@tweenjs/tween.js@23.1.3': + resolution: {integrity: sha512-vJmvvwFxYuGnF2axRtPYocag6Clbb5YS7kLL+SO/TeVFzHqDIWrNKYtcsPMibjDx9O+bu+psAy9NKfWklassUA==} + + '@types/body-parser@1.19.6': + resolution: {integrity: sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==} + + '@types/bonjour@3.5.13': + resolution: {integrity: sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ==} + + '@types/connect-history-api-fallback@1.5.4': + resolution: {integrity: sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw==} + + '@types/connect@3.4.38': + resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==} + + '@types/cors@2.8.19': + resolution: {integrity: sha512-mFNylyeyqN93lfe/9CSxOGREz8cpzAhH+E93xJ4xWQf62V8sQ/24reV2nyzUWM6H6Xji+GGHpkbLe7pVoUEskg==} + + '@types/eslint-scope@3.7.7': + resolution: {integrity: sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==} + + '@types/eslint@9.6.1': + resolution: {integrity: sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==} + + '@types/estree@1.0.8': + resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} + + '@types/estree@1.0.9': + resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==} + + '@types/express-serve-static-core@4.19.9': + resolution: {integrity: sha512-QP2ESEe/ImWY0HDwNAnK9PvEffUyhLTnWkk7KXzHfyeWAnlrDe1fN77bXl6ia8KT3wPlmA7t9/VPRpnf4Ex9sg==} + + '@types/express@4.17.25': + resolution: {integrity: sha512-dVd04UKsfpINUnK0yBoYHDF3xu7xVH4BuDotC/xGuycx4CgbP48X/KF/586bcObxT0HENHXEU8Nqtu6NR+eKhw==} + + '@types/fs-extra@8.1.5': + resolution: {integrity: sha512-0dzKcwO+S8s2kuF5Z9oUWatQJj5Uq/iqphEtE3GQJVRRYm/tD1LglU2UnXi2A8jLq5umkGouOXOR9y0n613ZwQ==} + + '@types/http-errors@2.0.5': + resolution: {integrity: sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==} + + '@types/http-proxy@1.17.17': + resolution: {integrity: sha512-ED6LB+Z1AVylNTu7hdzuBqOgMnvG/ld6wGCG8wFnAzKX5uyW2K3WD52v0gnLCTK/VLpXtKckgWuyScYK6cSPaw==} + + '@types/jasmine@5.1.15': + resolution: {integrity: sha512-ZAC8KjmV2MJxbNTrwXFN+HKeajpXQZp6KpPiR6Aa4XvaEnjP6qh23lL/Rqb7AYzlp3h/rcwDrQ7Gg7q28cQTQg==} + + '@types/json-schema@7.0.15': + resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + + '@types/matter-js@0.20.2': + resolution: {integrity: sha512-3PPKy3QxvZ89h9+wdBV2488I1JLVs7DEpIkPvgO8JC1mUdiVSO37ZIvVctOTD7hIq8OAL2gJ3ugGSuUip6DhCw==} + + '@types/mime@1.3.5': + resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==} + + '@types/node-forge@1.3.14': + resolution: {integrity: sha512-mhVF2BnD4BO+jtOp7z1CdzaK4mbuK0LLQYAvdOLqHTavxFNq4zA1EmYkpnFjP8HOUzedfQkRnp0E2ulSAYSzAw==} + + '@types/node@26.1.2': + resolution: {integrity: sha512-Vu4a5UFA9rIIFJ7rB/Vaafh9lrCQszopTCx6KjFboXTGQbPNasehVR5TEiithSDGyd1DEiUByggTZsg8jukeIg==} + + '@types/qs@6.15.1': + resolution: {integrity: sha512-GZHUBZR9hckSUhrxmp1nG6NwdpM9fCunJwyThLW1X3AyHgd9IlHb6VANpQQqDr2o/qQp6McZ3y/IA2rVzKzSbw==} + + '@types/range-parser@1.2.7': + resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==} + + '@types/retry@0.12.2': + resolution: {integrity: sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==} + + '@types/send@0.17.6': + resolution: {integrity: sha512-Uqt8rPBE8SY0RK8JB1EzVOIZ32uqy8HwdxCnoCOsYrvnswqmFZ/k+9Ikidlk/ImhsdvBsloHbAlewb2IEBV/Og==} + + '@types/send@1.2.1': + resolution: {integrity: sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==} + + '@types/serve-index@1.9.4': + resolution: {integrity: sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug==} + + '@types/serve-static@1.15.10': + resolution: {integrity: sha512-tRs1dB+g8Itk72rlSI2ZrW6vZg0YrLI81iQSTkMmOqnqCaNr/8Ek4VwWcN5vZgCYWbg/JJSGBlUaYGAOP73qBw==} + + '@types/slice-ansi@4.0.0': + resolution: {integrity: sha512-+OpjSaq85gvlZAYINyzKpLeiFkSC4EsC6IIiT6v6TLSU5k5U83fHGj9Lel8oKEXM0HqgrMVCjXPDPVICtxF7EQ==} + + '@types/sockjs@0.3.36': + resolution: {integrity: sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==} + + '@types/stats.js@0.17.4': + resolution: {integrity: sha512-jIBvWWShCvlBqBNIZt0KAshWpvSjhkwkEu4ZUcASoAvhmrgAUI2t1dXrjSL4xXVLB4FznPrIsX3nKXFl/Dt4vA==} + + '@types/three@0.185.1': + resolution: {integrity: sha512-db1xTb+EgYF2didW+eudSvVPtn75zo+fGsY8ShQrJY/B5ZBmC2Fiaykv3aImHAlCNEGuMPkPGXBJGLwzu5mC7A==} + + '@types/webxr@0.5.24': + resolution: {integrity: sha512-h8fgEd/DpoS9CBrjEQXR+dIDraopAEfu4wYVNY2tEPwk60stPWhvZMf4Foo5FakuQ7HFZoa8WceaWFervK2Ovg==} + + '@types/ws@8.18.1': + resolution: {integrity: sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==} + + '@vitejs/plugin-basic-ssl@1.2.0': + resolution: {integrity: sha512-mkQnxTkcldAzIsomk1UuLfAu9n+kpQ3JbHcpCp7d2Oo6ITtji8pHS3QToOWjhPFvNQSnhlkAjmGbhv2QvwO/7Q==} + engines: {node: '>=14.21.3'} + peerDependencies: + vite: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 + + '@webassemblyjs/ast@1.14.1': + resolution: {integrity: sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==} + + '@webassemblyjs/floating-point-hex-parser@1.13.2': + resolution: {integrity: sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==} + + '@webassemblyjs/helper-api-error@1.13.2': + resolution: {integrity: sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==} + + '@webassemblyjs/helper-buffer@1.14.1': + resolution: {integrity: sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==} + + '@webassemblyjs/helper-numbers@1.13.2': + resolution: {integrity: sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==} + + '@webassemblyjs/helper-wasm-bytecode@1.13.2': + resolution: {integrity: sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==} + + '@webassemblyjs/helper-wasm-section@1.14.1': + resolution: {integrity: sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==} + + '@webassemblyjs/ieee754@1.13.2': + resolution: {integrity: sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==} + + '@webassemblyjs/leb128@1.13.2': + resolution: {integrity: sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==} + + '@webassemblyjs/utf8@1.13.2': + resolution: {integrity: sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==} + + '@webassemblyjs/wasm-edit@1.14.1': + resolution: {integrity: sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==} + + '@webassemblyjs/wasm-gen@1.14.1': + resolution: {integrity: sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==} + + '@webassemblyjs/wasm-opt@1.14.1': + resolution: {integrity: sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==} + + '@webassemblyjs/wasm-parser@1.14.1': + resolution: {integrity: sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==} + + '@webassemblyjs/wast-printer@1.14.1': + resolution: {integrity: sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==} + + '@xmldom/xmldom@0.9.10': + resolution: {integrity: sha512-A9gOqLdi6cV4ibazAjcQufGj0B1y/vDqYrcuP6d/6x8P27gRS8643Dj9o1dEKtB6O7fwxb2FgBmJS2mX7gpvdw==} + engines: {node: '>=14.6'} + + '@xtuc/ieee754@1.2.0': + resolution: {integrity: sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==} + + '@xtuc/long@4.2.2': + resolution: {integrity: sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==} + + '@yarnpkg/lockfile@1.1.0': + resolution: {integrity: sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==} + + abbrev@3.0.1: + resolution: {integrity: sha512-AO2ac6pjRB3SJmGJo+v5/aK6Omggp6fsLrs6wN9bd35ulu4cCwaAU9+7ZhXjeqHVkaHThLuzH0nZr0YpCDhygg==} + engines: {node: ^18.17.0 || >=20.5.0} + + accepts@1.3.8: + resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} + engines: {node: '>= 0.6'} + + acorn-import-phases@1.0.4: + resolution: {integrity: sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==} + engines: {node: '>=10.13.0'} + peerDependencies: + acorn: ^8.14.0 + + acorn@8.18.0: + resolution: {integrity: sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ==} + engines: {node: '>=0.4.0'} + hasBin: true + + adjust-sourcemap-loader@4.0.0: + resolution: {integrity: sha512-OXwN5b9pCUXNQHJpwwD2qP40byEmSgzj8B4ydSN0uMNYWiFmJ6x6KwUllMmfk8Rwu/HJDFR7U8ubsWBoN0Xp0A==} + engines: {node: '>=8.9'} + + agent-base@7.1.4: + resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==} + engines: {node: '>= 14'} + + ajv-formats@2.1.1: + resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==} + peerDependencies: + ajv: ^8.0.0 + peerDependenciesMeta: + ajv: + optional: true + + ajv-formats@3.0.1: + resolution: {integrity: sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==} + peerDependencies: + ajv: ^8.0.0 + peerDependenciesMeta: + ajv: + optional: true + + ajv-keywords@5.1.0: + resolution: {integrity: sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==} + peerDependencies: + ajv: ^8.8.2 + + ajv@8.18.0: + resolution: {integrity: sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==} + + ajv@8.20.0: + resolution: {integrity: sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==} + + ansi-colors@4.1.3: + resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} + engines: {node: '>=6'} + + ansi-escapes@7.3.0: + resolution: {integrity: sha512-BvU8nYgGQBxcmMuEeUEmNTvrMVjJNSH7RgW24vXexN4Ven6qCvy4TntnvlnwnMLTVlcRQQdbRY8NKnaIoeWDNg==} + engines: {node: '>=18'} + + ansi-html-community@0.0.8: + resolution: {integrity: sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==} + engines: {'0': node >= 0.8.0} + hasBin: true + + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-regex@6.2.2: + resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==} + engines: {node: '>=12'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + ansi-styles@6.2.3: + resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==} + engines: {node: '>=12'} + + anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + + array-flatten@1.1.1: + resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} + + astral-regex@2.0.0: + resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==} + engines: {node: '>=8'} + + at-least-node@1.0.0: + resolution: {integrity: sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==} + engines: {node: '>= 4.0.0'} + + autoprefixer@10.4.20: + resolution: {integrity: sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==} + engines: {node: ^10 || ^12 || >=14} + hasBin: true + peerDependencies: + postcss: ^8.1.0 + + babel-loader@9.2.1: + resolution: {integrity: sha512-fqe8naHt46e0yIdkjUZYqddSXfej3AHajX+CSO5X7oy0EmPc6o5Xh+RClNoHjnieWz9AW4kZxW9yyFMhVB1QLA==} + engines: {node: '>= 14.15.0'} + peerDependencies: + '@babel/core': ^7.12.0 + webpack: '>=5' + + babel-plugin-polyfill-corejs2@0.4.17: + resolution: {integrity: sha512-aTyf30K/rqAsNwN76zYrdtx8obu0E4KoUME29B1xj+B3WxgvWkp943vYQ+z8Mv3lw9xHXMHpvSPOBxzAkIa94w==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + + babel-plugin-polyfill-corejs3@0.11.1: + resolution: {integrity: sha512-yGCqvBT4rwMczo28xkH/noxJ6MZ4nJfkVYdoDaC/utLtWrXxv27HVrzAeSbqR8SxDsp46n0YF47EbHoixy6rXQ==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + + babel-plugin-polyfill-regenerator@0.6.8: + resolution: {integrity: sha512-M762rNHfSF1EV3SLtnCJXFoQbbIIz0OyRwnCmV0KPC7qosSfCO0QLTSuJX3ayAebubhE6oYBAYPrBA5ljowaZg==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + balanced-match@4.0.4: + resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} + engines: {node: 18 || 20 || >=22} + + base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + + base64id@2.0.0: + resolution: {integrity: sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==} + engines: {node: ^4.5.0 || >= 5.9} + + baseline-browser-mapping@2.11.5: + resolution: {integrity: sha512-xJo6a6YZnwZfnyGmQKWMbVOcii7XRibjOskRh+WJ9UHQoX16xrQrcIgAMQOzfvs8XiLMx6ih/fsLPF73iY2D1A==} + engines: {node: '>=6.0.0'} + hasBin: true + + batch@0.6.1: + resolution: {integrity: sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==} + + beasties@0.3.2: + resolution: {integrity: sha512-p4AF8uYzm9Fwu8m/hSVTCPXrRBPmB34hQpHsec2KOaR9CZmgoU8IOv4Cvwq4hgz2p4hLMNbsdNl5XeA6XbAQwA==} + engines: {node: '>=14.0.0'} + + big-integer@1.6.52: + resolution: {integrity: sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==} + engines: {node: '>=0.6'} + + big.js@5.2.2: + resolution: {integrity: sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==} + + binary-extensions@2.3.0: + resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} + engines: {node: '>=8'} + + bl@4.1.0: + resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} + + body-parser@1.20.6: + resolution: {integrity: sha512-p5tAzS57i5MV9fZFDj9LeIiTZEufbSe2eDozP+ElheSUq1m74CRq1jI4mYNDdVs9vQztXFLuk/Gd6BWTdwRJ5g==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + + bonjour-service@1.4.3: + resolution: {integrity: sha512-2Kd5UYlFUVgAKMTyuBLl6w49wqfOnbxHqmuH0oCl/n7TfAikR0zoowNOP5BU4dfXmm+Vr9JyEN370auSMx+CNg==} + + boolbase@1.0.0: + resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} + + bplist-creator@0.1.0: + resolution: {integrity: sha512-sXaHZicyEEmY86WyueLTQesbeoH/mquvarJaQNbjuOQO+7gbFcDEWqKmcWA4cOTLzFlfgvkiVxolk1k5bBIpmg==} + + bplist-parser@0.3.1: + resolution: {integrity: sha512-PyJxiNtA5T2PlLIeBot4lbp7rj4OadzjnMZD/G5zuBNt8ei/yCU7+wW0h2bag9vr8c+/WuRWmSxbqAl9hL1rBA==} + engines: {node: '>= 5.10.0'} + + bplist-parser@0.3.2: + resolution: {integrity: sha512-apC2+fspHGI3mMKj+dGevkGo/tCqVB8jMb6i+OX+E29p0Iposz07fABkRIfVUPNd5A5VbuOz1bZbnmkKLYF+wQ==} + engines: {node: '>= 5.10.0'} + + brace-expansion@1.1.16: + resolution: {integrity: sha512-IDw48K2/2kRkg9LdJxurvq3lV3aBgq0REY89duEqFRthjlPdXHKMj7EnQOXVckxzgisinf3nHfrcE2FufFLXMw==} + + brace-expansion@2.1.2: + resolution: {integrity: sha512-w5JZcKgdhDOgOwm8H+KgbosopHMuGcl6qbulwjtz3SM7I7P3yW1eAjzMPLrIE+NQ9vjgANKHWeMHnrT0OXW1oA==} + + brace-expansion@5.0.8: + resolution: {integrity: sha512-JZyDyq3D4AUifKTPOB7DELf6XsB3WdPuNxCtob1vFXPsSXhdAiHBWJ/tJ8HAc9aH84BK+5JFZLNkJKx3G9kzQg==} + engines: {node: 20 || >=22} + + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} + + browserslist@4.28.7: + resolution: {integrity: sha512-JxV13hNrFxqjOc8alRbq9dK1MM79NEXYpma2B2J4wAtpWS5zIEIKqWPGCl7N4o7Uc7B7itylh7SuDujATRyyTw==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + + buffer-crc32@0.2.13: + resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} + + buffer-from@1.1.2: + resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + + buffer@5.7.1: + resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} + + bundle-name@4.1.0: + resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==} + engines: {node: '>=18'} + + bytes@3.1.2: + resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} + engines: {node: '>= 0.8'} + + cacache@19.0.1: + resolution: {integrity: sha512-hdsUxulXCi5STId78vRVYEtDAjq99ICAUktLTeTYsLoTE6Z8dS0c8pWNCxwdrk9YfJeobDZc2Y186hD/5ZQgFQ==} + engines: {node: ^18.17.0 || >=20.5.0} + + call-bind-apply-helpers@1.0.2: + resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} + engines: {node: '>= 0.4'} + + call-bound@1.0.4: + resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} + engines: {node: '>= 0.4'} + + callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + + caniuse-lite@1.0.30001806: + resolution: {integrity: sha512-72Cuvd95zbSYPKq6Fhg8eDJRlzgWDf7/mtoZv6Qe/DYNCEBdNxoA3+rZAU2ZhGCpZlns3EssFavaZomckT5Uuw==} + + chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + + chardet@2.2.0: + resolution: {integrity: sha512-rddelWYNPRrXq6PtNEN2S3f6t9ILzvqaN5pVgi4kqt9jHQaXIial9PznB5iSPVlQSLNaaH22ItWz3EJtQ10+OA==} + + chokidar@3.6.0: + resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} + engines: {node: '>= 8.10.0'} + + chokidar@4.0.3: + resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==} + engines: {node: '>= 14.16.0'} + + chownr@2.0.0: + resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} + engines: {node: '>=10'} + + chownr@3.0.0: + resolution: {integrity: sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==} + engines: {node: '>=18'} + + chrome-trace-event@1.0.4: + resolution: {integrity: sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==} + engines: {node: '>=6.0'} + + cli-cursor@3.1.0: + resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==} + engines: {node: '>=8'} + + cli-cursor@5.0.0: + resolution: {integrity: sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==} + engines: {node: '>=18'} + + cli-spinners@2.9.2: + resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==} + engines: {node: '>=6'} + + cli-truncate@4.0.0: + resolution: {integrity: sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==} + engines: {node: '>=18'} + + cli-width@4.1.0: + resolution: {integrity: sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==} + engines: {node: '>= 12'} + + cliui@7.0.4: + resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} + + cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + + clone-deep@4.0.1: + resolution: {integrity: sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==} + engines: {node: '>=6'} + + clone@1.0.4: + resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} + engines: {node: '>=0.8'} + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + colorette@2.0.20: + resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} + + commander@12.1.0: + resolution: {integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==} + engines: {node: '>=18'} + + commander@2.20.3: + resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} + + common-path-prefix@3.0.0: + resolution: {integrity: sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==} + + compressible@2.0.18: + resolution: {integrity: sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==} + engines: {node: '>= 0.6'} + + compression@1.8.1: + resolution: {integrity: sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==} + engines: {node: '>= 0.8.0'} + + concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + + connect-history-api-fallback@2.0.0: + resolution: {integrity: sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==} + engines: {node: '>=0.8'} + + connect@3.7.0: + resolution: {integrity: sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==} + engines: {node: '>= 0.10.0'} + + content-disposition@0.5.4: + resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} + engines: {node: '>= 0.6'} + + content-type@1.0.5: + resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} + engines: {node: '>= 0.6'} + + convert-source-map@1.9.0: + resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==} + + convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + + cookie-signature@1.0.7: + resolution: {integrity: sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==} + + cookie@0.7.2: + resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==} + engines: {node: '>= 0.6'} + + copy-anything@2.0.6: + resolution: {integrity: sha512-1j20GZTsvKNkc4BY3NpMOM8tt///wY3FpIzozTOFO2ffuZcV61nojHXVKIy3WM+7ADCy5FVhdZYHYDdgTU0yJw==} + + copy-webpack-plugin@12.0.2: + resolution: {integrity: sha512-SNwdBeHyII+rWvee/bTnAYyO8vfVdcSTud4EIb6jcZ8inLeWucJE0DnxXQBjlQ5zlteuuvooGQy3LIyGxhvlOA==} + engines: {node: '>= 18.12.0'} + peerDependencies: + webpack: ^5.1.0 + + core-js-compat@3.49.0: + resolution: {integrity: sha512-VQXt1jr9cBz03b331DFDCCP90b3fanciLkgiOoy8SBHy06gNf+vQ1A3WFLqG7I8TipYIKeYK9wxd0tUrvHcOZA==} + + core-util-is@1.0.3: + resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} + + cors@2.8.6: + resolution: {integrity: sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==} + engines: {node: '>= 0.10'} + + cosmiconfig@9.0.2: + resolution: {integrity: sha512-gtTZxTDau1wL7Y7zifc2dd8jHSK/k6BTx/2Xp/BpdlAdnlYWFVt7qhJqgwi7637yRwRQ3qL4ZidbB4I8tA5VOg==} + engines: {node: '>=14'} + peerDependencies: + typescript: '>=4.9.5' + peerDependenciesMeta: + typescript: + optional: true + + cross-spawn@7.0.6: + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} + engines: {node: '>= 8'} + + css-loader@7.1.2: + resolution: {integrity: sha512-6WvYYn7l/XEGN8Xu2vWFt9nVzrCn39vKyTEFf/ExEyoksJjjSZV/0/35XPlMbpnr6VGhZIUg5yJrL8tGfes/FA==} + engines: {node: '>= 18.12.0'} + peerDependencies: + '@rspack/core': 0.x || 1.x + webpack: ^5.27.0 + peerDependenciesMeta: + '@rspack/core': + optional: true + webpack: + optional: true + + css-select@5.2.2: + resolution: {integrity: sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==} + + css-what@6.2.2: + resolution: {integrity: sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==} + engines: {node: '>= 6'} + + cssesc@3.0.0: + resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} + engines: {node: '>=4'} + hasBin: true + + custom-event@1.0.1: + resolution: {integrity: sha512-GAj5FOq0Hd+RsCGVJxZuKaIDXDf3h6GQoNEjFgbLLI/trgtavwUbSnZ5pVfg27DVCaWjIohryS0JFwIJyT2cMg==} + + date-format@4.0.14: + resolution: {integrity: sha512-39BOQLs9ZjKh0/patS9nrT8wc3ioX3/eA/zgbKNopnF2wCqJEoxywwwElATYvRsXdnOxA/OQeQoFZ3rFjVajhg==} + engines: {node: '>=4.0'} + + debug@2.6.9: + resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + debug@4.4.3: + resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + default-browser-id@5.0.1: + resolution: {integrity: sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==} + engines: {node: '>=18'} + + default-browser@5.5.0: + resolution: {integrity: sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw==} + engines: {node: '>=18'} + + defaults@1.0.4: + resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} + + define-lazy-prop@2.0.0: + resolution: {integrity: sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==} + engines: {node: '>=8'} + + define-lazy-prop@3.0.0: + resolution: {integrity: sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==} + engines: {node: '>=12'} + + depd@1.1.2: + resolution: {integrity: sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==} + engines: {node: '>= 0.6'} + + depd@2.0.0: + resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} + engines: {node: '>= 0.8'} + + destroy@1.2.0: + resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + + detect-libc@2.1.2: + resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} + engines: {node: '>=8'} + + detect-node@2.1.0: + resolution: {integrity: sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==} + + di@0.0.1: + resolution: {integrity: sha512-uJaamHkagcZtHPqCIHZxnFrXlunQXgBOsZSUOWwFw31QJCAbyTBoHMW75YOTur5ZNx8pIeAKgf6GWIgaqqiLhA==} + + dns-packet@5.6.1: + resolution: {integrity: sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==} + engines: {node: '>=6'} + + dom-serialize@2.2.1: + resolution: {integrity: sha512-Yra4DbvoW7/Z6LBN560ZwXMjoNOSAN2wRsKFGc4iBeso+mpIA6qj1vfdf9HpMaKAqG6wXTy+1SYEzmNpKXOSsQ==} + + dom-serializer@2.0.0: + resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} + + domelementtype@2.3.0: + resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} + + domhandler@5.0.3: + resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} + engines: {node: '>= 4'} + + domutils@3.2.2: + resolution: {integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==} + + dunder-proto@1.0.1: + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} + + eastasianwidth@0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + + ee-first@1.1.1: + resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} + + electron-is-dev@2.0.0: + resolution: {integrity: sha512-3X99K852Yoqu9AcW50qz3ibYBWY79/pBhlMCab8ToEWS48R0T9tyxRiQhwylE7zQdXrMnx2JKqUJyMPmt5FBqA==} + + electron-to-chromium@1.5.397: + resolution: {integrity: sha512-khGTy9U9x02KEtsKM8vx5A62BsRmcOsIgDpWr1ImE32Ax8GxHGPHZf+Eu9H8zOOyHJnB0jTbseyTHbq2XCT8yw==} + + elementtree@0.1.7: + resolution: {integrity: sha512-wkgGT6kugeQk/P6VZ/f4T+4HB41BVgNBq5CDIZVbQ02nvTVqAiVTbskxxu3eA/X96lMlfYOwnLQpN2v5E1zDEg==} + engines: {node: '>= 0.4.0'} + + emoji-regex@10.6.0: + resolution: {integrity: sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==} + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + + emojis-list@3.0.0: + resolution: {integrity: sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==} + engines: {node: '>= 4'} + + encodeurl@1.0.2: + resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} + engines: {node: '>= 0.8'} + + encodeurl@2.0.0: + resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==} + engines: {node: '>= 0.8'} + + encoding@0.1.13: + resolution: {integrity: sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==} + + engine.io-parser@5.2.3: + resolution: {integrity: sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==} + engines: {node: '>=10.0.0'} + + engine.io@6.6.9: + resolution: {integrity: sha512-clKkw4C7nJ22mGgoVcCg6V/W/TxdNyIOTr89k2ONZu81qqkddPFDF0LXcbAwhzPD8DjkiRCjzuiO6Y+fkpD4vg==} + engines: {node: '>=10.2.0'} + + enhanced-resolve@5.24.3: + resolution: {integrity: sha512-PwKooW9JUzh5chmYfHM3IQl5OkK2u2Nm011MgeZrss3JmFraUx/fqrf78kk8GUMYoibx/14MdwTl/1WKkG7TpQ==} + engines: {node: '>=10.13.0'} + + ent@2.2.2: + resolution: {integrity: sha512-kKvD1tO6BM+oK9HzCPpUdRb4vKFQY/FPTFmurMvh6LlN68VMrdj77w8yp51/kDbpkFOS9J8w5W6zIzgM2H8/hw==} + engines: {node: '>= 0.4'} + + entities@4.5.0: + resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} + engines: {node: '>=0.12'} + + entities@6.0.1: + resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==} + engines: {node: '>=0.12'} + + entities@7.0.1: + resolution: {integrity: sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==} + engines: {node: '>=0.12'} + + env-paths@2.2.1: + resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} + engines: {node: '>=6'} + + environment@1.1.0: + resolution: {integrity: sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==} + engines: {node: '>=18'} + + err-code@2.0.3: + resolution: {integrity: sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==} + + errno@0.1.8: + resolution: {integrity: sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==} + hasBin: true + + error-ex@1.3.4: + resolution: {integrity: sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==} + + es-define-property@1.0.1: + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} + engines: {node: '>= 0.4'} + + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + + es-module-lexer@2.3.1: + resolution: {integrity: sha512-shc1dbU90Yl/xq1QrC7QRtfcwURZuVRfPhZbDoldJ1cn1gzDvBaBWlv0eFolj5+0znnPJz5TXLxsN77X/12KTA==} + + es-object-atoms@1.1.2: + resolution: {integrity: sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==} + engines: {node: '>= 0.4'} + + esbuild-wasm@0.28.0: + resolution: {integrity: sha512-5TRVKExcEmeMkccIZMzUq+Az6X2RoMAJyfl6SMMO1dMVhmvt0I2mx7gAb6zYi42n4d1ETcatFXazGKzA+aW7fg==} + engines: {node: '>=18'} + hasBin: true + + esbuild@0.25.12: + resolution: {integrity: sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==} + engines: {node: '>=18'} + hasBin: true + + esbuild@0.28.0: + resolution: {integrity: sha512-sNR9MHpXSUV/XB4zmsFKN+QgVG82Cc7+/aaxJ8Adi8hyOac+EXptIp45QBPaVyX3N70664wRbTcLTOemCAnyqw==} + engines: {node: '>=18'} + hasBin: true + + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} + + escape-html@1.0.3: + resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} + + eslint-scope@5.1.1: + resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} + engines: {node: '>=8.0.0'} + + esrecurse@4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + + estraverse@4.3.0: + resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==} + engines: {node: '>=4.0'} + + estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + + esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + + etag@1.8.1: + resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} + engines: {node: '>= 0.6'} + + eventemitter3@4.0.7: + resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} + + eventemitter3@5.0.4: + resolution: {integrity: sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==} + + events@3.3.0: + resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} + engines: {node: '>=0.8.x'} + + exponential-backoff@3.1.3: + resolution: {integrity: sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA==} + + express@4.22.2: + resolution: {integrity: sha512-IuL+Elrou2ZvCFHs18/CIzy2Nzvo25nZ1/D2eIZlz7c+QUayAcYoiM2BthCjs+EBHVpjYjcuLDAiCWgeIX3X1Q==} + engines: {node: '>= 0.10.0'} + + extend@3.0.2: + resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} + + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + fast-glob@3.3.3: + resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} + engines: {node: '>=8.6.0'} + + fast-uri@3.1.4: + resolution: {integrity: sha512-8JnbkQ4juDyvYs4mgFGQqg4yCYtFDtUtmp2QIQq11ZZe5CFQ5wcqm1rqDgAh/QdMySuBnPzMUiJUNZG5N/AiQw==} + + fastq@1.20.1: + resolution: {integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==} + + faye-websocket@0.11.4: + resolution: {integrity: sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==} + engines: {node: '>=0.8.0'} + + fd-slicer@1.1.0: + resolution: {integrity: sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==} + + fdir@6.5.0: + resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} + engines: {node: '>=12.0.0'} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + + fflate@0.8.3: + resolution: {integrity: sha512-tbZNuJrLwGUp3zshBtdy4W+ORxZuIh8a5ilyIEQDC5rY1f3U20JMry0Ll3WBzU58EZKsEuJFXhb5gwv8CsPvgA==} + + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} + + finalhandler@1.1.2: + resolution: {integrity: sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==} + engines: {node: '>= 0.8'} + + finalhandler@1.3.2: + resolution: {integrity: sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==} + engines: {node: '>= 0.8'} + + find-cache-dir@4.0.0: + resolution: {integrity: sha512-9ZonPT4ZAK4a+1pUPVPZJapbi7O5qbbJPdYw/NOQWZZbVLdDTYM3A4R9z/DpAM08IDaFGsvPgiGZ82WEwUDWjg==} + engines: {node: '>=14.16'} + + find-up@6.3.0: + resolution: {integrity: sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + flat@5.0.2: + resolution: {integrity: sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==} + hasBin: true + + flatted@3.4.3: + resolution: {integrity: sha512-/zipXxyO6rGvuNGDiULY9MvEGSkb2gaG4GGH4ygMi0ZZzyMHdUZBmntJmx5x1G2VuPytCwGN4xsJP6cw+sK+vQ==} + + follow-redirects@1.16.0: + resolution: {integrity: sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + + foreground-child@3.3.1: + resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} + engines: {node: '>=14'} + + forwarded@0.2.0: + resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} + engines: {node: '>= 0.6'} + + fraction.js@4.3.7: + resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} + + fresh@0.5.2: + resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} + engines: {node: '>= 0.6'} + + fs-extra@11.1.1: + resolution: {integrity: sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==} + engines: {node: '>=14.14'} + + fs-extra@11.4.0: + resolution: {integrity: sha512-EQsFzMUJkCKGr1ePqlYADkIUmHW1s3ZXr5Yqy6wbGrfUCphpl2maM/kyOIRA2HpP3AaFQTZXD4ldjek+nccddA==} + engines: {node: '>=14.14'} + + fs-extra@8.1.0: + resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==} + engines: {node: '>=6 <7 || >=8'} + + fs-extra@9.1.0: + resolution: {integrity: sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==} + engines: {node: '>=10'} + + fs-minipass@2.1.0: + resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==} + engines: {node: '>= 8'} + + fs-minipass@3.0.3: + resolution: {integrity: sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + fs.realpath@1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + gensync@1.0.0-beta.2: + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} + engines: {node: '>=6.9.0'} + + get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + + get-east-asian-width@1.6.0: + resolution: {integrity: sha512-QRbvDIbx6YklUe6RxeTeleMR0yv3cYH6PsPZHcnVn7xv7zO1BHN8r0XETu8n6Ye3Q+ahtSarc3WgtNWmehIBfA==} + engines: {node: '>=18'} + + get-intrinsic@1.3.0: + resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} + engines: {node: '>= 0.4'} + + get-proto@1.0.1: + resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} + engines: {node: '>= 0.4'} + + glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + + glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + + glob-to-regex.js@1.2.0: + resolution: {integrity: sha512-QMwlOQKU/IzqMUOAZWubUOT8Qft+Y0KQWnX9nK3ch0CJg0tTp4TvGZsTfudYKv2NzoQSyPcnA6TYeIQ3jGichQ==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + glob-to-regexp@0.4.1: + resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} + + glob@10.5.0: + resolution: {integrity: sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==} + deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me + hasBin: true + + glob@13.0.6: + resolution: {integrity: sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==} + engines: {node: 18 || 20 || >=22} + + glob@7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me + + globby@14.1.0: + resolution: {integrity: sha512-0Ia46fDOaT7k4og1PDW4YbodWWr3scS2vAr2lTbsplOt2WkKp0vQbkI9wKis/T5LV/dqPjO3bpS/z6GTJB82LA==} + engines: {node: '>=18'} + + gopd@1.2.0: + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + engines: {node: '>= 0.4'} + + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + + handle-thing@2.0.1: + resolution: {integrity: sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==} + + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + has-symbols@1.1.0: + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} + engines: {node: '>= 0.4'} + + has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + + hasown@2.0.4: + resolution: {integrity: sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==} + engines: {node: '>= 0.4'} + + hosted-git-info@8.1.0: + resolution: {integrity: sha512-Rw/B2DNQaPBICNXEm8balFz9a6WpZrkCGpcWFpy7nCj+NyhSdqXipmfvtmWt9xGfp0wZnBxB+iVpLmQMYt47Tw==} + engines: {node: ^18.17.0 || >=20.5.0} + + hpack.js@2.1.6: + resolution: {integrity: sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==} + + html-escaper@2.0.2: + resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} + + htmlparser2@10.1.0: + resolution: {integrity: sha512-VTZkM9GWRAtEpveh7MSF6SjjrpNVNNVJfFup7xTY3UpFtm67foy9HDVXneLtFVt4pMz5kZtgNcvCniNFb1hlEQ==} + + http-cache-semantics@4.2.0: + resolution: {integrity: sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==} + + http-deceiver@1.2.7: + resolution: {integrity: sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==} + + http-errors@1.8.1: + resolution: {integrity: sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==} + engines: {node: '>= 0.6'} + + http-errors@2.0.1: + resolution: {integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==} + engines: {node: '>= 0.8'} + + http-parser-js@0.5.10: + resolution: {integrity: sha512-Pysuw9XpUq5dVc/2SMHpuTY01RFl8fttgcyunjL7eEMhGM3cI4eOmiCycJDVCo/7O7ClfQD3SaI6ftDzqOXYMA==} + + http-proxy-agent@7.0.2: + resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} + engines: {node: '>= 14'} + + http-proxy-middleware@2.0.10: + resolution: {integrity: sha512-RKzRWNPxUZqbuk3BC5mGVJbBnWgr+diEnjJexIOytFbBzDy88Fbh/YvBr3DsNrl1jYAfjWfpATEv0NO35FDuPQ==} + engines: {node: '>=12.0.0'} + peerDependencies: + '@types/express': ^4.17.13 + peerDependenciesMeta: + '@types/express': + optional: true + + http-proxy-middleware@3.0.5: + resolution: {integrity: sha512-GLZZm1X38BPY4lkXA01jhwxvDoOkkXqjgVyUzVxiEK4iuRu03PZoYHhHRwxnfhQMDuaxi3vVri0YgSro/1oWqg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + http-proxy@1.18.1: + resolution: {integrity: sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==} + engines: {node: '>=8.0.0'} + + https-proxy-agent@7.0.6: + resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} + engines: {node: '>= 14'} + + hyperdyperid@1.2.0: + resolution: {integrity: sha512-Y93lCzHYgGWdrJ66yIktxiaGULYc6oGiABxhcO5AufBeOyoIdZF7bIfLaOrbM0iGIOXQQgxxRrFEnb+Y6w1n4A==} + engines: {node: '>=10.18'} + + iconv-lite@0.4.24: + resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} + engines: {node: '>=0.10.0'} + + iconv-lite@0.6.3: + resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} + engines: {node: '>=0.10.0'} + + iconv-lite@0.7.3: + resolution: {integrity: sha512-IKXpvIzjnC9XTAUbVBcMfGS0EPaIXtW6v+zr+RRp+hqULEpo0owZax6wyRwPOJbWbzjYspQwusTsfVr0ifh4uQ==} + engines: {node: '>=0.10.0'} + + icss-utils@5.1.0: + resolution: {integrity: sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==} + engines: {node: ^10 || ^12 || >= 14} + peerDependencies: + postcss: ^8.1.0 + + ieee754@1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + + ignore-walk@7.0.0: + resolution: {integrity: sha512-T4gbf83A4NH95zvhVYZc+qWocBBGlpzUXLPGurJggw/WIOwicfXJChLDP/iBZnN5WqROSu5Bm3hhle4z8a8YGQ==} + engines: {node: ^18.17.0 || >=20.5.0} + + ignore@7.0.6: + resolution: {integrity: sha512-BAg6QkE8W+TuQLrrw0Ugr7HegXduRuuj8/ti2kSOc+jz1dmx8/WNcjr6XGnq5YpDWxFwwaavqD0+jIUOKelTsw==} + engines: {node: '>= 4'} + + image-size@0.5.5: + resolution: {integrity: sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==} + engines: {node: '>=0.10.0'} + hasBin: true + + immutable@5.1.9: + resolution: {integrity: sha512-m8nVez3rwrgmWxtLMt1ZYXB2Lv7OKYn/disyxAlSDYAlKSlFoPPfIAmAM/M5xqL4m4C/wAPw7S2/CNaUii1Hxg==} + + import-fresh@3.3.1: + resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} + engines: {node: '>=6'} + + imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + + inflight@1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. + + inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + ini@4.1.3: + resolution: {integrity: sha512-X7rqawQBvfdjS10YU1y1YVreA3SsLrW9dX2CewP2EbBJM4ypVNLDkO5y04gejPwKIY9lR+7r9gn3rFPt/kmWFg==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + ini@5.0.0: + resolution: {integrity: sha512-+N0ngpO3e7cRUWOJAS7qw0IZIVc6XPrW4MlFBdD066F2L4k1L6ker3hLqSq7iXxU5tgS4WGkIUElWn5vogAEnw==} + engines: {node: ^18.17.0 || >=20.5.0} + + ip-address@10.3.1: + resolution: {integrity: sha512-1e9d3kb97NHJTIJDZW9rKqW2h6+dFa50Dy0fpPSMQp2ADje5gvKsXmdiK6dwY5t76TaTt5+P5N1Y/LoToIxP6g==} + engines: {node: '>= 12'} + + ipaddr.js@1.9.1: + resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} + engines: {node: '>= 0.10'} + + ipaddr.js@2.4.0: + resolution: {integrity: sha512-9VGk3HGanVE6JoZXHiCpnGy5X0jYDnN4EA4lntFPj+1vIWlFhIylq2CrrCOJH9EAhc5CYhq18F2Av2tgoAPsYQ==} + engines: {node: '>= 10'} + + is-arrayish@0.2.1: + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + + is-binary-path@2.1.0: + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} + + is-core-module@2.16.2: + resolution: {integrity: sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==} + engines: {node: '>= 0.4'} + + is-docker@2.2.1: + resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} + engines: {node: '>=8'} + hasBin: true + + is-docker@3.0.0: + resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + hasBin: true + + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + + is-fullwidth-code-point@4.0.0: + resolution: {integrity: sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==} + engines: {node: '>=12'} + + is-fullwidth-code-point@5.1.0: + resolution: {integrity: sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==} + engines: {node: '>=18'} + + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + + is-inside-container@1.0.0: + resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==} + engines: {node: '>=14.16'} + hasBin: true + + is-interactive@1.0.0: + resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==} + engines: {node: '>=8'} + + is-network-error@1.3.2: + resolution: {integrity: sha512-PhBY86zaxNZUuWP6h13Vu5oFe0XY6/UlKzQnYFELzGVHygP3MxmvTfYSG7GN3aIab/iWudSMgjSnG9Dq+nHrgA==} + engines: {node: '>=16'} + + is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + is-plain-obj@3.0.0: + resolution: {integrity: sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==} + engines: {node: '>=10'} + + is-plain-object@2.0.4: + resolution: {integrity: sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==} + engines: {node: '>=0.10.0'} + + is-plain-object@5.0.0: + resolution: {integrity: sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==} + engines: {node: '>=0.10.0'} + + is-regex@1.2.1: + resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==} + engines: {node: '>= 0.4'} + + is-unicode-supported@0.1.0: + resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} + engines: {node: '>=10'} + + is-what@3.14.1: + resolution: {integrity: sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==} + + is-wsl@2.2.0: + resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} + engines: {node: '>=8'} + + is-wsl@3.1.1: + resolution: {integrity: sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==} + engines: {node: '>=16'} + + isarray@1.0.0: + resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} + + isbinaryfile@4.0.10: + resolution: {integrity: sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw==} + engines: {node: '>= 8.0.0'} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + isexe@3.1.5: + resolution: {integrity: sha512-6B3tLtFqtQS4ekarvLVMZ+X+VlvQekbe4taUkf/rhVO3d/h0M2rfARm/pXLcPEsjjMsFgrFgSrhQIxcSVrBz8w==} + engines: {node: '>=18'} + + isobject@3.0.1: + resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==} + engines: {node: '>=0.10.0'} + + istanbul-lib-coverage@3.2.2: + resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} + engines: {node: '>=8'} + + istanbul-lib-instrument@5.2.1: + resolution: {integrity: sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==} + engines: {node: '>=8'} + + istanbul-lib-instrument@6.0.3: + resolution: {integrity: sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==} + engines: {node: '>=10'} + + istanbul-lib-report@3.0.1: + resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==} + engines: {node: '>=10'} + + istanbul-lib-source-maps@4.0.1: + resolution: {integrity: sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==} + engines: {node: '>=10'} + + istanbul-reports@3.2.0: + resolution: {integrity: sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==} + engines: {node: '>=8'} + + jackspeak@3.4.3: + resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} + + jasmine-core@4.6.1: + resolution: {integrity: sha512-VYz/BjjmC3klLJlLwA4Kw8ytk0zDSmbbDLNs794VnWmkcCB7I9aAL/D48VNQtmITyPvea2C3jdUMfc3kAoy0PQ==} + + jasmine-core@5.1.2: + resolution: {integrity: sha512-2oIUMGn00FdUiqz6epiiJr7xcFyNYj3rDcfmnzfkBnHyBQ3cBQUs4mmyGsOb7TTLb9kxk7dBcmEmqhDKkBoDyA==} + + jest-worker@27.5.1: + resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==} + engines: {node: '>= 10.13.0'} + + jiti@1.21.7: + resolution: {integrity: sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==} + hasBin: true + + js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + + js-yaml@4.3.0: + resolution: {integrity: sha512-1td788aAnnZ5qs7V2QIRl1owjtYpbKt749Y3xauqQgwIIGF/xXWz1wMTEBx5O3LK3lXLVuqXPdPxj2BoFHaW9Q==} + hasBin: true + + jsesc@3.1.0: + resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} + engines: {node: '>=6'} + hasBin: true + + json-buffer@3.0.1: + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + + json-parse-even-better-errors@2.3.1: + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + + json-parse-even-better-errors@4.0.0: + resolution: {integrity: sha512-lR4MXjGNgkJc7tkQ97kb2nuEMnNCyU//XYVH0MKTGcXEiSudQ5MKGKen3C5QubYy0vmq+JGitUg92uuywGEwIA==} + engines: {node: ^18.17.0 || >=20.5.0} + + json-schema-traverse@1.0.0: + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + + json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + + jsonc-parser@3.3.1: + resolution: {integrity: sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==} + + jsonfile@4.0.0: + resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} + + jsonfile@6.2.1: + resolution: {integrity: sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==} + + jsonparse@1.3.1: + resolution: {integrity: sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==} + engines: {'0': node >= 0.2.0} + + karma-chrome-launcher@3.2.0: + resolution: {integrity: sha512-rE9RkUPI7I9mAxByQWkGJFXfFD6lE4gC5nPuZdobf/QdTEJI6EU4yIay/cfU/xV4ZxlM5JiTv7zWYgA64NpS5Q==} + + karma-coverage@2.2.1: + resolution: {integrity: sha512-yj7hbequkQP2qOSb20GuNSIyE//PgJWHwC2IydLE6XRtsnaflv+/OSGNssPjobYUlhVVagy99TQpqUt3vAUG7A==} + engines: {node: '>=10.0.0'} + + karma-jasmine-html-reporter@2.1.0: + resolution: {integrity: sha512-sPQE1+nlsn6Hwb5t+HHwyy0A1FNCVKuL1192b+XNauMYWThz2kweiBVW1DqloRpVvZIJkIoHVB7XRpK78n1xbQ==} + peerDependencies: + jasmine-core: ^4.0.0 || ^5.0.0 + karma: ^6.0.0 + karma-jasmine: ^5.0.0 + + karma-jasmine@5.1.0: + resolution: {integrity: sha512-i/zQLFrfEpRyQoJF9fsCdTMOF5c2dK7C7OmsuKg2D0YSsuZSfQDiLuaiktbuio6F2wiCsZSnSnieIQ0ant/uzQ==} + engines: {node: '>=12'} + peerDependencies: + karma: ^6.0.0 + + karma-source-map-support@1.4.0: + resolution: {integrity: sha512-RsBECncGO17KAoJCYXjv+ckIz+Ii9NCi+9enk+rq6XC81ezYkb4/RHE6CTXdA7IOJqoF3wcaLfVG0CPmE5ca6A==} + + karma@6.4.4: + resolution: {integrity: sha512-LrtUxbdvt1gOpo3gxG+VAJlJAEMhbWlM4YrFQgql98FwF7+K8K12LYO4hnDdUkNjeztYrOXEMqgTajSWgmtI/w==} + engines: {node: '>= 10'} + hasBin: true + + keyv@4.5.4: + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + + kind-of@6.0.3: + resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} + engines: {node: '>=0.10.0'} + + kleur@3.0.3: + resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} + engines: {node: '>=6'} + + kleur@4.1.5: + resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} + engines: {node: '>=6'} + + launch-editor@2.14.1: + resolution: {integrity: sha512-QWBrQsMpH7gPr965dsKD/3cKWiNoTjpATQf++Xq63N6sKRGMwlVXz41O1IZTMfZQgBctD/K5Zt06+/I6pP6+HA==} + + less-loader@12.2.0: + resolution: {integrity: sha512-MYUxjSQSBUQmowc0l5nPieOYwMzGPUaTzB6inNW/bdPEG9zOL3eAAD1Qw5ZxSPk7we5dMojHwNODYMV1hq4EVg==} + engines: {node: '>= 18.12.0'} + peerDependencies: + '@rspack/core': 0.x || 1.x + less: ^3.5.0 || ^4.0.0 + webpack: ^5.0.0 + peerDependenciesMeta: + '@rspack/core': + optional: true + webpack: + optional: true + + less@4.2.2: + resolution: {integrity: sha512-tkuLHQlvWUTeQ3doAqnHbNn8T6WX1KA8yvbKG9x4VtKtIjHsVKQZCH11zRgAfbDAXC2UNIg/K9BYAAcEzUIrNg==} + engines: {node: '>=6'} + hasBin: true + + license-webpack-plugin@4.0.2: + resolution: {integrity: sha512-771TFWFD70G1wLTC4oU2Cw4qvtmNrIw+wRvBtn+okgHl7slJVi7zfNcdmqDL72BojM30VNJ2UHylr1o77U37Jw==} + peerDependencies: + webpack: '*' + peerDependenciesMeta: + webpack: + optional: true + + lines-and-columns@1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + + listr2@8.2.5: + resolution: {integrity: sha512-iyAZCeyD+c1gPyE9qpFu8af0Y+MRtmKOncdGoA2S5EY8iFq99dmmvkNnHiWo+pj0s7yH7l3KPIgee77tKpXPWQ==} + engines: {node: '>=18.0.0'} + + lmdb@3.2.6: + resolution: {integrity: sha512-SuHqzPl7mYStna8WRotY8XX/EUZBjjv3QyKIByeCLFfC9uXT/OIHByEcA07PzbMfQAM0KYJtLgtpMRlIe5dErQ==} + hasBin: true + + loader-runner@4.3.2: + resolution: {integrity: sha512-DFEqQ3ihfS9blba08cLfYf1NRAIEm+dDjic073DRDc3/JspI/8wYmtDsHwd3+4hwvdxSK7PGaElfTmm0awWJ4w==} + engines: {node: '>=6.11.5'} + + loader-utils@2.0.4: + resolution: {integrity: sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==} + engines: {node: '>=8.9.0'} + + loader-utils@3.3.1: + resolution: {integrity: sha512-FMJTLMXfCLMLfJxcX9PFqX5qD88Z5MRGaZCVzfuqeZSPsyiBzs+pahDQjbIWz2QIzPZz0NX9Zy4FX3lmK6YHIg==} + engines: {node: '>= 12.13.0'} + + locate-path@7.2.0: + resolution: {integrity: sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + lodash.debounce@4.0.8: + resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==} + + lodash@4.18.1: + resolution: {integrity: sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==} + + log-symbols@4.1.0: + resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} + engines: {node: '>=10'} + + log-update@6.1.0: + resolution: {integrity: sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==} + engines: {node: '>=18'} + + log4js@6.9.1: + resolution: {integrity: sha512-1somDdy9sChrr9/f4UlzhdaGfDR2c/SaD2a4T7qEkG4jTS57/B3qmnjLYePwQ8cqWnUHZI0iAKxMBpCZICiZ2g==} + engines: {node: '>=8.0'} + + lru-cache@10.4.3: + resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + + lru-cache@11.5.2: + resolution: {integrity: sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g==} + engines: {node: 20 || >=22} + + lru-cache@5.1.1: + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + + magic-string@0.30.17: + resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==} + + make-dir@2.1.0: + resolution: {integrity: sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==} + engines: {node: '>=6'} + + make-dir@4.0.0: + resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} + engines: {node: '>=10'} + + make-fetch-happen@14.0.3: + resolution: {integrity: sha512-QMjGbFTP0blj97EeidG5hk/QhKQ3T4ICckQGLgz38QF7Vgbk6e6FTARN8KhKxyBbWn8R0HU+bnw8aSoFPD4qtQ==} + engines: {node: ^18.17.0 || >=20.5.0} + + math-intrinsics@1.1.0: + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} + engines: {node: '>= 0.4'} + + matter-js@0.20.0: + resolution: {integrity: sha512-iC9fYR7zVT3HppNnsFsp9XOoQdQN2tUyfaKg4CHLH8bN+j6GT4Gw7IH2rP0tflAebrHFw730RR3DkVSZRX8hwA==} + + media-typer@0.3.0: + resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} + engines: {node: '>= 0.6'} + + memfs@4.64.0: + resolution: {integrity: sha512-Kw72fgY7Wn+sD8KmtNWSafl1dz0UvAsE/PHs3YVfLiaZuA3HxNm9sRLqAu0ATiBGJvME1PxZXbBZPv5GycDeAw==} + peerDependencies: + tslib: '2' + + merge-descriptors@1.0.3: + resolution: {integrity: sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==} + + merge-stream@2.0.0: + resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + + merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + + meshoptimizer@1.1.1: + resolution: {integrity: sha512-oRFNWJRDA/WTrVj7NWvqa5HqE1t9MYDj2VaWirQCzCCrAd2GHrqR/sQezCxiWATPNlKTcRaPRHPJwIRoPBAp5g==} + + methods@1.1.2: + resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} + engines: {node: '>= 0.6'} + + micromatch@4.0.8: + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} + engines: {node: '>=8.6'} + + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + mime-db@1.54.0: + resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==} + engines: {node: '>= 0.6'} + + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + + mime@1.6.0: + resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} + engines: {node: '>=4'} + hasBin: true + + mime@2.6.0: + resolution: {integrity: sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==} + engines: {node: '>=4.0.0'} + hasBin: true + + mimic-fn@2.1.0: + resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} + engines: {node: '>=6'} + + mimic-function@5.0.1: + resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==} + engines: {node: '>=18'} + + mini-css-extract-plugin@2.9.2: + resolution: {integrity: sha512-GJuACcS//jtq4kCtd5ii/M0SZf7OZRH+BxdqXZHaJfb8TJiVl+NgQRPwiYt2EuqeSkNydn/7vP+bcE27C5mb9w==} + engines: {node: '>= 12.13.0'} + peerDependencies: + webpack: ^5.0.0 + + minimalistic-assert@1.0.1: + resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==} + + minimatch@10.2.6: + resolution: {integrity: sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==} + engines: {node: 18 || 20 || >=22} + + minimatch@3.1.5: + resolution: {integrity: sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==} + + minimatch@9.0.9: + resolution: {integrity: sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==} + engines: {node: '>=16 || 14 >=14.17'} + + minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + + minipass-collect@2.0.1: + resolution: {integrity: sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw==} + engines: {node: '>=16 || 14 >=14.17'} + + minipass-fetch@4.0.1: + resolution: {integrity: sha512-j7U11C5HXigVuutxebFadoYBbd7VSdZWggSe64NVdvWNBqGAiXPL2QVCehjmw7lY1oF9gOllYbORh+hiNgfPgQ==} + engines: {node: ^18.17.0 || >=20.5.0} + + minipass-flush@1.0.7: + resolution: {integrity: sha512-TbqTz9cUwWyHS2Dy89P3ocAGUGxKjjLuR9z8w4WUTGAVgEj17/4nhgo2Du56i0Fm3Pm30g4iA8Lcqctc76jCzA==} + engines: {node: '>= 8'} + + minipass-pipeline@1.2.4: + resolution: {integrity: sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==} + engines: {node: '>=8'} + + minipass-sized@1.0.3: + resolution: {integrity: sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==} + engines: {node: '>=8'} + + minipass@3.3.6: + resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==} + engines: {node: '>=8'} + + minipass@5.0.0: + resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==} + engines: {node: '>=8'} + + minipass@7.1.3: + resolution: {integrity: sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==} + engines: {node: '>=16 || 14 >=14.17'} + + minizlib@2.1.2: + resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==} + engines: {node: '>= 8'} + + minizlib@3.1.0: + resolution: {integrity: sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==} + engines: {node: '>= 18'} + + mkdirp@0.5.6: + resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} + hasBin: true + + mkdirp@1.0.4: + resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} + engines: {node: '>=10'} + hasBin: true + + mrmime@2.0.1: + resolution: {integrity: sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==} + engines: {node: '>=10'} + + ms@2.0.0: + resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + msgpackr-extract@3.0.4: + resolution: {integrity: sha512-4kmO/MdyUIkLIvTPr8VHLil4AtoKIoniWPIEk5+CDy0xnWC84azhSFmuJ7PxZdsYtiP5kEeQsORAVIeMgxT+Hw==} + hasBin: true + + msgpackr@1.12.1: + resolution: {integrity: sha512-4EUH9tQHnMmEgzW/MdAP0KIfa1T9AF+htl0ffe2n5vb2EKn9y2co8ccpgWko6S52Jy1PQZKwRnx5/KkYjtd9MQ==} + + multicast-dns@7.2.5: + resolution: {integrity: sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==} + hasBin: true + + mute-stream@1.0.0: + resolution: {integrity: sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + mute-stream@2.0.0: + resolution: {integrity: sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==} + engines: {node: ^18.17.0 || >=20.5.0} + + nanoid@3.3.16: + resolution: {integrity: sha512-bzlKTyNJ7+LdGIIwy8ijFpIqEQIvafahV7eYykJ8Cvh42EdJeODoJ6gUJXpQJvej1BddH8OqTXZNE/KfbWAu8Q==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + native-run@2.0.3: + resolution: {integrity: sha512-U1PllBuzW5d1gfan+88L+Hky2eZx+9gv3Pf6rNBxKbORxi7boHzqiA6QFGSnqMem4j0A9tZ08NMIs5+0m/VS1Q==} + engines: {node: '>=16.0.0'} + hasBin: true + + needle@3.5.0: + resolution: {integrity: sha512-jaQyPKKk2YokHrEg+vFDYxXIHTCBgiZwSHOoVx/8V3GIBS8/VN6NdVRmg8q1ERtPkMvmOvebsgga4sAj5hls/w==} + engines: {node: '>= 4.4.x'} + hasBin: true + + negotiator@0.6.3: + resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} + engines: {node: '>= 0.6'} + + negotiator@0.6.4: + resolution: {integrity: sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==} + engines: {node: '>= 0.6'} + + negotiator@1.0.0: + resolution: {integrity: sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==} + engines: {node: '>= 0.6'} + + neo-async@2.6.2: + resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} + + node-addon-api@6.1.0: + resolution: {integrity: sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==} + + node-addon-api@7.1.1: + resolution: {integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==} + + node-forge@1.4.0: + resolution: {integrity: sha512-LarFH0+6VfriEhqMMcLX2F7SwSXeWwnEAJEsYm5QKWchiVYVvJyV9v7UDvUv+w5HO23ZpQTXDv/GxdDdMyOuoQ==} + engines: {node: '>= 6.13.0'} + + node-gyp-build-optional-packages@5.2.2: + resolution: {integrity: sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw==} + hasBin: true + + node-gyp@11.5.0: + resolution: {integrity: sha512-ra7Kvlhxn5V9Slyus0ygMa2h+UqExPqUIkfk7Pc8QTLT956JLSy51uWFwHtIYy0vI8cB4BDhc/S03+880My/LQ==} + engines: {node: ^18.17.0 || >=20.5.0} + hasBin: true + + node-releases@2.0.51: + resolution: {integrity: sha512-wRNIrw4DmVLKQlbgOMdkMx27Wrpzes2hh5Jtbi2bjPd+4wJstWIqP5A+lscnqbm0xxmT5Bpg8Lec5ItEBwx6BQ==} + engines: {node: '>=18'} + + nopt@8.1.0: + resolution: {integrity: sha512-ieGu42u/Qsa4TFktmaKEwM6MQH0pOWnaB3htzh0JRtx84+Mebc0cbZYN5bC+6WTZ4+77xrL9Pn5m7CV6VIkV7A==} + engines: {node: ^18.17.0 || >=20.5.0} + hasBin: true + + normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + + normalize-range@0.1.2: + resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==} + engines: {node: '>=0.10.0'} + + npm-bundled@4.0.0: + resolution: {integrity: sha512-IxaQZDMsqfQ2Lz37VvyyEtKLe8FsRZuysmedy/N06TU1RyVppYKXrO4xIhR0F+7ubIBox6Q7nir6fQI3ej39iA==} + engines: {node: ^18.17.0 || >=20.5.0} + + npm-install-checks@7.1.2: + resolution: {integrity: sha512-z9HJBCYw9Zr8BqXcllKIs5nI+QggAImbBdHphOzVYrz2CB4iQ6FzWyKmlqDZua+51nAu7FcemlbTc9VgQN5XDQ==} + engines: {node: ^18.17.0 || >=20.5.0} + + npm-normalize-package-bin@4.0.0: + resolution: {integrity: sha512-TZKxPvItzai9kN9H/TkmCtx/ZN/hvr3vUycjlfmH0ootY9yFBzNOpiXAdIn1Iteqsvk4lQn6B5PTrt+n6h8k/w==} + engines: {node: ^18.17.0 || >=20.5.0} + + npm-package-arg@12.0.2: + resolution: {integrity: sha512-f1NpFjNI9O4VbKMOlA5QoBq/vSQPORHcTZ2feJpFkTHJ9eQkdlmZEKSjcAhxTGInC7RlEyScT9ui67NaOsjFWA==} + engines: {node: ^18.17.0 || >=20.5.0} + + npm-packlist@9.0.0: + resolution: {integrity: sha512-8qSayfmHJQTx3nJWYbbUmflpyarbLMBc6LCAjYsiGtXxDB68HaZpb8re6zeaLGxZzDuMdhsg70jryJe+RrItVQ==} + engines: {node: ^18.17.0 || >=20.5.0} + + npm-pick-manifest@10.0.0: + resolution: {integrity: sha512-r4fFa4FqYY8xaM7fHecQ9Z2nE9hgNfJR+EmoKv0+chvzWkBcORX3r0FpTByP+CbOVJDladMXnPQGVN8PBLGuTQ==} + engines: {node: ^18.17.0 || >=20.5.0} + + npm-registry-fetch@18.0.2: + resolution: {integrity: sha512-LeVMZBBVy+oQb5R6FDV9OlJCcWDU+al10oKpe+nsvcHnG24Z3uM3SvJYKfGJlfGjVU8v9liejCrUR/M5HO5NEQ==} + engines: {node: ^18.17.0 || >=20.5.0} + + nth-check@2.1.1: + resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} + + object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + + object-inspect@1.13.4: + resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} + engines: {node: '>= 0.4'} + + obuf@1.1.2: + resolution: {integrity: sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==} + + on-finished@2.3.0: + resolution: {integrity: sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==} + engines: {node: '>= 0.8'} + + on-finished@2.4.1: + resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} + engines: {node: '>= 0.8'} + + on-headers@1.1.0: + resolution: {integrity: sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==} + engines: {node: '>= 0.8'} + + once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + + onetime@5.1.2: + resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} + engines: {node: '>=6'} + + onetime@7.0.0: + resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==} + engines: {node: '>=18'} + + open@10.1.0: + resolution: {integrity: sha512-mnkeQ1qP5Ue2wd+aivTD3NHd/lZ96Lu0jgf0pwktLPtx6cTZiH7tyeGRRHs0zX0rbrahXPnXlUnbeXyaBBuIaw==} + engines: {node: '>=18'} + + open@8.4.2: + resolution: {integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==} + engines: {node: '>=12'} + + ora@5.4.1: + resolution: {integrity: sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==} + engines: {node: '>=10'} + + ordered-binary@1.6.1: + resolution: {integrity: sha512-QkCdPooczexPLiXIrbVOPYkR3VO3T6v2OyKRkR1Xbhpy7/LAVXwahnRCgRp78Oe/Ehf0C/HATAxfSr6eA1oX+w==} + + p-limit@4.0.0: + resolution: {integrity: sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + p-locate@6.0.0: + resolution: {integrity: sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + p-map@7.0.6: + resolution: {integrity: sha512-I4Prw6ivkd6p8PiYR1tXASOAOBzIJwu0TB7fqaX0c/8c3QAehNYmX57EijyGGGBt3c/BIowGwV03RVBtXvHEVg==} + engines: {node: '>=18'} + + p-retry@6.2.1: + resolution: {integrity: sha512-hEt02O4hUct5wtwg4H4KcWgDdm+l1bOaEy/hWzd8xtXB9BqxTWBBhb+2ImAtH4Cv4rPjV76xN3Zumqk3k3AhhQ==} + engines: {node: '>=16.17'} + + package-json-from-dist@1.0.1: + resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} + + pacote@20.0.0: + resolution: {integrity: sha512-pRjC5UFwZCgx9kUFDVM9YEahv4guZ1nSLqwmWiLUnDbGsjs+U5w7z6Uc8HNR1a6x8qnu5y9xtGE6D1uAuYz+0A==} + engines: {node: ^18.17.0 || >=20.5.0} + hasBin: true + + parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + + parse-json@5.2.0: + resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} + engines: {node: '>=8'} + + parse-node-version@1.0.1: + resolution: {integrity: sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==} + engines: {node: '>= 0.10'} + + parse5-html-rewriting-stream@7.0.0: + resolution: {integrity: sha512-mazCyGWkmCRWDI15Zp+UiCqMp/0dgEmkZRvhlsqqKYr4SsVm/TvnSpD9fCvqCA2zoWJcfRym846ejWBBHRiYEg==} + + parse5-sax-parser@7.0.0: + resolution: {integrity: sha512-5A+v2SNsq8T6/mG3ahcz8ZtQ0OUFTatxPbeidoMB7tkJSGDY3tdfl4MHovtLQHkEn5CGxijNWRQHhRQ6IRpXKg==} + + parse5@7.3.0: + resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==} + + parseurl@1.3.3: + resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} + engines: {node: '>= 0.8'} + + path-exists@5.0.0: + resolution: {integrity: sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + path-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + + path-scurry@1.11.1: + resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} + engines: {node: '>=16 || 14 >=14.18'} + + path-scurry@2.0.2: + resolution: {integrity: sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==} + engines: {node: 18 || 20 || >=22} + + path-to-regexp@0.1.13: + resolution: {integrity: sha512-A/AGNMFN3c8bOlvV9RreMdrv7jsmF9XIfDeCd87+I8RNg6s78BhJxMu69NEMHBSJFxKidViTEdruRwEk/WIKqA==} + + path-type@6.0.0: + resolution: {integrity: sha512-Vj7sf++t5pBD637NSfkxpHSMfWaeig5+DKWLhcqIYx6mWQz5hdJTGDVMQiJcw1ZYkhs7AazKDGpRVji1LJCZUQ==} + engines: {node: '>=18'} + + pend@1.2.0: + resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==} + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + picomatch@2.3.2: + resolution: {integrity: sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==} + engines: {node: '>=8.6'} + + picomatch@4.0.4: + resolution: {integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==} + engines: {node: '>=12'} + + picomatch@4.0.5: + resolution: {integrity: sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==} + engines: {node: '>=12'} + + pify@4.0.1: + resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} + engines: {node: '>=6'} + + piscina@4.8.0: + resolution: {integrity: sha512-EZJb+ZxDrQf3dihsUL7p42pjNyrNIFJCrRHPMgxu/svsj+P3xS3fuEWp7k2+rfsavfl1N0G29b1HGs7J0m8rZA==} + + pkg-dir@7.0.0: + resolution: {integrity: sha512-Ie9z/WINcxxLp27BKOCHGde4ITq9UklYKDzVo1nhk5sqGEXU3FpkwP5GM2voTGJkGd9B3Otl+Q4uwSOeSUtOBA==} + engines: {node: '>=14.16'} + + plist@3.1.1: + resolution: {integrity: sha512-ZIfcLJC+7E7FBFnDxm9MPmt7D+DidyQ26lewieO75AdhA2ayMtsJSES0iWzqJQbcVRSrTufQoy0DR94xHue0oA==} + engines: {node: '>=10.4.0'} + + postcss-loader@8.1.1: + resolution: {integrity: sha512-0IeqyAsG6tYiDRCYKQJLAmgQr47DX6N7sFSWvQxt6AcupX8DIdmykuk/o/tx0Lze3ErGHJEp5OSRxrelC6+NdQ==} + engines: {node: '>= 18.12.0'} + peerDependencies: + '@rspack/core': 0.x || 1.x + postcss: ^7.0.0 || ^8.0.1 + webpack: ^5.0.0 + peerDependenciesMeta: + '@rspack/core': + optional: true + webpack: + optional: true + + postcss-media-query-parser@0.2.3: + resolution: {integrity: sha512-3sOlxmbKcSHMjlUXQZKQ06jOswE7oVkXPxmZdoB1r5l0q6gTFTQSHxNxOrCccElbW7dxNytifNEo8qidX2Vsig==} + + postcss-modules-extract-imports@3.1.0: + resolution: {integrity: sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==} + engines: {node: ^10 || ^12 || >= 14} + peerDependencies: + postcss: ^8.1.0 + + postcss-modules-local-by-default@4.2.0: + resolution: {integrity: sha512-5kcJm/zk+GJDSfw+V/42fJ5fhjL5YbFDl8nVdXkJPLLW+Vf9mTD5Xe0wqIaDnLuL2U6cDNpTr+UQ+v2HWIBhzw==} + engines: {node: ^10 || ^12 || >= 14} + peerDependencies: + postcss: ^8.1.0 + + postcss-modules-scope@3.2.1: + resolution: {integrity: sha512-m9jZstCVaqGjTAuny8MdgE88scJnCiQSlSrOWcTQgM2t32UBe+MUmFSO5t7VMSfAf/FJKImAxBav8ooCHJXCJA==} + engines: {node: ^10 || ^12 || >= 14} + peerDependencies: + postcss: ^8.1.0 + + postcss-modules-values@4.0.0: + resolution: {integrity: sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==} + engines: {node: ^10 || ^12 || >= 14} + peerDependencies: + postcss: ^8.1.0 + + postcss-selector-parser@7.1.4: + resolution: {integrity: sha512-HeP7D2wyhkR+XaK6v4W8oRF62Dsz4flyuczALJp61GckGm42u1saSSJ/0auvcBqxs3jMRFEcPK34At/0JBKdOg==} + engines: {node: '>=4'} + + postcss-value-parser@4.2.0: + resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} + + postcss@8.5.12: + resolution: {integrity: sha512-W62t/Se6rA0Az3DfCL0AqJwXuKwBeYg6nOaIgzP+xZ7N5BFCI7DYi1qs6ygUYT6rvfi6t9k65UMLJC+PHZpDAA==} + engines: {node: ^10 || ^12 || >=14} + + postcss@8.5.23: + resolution: {integrity: sha512-g50586zr4bZmwFiTlflMu8E0bDTb5I5gertgwAKmsdUlTQIhZtunzUlD1WSzwcVWPoAVpsrA6vlfCD7oXvRwgg==} + engines: {node: ^10 || ^12 || >=14} + + proc-log@5.0.0: + resolution: {integrity: sha512-Azwzvl90HaF0aCz1JrDdXQykFakSSNPaPoiZ9fm5qJIMHioDZEi7OAdRwSm6rSoPtY3Qutnm3L7ogmg3dc+wbQ==} + engines: {node: ^18.17.0 || >=20.5.0} + + process-nextick-args@2.0.1: + resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} + + promise-retry@2.0.1: + resolution: {integrity: sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==} + engines: {node: '>=10'} + + prompts@2.4.2: + resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} + engines: {node: '>= 6'} + + proxy-addr@2.0.7: + resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} + engines: {node: '>= 0.10'} + + prr@1.0.1: + resolution: {integrity: sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==} + + punycode@1.4.1: + resolution: {integrity: sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==} + + qjobs@1.2.0: + resolution: {integrity: sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg==} + engines: {node: '>=0.9'} + + qs@6.15.3: + resolution: {integrity: sha512-O9gl3zCl5h5blw1KGUzQKhA5oUXSl8rwUIM5o0S3nCXMliSvy5Dzx7/DJcI+SwgICv+IneSZwhBh1oSyEHA71A==} + engines: {node: '>=0.6'} + + queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + + randombytes@2.1.0: + resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} + + range-parser@1.2.1: + resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} + engines: {node: '>= 0.6'} + + range-parser@1.3.0: + resolution: {integrity: sha512-hek2mFQpPuI4E1BBKrSto+BU3e3x4xuarsbiwr3+lf7p44juvFMV0XFWQAP3xUyqXA4RrXLIoaSUGbSt056ZMw==} + engines: {node: '>= 0.6'} + + raw-body@2.5.3: + resolution: {integrity: sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==} + engines: {node: '>= 0.8'} + + readable-stream@2.3.8: + resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} + + readable-stream@3.6.2: + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} + + readdirp@3.6.0: + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} + + readdirp@4.1.2: + resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==} + engines: {node: '>= 14.18.0'} + + reflect-metadata@0.2.2: + resolution: {integrity: sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==} + + regenerate-unicode-properties@10.2.2: + resolution: {integrity: sha512-m03P+zhBeQd1RGnYxrGyDAPpWX/epKirLrp8e3qevZdVkKtnCrjjWczIbYc8+xd6vcTStVlqfycTx1KR4LOr0g==} + engines: {node: '>=4'} + + regenerate@1.4.2: + resolution: {integrity: sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==} + + regenerator-runtime@0.14.1: + resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} + + regex-parser@2.3.1: + resolution: {integrity: sha512-yXLRqatcCuKtVHsWrNg0JL3l1zGfdXeEvDa0bdu4tCDQw0RpMDZsqbkyRTUnKMR0tXF627V2oEWjBEaEdqTwtQ==} + + regexpu-core@6.4.0: + resolution: {integrity: sha512-0ghuzq67LI9bLXpOX/ISfve/Mq33a4aFRzoQYhnnok1JOFpmE/A2TBGkNVenOGEeSBCjIiWcc6MVOG5HEQv0sA==} + engines: {node: '>=4'} + + regjsgen@0.8.0: + resolution: {integrity: sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==} + + regjsparser@0.13.2: + resolution: {integrity: sha512-NgRBy2Nx/bE+9F27nVHnqcN5HjyLmecqsqx2PJHu3/IEtADD4WuxuXIVExD5PoSDFVrl78dOonfcOe5O+5nbzQ==} + hasBin: true + + require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + + require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + + requires-port@1.0.0: + resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==} + + resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + + resolve-url-loader@5.0.0: + resolution: {integrity: sha512-uZtduh8/8srhBoMx//5bwqjQ+rfYOUq8zC9NrMUGtjBiGTtFJM42s58/36+hTqeqINcnYe08Nj3LkK9lW4N8Xg==} + engines: {node: '>=12'} + + resolve@1.22.10: + resolution: {integrity: sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==} + engines: {node: '>= 0.4'} + hasBin: true + + resolve@1.22.12: + resolution: {integrity: sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==} + engines: {node: '>= 0.4'} + hasBin: true + + restore-cursor@3.1.0: + resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} + engines: {node: '>=8'} + + restore-cursor@5.1.0: + resolution: {integrity: sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==} + engines: {node: '>=18'} + + retry@0.12.0: + resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==} + engines: {node: '>= 4'} + + retry@0.13.1: + resolution: {integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==} + engines: {node: '>= 4'} + + reusify@1.1.0: + resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + + rfdc@1.4.1: + resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==} + + rimraf@3.0.2: + resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + deprecated: Rimraf versions prior to v4 are no longer supported + hasBin: true + + rimraf@6.1.3: + resolution: {integrity: sha512-LKg+Cr2ZF61fkcaK1UdkH2yEBBKnYjTyWzTJT6KNPcSPaiT7HSdhtMXQuN5wkTX0Xu72KQ1l8S42rlmexS2hSA==} + engines: {node: 20 || >=22} + hasBin: true + + rollup@4.59.0: + resolution: {integrity: sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + + rollup@4.62.3: + resolution: {integrity: sha512-Gu0c0iH9FzgX1L1t7ByIbbS3Vmdz+6KHm/EsqmmC71gUQ82yvZRkTK6XzrFObSka91WUVdynqp6nsfilzr5k6Q==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + + run-applescript@7.1.0: + resolution: {integrity: sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==} + engines: {node: '>=18'} + + run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + + rxjs@7.8.1: + resolution: {integrity: sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==} + + rxjs@7.8.2: + resolution: {integrity: sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==} + + safe-buffer@5.1.2: + resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} + + safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + + safe-regex-test@1.1.0: + resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==} + engines: {node: '>= 0.4'} + + safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + + sass-loader@16.0.5: + resolution: {integrity: sha512-oL+CMBXrj6BZ/zOq4os+UECPL+bWqt6OAC6DWS8Ln8GZRcMDjlJ4JC3FBDuHJdYaFWIdKNIBYmtZtK2MaMkNIw==} + engines: {node: '>= 18.12.0'} + peerDependencies: + '@rspack/core': 0.x || 1.x + node-sass: ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0 + sass: ^1.3.0 + sass-embedded: '*' + webpack: ^5.0.0 + peerDependenciesMeta: + '@rspack/core': + optional: true + node-sass: + optional: true + sass: + optional: true + sass-embedded: + optional: true + webpack: + optional: true + + sass@1.85.0: + resolution: {integrity: sha512-3ToiC1xZ1Y8aU7+CkgCI/tqyuPXEmYGJXO7H4uqp0xkLXUqp88rQQ4j1HmP37xSJLbCJPaIiv+cT1y+grssrww==} + engines: {node: '>=14.0.0'} + hasBin: true + + sax@1.1.4: + resolution: {integrity: sha512-5f3k2PbGGp+YtKJjOItpg3P99IMD84E4HOvcfleTb5joCHNXYLsR9yWFPOYGgaeMPDubQILTCMdsFb2OMeOjtg==} + + sax@1.6.1: + resolution: {integrity: sha512-42tBVwLWnaQvW5zc4HbZrTuWccECCZfBi92FDuwtqxasH+JbPB3/FOKb1m222K42R4WxuxzzMsTswfzgtSu64Q==} + engines: {node: '>=11.0.0'} + + schema-utils@4.3.3: + resolution: {integrity: sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==} + engines: {node: '>= 10.13.0'} + + select-hose@2.0.0: + resolution: {integrity: sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==} + + selfsigned@2.4.1: + resolution: {integrity: sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==} + engines: {node: '>=10'} + + semver@5.7.2: + resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} + hasBin: true + + semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + + semver@7.7.1: + resolution: {integrity: sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==} + engines: {node: '>=10'} + hasBin: true + + semver@7.8.5: + resolution: {integrity: sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==} + engines: {node: '>=10'} + hasBin: true + + send@0.19.2: + resolution: {integrity: sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==} + engines: {node: '>= 0.8.0'} + + serialize-javascript@6.0.2: + resolution: {integrity: sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==} + + serve-index@1.9.2: + resolution: {integrity: sha512-KDj11HScOaLmrPxl70KYNW1PksP4Nb/CLL2yvC+Qd2kHMPEEpfc4Re2e4FOay+bC/+XQl/7zAcWON3JVo5v3KQ==} + engines: {node: '>= 0.8.0'} + + serve-static@1.16.3: + resolution: {integrity: sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==} + engines: {node: '>= 0.8.0'} + + setprototypeof@1.2.0: + resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} + + shallow-clone@3.0.1: + resolution: {integrity: sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==} + engines: {node: '>=8'} + + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + shell-quote@1.10.0: + resolution: {integrity: sha512-w1aiOKwKuRgtwAReIIj89puqg+I7GvX4IbLrvmhXbzQsj1+Zwi4VO3+fa6ZF91TWSjIxoEkKnMeHcLEODK5ZXA==} + engines: {node: '>= 0.4'} + + side-channel-list@1.0.1: + resolution: {integrity: sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==} + engines: {node: '>= 0.4'} + + side-channel-map@1.0.1: + resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==} + engines: {node: '>= 0.4'} + + side-channel-weakmap@1.0.2: + resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==} + engines: {node: '>= 0.4'} + + side-channel@1.1.1: + resolution: {integrity: sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==} + engines: {node: '>= 0.4'} + + signal-exit@3.0.7: + resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + + sigstore@3.1.0: + resolution: {integrity: sha512-ZpzWAFHIFqyFE56dXqgX/DkDRZdz+rRcjoIk/RQU4IX0wiCv1l8S7ZrXDHcCc+uaf+6o7w3h2l3g6GYG5TKN9Q==} + engines: {node: ^18.17.0 || >=20.5.0} + + simple-plist@1.3.1: + resolution: {integrity: sha512-iMSw5i0XseMnrhtIzRb7XpQEXepa9xhWxGUojHBL43SIpQuDQkh3Wpy67ZbDzZVr6EKxvwVChnVpdl8hEVLDiw==} + + sisteransi@1.0.5: + resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} + + slash@5.1.0: + resolution: {integrity: sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==} + engines: {node: '>=14.16'} + + slice-ansi@4.0.0: + resolution: {integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==} + engines: {node: '>=10'} + + slice-ansi@5.0.0: + resolution: {integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==} + engines: {node: '>=12'} + + slice-ansi@7.1.2: + resolution: {integrity: sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==} + engines: {node: '>=18'} + + smart-buffer@4.2.0: + resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} + engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} + + socket.io-adapter@2.5.8: + resolution: {integrity: sha512-6Oy52pbg+kvdCVvjcN+FnY7BvxZ7cIHNScbvztT/It5d0vbwoJoVZmF2gjJmnV0/4WlXRfG15zc45ySk9Ah8bw==} + + socket.io-parser@4.2.7: + resolution: {integrity: sha512-IH/iSeO9T6gz1KkFleGDWkG9N3dl4jXVYUtMhIqH10Md0ttMer8nUNWiP1DKuNrybD2xBrixLJdCC9J6ECoYkg==} + engines: {node: '>=10.0.0'} + + socket.io@4.8.3: + resolution: {integrity: sha512-2Dd78bqzzjE6KPkD5fHZmDAKRNe3J15q+YHDrIsy9WEkqttc7GY+kT9OBLSMaPbQaEd0x1BjcmtMtXkfpc+T5A==} + engines: {node: '>=10.2.0'} + + sockjs@0.3.24: + resolution: {integrity: sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==} + + socks-proxy-agent@8.0.5: + resolution: {integrity: sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==} + engines: {node: '>= 14'} + + socks@2.8.9: + resolution: {integrity: sha512-LJhUYUvItdQ0LkJTmPeaEObWXAqFyfmP85x0tch/ez9cahmhlBBLbIqDFnvBnUJGagb0JbIQrkBs1wJ+yRYpEw==} + engines: {node: '>= 10.0.0', npm: '>= 3.0.0'} + + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} + + source-map-loader@5.0.0: + resolution: {integrity: sha512-k2Dur7CbSLcAH73sBcIkV5xjPV4SzqO1NJ7+XaQl8if3VODDUj3FNchNGpqgJSKbvUfJuhVdv8K2Eu8/TNl2eA==} + engines: {node: '>= 18.12.0'} + peerDependencies: + webpack: ^5.72.1 + + source-map-support@0.5.21: + resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} + + source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + + source-map@0.7.4: + resolution: {integrity: sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==} + engines: {node: '>= 8'} + + spdx-correct@3.2.0: + resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==} + + spdx-exceptions@2.5.0: + resolution: {integrity: sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==} + + spdx-expression-parse@3.0.1: + resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} + + spdx-license-ids@3.0.23: + resolution: {integrity: sha512-CWLcCCH7VLu13TgOH+r8p1O/Znwhqv/dbb6lqWy67G+pT1kHmeD/+V36AVb/vq8QMIQwVShJ6Ssl5FPh0fuSdw==} + + spdy-transport@3.0.0: + resolution: {integrity: sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==} + + spdy@4.0.2: + resolution: {integrity: sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==} + engines: {node: '>=6.0.0'} + + split2@4.2.0: + resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} + engines: {node: '>= 10.x'} + + ssri@12.0.0: + resolution: {integrity: sha512-S7iGNosepx9RadX82oimUkvr0Ct7IjJbEbs4mJcTxst8um95J3sDYU1RBEOvdu6oL1Wek2ODI5i4MAw+dZ6cAQ==} + engines: {node: ^18.17.0 || >=20.5.0} + + statuses@1.5.0: + resolution: {integrity: sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==} + engines: {node: '>= 0.6'} + + statuses@2.0.2: + resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==} + engines: {node: '>= 0.8'} + + stream-buffers@2.2.0: + resolution: {integrity: sha512-uyQK/mx5QjHun80FLJTfaWE7JtwfRMKBLkMne6udYOmvH0CawotVa7TfgYHzAnpphn4+TweIx1QKMnRIbipmUg==} + engines: {node: '>= 0.10.0'} + + streamroller@3.1.5: + resolution: {integrity: sha512-KFxaM7XT+irxvdqSP1LGLgNWbYN7ay5owZ3r/8t77p+EtSUAfUgtl7be3xtqtOmGUl9K9YPO2ca8133RlTjvKw==} + engines: {node: '>=8.0'} + + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + + string-width@5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} + + string-width@7.2.0: + resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} + engines: {node: '>=18'} + + string_decoder@1.1.1: + resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} + + string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + strip-ansi@7.2.0: + resolution: {integrity: sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==} + engines: {node: '>=12'} + + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + + supports-color@8.1.1: + resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} + engines: {node: '>=10'} + + supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + + symbol-observable@4.0.0: + resolution: {integrity: sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==} + engines: {node: '>=0.10'} + + tapable@2.3.3: + resolution: {integrity: sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==} + engines: {node: '>=6'} + + tar@6.2.1: + resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==} + engines: {node: '>=10'} + deprecated: Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me + + tar@7.5.22: + resolution: {integrity: sha512-MFO/QzvtAOmJbkhOaCTvbGcFN9L9b+JunIsDwaKljSOdcLMea3NJ1k9Usz/rjdfSXTq4dfzfeS7W4p4YOAAHeA==} + engines: {node: '>=18'} + + terser-webpack-plugin@5.6.1: + resolution: {integrity: sha512-201R5j+sJpK8nFWwKVyNfZot8FaJbLZDq5evriVzbV1wDtSXDjRUDRfJzHpAaxFDMEhsZL1QkeqM61wgsS3KaQ==} + engines: {node: '>= 10.13.0'} + peerDependencies: + '@minify-html/node': '*' + '@swc/core': '*' + '@swc/css': '*' + '@swc/html': '*' + clean-css: '*' + cssnano: '*' + csso: '*' + esbuild: '*' + html-minifier-terser: '*' + lightningcss: '*' + postcss: '*' + uglify-js: '*' + webpack: ^5.1.0 + peerDependenciesMeta: + '@minify-html/node': + optional: true + '@swc/core': + optional: true + '@swc/css': + optional: true + '@swc/html': + optional: true + clean-css: + optional: true + cssnano: + optional: true + csso: + optional: true + esbuild: + optional: true + html-minifier-terser: + optional: true + lightningcss: + optional: true + postcss: + optional: true + uglify-js: + optional: true + + terser@5.39.0: + resolution: {integrity: sha512-LBAhFyLho16harJoWMg/nZsQYgTrg5jXOn2nCYjRUcZZEdE3qa2zb8QEDRUGVZBW4rlazf2fxkg8tztybTaqWw==} + engines: {node: '>=10'} + hasBin: true + + thingies@2.6.1: + resolution: {integrity: sha512-cV/CMGTK3M4MlnJ/0At6ismOw/A0EEniDNScajjz/Br3c1sqE72YD01rGpPTKwd27wAxI5Pr+6+0w8yofzFRYw==} + engines: {node: '>=10.18'} + peerDependencies: + tslib: ^2 + + three@0.185.1: + resolution: {integrity: sha512-5aojFCXKwnjBRZvUnt3WFfEcvUJgkN5LlijRFN95hMy8WVkG4I0QNcJE+OuWvuJ0bOdStrbfXn0pkd6/QyiAlg==} + + through2@4.0.2: + resolution: {integrity: sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==} + + thunky@1.1.0: + resolution: {integrity: sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==} + + tinyglobby@0.2.17: + resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==} + engines: {node: '>=12.0.0'} + + tmp@0.2.7: + resolution: {integrity: sha512-e0votIpp4Uo2AJYSzVHV6xCcawuiez3DzqDAbrTc3YxBkplN6e+dM13ZeIcZnDg/QpSuU2zfZ3rzwY8ukEnaXw==} + engines: {node: '>=14.14'} + + to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + + toidentifier@1.0.1: + resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} + engines: {node: '>=0.6'} + + tree-dump@1.1.0: + resolution: {integrity: sha512-rMuvhU4MCDbcbnleZTFezWsaZXRFemSqAM+7jPnzUl1fo9w3YEKOxAeui0fz3OI4EU4hf23iyA7uQRVko+UaBA==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + tree-kill@1.2.2: + resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} + hasBin: true + + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + + tuf-js@3.1.0: + resolution: {integrity: sha512-3T3T04WzowbwV2FDiGXBbr81t64g1MUGGJRgT4x5o97N+8ArdhVCAF9IxFrxuSJmM3E5Asn7nKHkao0ibcZXAg==} + engines: {node: ^18.17.0 || >=20.5.0} + + type-is@1.6.18: + resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} + engines: {node: '>= 0.6'} + + typed-assert@1.0.9: + resolution: {integrity: sha512-KNNZtayBCtmnNmbo5mG47p1XsCyrx6iVqomjcZnec/1Y5GGARaxPs6r49RnSPeUP3YjNYiU9sQHAtY4BBvnZwg==} + + typescript@5.5.4: + resolution: {integrity: sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==} + engines: {node: '>=14.17'} + hasBin: true + + ua-parser-js@0.7.41: + resolution: {integrity: sha512-O3oYyCMPYgNNHuO7Jjk3uacJWZF8loBgwrfd/5LE/HyZ3lUIOdniQ7DNXJcIgZbwioZxk0fLfI4EVnetdiX5jg==} + hasBin: true + + undici-types@8.3.0: + resolution: {integrity: sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ==} + + unicode-canonical-property-names-ecmascript@2.0.1: + resolution: {integrity: sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==} + engines: {node: '>=4'} + + unicode-match-property-ecmascript@2.0.0: + resolution: {integrity: sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==} + engines: {node: '>=4'} + + unicode-match-property-value-ecmascript@2.2.1: + resolution: {integrity: sha512-JQ84qTuMg4nVkx8ga4A16a1epI9H6uTXAknqxkGF/aFfRLw1xC/Bp24HNLaZhHSkWd3+84t8iXnp1J0kYcZHhg==} + engines: {node: '>=4'} + + unicode-property-aliases-ecmascript@2.2.0: + resolution: {integrity: sha512-hpbDzxUY9BFwX+UeBnxv3Sh1q7HFxj48DTmXchNgRa46lO8uj3/1iEn3MiNUYTg1g9ctIqXCCERn8gYZhHC5lQ==} + engines: {node: '>=4'} + + unicorn-magic@0.3.0: + resolution: {integrity: sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==} + engines: {node: '>=18'} + + unique-filename@4.0.0: + resolution: {integrity: sha512-XSnEewXmQ+veP7xX2dS5Q4yZAvO40cBN2MWkJ7D/6sW4Dg6wYBNwM1Vrnz1FhH5AdeLIlUXRI9e28z1YZi71NQ==} + engines: {node: ^18.17.0 || >=20.5.0} + + unique-slug@5.0.0: + resolution: {integrity: sha512-9OdaqO5kwqR+1kVgHAhsp5vPNU0hnxRa26rBFNfNgM7M6pNtgzeBn3s/xbyCQL3dcjzOatcef6UUHpB/6MaETg==} + engines: {node: ^18.17.0 || >=20.5.0} + + universalify@0.1.2: + resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} + engines: {node: '>= 4.0.0'} + + universalify@2.0.1: + resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} + engines: {node: '>= 10.0.0'} + + unpipe@1.0.0: + resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} + engines: {node: '>= 0.8'} + + untildify@4.0.0: + resolution: {integrity: sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==} + engines: {node: '>=8'} + + update-browserslist-db@1.2.3: + resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + + util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + + utils-merge@1.0.1: + resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} + engines: {node: '>= 0.4.0'} + + uuid@7.0.3: + resolution: {integrity: sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg==} + deprecated: uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028). + hasBin: true + + uuid@8.3.2: + resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} + deprecated: uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028). + hasBin: true + + validate-npm-package-license@3.0.4: + resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} + + validate-npm-package-name@6.0.2: + resolution: {integrity: sha512-IUoow1YUtvoBBC06dXs8bR8B9vuA3aJfmQNKMoaPG/OFsPmoQvw8xh+6Ye25Gx9DQhoEom3Pcu9MKHerm/NpUQ==} + engines: {node: ^18.17.0 || >=20.5.0} + + vary@1.1.2: + resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} + engines: {node: '>= 0.8'} + + vite@6.4.2: + resolution: {integrity: sha512-2N/55r4JDJ4gdrCvGgINMy+HH3iRpNIz8K6SFwVsA+JbQScLiC+clmAxBgwiSPgcG9U15QmvqCGWzMbqda5zGQ==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + hasBin: true + peerDependencies: + '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 + jiti: '>=1.21.0' + less: '*' + lightningcss: ^1.21.0 + sass: '*' + sass-embedded: '*' + stylus: '*' + sugarss: '*' + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + '@types/node': + optional: true + jiti: + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + + void-elements@2.0.1: + resolution: {integrity: sha512-qZKX4RnBzH2ugr8Lxa7x+0V6XD9Sb/ouARtiasEQCHB1EVU4NXtmHsDDrx1dO4ne5fc3J6EW05BP1Dl0z0iung==} + engines: {node: '>=0.10.0'} + + watchpack@2.4.2: + resolution: {integrity: sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==} + engines: {node: '>=10.13.0'} + + watchpack@2.5.2: + resolution: {integrity: sha512-6i/00NBjP4yGPs+caKSyRfpTF/8Torsu0MOW3mMzIbhgISFder8i7xbqgHlLMwJrdiN8ndBV3UA1/AfzPSr+jg==} + engines: {node: '>=10.13.0'} + + wbuf@1.7.3: + resolution: {integrity: sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==} + + wcwidth@1.0.1: + resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} + + weak-lru-cache@1.2.2: + resolution: {integrity: sha512-DEAoo25RfSYMuTGc9vPJzZcZullwIqRDSI9LOy+fkCJPi6hykCnfKaXTuPBDuXAUcqHXyOgFtHNp/kB2FjYHbw==} + + webpack-dev-middleware@7.4.2: + resolution: {integrity: sha512-xOO8n6eggxnwYpy1NlzUKpvrjfJTvae5/D6WOK0S2LSo7vjmo5gCM1DbLUmFqrMTJP+W/0YZNctm7jasWvLuBA==} + engines: {node: '>= 18.12.0'} + peerDependencies: + webpack: ^5.0.0 + peerDependenciesMeta: + webpack: + optional: true + + webpack-dev-server@5.2.2: + resolution: {integrity: sha512-QcQ72gh8a+7JO63TAx/6XZf/CWhgMzu5m0QirvPfGvptOusAxG12w2+aua1Jkjr7hzaWDnJ2n6JFeexMHI+Zjg==} + engines: {node: '>= 18.12.0'} + hasBin: true + peerDependencies: + webpack: ^5.0.0 + webpack-cli: '*' + peerDependenciesMeta: + webpack: + optional: true + webpack-cli: + optional: true + + webpack-merge@6.0.1: + resolution: {integrity: sha512-hXXvrjtx2PLYx4qruKl+kyRSLc52V+cCvMxRjmKwoA+CBbbF5GfIBtR6kCvl0fYGqTUPKB+1ktVmTHqMOzgCBg==} + engines: {node: '>=18.0.0'} + + webpack-sources@3.5.1: + resolution: {integrity: sha512-jyuiGJdtvY434z5bUZrjz67v76/ePNvFZTp9Mdz29IlH4+GPsgyGjiv0fKI+M7BdkU6ADjulUcKAd3tUK3WlEw==} + engines: {node: '>=10.13.0'} + + webpack-subresource-integrity@5.1.0: + resolution: {integrity: sha512-sacXoX+xd8r4WKsy9MvH/q/vBtEHr86cpImXwyg74pFIpERKt6FmB8cXpeuh0ZLgclOlHI4Wcll7+R5L02xk9Q==} + engines: {node: '>= 12'} + peerDependencies: + html-webpack-plugin: '>= 5.0.0-beta.1 < 6' + webpack: ^5.12.0 + peerDependenciesMeta: + html-webpack-plugin: + optional: true + + webpack@5.105.0: + resolution: {integrity: sha512-gX/dMkRQc7QOMzgTe6KsYFM7DxeIONQSui1s0n/0xht36HvrgbxtM1xBlgx596NbpHuQU8P7QpKwrZYwUX48nw==} + engines: {node: '>=10.13.0'} + hasBin: true + peerDependencies: + webpack-cli: '*' + peerDependenciesMeta: + webpack-cli: + optional: true + + websocket-driver@0.7.5: + resolution: {integrity: sha512-ZL2+3c7kMBdIRCMz6l8jQMHyGVxj+UL+xVk74Ombiciboca8rHa15L86B19E5oh1pL9Ii/uj54gtsIrZGMo6zA==} + engines: {node: '>=0.8.0'} + + websocket-extensions@0.1.4: + resolution: {integrity: sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==} + engines: {node: '>=0.8.0'} + + which@1.3.1: + resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} + hasBin: true + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + which@5.0.0: + resolution: {integrity: sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ==} + engines: {node: ^18.17.0 || >=20.5.0} + hasBin: true + + wildcard@2.0.1: + resolution: {integrity: sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==} + + wrap-ansi@6.2.0: + resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} + engines: {node: '>=8'} + + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + + wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} + + wrap-ansi@9.0.2: + resolution: {integrity: sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==} + engines: {node: '>=18'} + + wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + + ws@8.21.1: + resolution: {integrity: sha512-+0NTnW77fFN/DjQi6k/Sq/Yvk4Sgajw7urW8V+asjXnRgDs9gyGkdb7EzgfhA4goXsRIZKE28fzIXBHEzhuiWw==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + + xcode@3.0.1: + resolution: {integrity: sha512-kCz5k7J7XbJtjABOvkc5lJmkiDh8VhjVCGNiqdKCscmVpdVUpEAyXv1xmCLkQJ5dsHqx3IPO4XW+NTDhU/fatA==} + engines: {node: '>=10.0.0'} + + xml2js@0.6.2: + resolution: {integrity: sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==} + engines: {node: '>=4.0.0'} + + xmlbuilder@11.0.1: + resolution: {integrity: sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==} + engines: {node: '>=4.0'} + + xmlbuilder@15.1.1: + resolution: {integrity: sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==} + engines: {node: '>=8.0'} + + y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + + yallist@3.1.1: + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + + yallist@4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + + yallist@5.0.0: + resolution: {integrity: sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==} + engines: {node: '>=18'} + + yargs-parser@20.2.9: + resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==} + engines: {node: '>=10'} + + yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + + yargs@16.2.2: + resolution: {integrity: sha512-Nt9ZJjXTv5R8MHbqby/wXQ6Gi0Bb3TcYZkR1bzuL4yB2OxWPkXknz513gEF0GoA6tn00UpbPvERW8rzCuWCA6w==} + engines: {node: '>=10'} + + yargs@17.7.2: + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + engines: {node: '>=12'} + + yargs@17.7.3: + resolution: {integrity: sha512-GZtjxm/J/4TSxuL3FNYjCmLktBTnIw/rVmKSIyKeYAZpmJB2ig9VauCC5xsa82GNKVKDAqpOn3KVzNt0zmrU0g==} + engines: {node: '>=12'} + + yauzl@2.10.0: + resolution: {integrity: sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==} + + yocto-queue@1.2.2: + resolution: {integrity: sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ==} + engines: {node: '>=12.20'} + + yoctocolors-cjs@2.1.3: + resolution: {integrity: sha512-U/PBtDf35ff0D8X8D0jfdzHYEPFxAI7jJlxZXwCSez5M3190m+QobIfh+sWDWSHMCWWJN2AWamkegn6vr6YBTw==} + engines: {node: '>=18'} + + zone.js@0.15.1: + resolution: {integrity: sha512-XE96n56IQpJM7NAoXswY3XRLcWFW83xe0BiAOeMD7K5k5xecOeul3Qcpx6GqEeeHNkW5DWL5zOyTbEfB4eti8w==} + +snapshots: + + '@ampproject/remapping@2.3.0': + dependencies: + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + + '@angular-devkit/architect@0.1902.27(chokidar@4.0.3)': + dependencies: + '@angular-devkit/core': 19.2.27(chokidar@4.0.3) + rxjs: 7.8.1 + transitivePeerDependencies: + - chokidar + + '@angular-devkit/build-angular@19.2.27(@angular/compiler-cli@19.2.25(@angular/compiler@19.2.25)(supports-color@8.1.1)(typescript@5.5.4))(@angular/compiler@19.2.25)(@angular/service-worker@19.2.25(@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@types/node@26.1.2)(chokidar@4.0.3)(debug@4.4.3(supports-color@8.1.1))(jiti@1.21.7)(karma@6.4.4(debug@4.4.3(supports-color@8.1.1))(supports-color@8.1.1))(supports-color@8.1.1)(typescript@5.5.4)(vite@6.4.2(@types/node@26.1.2)(jiti@1.21.7)(less@4.2.2)(sass@1.85.0)(terser@5.39.0))': + dependencies: + '@ampproject/remapping': 2.3.0 + '@angular-devkit/architect': 0.1902.27(chokidar@4.0.3) + '@angular-devkit/build-webpack': 0.1902.27(chokidar@4.0.3)(webpack-dev-server@5.2.2(debug@4.4.3(supports-color@8.1.1))(supports-color@8.1.1)(tslib@2.8.1)(webpack@5.105.0(esbuild@0.28.0)(postcss@8.5.12)))(webpack@5.105.0(esbuild@0.28.0)(postcss@8.5.12)) + '@angular-devkit/core': 19.2.27(chokidar@4.0.3) + '@angular/build': 19.2.27(@angular/compiler-cli@19.2.25(@angular/compiler@19.2.25)(supports-color@8.1.1)(typescript@5.5.4))(@angular/compiler@19.2.25)(@angular/service-worker@19.2.25(@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@types/node@26.1.2)(chokidar@4.0.3)(jiti@1.21.7)(karma@6.4.4(debug@4.4.3(supports-color@8.1.1))(supports-color@8.1.1))(less@4.2.2)(postcss@8.5.12)(supports-color@8.1.1)(terser@5.39.0)(typescript@5.5.4) + '@angular/compiler-cli': 19.2.25(@angular/compiler@19.2.25)(supports-color@8.1.1)(typescript@5.5.4) + '@babel/core': 7.26.10(supports-color@8.1.1) + '@babel/generator': 7.26.10 + '@babel/helper-annotate-as-pure': 7.25.9 + '@babel/helper-split-export-declaration': 7.24.7 + '@babel/plugin-transform-async-generator-functions': 7.26.8(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-async-to-generator': 7.25.9(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-runtime': 7.26.10(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/preset-env': 7.26.9(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/runtime': 7.26.10 + '@discoveryjs/json-ext': 0.6.3 + '@ngtools/webpack': 19.2.27(@angular/compiler-cli@19.2.25(@angular/compiler@19.2.25)(supports-color@8.1.1)(typescript@5.5.4))(typescript@5.5.4)(webpack@5.105.0(esbuild@0.28.0)(postcss@8.5.12)) + '@vitejs/plugin-basic-ssl': 1.2.0(vite@6.4.2(@types/node@26.1.2)(jiti@1.21.7)(less@4.2.2)(sass@1.85.0)(terser@5.39.0)) + ansi-colors: 4.1.3 + autoprefixer: 10.4.20(postcss@8.5.12) + babel-loader: 9.2.1(@babel/core@7.26.10(supports-color@8.1.1))(webpack@5.105.0(esbuild@0.28.0)(postcss@8.5.12)) + browserslist: 4.28.7 + copy-webpack-plugin: 12.0.2(webpack@5.105.0(esbuild@0.28.0)(postcss@8.5.12)) + css-loader: 7.1.2(webpack@5.105.0(esbuild@0.28.0)(postcss@8.5.12)) + esbuild-wasm: 0.28.0 + fast-glob: 3.3.3 + http-proxy-middleware: 3.0.5(supports-color@8.1.1) + istanbul-lib-instrument: 6.0.3(supports-color@8.1.1) + jsonc-parser: 3.3.1 + karma-source-map-support: 1.4.0 + less: 4.2.2 + less-loader: 12.2.0(less@4.2.2)(webpack@5.105.0(esbuild@0.28.0)(postcss@8.5.12)) + license-webpack-plugin: 4.0.2(webpack@5.105.0(esbuild@0.28.0)(postcss@8.5.12)) + loader-utils: 3.3.1 + mini-css-extract-plugin: 2.9.2(webpack@5.105.0(esbuild@0.28.0)(postcss@8.5.12)) + open: 10.1.0 + ora: 5.4.1 + picomatch: 4.0.4 + piscina: 4.8.0 + postcss: 8.5.12 + postcss-loader: 8.1.1(postcss@8.5.12)(typescript@5.5.4)(webpack@5.105.0(esbuild@0.28.0)(postcss@8.5.12)) + resolve-url-loader: 5.0.0 + rxjs: 7.8.1 + sass: 1.85.0 + sass-loader: 16.0.5(sass@1.85.0)(webpack@5.105.0(esbuild@0.28.0)(postcss@8.5.12)) + semver: 7.7.1 + source-map-loader: 5.0.0(webpack@5.105.0(esbuild@0.28.0)(postcss@8.5.12)) + source-map-support: 0.5.21 + terser: 5.39.0 + tree-kill: 1.2.2 + tslib: 2.8.1 + typescript: 5.5.4 + webpack: 5.105.0(esbuild@0.28.0)(postcss@8.5.12) + webpack-dev-middleware: 7.4.2(tslib@2.8.1)(webpack@5.105.0(esbuild@0.28.0)(postcss@8.5.12)) + webpack-dev-server: 5.2.2(debug@4.4.3(supports-color@8.1.1))(supports-color@8.1.1)(tslib@2.8.1)(webpack@5.105.0(esbuild@0.28.0)(postcss@8.5.12)) + webpack-merge: 6.0.1 + webpack-subresource-integrity: 5.1.0(webpack@5.105.0(esbuild@0.28.0)(postcss@8.5.12)) + optionalDependencies: + '@angular/service-worker': 19.2.25(@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) + esbuild: 0.28.0 + karma: 6.4.4(debug@4.4.3(supports-color@8.1.1))(supports-color@8.1.1) + transitivePeerDependencies: + - '@angular/compiler' + - '@minify-html/node' + - '@rspack/core' + - '@swc/core' + - '@swc/css' + - '@swc/html' + - '@types/node' + - bufferutil + - chokidar + - clean-css + - cssnano + - csso + - debug + - html-minifier-terser + - html-webpack-plugin + - jiti + - lightningcss + - node-sass + - sass-embedded + - stylus + - sugarss + - supports-color + - tsx + - uglify-js + - utf-8-validate + - vite + - webpack-cli + - yaml + + '@angular-devkit/build-webpack@0.1902.27(chokidar@4.0.3)(webpack-dev-server@5.2.2(debug@4.4.3(supports-color@8.1.1))(supports-color@8.1.1)(tslib@2.8.1)(webpack@5.105.0(esbuild@0.28.0)(postcss@8.5.12)))(webpack@5.105.0(esbuild@0.28.0)(postcss@8.5.12))': + dependencies: + '@angular-devkit/architect': 0.1902.27(chokidar@4.0.3) + rxjs: 7.8.1 + webpack: 5.105.0(esbuild@0.28.0)(postcss@8.5.12) + webpack-dev-server: 5.2.2(debug@4.4.3(supports-color@8.1.1))(supports-color@8.1.1)(tslib@2.8.1)(webpack@5.105.0(esbuild@0.28.0)(postcss@8.5.12)) + transitivePeerDependencies: + - chokidar + + '@angular-devkit/core@19.2.27(chokidar@4.0.3)': + dependencies: + ajv: 8.18.0 + ajv-formats: 3.0.1(ajv@8.18.0) + jsonc-parser: 3.3.1 + picomatch: 4.0.4 + rxjs: 7.8.1 + source-map: 0.7.4 + optionalDependencies: + chokidar: 4.0.3 + + '@angular-devkit/schematics@19.2.27(chokidar@4.0.3)': + dependencies: + '@angular-devkit/core': 19.2.27(chokidar@4.0.3) + jsonc-parser: 3.3.1 + magic-string: 0.30.17 + ora: 5.4.1 + rxjs: 7.8.1 + transitivePeerDependencies: + - chokidar + + '@angular/animations@19.2.25(@angular/common@19.2.25(@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1))': + dependencies: + '@angular/common': 19.2.25(@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) + '@angular/core': 19.2.25(rxjs@7.8.2)(zone.js@0.15.1) + tslib: 2.8.1 + + '@angular/build@19.2.27(@angular/compiler-cli@19.2.25(@angular/compiler@19.2.25)(supports-color@8.1.1)(typescript@5.5.4))(@angular/compiler@19.2.25)(@angular/service-worker@19.2.25(@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@types/node@26.1.2)(chokidar@4.0.3)(jiti@1.21.7)(karma@6.4.4(debug@4.4.3(supports-color@8.1.1))(supports-color@8.1.1))(less@4.2.2)(postcss@8.5.12)(supports-color@8.1.1)(terser@5.39.0)(typescript@5.5.4)': + dependencies: + '@ampproject/remapping': 2.3.0 + '@angular-devkit/architect': 0.1902.27(chokidar@4.0.3) + '@angular/compiler': 19.2.25 + '@angular/compiler-cli': 19.2.25(@angular/compiler@19.2.25)(supports-color@8.1.1)(typescript@5.5.4) + '@babel/core': 7.26.10(supports-color@8.1.1) + '@babel/helper-annotate-as-pure': 7.25.9 + '@babel/helper-split-export-declaration': 7.24.7 + '@babel/plugin-syntax-import-attributes': 7.26.0(@babel/core@7.26.10(supports-color@8.1.1)) + '@inquirer/confirm': 5.1.6(@types/node@26.1.2) + '@vitejs/plugin-basic-ssl': 1.2.0(vite@6.4.2(@types/node@26.1.2)(jiti@1.21.7)(less@4.2.2)(sass@1.85.0)(terser@5.39.0)) + beasties: 0.3.2 + browserslist: 4.28.7 + esbuild: 0.28.0 + fast-glob: 3.3.3 + https-proxy-agent: 7.0.6(supports-color@8.1.1) + istanbul-lib-instrument: 6.0.3(supports-color@8.1.1) + listr2: 8.2.5 + magic-string: 0.30.17 + mrmime: 2.0.1 + parse5-html-rewriting-stream: 7.0.0 + picomatch: 4.0.4 + piscina: 4.8.0 + rollup: 4.59.0 + sass: 1.85.0 + semver: 7.7.1 + source-map-support: 0.5.21 + typescript: 5.5.4 + vite: 6.4.2(@types/node@26.1.2)(jiti@1.21.7)(less@4.2.2)(sass@1.85.0)(terser@5.39.0) + watchpack: 2.4.2 + optionalDependencies: + '@angular/service-worker': 19.2.25(@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) + karma: 6.4.4(debug@4.4.3(supports-color@8.1.1))(supports-color@8.1.1) + less: 4.2.2 + lmdb: 3.2.6 + postcss: 8.5.12 + transitivePeerDependencies: + - '@types/node' + - chokidar + - jiti + - lightningcss + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + - tsx + - yaml + + '@angular/cli@19.2.27(@types/node@26.1.2)(chokidar@4.0.3)(supports-color@8.1.1)': + dependencies: + '@angular-devkit/architect': 0.1902.27(chokidar@4.0.3) + '@angular-devkit/core': 19.2.27(chokidar@4.0.3) + '@angular-devkit/schematics': 19.2.27(chokidar@4.0.3) + '@inquirer/prompts': 7.3.2(@types/node@26.1.2) + '@listr2/prompt-adapter-inquirer': 2.0.18(@inquirer/prompts@7.3.2(@types/node@26.1.2)) + '@schematics/angular': 19.2.27(chokidar@4.0.3) + '@yarnpkg/lockfile': 1.1.0 + ini: 5.0.0 + jsonc-parser: 3.3.1 + listr2: 8.2.5 + npm-package-arg: 12.0.2 + npm-pick-manifest: 10.0.0 + pacote: 20.0.0(supports-color@8.1.1) + resolve: 1.22.10 + semver: 7.7.1 + symbol-observable: 4.0.0 + yargs: 17.7.2 + transitivePeerDependencies: + - '@types/node' + - chokidar + - supports-color + + '@angular/common@19.2.25(@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2)': + dependencies: + '@angular/core': 19.2.25(rxjs@7.8.2)(zone.js@0.15.1) + rxjs: 7.8.2 + tslib: 2.8.1 + + '@angular/compiler-cli@19.2.25(@angular/compiler@19.2.25)(supports-color@8.1.1)(typescript@5.5.4)': + dependencies: + '@angular/compiler': 19.2.25 + '@babel/core': 7.26.9(supports-color@8.1.1) + '@jridgewell/sourcemap-codec': 1.5.5 + chokidar: 4.0.3 + convert-source-map: 1.9.0 + reflect-metadata: 0.2.2 + semver: 7.8.5 + tslib: 2.8.1 + typescript: 5.5.4 + yargs: 17.7.3 + transitivePeerDependencies: + - supports-color + + '@angular/compiler@19.2.25': + dependencies: + tslib: 2.8.1 + + '@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1)': + dependencies: + rxjs: 7.8.2 + tslib: 2.8.1 + zone.js: 0.15.1 + + '@angular/forms@19.2.25(@angular/common@19.2.25(@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@19.2.25(@angular/animations@19.2.25(@angular/common@19.2.25(@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@19.2.25(@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2)': + dependencies: + '@angular/common': 19.2.25(@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) + '@angular/core': 19.2.25(rxjs@7.8.2)(zone.js@0.15.1) + '@angular/platform-browser': 19.2.25(@angular/animations@19.2.25(@angular/common@19.2.25(@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@19.2.25(@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1)) + rxjs: 7.8.2 + tslib: 2.8.1 + + '@angular/platform-browser-dynamic@19.2.25(@angular/common@19.2.25(@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/compiler@19.2.25)(@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@19.2.25(@angular/animations@19.2.25(@angular/common@19.2.25(@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@19.2.25(@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1)))': + dependencies: + '@angular/common': 19.2.25(@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) + '@angular/compiler': 19.2.25 + '@angular/core': 19.2.25(rxjs@7.8.2)(zone.js@0.15.1) + '@angular/platform-browser': 19.2.25(@angular/animations@19.2.25(@angular/common@19.2.25(@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@19.2.25(@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1)) + tslib: 2.8.1 + + '@angular/platform-browser@19.2.25(@angular/animations@19.2.25(@angular/common@19.2.25(@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@19.2.25(@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1))': + dependencies: + '@angular/common': 19.2.25(@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) + '@angular/core': 19.2.25(rxjs@7.8.2)(zone.js@0.15.1) + tslib: 2.8.1 + optionalDependencies: + '@angular/animations': 19.2.25(@angular/common@19.2.25(@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1)) + + '@angular/router@19.2.25(@angular/common@19.2.25(@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@19.2.25(@angular/animations@19.2.25(@angular/common@19.2.25(@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@19.2.25(@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2)': + dependencies: + '@angular/common': 19.2.25(@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) + '@angular/core': 19.2.25(rxjs@7.8.2)(zone.js@0.15.1) + '@angular/platform-browser': 19.2.25(@angular/animations@19.2.25(@angular/common@19.2.25(@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@19.2.25(@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1)) + rxjs: 7.8.2 + tslib: 2.8.1 + + '@angular/service-worker@19.2.25(@angular/core@19.2.25(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2)': + dependencies: + '@angular/core': 19.2.25(rxjs@7.8.2)(zone.js@0.15.1) + rxjs: 7.8.2 + tslib: 2.8.1 + + '@babel/code-frame@7.29.7': + dependencies: + '@babel/helper-validator-identifier': 7.29.7 + js-tokens: 4.0.0 + picocolors: 1.1.1 + + '@babel/compat-data@7.29.7': {} + + '@babel/core@7.26.10(supports-color@8.1.1)': + dependencies: + '@ampproject/remapping': 2.3.0 + '@babel/code-frame': 7.29.7 + '@babel/generator': 7.26.10 + '@babel/helper-compilation-targets': 7.29.7 + '@babel/helper-module-transforms': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/helpers': 7.29.7 + '@babel/parser': 7.29.7 + '@babel/template': 7.29.7 + '@babel/traverse': 7.29.7(supports-color@8.1.1) + '@babel/types': 7.29.7 + convert-source-map: 2.0.0 + debug: 4.4.3(supports-color@8.1.1) + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/core@7.26.9(supports-color@8.1.1)': + dependencies: + '@ampproject/remapping': 2.3.0 + '@babel/code-frame': 7.29.7 + '@babel/generator': 7.29.7 + '@babel/helper-compilation-targets': 7.29.7 + '@babel/helper-module-transforms': 7.29.7(@babel/core@7.26.9(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/helpers': 7.29.7 + '@babel/parser': 7.29.7 + '@babel/template': 7.29.7 + '@babel/traverse': 7.29.7(supports-color@8.1.1) + '@babel/types': 7.29.7 + convert-source-map: 2.0.0 + debug: 4.4.3(supports-color@8.1.1) + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/core@7.29.7(supports-color@8.1.1)': + dependencies: + '@babel/code-frame': 7.29.7 + '@babel/generator': 7.29.7 + '@babel/helper-compilation-targets': 7.29.7 + '@babel/helper-module-transforms': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/helpers': 7.29.7 + '@babel/parser': 7.29.7 + '@babel/template': 7.29.7 + '@babel/traverse': 7.29.7(supports-color@8.1.1) + '@babel/types': 7.29.7 + '@jridgewell/remapping': 2.3.5 + convert-source-map: 2.0.0 + debug: 4.4.3(supports-color@8.1.1) + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/generator@7.26.10': + dependencies: + '@babel/parser': 7.29.7 + '@babel/types': 7.29.7 + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + jsesc: 3.1.0 + + '@babel/generator@7.29.7': + dependencies: + '@babel/parser': 7.29.7 + '@babel/types': 7.29.7 + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + jsesc: 3.1.0 + + '@babel/helper-annotate-as-pure@7.25.9': + dependencies: + '@babel/types': 7.29.7 + + '@babel/helper-annotate-as-pure@7.29.7': + dependencies: + '@babel/types': 7.29.7 + + '@babel/helper-compilation-targets@7.29.7': + dependencies: + '@babel/compat-data': 7.29.7 + '@babel/helper-validator-option': 7.29.7 + browserslist: 4.28.7 + lru-cache: 5.1.1 + semver: 6.3.1 + + '@babel/helper-create-class-features-plugin@7.29.7(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1)': + dependencies: + '@babel/core': 7.26.10(supports-color@8.1.1) + '@babel/helper-annotate-as-pure': 7.29.7 + '@babel/helper-member-expression-to-functions': 7.29.7(supports-color@8.1.1) + '@babel/helper-optimise-call-expression': 7.29.7 + '@babel/helper-replace-supers': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/helper-skip-transparent-expression-wrappers': 7.29.7(supports-color@8.1.1) + '@babel/traverse': 7.29.7(supports-color@8.1.1) + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/helper-create-regexp-features-plugin@7.29.7(@babel/core@7.26.10(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.26.10(supports-color@8.1.1) + '@babel/helper-annotate-as-pure': 7.29.7 + regexpu-core: 6.4.0 + semver: 6.3.1 + + '@babel/helper-define-polyfill-provider@0.6.8(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1)': + dependencies: + '@babel/core': 7.26.10(supports-color@8.1.1) + '@babel/helper-compilation-targets': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 + debug: 4.4.3(supports-color@8.1.1) + lodash.debounce: 4.0.8 + resolve: 1.22.12 + transitivePeerDependencies: + - supports-color + + '@babel/helper-globals@7.29.7': {} + + '@babel/helper-member-expression-to-functions@7.29.7(supports-color@8.1.1)': + dependencies: + '@babel/traverse': 7.29.7(supports-color@8.1.1) + '@babel/types': 7.29.7 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-imports@7.29.7(supports-color@8.1.1)': + dependencies: + '@babel/traverse': 7.29.7(supports-color@8.1.1) + '@babel/types': 7.29.7 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-transforms@7.29.7(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1)': + dependencies: + '@babel/core': 7.26.10(supports-color@8.1.1) + '@babel/helper-module-imports': 7.29.7(supports-color@8.1.1) + '@babel/helper-validator-identifier': 7.29.7 + '@babel/traverse': 7.29.7(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-transforms@7.29.7(@babel/core@7.26.9(supports-color@8.1.1))(supports-color@8.1.1)': + dependencies: + '@babel/core': 7.26.9(supports-color@8.1.1) + '@babel/helper-module-imports': 7.29.7(supports-color@8.1.1) + '@babel/helper-validator-identifier': 7.29.7 + '@babel/traverse': 7.29.7(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-transforms@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1)': + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-module-imports': 7.29.7(supports-color@8.1.1) + '@babel/helper-validator-identifier': 7.29.7 + '@babel/traverse': 7.29.7(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + + '@babel/helper-optimise-call-expression@7.29.7': + dependencies: + '@babel/types': 7.29.7 + + '@babel/helper-plugin-utils@7.29.7': {} + + '@babel/helper-remap-async-to-generator@7.29.7(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1)': + dependencies: + '@babel/core': 7.26.10(supports-color@8.1.1) + '@babel/helper-annotate-as-pure': 7.29.7 + '@babel/helper-wrap-function': 7.29.7(supports-color@8.1.1) + '@babel/traverse': 7.29.7(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + + '@babel/helper-replace-supers@7.29.7(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1)': + dependencies: + '@babel/core': 7.26.10(supports-color@8.1.1) + '@babel/helper-member-expression-to-functions': 7.29.7(supports-color@8.1.1) + '@babel/helper-optimise-call-expression': 7.29.7 + '@babel/traverse': 7.29.7(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + + '@babel/helper-skip-transparent-expression-wrappers@7.29.7(supports-color@8.1.1)': + dependencies: + '@babel/traverse': 7.29.7(supports-color@8.1.1) + '@babel/types': 7.29.7 + transitivePeerDependencies: + - supports-color + + '@babel/helper-split-export-declaration@7.24.7': + dependencies: + '@babel/types': 7.29.7 + + '@babel/helper-string-parser@7.29.7': {} + + '@babel/helper-validator-identifier@7.29.7': {} + + '@babel/helper-validator-option@7.29.7': {} + + '@babel/helper-wrap-function@7.29.7(supports-color@8.1.1)': + dependencies: + '@babel/template': 7.29.7 + '@babel/traverse': 7.29.7(supports-color@8.1.1) + '@babel/types': 7.29.7 + transitivePeerDependencies: + - supports-color + + '@babel/helpers@7.29.7': + dependencies: + '@babel/template': 7.29.7 + '@babel/types': 7.29.7 + + '@babel/parser@7.29.7': + dependencies: + '@babel/types': 7.29.7 + + '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.29.7(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1)': + dependencies: + '@babel/core': 7.26.10(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + '@babel/traverse': 7.29.7(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-bugfix-safari-class-field-initializer-scope@7.29.7(@babel/core@7.26.10(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.26.10(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.29.7(@babel/core@7.26.10(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.26.10(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.29.7(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1)': + dependencies: + '@babel/core': 7.26.10(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + '@babel/helper-skip-transparent-expression-wrappers': 7.29.7(supports-color@8.1.1) + '@babel/plugin-transform-optional-chaining': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.29.7(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1)': + dependencies: + '@babel/core': 7.26.10(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + '@babel/traverse': 7.29.7(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2(@babel/core@7.26.10(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.26.10(supports-color@8.1.1) + + '@babel/plugin-syntax-import-assertions@7.29.7(@babel/core@7.26.10(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.26.10(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-syntax-import-attributes@7.26.0(@babel/core@7.26.10(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.26.10(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-syntax-import-attributes@7.29.7(@babel/core@7.26.10(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.26.10(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@7.26.10(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.26.10(supports-color@8.1.1) + '@babel/helper-create-regexp-features-plugin': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1)) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-transform-arrow-functions@7.29.7(@babel/core@7.26.10(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.26.10(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-transform-async-generator-functions@7.26.8(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1)': + dependencies: + '@babel/core': 7.26.10(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + '@babel/helper-remap-async-to-generator': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/traverse': 7.29.7(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-async-to-generator@7.25.9(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1)': + dependencies: + '@babel/core': 7.26.10(supports-color@8.1.1) + '@babel/helper-module-imports': 7.29.7(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + '@babel/helper-remap-async-to-generator': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-block-scoped-functions@7.29.7(@babel/core@7.26.10(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.26.10(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-transform-block-scoping@7.29.7(@babel/core@7.26.10(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.26.10(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-transform-class-properties@7.29.7(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1)': + dependencies: + '@babel/core': 7.26.10(supports-color@8.1.1) + '@babel/helper-create-class-features-plugin': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-class-static-block@7.29.7(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1)': + dependencies: + '@babel/core': 7.26.10(supports-color@8.1.1) + '@babel/helper-create-class-features-plugin': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-classes@7.29.7(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1)': + dependencies: + '@babel/core': 7.26.10(supports-color@8.1.1) + '@babel/helper-annotate-as-pure': 7.29.7 + '@babel/helper-compilation-targets': 7.29.7 + '@babel/helper-globals': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 + '@babel/helper-replace-supers': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/traverse': 7.29.7(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-computed-properties@7.29.7(@babel/core@7.26.10(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.26.10(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + '@babel/template': 7.29.7 + + '@babel/plugin-transform-destructuring@7.29.7(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1)': + dependencies: + '@babel/core': 7.26.10(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + '@babel/traverse': 7.29.7(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-dotall-regex@7.29.7(@babel/core@7.26.10(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.26.10(supports-color@8.1.1) + '@babel/helper-create-regexp-features-plugin': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1)) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-transform-duplicate-keys@7.29.7(@babel/core@7.26.10(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.26.10(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.29.7(@babel/core@7.26.10(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.26.10(supports-color@8.1.1) + '@babel/helper-create-regexp-features-plugin': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1)) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-transform-dynamic-import@7.29.7(@babel/core@7.26.10(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.26.10(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-transform-exponentiation-operator@7.29.7(@babel/core@7.26.10(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.26.10(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-transform-export-namespace-from@7.29.7(@babel/core@7.26.10(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.26.10(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-transform-for-of@7.29.7(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1)': + dependencies: + '@babel/core': 7.26.10(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + '@babel/helper-skip-transparent-expression-wrappers': 7.29.7(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-function-name@7.29.7(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1)': + dependencies: + '@babel/core': 7.26.10(supports-color@8.1.1) + '@babel/helper-compilation-targets': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 + '@babel/traverse': 7.29.7(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-json-strings@7.29.7(@babel/core@7.26.10(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.26.10(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-transform-literals@7.29.7(@babel/core@7.26.10(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.26.10(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-transform-logical-assignment-operators@7.29.7(@babel/core@7.26.10(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.26.10(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-transform-member-expression-literals@7.29.7(@babel/core@7.26.10(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.26.10(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-transform-modules-amd@7.29.7(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1)': + dependencies: + '@babel/core': 7.26.10(supports-color@8.1.1) + '@babel/helper-module-transforms': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-modules-commonjs@7.29.7(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1)': + dependencies: + '@babel/core': 7.26.10(supports-color@8.1.1) + '@babel/helper-module-transforms': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-modules-systemjs@7.29.7(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1)': + dependencies: + '@babel/core': 7.26.10(supports-color@8.1.1) + '@babel/helper-module-transforms': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + '@babel/helper-validator-identifier': 7.29.7 + '@babel/traverse': 7.29.7(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-modules-umd@7.29.7(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1)': + dependencies: + '@babel/core': 7.26.10(supports-color@8.1.1) + '@babel/helper-module-transforms': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-named-capturing-groups-regex@7.29.7(@babel/core@7.26.10(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.26.10(supports-color@8.1.1) + '@babel/helper-create-regexp-features-plugin': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1)) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-transform-new-target@7.29.7(@babel/core@7.26.10(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.26.10(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-transform-nullish-coalescing-operator@7.29.7(@babel/core@7.26.10(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.26.10(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-transform-numeric-separator@7.29.7(@babel/core@7.26.10(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.26.10(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-transform-object-rest-spread@7.29.7(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1)': + dependencies: + '@babel/core': 7.26.10(supports-color@8.1.1) + '@babel/helper-compilation-targets': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 + '@babel/plugin-transform-destructuring': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-parameters': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1)) + '@babel/traverse': 7.29.7(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-object-super@7.29.7(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1)': + dependencies: + '@babel/core': 7.26.10(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + '@babel/helper-replace-supers': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-optional-catch-binding@7.29.7(@babel/core@7.26.10(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.26.10(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-transform-optional-chaining@7.29.7(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1)': + dependencies: + '@babel/core': 7.26.10(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + '@babel/helper-skip-transparent-expression-wrappers': 7.29.7(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-parameters@7.29.7(@babel/core@7.26.10(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.26.10(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-transform-private-methods@7.29.7(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1)': + dependencies: + '@babel/core': 7.26.10(supports-color@8.1.1) + '@babel/helper-create-class-features-plugin': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-private-property-in-object@7.29.7(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1)': + dependencies: + '@babel/core': 7.26.10(supports-color@8.1.1) + '@babel/helper-annotate-as-pure': 7.29.7 + '@babel/helper-create-class-features-plugin': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-property-literals@7.29.7(@babel/core@7.26.10(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.26.10(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-transform-regenerator@7.29.7(@babel/core@7.26.10(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.26.10(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-transform-regexp-modifiers@7.29.7(@babel/core@7.26.10(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.26.10(supports-color@8.1.1) + '@babel/helper-create-regexp-features-plugin': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1)) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-transform-reserved-words@7.29.7(@babel/core@7.26.10(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.26.10(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-transform-runtime@7.26.10(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1)': + dependencies: + '@babel/core': 7.26.10(supports-color@8.1.1) + '@babel/helper-module-imports': 7.29.7(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + babel-plugin-polyfill-corejs2: 0.4.17(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1) + babel-plugin-polyfill-corejs3: 0.11.1(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1) + babel-plugin-polyfill-regenerator: 0.6.8(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1) + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-shorthand-properties@7.29.7(@babel/core@7.26.10(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.26.10(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-transform-spread@7.29.7(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1)': + dependencies: + '@babel/core': 7.26.10(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + '@babel/helper-skip-transparent-expression-wrappers': 7.29.7(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-sticky-regex@7.29.7(@babel/core@7.26.10(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.26.10(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-transform-template-literals@7.29.7(@babel/core@7.26.10(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.26.10(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-transform-typeof-symbol@7.29.7(@babel/core@7.26.10(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.26.10(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-transform-unicode-escapes@7.29.7(@babel/core@7.26.10(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.26.10(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-transform-unicode-property-regex@7.29.7(@babel/core@7.26.10(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.26.10(supports-color@8.1.1) + '@babel/helper-create-regexp-features-plugin': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1)) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-transform-unicode-regex@7.29.7(@babel/core@7.26.10(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.26.10(supports-color@8.1.1) + '@babel/helper-create-regexp-features-plugin': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1)) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-transform-unicode-sets-regex@7.29.7(@babel/core@7.26.10(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.26.10(supports-color@8.1.1) + '@babel/helper-create-regexp-features-plugin': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1)) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/preset-env@7.26.9(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1)': + dependencies: + '@babel/compat-data': 7.29.7 + '@babel/core': 7.26.10(supports-color@8.1.1) + '@babel/helper-compilation-targets': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 + '@babel/helper-validator-option': 7.29.7 + '@babel/plugin-bugfix-firefox-class-in-computed-class-key': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-bugfix-safari-class-field-initializer-scope': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1)) + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1)) + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-proposal-private-property-in-object': 7.21.0-placeholder-for-preset-env.2(@babel/core@7.26.10(supports-color@8.1.1)) + '@babel/plugin-syntax-import-assertions': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1)) + '@babel/plugin-syntax-import-attributes': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1)) + '@babel/plugin-syntax-unicode-sets-regex': 7.18.6(@babel/core@7.26.10(supports-color@8.1.1)) + '@babel/plugin-transform-arrow-functions': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1)) + '@babel/plugin-transform-async-generator-functions': 7.26.8(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-async-to-generator': 7.25.9(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-block-scoped-functions': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1)) + '@babel/plugin-transform-block-scoping': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1)) + '@babel/plugin-transform-class-properties': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-class-static-block': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-classes': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-computed-properties': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1)) + '@babel/plugin-transform-destructuring': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-dotall-regex': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1)) + '@babel/plugin-transform-duplicate-keys': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1)) + '@babel/plugin-transform-duplicate-named-capturing-groups-regex': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1)) + '@babel/plugin-transform-dynamic-import': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1)) + '@babel/plugin-transform-exponentiation-operator': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1)) + '@babel/plugin-transform-export-namespace-from': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1)) + '@babel/plugin-transform-for-of': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-function-name': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-json-strings': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1)) + '@babel/plugin-transform-literals': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1)) + '@babel/plugin-transform-logical-assignment-operators': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1)) + '@babel/plugin-transform-member-expression-literals': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1)) + '@babel/plugin-transform-modules-amd': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-modules-commonjs': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-modules-systemjs': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-modules-umd': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-named-capturing-groups-regex': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1)) + '@babel/plugin-transform-new-target': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1)) + '@babel/plugin-transform-nullish-coalescing-operator': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1)) + '@babel/plugin-transform-numeric-separator': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1)) + '@babel/plugin-transform-object-rest-spread': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-object-super': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-optional-catch-binding': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1)) + '@babel/plugin-transform-optional-chaining': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-parameters': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1)) + '@babel/plugin-transform-private-methods': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-private-property-in-object': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-property-literals': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1)) + '@babel/plugin-transform-regenerator': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1)) + '@babel/plugin-transform-regexp-modifiers': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1)) + '@babel/plugin-transform-reserved-words': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1)) + '@babel/plugin-transform-shorthand-properties': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1)) + '@babel/plugin-transform-spread': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-sticky-regex': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1)) + '@babel/plugin-transform-template-literals': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1)) + '@babel/plugin-transform-typeof-symbol': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1)) + '@babel/plugin-transform-unicode-escapes': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1)) + '@babel/plugin-transform-unicode-property-regex': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1)) + '@babel/plugin-transform-unicode-regex': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1)) + '@babel/plugin-transform-unicode-sets-regex': 7.29.7(@babel/core@7.26.10(supports-color@8.1.1)) + '@babel/preset-modules': 0.1.6-no-external-plugins(@babel/core@7.26.10(supports-color@8.1.1)) + babel-plugin-polyfill-corejs2: 0.4.17(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1) + babel-plugin-polyfill-corejs3: 0.11.1(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1) + babel-plugin-polyfill-regenerator: 0.6.8(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1) + core-js-compat: 3.49.0 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/preset-modules@0.1.6-no-external-plugins(@babel/core@7.26.10(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.26.10(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + '@babel/types': 7.29.7 + esutils: 2.0.3 + + '@babel/runtime@7.26.10': + dependencies: + regenerator-runtime: 0.14.1 + + '@babel/template@7.29.7': + dependencies: + '@babel/code-frame': 7.29.7 + '@babel/parser': 7.29.7 + '@babel/types': 7.29.7 + + '@babel/traverse@7.29.7(supports-color@8.1.1)': + dependencies: + '@babel/code-frame': 7.29.7 + '@babel/generator': 7.29.7 + '@babel/helper-globals': 7.29.7 + '@babel/parser': 7.29.7 + '@babel/template': 7.29.7 + '@babel/types': 7.29.7 + debug: 4.4.3(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + + '@babel/types@7.29.7': + dependencies: + '@babel/helper-string-parser': 7.29.7 + '@babel/helper-validator-identifier': 7.29.7 + + '@capacitor-community/electron@5.0.1(supports-color@8.1.1)': + dependencies: + '@capacitor/cli': 8.5.0(supports-color@8.1.1) + '@capacitor/core': 8.5.0 + '@ionic/utils-fs': 3.1.7(supports-color@8.1.1) + chalk: 4.1.2 + electron-is-dev: 2.0.0 + events: 3.3.0 + fs-extra: 11.1.1 + keyv: 4.5.4 + mime-types: 2.1.35 + ora: 5.4.1 + transitivePeerDependencies: + - supports-color + + '@capacitor/android@8.5.0(@capacitor/core@8.5.0)': + dependencies: + '@capacitor/core': 8.5.0 + + '@capacitor/cli@8.5.0(supports-color@8.1.1)': + dependencies: + '@ionic/cli-framework-output': 2.2.8(supports-color@8.1.1) + '@ionic/utils-subprocess': 3.0.1(supports-color@8.1.1) + '@ionic/utils-terminal': 2.3.5(supports-color@8.1.1) + commander: 12.1.0 + debug: 4.4.3(supports-color@8.1.1) + env-paths: 2.2.1 + fs-extra: 11.4.0 + kleur: 4.1.5 + native-run: 2.0.3(supports-color@8.1.1) + open: 8.4.2 + plist: 3.1.1 + prompts: 2.4.2 + rimraf: 6.1.3 + semver: 7.8.5 + tar: 7.5.22 + tslib: 2.8.1 + xcode: 3.0.1 + xml2js: 0.6.2 + transitivePeerDependencies: + - supports-color + + '@capacitor/core@8.5.0': + dependencies: + tslib: 2.8.1 + + '@capacitor/ios@8.5.0(@capacitor/core@8.5.0)': + dependencies: + '@capacitor/core': 8.5.0 + + '@colors/colors@1.5.0': {} + + '@dimforge/rapier3d-compat@0.12.0': {} + + '@discoveryjs/json-ext@0.6.3': {} + + '@esbuild/aix-ppc64@0.25.12': + optional: true + + '@esbuild/aix-ppc64@0.28.0': + optional: true + + '@esbuild/android-arm64@0.25.12': + optional: true + + '@esbuild/android-arm64@0.28.0': + optional: true + + '@esbuild/android-arm@0.25.12': + optional: true + + '@esbuild/android-arm@0.28.0': + optional: true + + '@esbuild/android-x64@0.25.12': + optional: true + + '@esbuild/android-x64@0.28.0': + optional: true + + '@esbuild/darwin-arm64@0.25.12': + optional: true + + '@esbuild/darwin-arm64@0.28.0': + optional: true + + '@esbuild/darwin-x64@0.25.12': + optional: true + + '@esbuild/darwin-x64@0.28.0': + optional: true + + '@esbuild/freebsd-arm64@0.25.12': + optional: true + + '@esbuild/freebsd-arm64@0.28.0': + optional: true + + '@esbuild/freebsd-x64@0.25.12': + optional: true + + '@esbuild/freebsd-x64@0.28.0': + optional: true + + '@esbuild/linux-arm64@0.25.12': + optional: true + + '@esbuild/linux-arm64@0.28.0': + optional: true + + '@esbuild/linux-arm@0.25.12': + optional: true + + '@esbuild/linux-arm@0.28.0': + optional: true + + '@esbuild/linux-ia32@0.25.12': + optional: true + + '@esbuild/linux-ia32@0.28.0': + optional: true + + '@esbuild/linux-loong64@0.25.12': + optional: true + + '@esbuild/linux-loong64@0.28.0': + optional: true + + '@esbuild/linux-mips64el@0.25.12': + optional: true + + '@esbuild/linux-mips64el@0.28.0': + optional: true + + '@esbuild/linux-ppc64@0.25.12': + optional: true + + '@esbuild/linux-ppc64@0.28.0': + optional: true + + '@esbuild/linux-riscv64@0.25.12': + optional: true + + '@esbuild/linux-riscv64@0.28.0': + optional: true + + '@esbuild/linux-s390x@0.25.12': + optional: true + + '@esbuild/linux-s390x@0.28.0': + optional: true + + '@esbuild/linux-x64@0.25.12': + optional: true + + '@esbuild/linux-x64@0.28.0': + optional: true + + '@esbuild/netbsd-arm64@0.25.12': + optional: true + + '@esbuild/netbsd-arm64@0.28.0': + optional: true + + '@esbuild/netbsd-x64@0.25.12': + optional: true + + '@esbuild/netbsd-x64@0.28.0': + optional: true + + '@esbuild/openbsd-arm64@0.25.12': + optional: true + + '@esbuild/openbsd-arm64@0.28.0': + optional: true + + '@esbuild/openbsd-x64@0.25.12': + optional: true + + '@esbuild/openbsd-x64@0.28.0': + optional: true + + '@esbuild/openharmony-arm64@0.25.12': + optional: true + + '@esbuild/openharmony-arm64@0.28.0': + optional: true + + '@esbuild/sunos-x64@0.25.12': + optional: true + + '@esbuild/sunos-x64@0.28.0': + optional: true + + '@esbuild/win32-arm64@0.25.12': + optional: true + + '@esbuild/win32-arm64@0.28.0': + optional: true + + '@esbuild/win32-ia32@0.25.12': + optional: true + + '@esbuild/win32-ia32@0.28.0': + optional: true + + '@esbuild/win32-x64@0.25.12': + optional: true + + '@esbuild/win32-x64@0.28.0': + optional: true + + '@inquirer/ansi@1.0.2': {} + + '@inquirer/checkbox@4.3.2(@types/node@26.1.2)': + dependencies: + '@inquirer/ansi': 1.0.2 + '@inquirer/core': 10.3.2(@types/node@26.1.2) + '@inquirer/figures': 1.0.15 + '@inquirer/type': 3.0.10(@types/node@26.1.2) + yoctocolors-cjs: 2.1.3 + optionalDependencies: + '@types/node': 26.1.2 + + '@inquirer/confirm@5.1.21(@types/node@26.1.2)': + dependencies: + '@inquirer/core': 10.3.2(@types/node@26.1.2) + '@inquirer/type': 3.0.10(@types/node@26.1.2) + optionalDependencies: + '@types/node': 26.1.2 + + '@inquirer/confirm@5.1.6(@types/node@26.1.2)': + dependencies: + '@inquirer/core': 10.3.2(@types/node@26.1.2) + '@inquirer/type': 3.0.10(@types/node@26.1.2) + optionalDependencies: + '@types/node': 26.1.2 + + '@inquirer/core@10.3.2(@types/node@26.1.2)': + dependencies: + '@inquirer/ansi': 1.0.2 + '@inquirer/figures': 1.0.15 + '@inquirer/type': 3.0.10(@types/node@26.1.2) + cli-width: 4.1.0 + mute-stream: 2.0.0 + signal-exit: 4.1.0 + wrap-ansi: 6.2.0 + yoctocolors-cjs: 2.1.3 + optionalDependencies: + '@types/node': 26.1.2 + + '@inquirer/editor@4.2.23(@types/node@26.1.2)': + dependencies: + '@inquirer/core': 10.3.2(@types/node@26.1.2) + '@inquirer/external-editor': 1.0.3(@types/node@26.1.2) + '@inquirer/type': 3.0.10(@types/node@26.1.2) + optionalDependencies: + '@types/node': 26.1.2 + + '@inquirer/expand@4.0.23(@types/node@26.1.2)': + dependencies: + '@inquirer/core': 10.3.2(@types/node@26.1.2) + '@inquirer/type': 3.0.10(@types/node@26.1.2) + yoctocolors-cjs: 2.1.3 + optionalDependencies: + '@types/node': 26.1.2 + + '@inquirer/external-editor@1.0.3(@types/node@26.1.2)': + dependencies: + chardet: 2.2.0 + iconv-lite: 0.7.3 + optionalDependencies: + '@types/node': 26.1.2 + + '@inquirer/figures@1.0.15': {} + + '@inquirer/input@4.3.1(@types/node@26.1.2)': + dependencies: + '@inquirer/core': 10.3.2(@types/node@26.1.2) + '@inquirer/type': 3.0.10(@types/node@26.1.2) + optionalDependencies: + '@types/node': 26.1.2 + + '@inquirer/number@3.0.23(@types/node@26.1.2)': + dependencies: + '@inquirer/core': 10.3.2(@types/node@26.1.2) + '@inquirer/type': 3.0.10(@types/node@26.1.2) + optionalDependencies: + '@types/node': 26.1.2 + + '@inquirer/password@4.0.23(@types/node@26.1.2)': + dependencies: + '@inquirer/ansi': 1.0.2 + '@inquirer/core': 10.3.2(@types/node@26.1.2) + '@inquirer/type': 3.0.10(@types/node@26.1.2) + optionalDependencies: + '@types/node': 26.1.2 + + '@inquirer/prompts@7.3.2(@types/node@26.1.2)': + dependencies: + '@inquirer/checkbox': 4.3.2(@types/node@26.1.2) + '@inquirer/confirm': 5.1.21(@types/node@26.1.2) + '@inquirer/editor': 4.2.23(@types/node@26.1.2) + '@inquirer/expand': 4.0.23(@types/node@26.1.2) + '@inquirer/input': 4.3.1(@types/node@26.1.2) + '@inquirer/number': 3.0.23(@types/node@26.1.2) + '@inquirer/password': 4.0.23(@types/node@26.1.2) + '@inquirer/rawlist': 4.1.11(@types/node@26.1.2) + '@inquirer/search': 3.2.2(@types/node@26.1.2) + '@inquirer/select': 4.4.2(@types/node@26.1.2) + optionalDependencies: + '@types/node': 26.1.2 + + '@inquirer/rawlist@4.1.11(@types/node@26.1.2)': + dependencies: + '@inquirer/core': 10.3.2(@types/node@26.1.2) + '@inquirer/type': 3.0.10(@types/node@26.1.2) + yoctocolors-cjs: 2.1.3 + optionalDependencies: + '@types/node': 26.1.2 + + '@inquirer/search@3.2.2(@types/node@26.1.2)': + dependencies: + '@inquirer/core': 10.3.2(@types/node@26.1.2) + '@inquirer/figures': 1.0.15 + '@inquirer/type': 3.0.10(@types/node@26.1.2) + yoctocolors-cjs: 2.1.3 + optionalDependencies: + '@types/node': 26.1.2 + + '@inquirer/select@4.4.2(@types/node@26.1.2)': + dependencies: + '@inquirer/ansi': 1.0.2 + '@inquirer/core': 10.3.2(@types/node@26.1.2) + '@inquirer/figures': 1.0.15 + '@inquirer/type': 3.0.10(@types/node@26.1.2) + yoctocolors-cjs: 2.1.3 + optionalDependencies: + '@types/node': 26.1.2 + + '@inquirer/type@1.5.5': + dependencies: + mute-stream: 1.0.0 + + '@inquirer/type@3.0.10(@types/node@26.1.2)': + optionalDependencies: + '@types/node': 26.1.2 + + '@ionic/cli-framework-output@2.2.8(supports-color@8.1.1)': + dependencies: + '@ionic/utils-terminal': 2.3.5(supports-color@8.1.1) + debug: 4.4.3(supports-color@8.1.1) + tslib: 2.8.1 + transitivePeerDependencies: + - supports-color + + '@ionic/utils-array@2.1.6(supports-color@8.1.1)': + dependencies: + debug: 4.4.3(supports-color@8.1.1) + tslib: 2.8.1 + transitivePeerDependencies: + - supports-color + + '@ionic/utils-fs@3.1.7(supports-color@8.1.1)': + dependencies: + '@types/fs-extra': 8.1.5 + debug: 4.4.3(supports-color@8.1.1) + fs-extra: 9.1.0 + tslib: 2.8.1 + transitivePeerDependencies: + - supports-color + + '@ionic/utils-object@2.1.6(supports-color@8.1.1)': + dependencies: + debug: 4.4.3(supports-color@8.1.1) + tslib: 2.8.1 + transitivePeerDependencies: + - supports-color + + '@ionic/utils-process@2.1.12(supports-color@8.1.1)': + dependencies: + '@ionic/utils-object': 2.1.6(supports-color@8.1.1) + '@ionic/utils-terminal': 2.3.5(supports-color@8.1.1) + debug: 4.4.3(supports-color@8.1.1) + signal-exit: 3.0.7 + tree-kill: 1.2.2 + tslib: 2.8.1 + transitivePeerDependencies: + - supports-color + + '@ionic/utils-stream@3.1.7(supports-color@8.1.1)': + dependencies: + debug: 4.4.3(supports-color@8.1.1) + tslib: 2.8.1 + transitivePeerDependencies: + - supports-color + + '@ionic/utils-subprocess@3.0.1(supports-color@8.1.1)': + dependencies: + '@ionic/utils-array': 2.1.6(supports-color@8.1.1) + '@ionic/utils-fs': 3.1.7(supports-color@8.1.1) + '@ionic/utils-process': 2.1.12(supports-color@8.1.1) + '@ionic/utils-stream': 3.1.7(supports-color@8.1.1) + '@ionic/utils-terminal': 2.3.5(supports-color@8.1.1) + cross-spawn: 7.0.6 + debug: 4.4.3(supports-color@8.1.1) + tslib: 2.8.1 + transitivePeerDependencies: + - supports-color + + '@ionic/utils-terminal@2.3.5(supports-color@8.1.1)': + dependencies: + '@types/slice-ansi': 4.0.0 + debug: 4.4.3(supports-color@8.1.1) + signal-exit: 3.0.7 + slice-ansi: 4.0.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + tslib: 2.8.1 + untildify: 4.0.0 + wrap-ansi: 7.0.0 + transitivePeerDependencies: + - supports-color + + '@isaacs/cliui@8.0.2': + dependencies: + string-width: 5.1.2 + string-width-cjs: string-width@4.2.3 + strip-ansi: 7.2.0 + strip-ansi-cjs: strip-ansi@6.0.1 + wrap-ansi: 8.1.0 + wrap-ansi-cjs: wrap-ansi@7.0.0 + + '@isaacs/fs-minipass@4.0.1': + dependencies: + minipass: 7.1.3 + + '@istanbuljs/schema@0.1.6': {} + + '@jridgewell/gen-mapping@0.3.13': + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/remapping@2.3.5': + dependencies: + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/resolve-uri@3.1.2': {} + + '@jridgewell/source-map@0.3.11': + dependencies: + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/sourcemap-codec@1.5.5': {} + + '@jridgewell/trace-mapping@0.3.31': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.5 + + '@jsonjoy.com/base64@1.1.2(tslib@2.8.1)': + dependencies: + tslib: 2.8.1 + + '@jsonjoy.com/base64@17.67.0(tslib@2.8.1)': + dependencies: + tslib: 2.8.1 + + '@jsonjoy.com/buffers@1.2.1(tslib@2.8.1)': + dependencies: + tslib: 2.8.1 + + '@jsonjoy.com/buffers@17.67.0(tslib@2.8.1)': + dependencies: + tslib: 2.8.1 + + '@jsonjoy.com/codegen@1.0.0(tslib@2.8.1)': + dependencies: + tslib: 2.8.1 + + '@jsonjoy.com/codegen@17.67.0(tslib@2.8.1)': + dependencies: + tslib: 2.8.1 + + '@jsonjoy.com/fs-core@4.64.0(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/fs-node-builtins': 4.64.0(tslib@2.8.1) + '@jsonjoy.com/fs-node-utils': 4.64.0(tslib@2.8.1) + thingies: 2.6.1(tslib@2.8.1) + tslib: 2.8.1 + + '@jsonjoy.com/fs-fsa@4.64.0(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/fs-core': 4.64.0(tslib@2.8.1) + '@jsonjoy.com/fs-node-builtins': 4.64.0(tslib@2.8.1) + '@jsonjoy.com/fs-node-utils': 4.64.0(tslib@2.8.1) + thingies: 2.6.1(tslib@2.8.1) + tslib: 2.8.1 + + '@jsonjoy.com/fs-node-builtins@4.64.0(tslib@2.8.1)': + dependencies: + tslib: 2.8.1 + + '@jsonjoy.com/fs-node-to-fsa@4.64.0(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/fs-fsa': 4.64.0(tslib@2.8.1) + '@jsonjoy.com/fs-node-builtins': 4.64.0(tslib@2.8.1) + '@jsonjoy.com/fs-node-utils': 4.64.0(tslib@2.8.1) + tslib: 2.8.1 + + '@jsonjoy.com/fs-node-utils@4.64.0(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/fs-node-builtins': 4.64.0(tslib@2.8.1) + glob-to-regex.js: 1.2.0(tslib@2.8.1) + tslib: 2.8.1 + + '@jsonjoy.com/fs-node@4.64.0(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/fs-core': 4.64.0(tslib@2.8.1) + '@jsonjoy.com/fs-node-builtins': 4.64.0(tslib@2.8.1) + '@jsonjoy.com/fs-node-utils': 4.64.0(tslib@2.8.1) + '@jsonjoy.com/fs-print': 4.64.0(tslib@2.8.1) + '@jsonjoy.com/fs-snapshot': 4.64.0(tslib@2.8.1) + glob-to-regex.js: 1.2.0(tslib@2.8.1) + thingies: 2.6.1(tslib@2.8.1) + tslib: 2.8.1 + + '@jsonjoy.com/fs-print@4.64.0(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/fs-node-utils': 4.64.0(tslib@2.8.1) + tree-dump: 1.1.0(tslib@2.8.1) + tslib: 2.8.1 + + '@jsonjoy.com/fs-snapshot@4.64.0(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/buffers': 17.67.0(tslib@2.8.1) + '@jsonjoy.com/fs-node-utils': 4.64.0(tslib@2.8.1) + '@jsonjoy.com/json-pack': 17.67.0(tslib@2.8.1) + '@jsonjoy.com/util': 17.67.0(tslib@2.8.1) + tslib: 2.8.1 + + '@jsonjoy.com/json-pack@1.21.0(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/base64': 1.1.2(tslib@2.8.1) + '@jsonjoy.com/buffers': 1.2.1(tslib@2.8.1) + '@jsonjoy.com/codegen': 1.0.0(tslib@2.8.1) + '@jsonjoy.com/json-pointer': 1.0.2(tslib@2.8.1) + '@jsonjoy.com/util': 1.9.0(tslib@2.8.1) + hyperdyperid: 1.2.0 + thingies: 2.6.1(tslib@2.8.1) + tree-dump: 1.1.0(tslib@2.8.1) + tslib: 2.8.1 + + '@jsonjoy.com/json-pack@17.67.0(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/base64': 17.67.0(tslib@2.8.1) + '@jsonjoy.com/buffers': 17.67.0(tslib@2.8.1) + '@jsonjoy.com/codegen': 17.67.0(tslib@2.8.1) + '@jsonjoy.com/json-pointer': 17.67.0(tslib@2.8.1) + '@jsonjoy.com/util': 17.67.0(tslib@2.8.1) + hyperdyperid: 1.2.0 + thingies: 2.6.1(tslib@2.8.1) + tree-dump: 1.1.0(tslib@2.8.1) + tslib: 2.8.1 + + '@jsonjoy.com/json-pointer@1.0.2(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/codegen': 1.0.0(tslib@2.8.1) + '@jsonjoy.com/util': 1.9.0(tslib@2.8.1) + tslib: 2.8.1 + + '@jsonjoy.com/json-pointer@17.67.0(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/util': 17.67.0(tslib@2.8.1) + tslib: 2.8.1 + + '@jsonjoy.com/util@1.9.0(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/buffers': 1.2.1(tslib@2.8.1) + '@jsonjoy.com/codegen': 1.0.0(tslib@2.8.1) + tslib: 2.8.1 + + '@jsonjoy.com/util@17.67.0(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/buffers': 17.67.0(tslib@2.8.1) + '@jsonjoy.com/codegen': 17.67.0(tslib@2.8.1) + tslib: 2.8.1 + + '@leichtgewicht/ip-codec@2.0.5': {} + + '@listr2/prompt-adapter-inquirer@2.0.18(@inquirer/prompts@7.3.2(@types/node@26.1.2))': + dependencies: + '@inquirer/prompts': 7.3.2(@types/node@26.1.2) + '@inquirer/type': 1.5.5 + + '@lmdb/lmdb-darwin-arm64@3.2.6': + optional: true + + '@lmdb/lmdb-darwin-x64@3.2.6': + optional: true + + '@lmdb/lmdb-linux-arm64@3.2.6': + optional: true + + '@lmdb/lmdb-linux-arm@3.2.6': + optional: true + + '@lmdb/lmdb-linux-x64@3.2.6': + optional: true + + '@lmdb/lmdb-win32-x64@3.2.6': + optional: true + + '@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.4': + optional: true + + '@msgpackr-extract/msgpackr-extract-darwin-x64@3.0.4': + optional: true + + '@msgpackr-extract/msgpackr-extract-linux-arm64@3.0.4': + optional: true + + '@msgpackr-extract/msgpackr-extract-linux-arm@3.0.4': + optional: true + + '@msgpackr-extract/msgpackr-extract-linux-x64@3.0.4': + optional: true + + '@msgpackr-extract/msgpackr-extract-win32-x64@3.0.4': + optional: true + + '@napi-rs/nice-android-arm-eabi@1.1.1': + optional: true + + '@napi-rs/nice-android-arm64@1.1.1': + optional: true + + '@napi-rs/nice-darwin-arm64@1.1.1': + optional: true + + '@napi-rs/nice-darwin-x64@1.1.1': + optional: true + + '@napi-rs/nice-freebsd-x64@1.1.1': + optional: true + + '@napi-rs/nice-linux-arm-gnueabihf@1.1.1': + optional: true + + '@napi-rs/nice-linux-arm64-gnu@1.1.1': + optional: true + + '@napi-rs/nice-linux-arm64-musl@1.1.1': + optional: true + + '@napi-rs/nice-linux-ppc64-gnu@1.1.1': + optional: true + + '@napi-rs/nice-linux-riscv64-gnu@1.1.1': + optional: true + + '@napi-rs/nice-linux-s390x-gnu@1.1.1': + optional: true + + '@napi-rs/nice-linux-x64-gnu@1.1.1': + optional: true + + '@napi-rs/nice-linux-x64-musl@1.1.1': + optional: true + + '@napi-rs/nice-openharmony-arm64@1.1.1': + optional: true + + '@napi-rs/nice-win32-arm64-msvc@1.1.1': + optional: true + + '@napi-rs/nice-win32-ia32-msvc@1.1.1': + optional: true + + '@napi-rs/nice-win32-x64-msvc@1.1.1': + optional: true + + '@napi-rs/nice@1.1.1': + optionalDependencies: + '@napi-rs/nice-android-arm-eabi': 1.1.1 + '@napi-rs/nice-android-arm64': 1.1.1 + '@napi-rs/nice-darwin-arm64': 1.1.1 + '@napi-rs/nice-darwin-x64': 1.1.1 + '@napi-rs/nice-freebsd-x64': 1.1.1 + '@napi-rs/nice-linux-arm-gnueabihf': 1.1.1 + '@napi-rs/nice-linux-arm64-gnu': 1.1.1 + '@napi-rs/nice-linux-arm64-musl': 1.1.1 + '@napi-rs/nice-linux-ppc64-gnu': 1.1.1 + '@napi-rs/nice-linux-riscv64-gnu': 1.1.1 + '@napi-rs/nice-linux-s390x-gnu': 1.1.1 + '@napi-rs/nice-linux-x64-gnu': 1.1.1 + '@napi-rs/nice-linux-x64-musl': 1.1.1 + '@napi-rs/nice-openharmony-arm64': 1.1.1 + '@napi-rs/nice-win32-arm64-msvc': 1.1.1 + '@napi-rs/nice-win32-ia32-msvc': 1.1.1 + '@napi-rs/nice-win32-x64-msvc': 1.1.1 + optional: true + + '@ngtools/webpack@19.2.27(@angular/compiler-cli@19.2.25(@angular/compiler@19.2.25)(supports-color@8.1.1)(typescript@5.5.4))(typescript@5.5.4)(webpack@5.105.0(esbuild@0.28.0)(postcss@8.5.12))': + dependencies: + '@angular/compiler-cli': 19.2.25(@angular/compiler@19.2.25)(supports-color@8.1.1)(typescript@5.5.4) + typescript: 5.5.4 + webpack: 5.105.0(esbuild@0.28.0)(postcss@8.5.12) + + '@nodelib/fs.scandir@2.1.5': + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + + '@nodelib/fs.stat@2.0.5': {} + + '@nodelib/fs.walk@1.2.8': + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.20.1 + + '@npmcli/agent@3.0.0(supports-color@8.1.1)': + dependencies: + agent-base: 7.1.4 + http-proxy-agent: 7.0.2(supports-color@8.1.1) + https-proxy-agent: 7.0.6(supports-color@8.1.1) + lru-cache: 10.4.3 + socks-proxy-agent: 8.0.5(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + + '@npmcli/fs@4.0.0': + dependencies: + semver: 7.8.5 + + '@npmcli/git@6.0.3': + dependencies: + '@npmcli/promise-spawn': 8.0.3 + ini: 5.0.0 + lru-cache: 10.4.3 + npm-pick-manifest: 10.0.0 + proc-log: 5.0.0 + promise-retry: 2.0.1 + semver: 7.8.5 + which: 5.0.0 + + '@npmcli/installed-package-contents@3.0.0': + dependencies: + npm-bundled: 4.0.0 + npm-normalize-package-bin: 4.0.0 + + '@npmcli/node-gyp@4.0.0': {} + + '@npmcli/package-json@6.2.0': + dependencies: + '@npmcli/git': 6.0.3 + glob: 10.5.0 + hosted-git-info: 8.1.0 + json-parse-even-better-errors: 4.0.0 + proc-log: 5.0.0 + semver: 7.8.5 + validate-npm-package-license: 3.0.4 + + '@npmcli/promise-spawn@8.0.3': + dependencies: + which: 5.0.0 + + '@npmcli/redact@3.2.2': {} + + '@npmcli/run-script@9.1.0(supports-color@8.1.1)': + dependencies: + '@npmcli/node-gyp': 4.0.0 + '@npmcli/package-json': 6.2.0 + '@npmcli/promise-spawn': 8.0.3 + node-gyp: 11.5.0(supports-color@8.1.1) + proc-log: 5.0.0 + which: 5.0.0 + transitivePeerDependencies: + - supports-color + + '@parcel/watcher-android-arm64@2.6.0': + optional: true + + '@parcel/watcher-darwin-arm64@2.6.0': + optional: true + + '@parcel/watcher-darwin-x64@2.6.0': + optional: true + + '@parcel/watcher-freebsd-x64@2.6.0': + optional: true + + '@parcel/watcher-linux-arm-glibc@2.6.0': + optional: true + + '@parcel/watcher-linux-arm-musl@2.6.0': + optional: true + + '@parcel/watcher-linux-arm64-glibc@2.6.0': + optional: true + + '@parcel/watcher-linux-arm64-musl@2.6.0': + optional: true + + '@parcel/watcher-linux-x64-glibc@2.6.0': + optional: true + + '@parcel/watcher-linux-x64-musl@2.6.0': + optional: true + + '@parcel/watcher-win32-arm64@2.6.0': + optional: true + + '@parcel/watcher-win32-x64@2.6.0': + optional: true + + '@parcel/watcher@2.6.0': + dependencies: + detect-libc: 2.1.2 + is-glob: 4.0.3 + node-addon-api: 7.1.1 + picomatch: 4.0.5 + optionalDependencies: + '@parcel/watcher-android-arm64': 2.6.0 + '@parcel/watcher-darwin-arm64': 2.6.0 + '@parcel/watcher-darwin-x64': 2.6.0 + '@parcel/watcher-freebsd-x64': 2.6.0 + '@parcel/watcher-linux-arm-glibc': 2.6.0 + '@parcel/watcher-linux-arm-musl': 2.6.0 + '@parcel/watcher-linux-arm64-glibc': 2.6.0 + '@parcel/watcher-linux-arm64-musl': 2.6.0 + '@parcel/watcher-linux-x64-glibc': 2.6.0 + '@parcel/watcher-linux-x64-musl': 2.6.0 + '@parcel/watcher-win32-arm64': 2.6.0 + '@parcel/watcher-win32-x64': 2.6.0 + optional: true + + '@pkgjs/parseargs@0.11.0': + optional: true + + '@rollup/rollup-android-arm-eabi@4.59.0': + optional: true + + '@rollup/rollup-android-arm-eabi@4.62.3': + optional: true + + '@rollup/rollup-android-arm64@4.59.0': + optional: true + + '@rollup/rollup-android-arm64@4.62.3': + optional: true + + '@rollup/rollup-darwin-arm64@4.59.0': + optional: true + + '@rollup/rollup-darwin-arm64@4.62.3': + optional: true + + '@rollup/rollup-darwin-x64@4.59.0': + optional: true + + '@rollup/rollup-darwin-x64@4.62.3': + optional: true + + '@rollup/rollup-freebsd-arm64@4.59.0': + optional: true + + '@rollup/rollup-freebsd-arm64@4.62.3': + optional: true + + '@rollup/rollup-freebsd-x64@4.59.0': + optional: true + + '@rollup/rollup-freebsd-x64@4.62.3': + optional: true + + '@rollup/rollup-linux-arm-gnueabihf@4.59.0': + optional: true + + '@rollup/rollup-linux-arm-gnueabihf@4.62.3': + optional: true + + '@rollup/rollup-linux-arm-musleabihf@4.59.0': + optional: true + + '@rollup/rollup-linux-arm-musleabihf@4.62.3': + optional: true + + '@rollup/rollup-linux-arm64-gnu@4.59.0': + optional: true + + '@rollup/rollup-linux-arm64-gnu@4.62.3': + optional: true + + '@rollup/rollup-linux-arm64-musl@4.59.0': + optional: true + + '@rollup/rollup-linux-arm64-musl@4.62.3': + optional: true + + '@rollup/rollup-linux-loong64-gnu@4.59.0': + optional: true + + '@rollup/rollup-linux-loong64-gnu@4.62.3': + optional: true + + '@rollup/rollup-linux-loong64-musl@4.59.0': + optional: true + + '@rollup/rollup-linux-loong64-musl@4.62.3': + optional: true + + '@rollup/rollup-linux-ppc64-gnu@4.59.0': + optional: true + + '@rollup/rollup-linux-ppc64-gnu@4.62.3': + optional: true + + '@rollup/rollup-linux-ppc64-musl@4.59.0': + optional: true + + '@rollup/rollup-linux-ppc64-musl@4.62.3': + optional: true + + '@rollup/rollup-linux-riscv64-gnu@4.59.0': + optional: true + + '@rollup/rollup-linux-riscv64-gnu@4.62.3': + optional: true + + '@rollup/rollup-linux-riscv64-musl@4.59.0': + optional: true + + '@rollup/rollup-linux-riscv64-musl@4.62.3': + optional: true + + '@rollup/rollup-linux-s390x-gnu@4.59.0': + optional: true + + '@rollup/rollup-linux-s390x-gnu@4.62.3': + optional: true + + '@rollup/rollup-linux-x64-gnu@4.59.0': + optional: true + + '@rollup/rollup-linux-x64-gnu@4.62.3': + optional: true + + '@rollup/rollup-linux-x64-musl@4.59.0': + optional: true + + '@rollup/rollup-linux-x64-musl@4.62.3': + optional: true + + '@rollup/rollup-openbsd-x64@4.59.0': + optional: true + + '@rollup/rollup-openbsd-x64@4.62.3': + optional: true + + '@rollup/rollup-openharmony-arm64@4.59.0': + optional: true + + '@rollup/rollup-openharmony-arm64@4.62.3': + optional: true + + '@rollup/rollup-win32-arm64-msvc@4.59.0': + optional: true + + '@rollup/rollup-win32-arm64-msvc@4.62.3': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.59.0': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.62.3': + optional: true + + '@rollup/rollup-win32-x64-gnu@4.59.0': + optional: true + + '@rollup/rollup-win32-x64-gnu@4.62.3': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.59.0': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.62.3': + optional: true + + '@schematics/angular@19.2.27(chokidar@4.0.3)': + dependencies: + '@angular-devkit/core': 19.2.27(chokidar@4.0.3) + '@angular-devkit/schematics': 19.2.27(chokidar@4.0.3) + jsonc-parser: 3.3.1 + transitivePeerDependencies: + - chokidar + + '@sigstore/bundle@3.1.0': + dependencies: + '@sigstore/protobuf-specs': 0.4.3 + + '@sigstore/core@2.0.0': {} + + '@sigstore/protobuf-specs@0.4.3': {} + + '@sigstore/sign@3.1.0(supports-color@8.1.1)': + dependencies: + '@sigstore/bundle': 3.1.0 + '@sigstore/core': 2.0.0 + '@sigstore/protobuf-specs': 0.4.3 + make-fetch-happen: 14.0.3(supports-color@8.1.1) + proc-log: 5.0.0 + promise-retry: 2.0.1 + transitivePeerDependencies: + - supports-color + + '@sigstore/tuf@3.1.1(supports-color@8.1.1)': + dependencies: + '@sigstore/protobuf-specs': 0.4.3 + tuf-js: 3.1.0(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + + '@sigstore/verify@2.1.1': + dependencies: + '@sigstore/bundle': 3.1.0 + '@sigstore/core': 2.0.0 + '@sigstore/protobuf-specs': 0.4.3 + + '@sindresorhus/merge-streams@2.3.0': {} + + '@socket.io/component-emitter@3.1.2': {} + + '@tufjs/canonical-json@2.0.0': {} + + '@tufjs/models@3.0.1': + dependencies: + '@tufjs/canonical-json': 2.0.0 + minimatch: 9.0.9 + + '@tweenjs/tween.js@23.1.3': {} + + '@types/body-parser@1.19.6': + dependencies: + '@types/connect': 3.4.38 + '@types/node': 26.1.2 + + '@types/bonjour@3.5.13': + dependencies: + '@types/node': 26.1.2 + + '@types/connect-history-api-fallback@1.5.4': + dependencies: + '@types/express-serve-static-core': 4.19.9 + '@types/node': 26.1.2 + + '@types/connect@3.4.38': + dependencies: + '@types/node': 26.1.2 + + '@types/cors@2.8.19': + dependencies: + '@types/node': 26.1.2 + + '@types/eslint-scope@3.7.7': + dependencies: + '@types/eslint': 9.6.1 + '@types/estree': 1.0.9 + + '@types/eslint@9.6.1': + dependencies: + '@types/estree': 1.0.9 + '@types/json-schema': 7.0.15 + + '@types/estree@1.0.8': {} + + '@types/estree@1.0.9': {} + + '@types/express-serve-static-core@4.19.9': + dependencies: + '@types/node': 26.1.2 + '@types/qs': 6.15.1 + '@types/range-parser': 1.2.7 + '@types/send': 1.2.1 + + '@types/express@4.17.25': + dependencies: + '@types/body-parser': 1.19.6 + '@types/express-serve-static-core': 4.19.9 + '@types/qs': 6.15.1 + '@types/serve-static': 1.15.10 + + '@types/fs-extra@8.1.5': + dependencies: + '@types/node': 26.1.2 + + '@types/http-errors@2.0.5': {} + + '@types/http-proxy@1.17.17': + dependencies: + '@types/node': 26.1.2 + + '@types/jasmine@5.1.15': {} + + '@types/json-schema@7.0.15': {} + + '@types/matter-js@0.20.2': {} + + '@types/mime@1.3.5': {} + + '@types/node-forge@1.3.14': + dependencies: + '@types/node': 26.1.2 + + '@types/node@26.1.2': + dependencies: + undici-types: 8.3.0 + + '@types/qs@6.15.1': {} + + '@types/range-parser@1.2.7': {} + + '@types/retry@0.12.2': {} + + '@types/send@0.17.6': + dependencies: + '@types/mime': 1.3.5 + '@types/node': 26.1.2 + + '@types/send@1.2.1': + dependencies: + '@types/node': 26.1.2 + + '@types/serve-index@1.9.4': + dependencies: + '@types/express': 4.17.25 + + '@types/serve-static@1.15.10': + dependencies: + '@types/http-errors': 2.0.5 + '@types/node': 26.1.2 + '@types/send': 0.17.6 + + '@types/slice-ansi@4.0.0': {} + + '@types/sockjs@0.3.36': + dependencies: + '@types/node': 26.1.2 + + '@types/stats.js@0.17.4': {} + + '@types/three@0.185.1': + dependencies: + '@dimforge/rapier3d-compat': 0.12.0 + '@tweenjs/tween.js': 23.1.3 + '@types/stats.js': 0.17.4 + '@types/webxr': 0.5.24 + fflate: 0.8.3 + meshoptimizer: 1.1.1 + + '@types/webxr@0.5.24': {} + + '@types/ws@8.18.1': + dependencies: + '@types/node': 26.1.2 + + '@vitejs/plugin-basic-ssl@1.2.0(vite@6.4.2(@types/node@26.1.2)(jiti@1.21.7)(less@4.2.2)(sass@1.85.0)(terser@5.39.0))': + dependencies: + vite: 6.4.2(@types/node@26.1.2)(jiti@1.21.7)(less@4.2.2)(sass@1.85.0)(terser@5.39.0) + + '@webassemblyjs/ast@1.14.1': + dependencies: + '@webassemblyjs/helper-numbers': 1.13.2 + '@webassemblyjs/helper-wasm-bytecode': 1.13.2 + + '@webassemblyjs/floating-point-hex-parser@1.13.2': {} + + '@webassemblyjs/helper-api-error@1.13.2': {} + + '@webassemblyjs/helper-buffer@1.14.1': {} + + '@webassemblyjs/helper-numbers@1.13.2': + dependencies: + '@webassemblyjs/floating-point-hex-parser': 1.13.2 + '@webassemblyjs/helper-api-error': 1.13.2 + '@xtuc/long': 4.2.2 + + '@webassemblyjs/helper-wasm-bytecode@1.13.2': {} + + '@webassemblyjs/helper-wasm-section@1.14.1': + dependencies: + '@webassemblyjs/ast': 1.14.1 + '@webassemblyjs/helper-buffer': 1.14.1 + '@webassemblyjs/helper-wasm-bytecode': 1.13.2 + '@webassemblyjs/wasm-gen': 1.14.1 + + '@webassemblyjs/ieee754@1.13.2': + dependencies: + '@xtuc/ieee754': 1.2.0 + + '@webassemblyjs/leb128@1.13.2': + dependencies: + '@xtuc/long': 4.2.2 + + '@webassemblyjs/utf8@1.13.2': {} + + '@webassemblyjs/wasm-edit@1.14.1': + dependencies: + '@webassemblyjs/ast': 1.14.1 + '@webassemblyjs/helper-buffer': 1.14.1 + '@webassemblyjs/helper-wasm-bytecode': 1.13.2 + '@webassemblyjs/helper-wasm-section': 1.14.1 + '@webassemblyjs/wasm-gen': 1.14.1 + '@webassemblyjs/wasm-opt': 1.14.1 + '@webassemblyjs/wasm-parser': 1.14.1 + '@webassemblyjs/wast-printer': 1.14.1 + + '@webassemblyjs/wasm-gen@1.14.1': + dependencies: + '@webassemblyjs/ast': 1.14.1 + '@webassemblyjs/helper-wasm-bytecode': 1.13.2 + '@webassemblyjs/ieee754': 1.13.2 + '@webassemblyjs/leb128': 1.13.2 + '@webassemblyjs/utf8': 1.13.2 + + '@webassemblyjs/wasm-opt@1.14.1': + dependencies: + '@webassemblyjs/ast': 1.14.1 + '@webassemblyjs/helper-buffer': 1.14.1 + '@webassemblyjs/wasm-gen': 1.14.1 + '@webassemblyjs/wasm-parser': 1.14.1 + + '@webassemblyjs/wasm-parser@1.14.1': + dependencies: + '@webassemblyjs/ast': 1.14.1 + '@webassemblyjs/helper-api-error': 1.13.2 + '@webassemblyjs/helper-wasm-bytecode': 1.13.2 + '@webassemblyjs/ieee754': 1.13.2 + '@webassemblyjs/leb128': 1.13.2 + '@webassemblyjs/utf8': 1.13.2 + + '@webassemblyjs/wast-printer@1.14.1': + dependencies: + '@webassemblyjs/ast': 1.14.1 + '@xtuc/long': 4.2.2 + + '@xmldom/xmldom@0.9.10': {} + + '@xtuc/ieee754@1.2.0': {} + + '@xtuc/long@4.2.2': {} + + '@yarnpkg/lockfile@1.1.0': {} + + abbrev@3.0.1: {} + + accepts@1.3.8: + dependencies: + mime-types: 2.1.35 + negotiator: 0.6.3 + + acorn-import-phases@1.0.4(acorn@8.18.0): + dependencies: + acorn: 8.18.0 + + acorn@8.18.0: {} + + adjust-sourcemap-loader@4.0.0: + dependencies: + loader-utils: 2.0.4 + regex-parser: 2.3.1 + + agent-base@7.1.4: {} + + ajv-formats@2.1.1(ajv@8.20.0): + optionalDependencies: + ajv: 8.20.0 + + ajv-formats@3.0.1(ajv@8.18.0): + optionalDependencies: + ajv: 8.18.0 + + ajv-keywords@5.1.0(ajv@8.20.0): + dependencies: + ajv: 8.20.0 + fast-deep-equal: 3.1.3 + + ajv@8.18.0: + dependencies: + fast-deep-equal: 3.1.3 + fast-uri: 3.1.4 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + + ajv@8.20.0: + dependencies: + fast-deep-equal: 3.1.3 + fast-uri: 3.1.4 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + + ansi-colors@4.1.3: {} + + ansi-escapes@7.3.0: + dependencies: + environment: 1.1.0 + + ansi-html-community@0.0.8: {} + + ansi-regex@5.0.1: {} + + ansi-regex@6.2.2: {} + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + ansi-styles@6.2.3: {} + + anymatch@3.1.3: + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.2 + + argparse@2.0.1: {} + + array-flatten@1.1.1: {} + + astral-regex@2.0.0: {} + + at-least-node@1.0.0: {} + + autoprefixer@10.4.20(postcss@8.5.12): + dependencies: + browserslist: 4.28.7 + caniuse-lite: 1.0.30001806 + fraction.js: 4.3.7 + normalize-range: 0.1.2 + picocolors: 1.1.1 + postcss: 8.5.12 + postcss-value-parser: 4.2.0 + + babel-loader@9.2.1(@babel/core@7.26.10(supports-color@8.1.1))(webpack@5.105.0(esbuild@0.28.0)(postcss@8.5.12)): + dependencies: + '@babel/core': 7.26.10(supports-color@8.1.1) + find-cache-dir: 4.0.0 + schema-utils: 4.3.3 + webpack: 5.105.0(esbuild@0.28.0)(postcss@8.5.12) + + babel-plugin-polyfill-corejs2@0.4.17(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1): + dependencies: + '@babel/compat-data': 7.29.7 + '@babel/core': 7.26.10(supports-color@8.1.1) + '@babel/helper-define-polyfill-provider': 0.6.8(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1) + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + babel-plugin-polyfill-corejs3@0.11.1(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1): + dependencies: + '@babel/core': 7.26.10(supports-color@8.1.1) + '@babel/helper-define-polyfill-provider': 0.6.8(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1) + core-js-compat: 3.49.0 + transitivePeerDependencies: + - supports-color + + babel-plugin-polyfill-regenerator@0.6.8(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1): + dependencies: + '@babel/core': 7.26.10(supports-color@8.1.1) + '@babel/helper-define-polyfill-provider': 0.6.8(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + + balanced-match@1.0.2: {} + + balanced-match@4.0.4: {} + + base64-js@1.5.1: {} + + base64id@2.0.0: {} + + baseline-browser-mapping@2.11.5: {} + + batch@0.6.1: {} + + beasties@0.3.2: + dependencies: + css-select: 5.2.2 + css-what: 6.2.2 + dom-serializer: 2.0.0 + domhandler: 5.0.3 + htmlparser2: 10.1.0 + picocolors: 1.1.1 + postcss: 8.5.12 + postcss-media-query-parser: 0.2.3 + + big-integer@1.6.52: {} + + big.js@5.2.2: {} + + binary-extensions@2.3.0: {} + + bl@4.1.0: + dependencies: + buffer: 5.7.1 + inherits: 2.0.4 + readable-stream: 3.6.2 + + body-parser@1.20.6(supports-color@8.1.1): + dependencies: + bytes: 3.1.2 + content-type: 1.0.5 + debug: 2.6.9(supports-color@8.1.1) + depd: 2.0.0 + destroy: 1.2.0 + http-errors: 2.0.1 + iconv-lite: 0.4.24 + on-finished: 2.4.1 + qs: 6.15.3 + raw-body: 2.5.3 + type-is: 1.6.18 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + + bonjour-service@1.4.3: + dependencies: + fast-deep-equal: 3.1.3 + multicast-dns: 7.2.5 + + boolbase@1.0.0: {} + + bplist-creator@0.1.0: + dependencies: + stream-buffers: 2.2.0 + + bplist-parser@0.3.1: + dependencies: + big-integer: 1.6.52 + + bplist-parser@0.3.2: + dependencies: + big-integer: 1.6.52 + + brace-expansion@1.1.16: + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + + brace-expansion@2.1.2: + dependencies: + balanced-match: 1.0.2 + + brace-expansion@5.0.8: + dependencies: + balanced-match: 4.0.4 + + braces@3.0.3: + dependencies: + fill-range: 7.1.1 + + browserslist@4.28.7: + dependencies: + baseline-browser-mapping: 2.11.5 + caniuse-lite: 1.0.30001806 + electron-to-chromium: 1.5.397 + node-releases: 2.0.51 + update-browserslist-db: 1.2.3(browserslist@4.28.7) + + buffer-crc32@0.2.13: {} + + buffer-from@1.1.2: {} + + buffer@5.7.1: + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + + bundle-name@4.1.0: + dependencies: + run-applescript: 7.1.0 + + bytes@3.1.2: {} + + cacache@19.0.1: + dependencies: + '@npmcli/fs': 4.0.0 + fs-minipass: 3.0.3 + glob: 10.5.0 + lru-cache: 10.4.3 + minipass: 7.1.3 + minipass-collect: 2.0.1 + minipass-flush: 1.0.7 + minipass-pipeline: 1.2.4 + p-map: 7.0.6 + ssri: 12.0.0 + tar: 7.5.22 + unique-filename: 4.0.0 + + call-bind-apply-helpers@1.0.2: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + + call-bound@1.0.4: + dependencies: + call-bind-apply-helpers: 1.0.2 + get-intrinsic: 1.3.0 + + callsites@3.1.0: {} + + caniuse-lite@1.0.30001806: {} + + chalk@4.1.2: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + chardet@2.2.0: {} + + chokidar@3.6.0: + dependencies: + anymatch: 3.1.3 + braces: 3.0.3 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.6.0 + optionalDependencies: + fsevents: 2.3.3 + + chokidar@4.0.3: + dependencies: + readdirp: 4.1.2 + + chownr@2.0.0: {} + + chownr@3.0.0: {} + + chrome-trace-event@1.0.4: {} + + cli-cursor@3.1.0: + dependencies: + restore-cursor: 3.1.0 + + cli-cursor@5.0.0: + dependencies: + restore-cursor: 5.1.0 + + cli-spinners@2.9.2: {} + + cli-truncate@4.0.0: + dependencies: + slice-ansi: 5.0.0 + string-width: 7.2.0 + + cli-width@4.1.0: {} + + cliui@7.0.4: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + + cliui@8.0.1: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + + clone-deep@4.0.1: + dependencies: + is-plain-object: 2.0.4 + kind-of: 6.0.3 + shallow-clone: 3.0.1 + + clone@1.0.4: {} + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.4: {} + + colorette@2.0.20: {} + + commander@12.1.0: {} + + commander@2.20.3: {} + + common-path-prefix@3.0.0: {} + + compressible@2.0.18: + dependencies: + mime-db: 1.54.0 + + compression@1.8.1(supports-color@8.1.1): + dependencies: + bytes: 3.1.2 + compressible: 2.0.18 + debug: 2.6.9(supports-color@8.1.1) + negotiator: 0.6.4 + on-headers: 1.1.0 + safe-buffer: 5.2.1 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + + concat-map@0.0.1: {} + + connect-history-api-fallback@2.0.0: {} + + connect@3.7.0(supports-color@8.1.1): + dependencies: + debug: 2.6.9(supports-color@8.1.1) + finalhandler: 1.1.2(supports-color@8.1.1) + parseurl: 1.3.3 + utils-merge: 1.0.1 + transitivePeerDependencies: + - supports-color + + content-disposition@0.5.4: + dependencies: + safe-buffer: 5.2.1 + + content-type@1.0.5: {} + + convert-source-map@1.9.0: {} + + convert-source-map@2.0.0: {} + + cookie-signature@1.0.7: {} + + cookie@0.7.2: {} + + copy-anything@2.0.6: + dependencies: + is-what: 3.14.1 + + copy-webpack-plugin@12.0.2(webpack@5.105.0(esbuild@0.28.0)(postcss@8.5.12)): + dependencies: + fast-glob: 3.3.3 + glob-parent: 6.0.2 + globby: 14.1.0 + normalize-path: 3.0.0 + schema-utils: 4.3.3 + serialize-javascript: 6.0.2 + webpack: 5.105.0(esbuild@0.28.0)(postcss@8.5.12) + + core-js-compat@3.49.0: + dependencies: + browserslist: 4.28.7 + + core-util-is@1.0.3: {} + + cors@2.8.6: + dependencies: + object-assign: 4.1.1 + vary: 1.1.2 + + cosmiconfig@9.0.2(typescript@5.5.4): + dependencies: + env-paths: 2.2.1 + import-fresh: 3.3.1 + js-yaml: 4.3.0 + parse-json: 5.2.0 + optionalDependencies: + typescript: 5.5.4 + + cross-spawn@7.0.6: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + css-loader@7.1.2(webpack@5.105.0(esbuild@0.28.0)(postcss@8.5.12)): + dependencies: + icss-utils: 5.1.0(postcss@8.5.12) + postcss: 8.5.12 + postcss-modules-extract-imports: 3.1.0(postcss@8.5.12) + postcss-modules-local-by-default: 4.2.0(postcss@8.5.12) + postcss-modules-scope: 3.2.1(postcss@8.5.12) + postcss-modules-values: 4.0.0(postcss@8.5.12) + postcss-value-parser: 4.2.0 + semver: 7.7.1 + optionalDependencies: + webpack: 5.105.0(esbuild@0.28.0)(postcss@8.5.12) + + css-select@5.2.2: + dependencies: + boolbase: 1.0.0 + css-what: 6.2.2 + domhandler: 5.0.3 + domutils: 3.2.2 + nth-check: 2.1.1 + + css-what@6.2.2: {} + + cssesc@3.0.0: {} + + custom-event@1.0.1: {} + + date-format@4.0.14: {} + + debug@2.6.9(supports-color@8.1.1): + dependencies: + ms: 2.0.0 + optionalDependencies: + supports-color: 8.1.1 + + debug@4.4.3(supports-color@8.1.1): + dependencies: + ms: 2.1.3 + optionalDependencies: + supports-color: 8.1.1 + + default-browser-id@5.0.1: {} + + default-browser@5.5.0: + dependencies: + bundle-name: 4.1.0 + default-browser-id: 5.0.1 + + defaults@1.0.4: + dependencies: + clone: 1.0.4 + + define-lazy-prop@2.0.0: {} + + define-lazy-prop@3.0.0: {} + + depd@1.1.2: {} + + depd@2.0.0: {} + + destroy@1.2.0: {} + + detect-libc@2.1.2: + optional: true + + detect-node@2.1.0: {} + + di@0.0.1: {} + + dns-packet@5.6.1: + dependencies: + '@leichtgewicht/ip-codec': 2.0.5 + + dom-serialize@2.2.1: + dependencies: + custom-event: 1.0.1 + ent: 2.2.2 + extend: 3.0.2 + void-elements: 2.0.1 + + dom-serializer@2.0.0: + dependencies: + domelementtype: 2.3.0 + domhandler: 5.0.3 + entities: 4.5.0 + + domelementtype@2.3.0: {} + + domhandler@5.0.3: + dependencies: + domelementtype: 2.3.0 + + domutils@3.2.2: + dependencies: + dom-serializer: 2.0.0 + domelementtype: 2.3.0 + domhandler: 5.0.3 + + dunder-proto@1.0.1: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-errors: 1.3.0 + gopd: 1.2.0 + + eastasianwidth@0.2.0: {} + + ee-first@1.1.1: {} + + electron-is-dev@2.0.0: {} + + electron-to-chromium@1.5.397: {} + + elementtree@0.1.7: + dependencies: + sax: 1.1.4 + + emoji-regex@10.6.0: {} + + emoji-regex@8.0.0: {} + + emoji-regex@9.2.2: {} + + emojis-list@3.0.0: {} + + encodeurl@1.0.2: {} + + encodeurl@2.0.0: {} + + encoding@0.1.13: + dependencies: + iconv-lite: 0.6.3 + optional: true + + engine.io-parser@5.2.3: {} + + engine.io@6.6.9(supports-color@8.1.1): + dependencies: + '@types/cors': 2.8.19 + '@types/node': 26.1.2 + '@types/ws': 8.18.1 + accepts: 1.3.8 + base64id: 2.0.0 + cookie: 0.7.2 + cors: 2.8.6 + debug: 4.4.3(supports-color@8.1.1) + engine.io-parser: 5.2.3 + ws: 8.21.1 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + enhanced-resolve@5.24.3: + dependencies: + graceful-fs: 4.2.11 + tapable: 2.3.3 + + ent@2.2.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + punycode: 1.4.1 + safe-regex-test: 1.1.0 + + entities@4.5.0: {} + + entities@6.0.1: {} + + entities@7.0.1: {} + + env-paths@2.2.1: {} + + environment@1.1.0: {} + + err-code@2.0.3: {} + + errno@0.1.8: + dependencies: + prr: 1.0.1 + optional: true + + error-ex@1.3.4: + dependencies: + is-arrayish: 0.2.1 + + es-define-property@1.0.1: {} + + es-errors@1.3.0: {} + + es-module-lexer@2.3.1: {} + + es-object-atoms@1.1.2: + dependencies: + es-errors: 1.3.0 + + esbuild-wasm@0.28.0: {} + + esbuild@0.25.12: + optionalDependencies: + '@esbuild/aix-ppc64': 0.25.12 + '@esbuild/android-arm': 0.25.12 + '@esbuild/android-arm64': 0.25.12 + '@esbuild/android-x64': 0.25.12 + '@esbuild/darwin-arm64': 0.25.12 + '@esbuild/darwin-x64': 0.25.12 + '@esbuild/freebsd-arm64': 0.25.12 + '@esbuild/freebsd-x64': 0.25.12 + '@esbuild/linux-arm': 0.25.12 + '@esbuild/linux-arm64': 0.25.12 + '@esbuild/linux-ia32': 0.25.12 + '@esbuild/linux-loong64': 0.25.12 + '@esbuild/linux-mips64el': 0.25.12 + '@esbuild/linux-ppc64': 0.25.12 + '@esbuild/linux-riscv64': 0.25.12 + '@esbuild/linux-s390x': 0.25.12 + '@esbuild/linux-x64': 0.25.12 + '@esbuild/netbsd-arm64': 0.25.12 + '@esbuild/netbsd-x64': 0.25.12 + '@esbuild/openbsd-arm64': 0.25.12 + '@esbuild/openbsd-x64': 0.25.12 + '@esbuild/openharmony-arm64': 0.25.12 + '@esbuild/sunos-x64': 0.25.12 + '@esbuild/win32-arm64': 0.25.12 + '@esbuild/win32-ia32': 0.25.12 + '@esbuild/win32-x64': 0.25.12 + + esbuild@0.28.0: + optionalDependencies: + '@esbuild/aix-ppc64': 0.28.0 + '@esbuild/android-arm': 0.28.0 + '@esbuild/android-arm64': 0.28.0 + '@esbuild/android-x64': 0.28.0 + '@esbuild/darwin-arm64': 0.28.0 + '@esbuild/darwin-x64': 0.28.0 + '@esbuild/freebsd-arm64': 0.28.0 + '@esbuild/freebsd-x64': 0.28.0 + '@esbuild/linux-arm': 0.28.0 + '@esbuild/linux-arm64': 0.28.0 + '@esbuild/linux-ia32': 0.28.0 + '@esbuild/linux-loong64': 0.28.0 + '@esbuild/linux-mips64el': 0.28.0 + '@esbuild/linux-ppc64': 0.28.0 + '@esbuild/linux-riscv64': 0.28.0 + '@esbuild/linux-s390x': 0.28.0 + '@esbuild/linux-x64': 0.28.0 + '@esbuild/netbsd-arm64': 0.28.0 + '@esbuild/netbsd-x64': 0.28.0 + '@esbuild/openbsd-arm64': 0.28.0 + '@esbuild/openbsd-x64': 0.28.0 + '@esbuild/openharmony-arm64': 0.28.0 + '@esbuild/sunos-x64': 0.28.0 + '@esbuild/win32-arm64': 0.28.0 + '@esbuild/win32-ia32': 0.28.0 + '@esbuild/win32-x64': 0.28.0 + + escalade@3.2.0: {} + + escape-html@1.0.3: {} + + eslint-scope@5.1.1: + dependencies: + esrecurse: 4.3.0 + estraverse: 4.3.0 + + esrecurse@4.3.0: + dependencies: + estraverse: 5.3.0 + + estraverse@4.3.0: {} + + estraverse@5.3.0: {} + + esutils@2.0.3: {} + + etag@1.8.1: {} + + eventemitter3@4.0.7: {} + + eventemitter3@5.0.4: {} + + events@3.3.0: {} + + exponential-backoff@3.1.3: {} + + express@4.22.2(supports-color@8.1.1): + dependencies: + accepts: 1.3.8 + array-flatten: 1.1.1 + body-parser: 1.20.6(supports-color@8.1.1) + content-disposition: 0.5.4 + content-type: 1.0.5 + cookie: 0.7.2 + cookie-signature: 1.0.7 + debug: 2.6.9(supports-color@8.1.1) + depd: 2.0.0 + encodeurl: 2.0.0 + escape-html: 1.0.3 + etag: 1.8.1 + finalhandler: 1.3.2(supports-color@8.1.1) + fresh: 0.5.2 + http-errors: 2.0.1 + merge-descriptors: 1.0.3 + methods: 1.1.2 + on-finished: 2.4.1 + parseurl: 1.3.3 + path-to-regexp: 0.1.13 + proxy-addr: 2.0.7 + qs: 6.15.3 + range-parser: 1.2.1 + safe-buffer: 5.2.1 + send: 0.19.2(supports-color@8.1.1) + serve-static: 1.16.3(supports-color@8.1.1) + setprototypeof: 1.2.0 + statuses: 2.0.2 + type-is: 1.6.18 + utils-merge: 1.0.1 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + + extend@3.0.2: {} + + fast-deep-equal@3.1.3: {} + + fast-glob@3.3.3: + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.8 + + fast-uri@3.1.4: {} + + fastq@1.20.1: + dependencies: + reusify: 1.1.0 + + faye-websocket@0.11.4: + dependencies: + websocket-driver: 0.7.5 + + fd-slicer@1.1.0: + dependencies: + pend: 1.2.0 + + fdir@6.5.0(picomatch@4.0.5): + optionalDependencies: + picomatch: 4.0.5 + + fflate@0.8.3: {} + + fill-range@7.1.1: + dependencies: + to-regex-range: 5.0.1 + + finalhandler@1.1.2(supports-color@8.1.1): + dependencies: + debug: 2.6.9(supports-color@8.1.1) + encodeurl: 1.0.2 + escape-html: 1.0.3 + on-finished: 2.3.0 + parseurl: 1.3.3 + statuses: 1.5.0 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + + finalhandler@1.3.2(supports-color@8.1.1): + dependencies: + debug: 2.6.9(supports-color@8.1.1) + encodeurl: 2.0.0 + escape-html: 1.0.3 + on-finished: 2.4.1 + parseurl: 1.3.3 + statuses: 2.0.2 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + + find-cache-dir@4.0.0: + dependencies: + common-path-prefix: 3.0.0 + pkg-dir: 7.0.0 + + find-up@6.3.0: + dependencies: + locate-path: 7.2.0 + path-exists: 5.0.0 + + flat@5.0.2: {} + + flatted@3.4.3: {} + + follow-redirects@1.16.0(debug@4.4.3(supports-color@8.1.1)): + optionalDependencies: + debug: 4.4.3(supports-color@8.1.1) + + foreground-child@3.3.1: + dependencies: + cross-spawn: 7.0.6 + signal-exit: 4.1.0 + + forwarded@0.2.0: {} + + fraction.js@4.3.7: {} + + fresh@0.5.2: {} + + fs-extra@11.1.1: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.2.1 + universalify: 2.0.1 + + fs-extra@11.4.0: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.2.1 + universalify: 2.0.1 + + fs-extra@8.1.0: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 4.0.0 + universalify: 0.1.2 + + fs-extra@9.1.0: + dependencies: + at-least-node: 1.0.0 + graceful-fs: 4.2.11 + jsonfile: 6.2.1 + universalify: 2.0.1 + + fs-minipass@2.1.0: + dependencies: + minipass: 3.3.6 + + fs-minipass@3.0.3: + dependencies: + minipass: 7.1.3 + + fs.realpath@1.0.0: {} + + fsevents@2.3.3: + optional: true + + function-bind@1.1.2: {} + + gensync@1.0.0-beta.2: {} + + get-caller-file@2.0.5: {} + + get-east-asian-width@1.6.0: {} + + get-intrinsic@1.3.0: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.2 + function-bind: 1.1.2 + get-proto: 1.0.1 + gopd: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.4 + math-intrinsics: 1.1.0 + + get-proto@1.0.1: + dependencies: + dunder-proto: 1.0.1 + es-object-atoms: 1.1.2 + + glob-parent@5.1.2: + dependencies: + is-glob: 4.0.3 + + glob-parent@6.0.2: + dependencies: + is-glob: 4.0.3 + + glob-to-regex.js@1.2.0(tslib@2.8.1): + dependencies: + tslib: 2.8.1 + + glob-to-regexp@0.4.1: {} + + glob@10.5.0: + dependencies: + foreground-child: 3.3.1 + jackspeak: 3.4.3 + minimatch: 9.0.9 + minipass: 7.1.3 + package-json-from-dist: 1.0.1 + path-scurry: 1.11.1 + + glob@13.0.6: + dependencies: + minimatch: 10.2.6 + minipass: 7.1.3 + path-scurry: 2.0.2 + + glob@7.2.3: + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.5 + once: 1.4.0 + path-is-absolute: 1.0.1 + + globby@14.1.0: + dependencies: + '@sindresorhus/merge-streams': 2.3.0 + fast-glob: 3.3.3 + ignore: 7.0.6 + path-type: 6.0.0 + slash: 5.1.0 + unicorn-magic: 0.3.0 + + gopd@1.2.0: {} + + graceful-fs@4.2.11: {} + + handle-thing@2.0.1: {} + + has-flag@4.0.0: {} + + has-symbols@1.1.0: {} + + has-tostringtag@1.0.2: + dependencies: + has-symbols: 1.1.0 + + hasown@2.0.4: + dependencies: + function-bind: 1.1.2 + + hosted-git-info@8.1.0: + dependencies: + lru-cache: 10.4.3 + + hpack.js@2.1.6: + dependencies: + inherits: 2.0.4 + obuf: 1.1.2 + readable-stream: 2.3.8 + wbuf: 1.7.3 + + html-escaper@2.0.2: {} + + htmlparser2@10.1.0: + dependencies: + domelementtype: 2.3.0 + domhandler: 5.0.3 + domutils: 3.2.2 + entities: 7.0.1 + + http-cache-semantics@4.2.0: {} + + http-deceiver@1.2.7: {} + + http-errors@1.8.1: + dependencies: + depd: 1.1.2 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: 1.5.0 + toidentifier: 1.0.1 + + http-errors@2.0.1: + dependencies: + depd: 2.0.0 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: 2.0.2 + toidentifier: 1.0.1 + + http-parser-js@0.5.10: {} + + http-proxy-agent@7.0.2(supports-color@8.1.1): + dependencies: + agent-base: 7.1.4 + debug: 4.4.3(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + + http-proxy-middleware@2.0.10(@types/express@4.17.25)(debug@4.4.3(supports-color@8.1.1)): + dependencies: + '@types/http-proxy': 1.17.17 + http-proxy: 1.18.1(debug@4.4.3(supports-color@8.1.1)) + is-glob: 4.0.3 + is-plain-obj: 3.0.0 + micromatch: 4.0.8 + optionalDependencies: + '@types/express': 4.17.25 + transitivePeerDependencies: + - debug + + http-proxy-middleware@3.0.5(supports-color@8.1.1): + dependencies: + '@types/http-proxy': 1.17.17 + debug: 4.4.3(supports-color@8.1.1) + http-proxy: 1.18.1(debug@4.4.3(supports-color@8.1.1)) + is-glob: 4.0.3 + is-plain-object: 5.0.0 + micromatch: 4.0.8 + transitivePeerDependencies: + - supports-color + + http-proxy@1.18.1(debug@4.4.3(supports-color@8.1.1)): + dependencies: + eventemitter3: 4.0.7 + follow-redirects: 1.16.0(debug@4.4.3(supports-color@8.1.1)) + requires-port: 1.0.0 + transitivePeerDependencies: + - debug + + https-proxy-agent@7.0.6(supports-color@8.1.1): + dependencies: + agent-base: 7.1.4 + debug: 4.4.3(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + + hyperdyperid@1.2.0: {} + + iconv-lite@0.4.24: + dependencies: + safer-buffer: 2.1.2 + + iconv-lite@0.6.3: + dependencies: + safer-buffer: 2.1.2 + + iconv-lite@0.7.3: + dependencies: + safer-buffer: 2.1.2 + + icss-utils@5.1.0(postcss@8.5.12): + dependencies: + postcss: 8.5.12 + + ieee754@1.2.1: {} + + ignore-walk@7.0.0: + dependencies: + minimatch: 9.0.9 + + ignore@7.0.6: {} + + image-size@0.5.5: + optional: true + + immutable@5.1.9: {} + + import-fresh@3.3.1: + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + + imurmurhash@0.1.4: {} + + inflight@1.0.6: + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + + inherits@2.0.4: {} + + ini@4.1.3: {} + + ini@5.0.0: {} + + ip-address@10.3.1: {} + + ipaddr.js@1.9.1: {} + + ipaddr.js@2.4.0: {} + + is-arrayish@0.2.1: {} + + is-binary-path@2.1.0: + dependencies: + binary-extensions: 2.3.0 + + is-core-module@2.16.2: + dependencies: + hasown: 2.0.4 + + is-docker@2.2.1: {} + + is-docker@3.0.0: {} + + is-extglob@2.1.1: {} + + is-fullwidth-code-point@3.0.0: {} + + is-fullwidth-code-point@4.0.0: {} + + is-fullwidth-code-point@5.1.0: + dependencies: + get-east-asian-width: 1.6.0 + + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + + is-inside-container@1.0.0: + dependencies: + is-docker: 3.0.0 + + is-interactive@1.0.0: {} + + is-network-error@1.3.2: {} + + is-number@7.0.0: {} + + is-plain-obj@3.0.0: {} + + is-plain-object@2.0.4: + dependencies: + isobject: 3.0.1 + + is-plain-object@5.0.0: {} + + is-regex@1.2.1: + dependencies: + call-bound: 1.0.4 + gopd: 1.2.0 + has-tostringtag: 1.0.2 + hasown: 2.0.4 + + is-unicode-supported@0.1.0: {} + + is-what@3.14.1: {} + + is-wsl@2.2.0: + dependencies: + is-docker: 2.2.1 + + is-wsl@3.1.1: + dependencies: + is-inside-container: 1.0.0 + + isarray@1.0.0: {} + + isbinaryfile@4.0.10: {} + + isexe@2.0.0: {} + + isexe@3.1.5: {} + + isobject@3.0.1: {} + + istanbul-lib-coverage@3.2.2: {} + + istanbul-lib-instrument@5.2.1(supports-color@8.1.1): + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/parser': 7.29.7 + '@istanbuljs/schema': 0.1.6 + istanbul-lib-coverage: 3.2.2 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + istanbul-lib-instrument@6.0.3(supports-color@8.1.1): + dependencies: + '@babel/core': 7.26.10(supports-color@8.1.1) + '@babel/parser': 7.29.7 + '@istanbuljs/schema': 0.1.6 + istanbul-lib-coverage: 3.2.2 + semver: 7.7.1 + transitivePeerDependencies: + - supports-color + + istanbul-lib-report@3.0.1: + dependencies: + istanbul-lib-coverage: 3.2.2 + make-dir: 4.0.0 + supports-color: 7.2.0 + + istanbul-lib-source-maps@4.0.1(supports-color@8.1.1): + dependencies: + debug: 4.4.3(supports-color@8.1.1) + istanbul-lib-coverage: 3.2.2 + source-map: 0.6.1 + transitivePeerDependencies: + - supports-color + + istanbul-reports@3.2.0: + dependencies: + html-escaper: 2.0.2 + istanbul-lib-report: 3.0.1 + + jackspeak@3.4.3: + dependencies: + '@isaacs/cliui': 8.0.2 + optionalDependencies: + '@pkgjs/parseargs': 0.11.0 + + jasmine-core@4.6.1: {} + + jasmine-core@5.1.2: {} + + jest-worker@27.5.1: + dependencies: + '@types/node': 26.1.2 + merge-stream: 2.0.0 + supports-color: 8.1.1 + + jiti@1.21.7: {} + + js-tokens@4.0.0: {} + + js-yaml@4.3.0: + dependencies: + argparse: 2.0.1 + + jsesc@3.1.0: {} + + json-buffer@3.0.1: {} + + json-parse-even-better-errors@2.3.1: {} + + json-parse-even-better-errors@4.0.0: {} + + json-schema-traverse@1.0.0: {} + + json5@2.2.3: {} + + jsonc-parser@3.3.1: {} + + jsonfile@4.0.0: + optionalDependencies: + graceful-fs: 4.2.11 + + jsonfile@6.2.1: + dependencies: + universalify: 2.0.1 + optionalDependencies: + graceful-fs: 4.2.11 + + jsonparse@1.3.1: {} + + karma-chrome-launcher@3.2.0: + dependencies: + which: 1.3.1 + + karma-coverage@2.2.1(supports-color@8.1.1): + dependencies: + istanbul-lib-coverage: 3.2.2 + istanbul-lib-instrument: 5.2.1(supports-color@8.1.1) + istanbul-lib-report: 3.0.1 + istanbul-lib-source-maps: 4.0.1(supports-color@8.1.1) + istanbul-reports: 3.2.0 + minimatch: 3.1.5 + transitivePeerDependencies: + - supports-color + + karma-jasmine-html-reporter@2.1.0(jasmine-core@5.1.2)(karma-jasmine@5.1.0(karma@6.4.4(debug@4.4.3(supports-color@8.1.1))(supports-color@8.1.1)))(karma@6.4.4(debug@4.4.3(supports-color@8.1.1))(supports-color@8.1.1)): + dependencies: + jasmine-core: 5.1.2 + karma: 6.4.4(debug@4.4.3(supports-color@8.1.1))(supports-color@8.1.1) + karma-jasmine: 5.1.0(karma@6.4.4(debug@4.4.3(supports-color@8.1.1))(supports-color@8.1.1)) + + karma-jasmine@5.1.0(karma@6.4.4(debug@4.4.3(supports-color@8.1.1))(supports-color@8.1.1)): + dependencies: + jasmine-core: 4.6.1 + karma: 6.4.4(debug@4.4.3(supports-color@8.1.1))(supports-color@8.1.1) + + karma-source-map-support@1.4.0: + dependencies: + source-map-support: 0.5.21 + + karma@6.4.4(debug@4.4.3(supports-color@8.1.1))(supports-color@8.1.1): + dependencies: + '@colors/colors': 1.5.0 + body-parser: 1.20.6(supports-color@8.1.1) + braces: 3.0.3 + chokidar: 3.6.0 + connect: 3.7.0(supports-color@8.1.1) + di: 0.0.1 + dom-serialize: 2.2.1 + glob: 7.2.3 + graceful-fs: 4.2.11 + http-proxy: 1.18.1(debug@4.4.3(supports-color@8.1.1)) + isbinaryfile: 4.0.10 + lodash: 4.18.1 + log4js: 6.9.1(supports-color@8.1.1) + mime: 2.6.0 + minimatch: 3.1.5 + mkdirp: 0.5.6 + qjobs: 1.2.0 + range-parser: 1.3.0 + rimraf: 3.0.2 + socket.io: 4.8.3(supports-color@8.1.1) + source-map: 0.6.1 + tmp: 0.2.7 + ua-parser-js: 0.7.41 + yargs: 16.2.2 + transitivePeerDependencies: + - bufferutil + - debug + - supports-color + - utf-8-validate + + keyv@4.5.4: + dependencies: + json-buffer: 3.0.1 + + kind-of@6.0.3: {} + + kleur@3.0.3: {} + + kleur@4.1.5: {} + + launch-editor@2.14.1: + dependencies: + picocolors: 1.1.1 + shell-quote: 1.10.0 + + less-loader@12.2.0(less@4.2.2)(webpack@5.105.0(esbuild@0.28.0)(postcss@8.5.12)): + dependencies: + less: 4.2.2 + optionalDependencies: + webpack: 5.105.0(esbuild@0.28.0)(postcss@8.5.12) + + less@4.2.2: + dependencies: + copy-anything: 2.0.6 + parse-node-version: 1.0.1 + tslib: 2.8.1 + optionalDependencies: + errno: 0.1.8 + graceful-fs: 4.2.11 + image-size: 0.5.5 + make-dir: 2.1.0 + mime: 1.6.0 + needle: 3.5.0 + source-map: 0.6.1 + + license-webpack-plugin@4.0.2(webpack@5.105.0(esbuild@0.28.0)(postcss@8.5.12)): + dependencies: + webpack-sources: 3.5.1 + optionalDependencies: + webpack: 5.105.0(esbuild@0.28.0)(postcss@8.5.12) + + lines-and-columns@1.2.4: {} + + listr2@8.2.5: + dependencies: + cli-truncate: 4.0.0 + colorette: 2.0.20 + eventemitter3: 5.0.4 + log-update: 6.1.0 + rfdc: 1.4.1 + wrap-ansi: 9.0.2 + + lmdb@3.2.6: + dependencies: + msgpackr: 1.12.1 + node-addon-api: 6.1.0 + node-gyp-build-optional-packages: 5.2.2 + ordered-binary: 1.6.1 + weak-lru-cache: 1.2.2 + optionalDependencies: + '@lmdb/lmdb-darwin-arm64': 3.2.6 + '@lmdb/lmdb-darwin-x64': 3.2.6 + '@lmdb/lmdb-linux-arm': 3.2.6 + '@lmdb/lmdb-linux-arm64': 3.2.6 + '@lmdb/lmdb-linux-x64': 3.2.6 + '@lmdb/lmdb-win32-x64': 3.2.6 + optional: true + + loader-runner@4.3.2: {} + + loader-utils@2.0.4: + dependencies: + big.js: 5.2.2 + emojis-list: 3.0.0 + json5: 2.2.3 + + loader-utils@3.3.1: {} + + locate-path@7.2.0: + dependencies: + p-locate: 6.0.0 + + lodash.debounce@4.0.8: {} + + lodash@4.18.1: {} + + log-symbols@4.1.0: + dependencies: + chalk: 4.1.2 + is-unicode-supported: 0.1.0 + + log-update@6.1.0: + dependencies: + ansi-escapes: 7.3.0 + cli-cursor: 5.0.0 + slice-ansi: 7.1.2 + strip-ansi: 7.2.0 + wrap-ansi: 9.0.2 + + log4js@6.9.1(supports-color@8.1.1): + dependencies: + date-format: 4.0.14 + debug: 4.4.3(supports-color@8.1.1) + flatted: 3.4.3 + rfdc: 1.4.1 + streamroller: 3.1.5(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + + lru-cache@10.4.3: {} + + lru-cache@11.5.2: {} + + lru-cache@5.1.1: + dependencies: + yallist: 3.1.1 + + magic-string@0.30.17: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + + make-dir@2.1.0: + dependencies: + pify: 4.0.1 + semver: 5.7.2 + optional: true + + make-dir@4.0.0: + dependencies: + semver: 7.8.5 + + make-fetch-happen@14.0.3(supports-color@8.1.1): + dependencies: + '@npmcli/agent': 3.0.0(supports-color@8.1.1) + cacache: 19.0.1 + http-cache-semantics: 4.2.0 + minipass: 7.1.3 + minipass-fetch: 4.0.1 + minipass-flush: 1.0.7 + minipass-pipeline: 1.2.4 + negotiator: 1.0.0 + proc-log: 5.0.0 + promise-retry: 2.0.1 + ssri: 12.0.0 + transitivePeerDependencies: + - supports-color + + math-intrinsics@1.1.0: {} + + matter-js@0.20.0: {} + + media-typer@0.3.0: {} + + memfs@4.64.0(tslib@2.8.1): + dependencies: + '@jsonjoy.com/fs-core': 4.64.0(tslib@2.8.1) + '@jsonjoy.com/fs-fsa': 4.64.0(tslib@2.8.1) + '@jsonjoy.com/fs-node': 4.64.0(tslib@2.8.1) + '@jsonjoy.com/fs-node-builtins': 4.64.0(tslib@2.8.1) + '@jsonjoy.com/fs-node-to-fsa': 4.64.0(tslib@2.8.1) + '@jsonjoy.com/fs-node-utils': 4.64.0(tslib@2.8.1) + '@jsonjoy.com/fs-print': 4.64.0(tslib@2.8.1) + '@jsonjoy.com/fs-snapshot': 4.64.0(tslib@2.8.1) + '@jsonjoy.com/json-pack': 1.21.0(tslib@2.8.1) + '@jsonjoy.com/util': 1.9.0(tslib@2.8.1) + glob-to-regex.js: 1.2.0(tslib@2.8.1) + thingies: 2.6.1(tslib@2.8.1) + tree-dump: 1.1.0(tslib@2.8.1) + tslib: 2.8.1 + + merge-descriptors@1.0.3: {} + + merge-stream@2.0.0: {} + + merge2@1.4.1: {} + + meshoptimizer@1.1.1: {} + + methods@1.1.2: {} + + micromatch@4.0.8: + dependencies: + braces: 3.0.3 + picomatch: 2.3.2 + + mime-db@1.52.0: {} + + mime-db@1.54.0: {} + + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 + + mime@1.6.0: {} + + mime@2.6.0: {} + + mimic-fn@2.1.0: {} + + mimic-function@5.0.1: {} + + mini-css-extract-plugin@2.9.2(webpack@5.105.0(esbuild@0.28.0)(postcss@8.5.12)): + dependencies: + schema-utils: 4.3.3 + tapable: 2.3.3 + webpack: 5.105.0(esbuild@0.28.0)(postcss@8.5.12) + + minimalistic-assert@1.0.1: {} + + minimatch@10.2.6: + dependencies: + brace-expansion: 5.0.8 + + minimatch@3.1.5: + dependencies: + brace-expansion: 1.1.16 + + minimatch@9.0.9: + dependencies: + brace-expansion: 2.1.2 + + minimist@1.2.8: {} + + minipass-collect@2.0.1: + dependencies: + minipass: 7.1.3 + + minipass-fetch@4.0.1: + dependencies: + minipass: 7.1.3 + minipass-sized: 1.0.3 + minizlib: 3.1.0 + optionalDependencies: + encoding: 0.1.13 + + minipass-flush@1.0.7: + dependencies: + minipass: 3.3.6 + + minipass-pipeline@1.2.4: + dependencies: + minipass: 3.3.6 + + minipass-sized@1.0.3: + dependencies: + minipass: 3.3.6 + + minipass@3.3.6: + dependencies: + yallist: 4.0.0 + + minipass@5.0.0: {} + + minipass@7.1.3: {} + + minizlib@2.1.2: + dependencies: + minipass: 3.3.6 + yallist: 4.0.0 + + minizlib@3.1.0: + dependencies: + minipass: 7.1.3 + + mkdirp@0.5.6: + dependencies: + minimist: 1.2.8 + + mkdirp@1.0.4: {} + + mrmime@2.0.1: {} + + ms@2.0.0: {} + + ms@2.1.3: {} + + msgpackr-extract@3.0.4: + dependencies: + node-gyp-build-optional-packages: 5.2.2 + optionalDependencies: + '@msgpackr-extract/msgpackr-extract-darwin-arm64': 3.0.4 + '@msgpackr-extract/msgpackr-extract-darwin-x64': 3.0.4 + '@msgpackr-extract/msgpackr-extract-linux-arm': 3.0.4 + '@msgpackr-extract/msgpackr-extract-linux-arm64': 3.0.4 + '@msgpackr-extract/msgpackr-extract-linux-x64': 3.0.4 + '@msgpackr-extract/msgpackr-extract-win32-x64': 3.0.4 + optional: true + + msgpackr@1.12.1: + optionalDependencies: + msgpackr-extract: 3.0.4 + optional: true + + multicast-dns@7.2.5: + dependencies: + dns-packet: 5.6.1 + thunky: 1.1.0 + + mute-stream@1.0.0: {} + + mute-stream@2.0.0: {} + + nanoid@3.3.16: {} + + native-run@2.0.3(supports-color@8.1.1): + dependencies: + '@ionic/utils-fs': 3.1.7(supports-color@8.1.1) + '@ionic/utils-terminal': 2.3.5(supports-color@8.1.1) + bplist-parser: 0.3.2 + debug: 4.4.3(supports-color@8.1.1) + elementtree: 0.1.7 + ini: 4.1.3 + plist: 3.1.1 + split2: 4.2.0 + through2: 4.0.2 + tslib: 2.8.1 + yauzl: 2.10.0 + transitivePeerDependencies: + - supports-color + + needle@3.5.0: + dependencies: + iconv-lite: 0.6.3 + sax: 1.6.1 + optional: true + + negotiator@0.6.3: {} + + negotiator@0.6.4: {} + + negotiator@1.0.0: {} + + neo-async@2.6.2: {} + + node-addon-api@6.1.0: + optional: true + + node-addon-api@7.1.1: + optional: true + + node-forge@1.4.0: {} + + node-gyp-build-optional-packages@5.2.2: + dependencies: + detect-libc: 2.1.2 + optional: true + + node-gyp@11.5.0(supports-color@8.1.1): + dependencies: + env-paths: 2.2.1 + exponential-backoff: 3.1.3 + graceful-fs: 4.2.11 + make-fetch-happen: 14.0.3(supports-color@8.1.1) + nopt: 8.1.0 + proc-log: 5.0.0 + semver: 7.8.5 + tar: 7.5.22 + tinyglobby: 0.2.17 + which: 5.0.0 + transitivePeerDependencies: + - supports-color + + node-releases@2.0.51: {} + + nopt@8.1.0: + dependencies: + abbrev: 3.0.1 + + normalize-path@3.0.0: {} + + normalize-range@0.1.2: {} + + npm-bundled@4.0.0: + dependencies: + npm-normalize-package-bin: 4.0.0 + + npm-install-checks@7.1.2: + dependencies: + semver: 7.8.5 + + npm-normalize-package-bin@4.0.0: {} + + npm-package-arg@12.0.2: + dependencies: + hosted-git-info: 8.1.0 + proc-log: 5.0.0 + semver: 7.7.1 + validate-npm-package-name: 6.0.2 + + npm-packlist@9.0.0: + dependencies: + ignore-walk: 7.0.0 + + npm-pick-manifest@10.0.0: + dependencies: + npm-install-checks: 7.1.2 + npm-normalize-package-bin: 4.0.0 + npm-package-arg: 12.0.2 + semver: 7.7.1 + + npm-registry-fetch@18.0.2(supports-color@8.1.1): + dependencies: + '@npmcli/redact': 3.2.2 + jsonparse: 1.3.1 + make-fetch-happen: 14.0.3(supports-color@8.1.1) + minipass: 7.1.3 + minipass-fetch: 4.0.1 + minizlib: 3.1.0 + npm-package-arg: 12.0.2 + proc-log: 5.0.0 + transitivePeerDependencies: + - supports-color + + nth-check@2.1.1: + dependencies: + boolbase: 1.0.0 + + object-assign@4.1.1: {} + + object-inspect@1.13.4: {} + + obuf@1.1.2: {} + + on-finished@2.3.0: + dependencies: + ee-first: 1.1.1 + + on-finished@2.4.1: + dependencies: + ee-first: 1.1.1 + + on-headers@1.1.0: {} + + once@1.4.0: + dependencies: + wrappy: 1.0.2 + + onetime@5.1.2: + dependencies: + mimic-fn: 2.1.0 + + onetime@7.0.0: + dependencies: + mimic-function: 5.0.1 + + open@10.1.0: + dependencies: + default-browser: 5.5.0 + define-lazy-prop: 3.0.0 + is-inside-container: 1.0.0 + is-wsl: 3.1.1 + + open@8.4.2: + dependencies: + define-lazy-prop: 2.0.0 + is-docker: 2.2.1 + is-wsl: 2.2.0 + + ora@5.4.1: + dependencies: + bl: 4.1.0 + chalk: 4.1.2 + cli-cursor: 3.1.0 + cli-spinners: 2.9.2 + is-interactive: 1.0.0 + is-unicode-supported: 0.1.0 + log-symbols: 4.1.0 + strip-ansi: 6.0.1 + wcwidth: 1.0.1 + + ordered-binary@1.6.1: + optional: true + + p-limit@4.0.0: + dependencies: + yocto-queue: 1.2.2 + + p-locate@6.0.0: + dependencies: + p-limit: 4.0.0 + + p-map@7.0.6: {} + + p-retry@6.2.1: + dependencies: + '@types/retry': 0.12.2 + is-network-error: 1.3.2 + retry: 0.13.1 + + package-json-from-dist@1.0.1: {} + + pacote@20.0.0(supports-color@8.1.1): + dependencies: + '@npmcli/git': 6.0.3 + '@npmcli/installed-package-contents': 3.0.0 + '@npmcli/package-json': 6.2.0 + '@npmcli/promise-spawn': 8.0.3 + '@npmcli/run-script': 9.1.0(supports-color@8.1.1) + cacache: 19.0.1 + fs-minipass: 3.0.3 + minipass: 7.1.3 + npm-package-arg: 12.0.2 + npm-packlist: 9.0.0 + npm-pick-manifest: 10.0.0 + npm-registry-fetch: 18.0.2(supports-color@8.1.1) + proc-log: 5.0.0 + promise-retry: 2.0.1 + sigstore: 3.1.0(supports-color@8.1.1) + ssri: 12.0.0 + tar: 6.2.1 + transitivePeerDependencies: + - supports-color + + parent-module@1.0.1: + dependencies: + callsites: 3.1.0 + + parse-json@5.2.0: + dependencies: + '@babel/code-frame': 7.29.7 + error-ex: 1.3.4 + json-parse-even-better-errors: 2.3.1 + lines-and-columns: 1.2.4 + + parse-node-version@1.0.1: {} + + parse5-html-rewriting-stream@7.0.0: + dependencies: + entities: 4.5.0 + parse5: 7.3.0 + parse5-sax-parser: 7.0.0 + + parse5-sax-parser@7.0.0: + dependencies: + parse5: 7.3.0 + + parse5@7.3.0: + dependencies: + entities: 6.0.1 + + parseurl@1.3.3: {} + + path-exists@5.0.0: {} + + path-is-absolute@1.0.1: {} + + path-key@3.1.1: {} + + path-parse@1.0.7: {} + + path-scurry@1.11.1: + dependencies: + lru-cache: 10.4.3 + minipass: 7.1.3 + + path-scurry@2.0.2: + dependencies: + lru-cache: 11.5.2 + minipass: 7.1.3 + + path-to-regexp@0.1.13: {} + + path-type@6.0.0: {} + + pend@1.2.0: {} + + picocolors@1.1.1: {} + + picomatch@2.3.2: {} + + picomatch@4.0.4: {} + + picomatch@4.0.5: {} + + pify@4.0.1: + optional: true + + piscina@4.8.0: + optionalDependencies: + '@napi-rs/nice': 1.1.1 + + pkg-dir@7.0.0: + dependencies: + find-up: 6.3.0 + + plist@3.1.1: + dependencies: + '@xmldom/xmldom': 0.9.10 + base64-js: 1.5.1 + xmlbuilder: 15.1.1 + + postcss-loader@8.1.1(postcss@8.5.12)(typescript@5.5.4)(webpack@5.105.0(esbuild@0.28.0)(postcss@8.5.12)): + dependencies: + cosmiconfig: 9.0.2(typescript@5.5.4) + jiti: 1.21.7 + postcss: 8.5.12 + semver: 7.7.1 + optionalDependencies: + webpack: 5.105.0(esbuild@0.28.0)(postcss@8.5.12) + transitivePeerDependencies: + - typescript + + postcss-media-query-parser@0.2.3: {} + + postcss-modules-extract-imports@3.1.0(postcss@8.5.12): + dependencies: + postcss: 8.5.12 + + postcss-modules-local-by-default@4.2.0(postcss@8.5.12): + dependencies: + icss-utils: 5.1.0(postcss@8.5.12) + postcss: 8.5.12 + postcss-selector-parser: 7.1.4 + postcss-value-parser: 4.2.0 + + postcss-modules-scope@3.2.1(postcss@8.5.12): + dependencies: + postcss: 8.5.12 + postcss-selector-parser: 7.1.4 + + postcss-modules-values@4.0.0(postcss@8.5.12): + dependencies: + icss-utils: 5.1.0(postcss@8.5.12) + postcss: 8.5.12 + + postcss-selector-parser@7.1.4: + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + + postcss-value-parser@4.2.0: {} + + postcss@8.5.12: + dependencies: + nanoid: 3.3.16 + picocolors: 1.1.1 + source-map-js: 1.2.1 + + postcss@8.5.23: + dependencies: + nanoid: 3.3.16 + picocolors: 1.1.1 + source-map-js: 1.2.1 + + proc-log@5.0.0: {} + + process-nextick-args@2.0.1: {} + + promise-retry@2.0.1: + dependencies: + err-code: 2.0.3 + retry: 0.12.0 + + prompts@2.4.2: + dependencies: + kleur: 3.0.3 + sisteransi: 1.0.5 + + proxy-addr@2.0.7: + dependencies: + forwarded: 0.2.0 + ipaddr.js: 1.9.1 + + prr@1.0.1: + optional: true + + punycode@1.4.1: {} + + qjobs@1.2.0: {} + + qs@6.15.3: + dependencies: + es-define-property: 1.0.1 + side-channel: 1.1.1 + + queue-microtask@1.2.3: {} + + randombytes@2.1.0: + dependencies: + safe-buffer: 5.2.1 + + range-parser@1.2.1: {} + + range-parser@1.3.0: {} + + raw-body@2.5.3: + dependencies: + bytes: 3.1.2 + http-errors: 2.0.1 + iconv-lite: 0.4.24 + unpipe: 1.0.0 + + readable-stream@2.3.8: + dependencies: + core-util-is: 1.0.3 + inherits: 2.0.4 + isarray: 1.0.0 + process-nextick-args: 2.0.1 + safe-buffer: 5.1.2 + string_decoder: 1.1.1 + util-deprecate: 1.0.2 + + readable-stream@3.6.2: + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + + readdirp@3.6.0: + dependencies: + picomatch: 2.3.2 + + readdirp@4.1.2: {} + + reflect-metadata@0.2.2: {} + + regenerate-unicode-properties@10.2.2: + dependencies: + regenerate: 1.4.2 + + regenerate@1.4.2: {} + + regenerator-runtime@0.14.1: {} + + regex-parser@2.3.1: {} + + regexpu-core@6.4.0: + dependencies: + regenerate: 1.4.2 + regenerate-unicode-properties: 10.2.2 + regjsgen: 0.8.0 + regjsparser: 0.13.2 + unicode-match-property-ecmascript: 2.0.0 + unicode-match-property-value-ecmascript: 2.2.1 + + regjsgen@0.8.0: {} + + regjsparser@0.13.2: + dependencies: + jsesc: 3.1.0 + + require-directory@2.1.1: {} + + require-from-string@2.0.2: {} + + requires-port@1.0.0: {} + + resolve-from@4.0.0: {} + + resolve-url-loader@5.0.0: + dependencies: + adjust-sourcemap-loader: 4.0.0 + convert-source-map: 1.9.0 + loader-utils: 2.0.4 + postcss: 8.5.12 + source-map: 0.6.1 + + resolve@1.22.10: + dependencies: + is-core-module: 2.16.2 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + + resolve@1.22.12: + dependencies: + es-errors: 1.3.0 + is-core-module: 2.16.2 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + + restore-cursor@3.1.0: + dependencies: + onetime: 5.1.2 + signal-exit: 3.0.7 + + restore-cursor@5.1.0: + dependencies: + onetime: 7.0.0 + signal-exit: 4.1.0 + + retry@0.12.0: {} + + retry@0.13.1: {} + + reusify@1.1.0: {} + + rfdc@1.4.1: {} + + rimraf@3.0.2: + dependencies: + glob: 7.2.3 + + rimraf@6.1.3: + dependencies: + glob: 13.0.6 + package-json-from-dist: 1.0.1 + + rollup@4.59.0: + dependencies: + '@types/estree': 1.0.8 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.59.0 + '@rollup/rollup-android-arm64': 4.59.0 + '@rollup/rollup-darwin-arm64': 4.59.0 + '@rollup/rollup-darwin-x64': 4.59.0 + '@rollup/rollup-freebsd-arm64': 4.59.0 + '@rollup/rollup-freebsd-x64': 4.59.0 + '@rollup/rollup-linux-arm-gnueabihf': 4.59.0 + '@rollup/rollup-linux-arm-musleabihf': 4.59.0 + '@rollup/rollup-linux-arm64-gnu': 4.59.0 + '@rollup/rollup-linux-arm64-musl': 4.59.0 + '@rollup/rollup-linux-loong64-gnu': 4.59.0 + '@rollup/rollup-linux-loong64-musl': 4.59.0 + '@rollup/rollup-linux-ppc64-gnu': 4.59.0 + '@rollup/rollup-linux-ppc64-musl': 4.59.0 + '@rollup/rollup-linux-riscv64-gnu': 4.59.0 + '@rollup/rollup-linux-riscv64-musl': 4.59.0 + '@rollup/rollup-linux-s390x-gnu': 4.59.0 + '@rollup/rollup-linux-x64-gnu': 4.59.0 + '@rollup/rollup-linux-x64-musl': 4.59.0 + '@rollup/rollup-openbsd-x64': 4.59.0 + '@rollup/rollup-openharmony-arm64': 4.59.0 + '@rollup/rollup-win32-arm64-msvc': 4.59.0 + '@rollup/rollup-win32-ia32-msvc': 4.59.0 + '@rollup/rollup-win32-x64-gnu': 4.59.0 + '@rollup/rollup-win32-x64-msvc': 4.59.0 + fsevents: 2.3.3 + + rollup@4.62.3: + dependencies: + '@types/estree': 1.0.9 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.62.3 + '@rollup/rollup-android-arm64': 4.62.3 + '@rollup/rollup-darwin-arm64': 4.62.3 + '@rollup/rollup-darwin-x64': 4.62.3 + '@rollup/rollup-freebsd-arm64': 4.62.3 + '@rollup/rollup-freebsd-x64': 4.62.3 + '@rollup/rollup-linux-arm-gnueabihf': 4.62.3 + '@rollup/rollup-linux-arm-musleabihf': 4.62.3 + '@rollup/rollup-linux-arm64-gnu': 4.62.3 + '@rollup/rollup-linux-arm64-musl': 4.62.3 + '@rollup/rollup-linux-loong64-gnu': 4.62.3 + '@rollup/rollup-linux-loong64-musl': 4.62.3 + '@rollup/rollup-linux-ppc64-gnu': 4.62.3 + '@rollup/rollup-linux-ppc64-musl': 4.62.3 + '@rollup/rollup-linux-riscv64-gnu': 4.62.3 + '@rollup/rollup-linux-riscv64-musl': 4.62.3 + '@rollup/rollup-linux-s390x-gnu': 4.62.3 + '@rollup/rollup-linux-x64-gnu': 4.62.3 + '@rollup/rollup-linux-x64-musl': 4.62.3 + '@rollup/rollup-openbsd-x64': 4.62.3 + '@rollup/rollup-openharmony-arm64': 4.62.3 + '@rollup/rollup-win32-arm64-msvc': 4.62.3 + '@rollup/rollup-win32-ia32-msvc': 4.62.3 + '@rollup/rollup-win32-x64-gnu': 4.62.3 + '@rollup/rollup-win32-x64-msvc': 4.62.3 + fsevents: 2.3.3 + + run-applescript@7.1.0: {} + + run-parallel@1.2.0: + dependencies: + queue-microtask: 1.2.3 + + rxjs@7.8.1: + dependencies: + tslib: 2.8.1 + + rxjs@7.8.2: + dependencies: + tslib: 2.8.1 + + safe-buffer@5.1.2: {} + + safe-buffer@5.2.1: {} + + safe-regex-test@1.1.0: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-regex: 1.2.1 + + safer-buffer@2.1.2: {} + + sass-loader@16.0.5(sass@1.85.0)(webpack@5.105.0(esbuild@0.28.0)(postcss@8.5.12)): + dependencies: + neo-async: 2.6.2 + optionalDependencies: + sass: 1.85.0 + webpack: 5.105.0(esbuild@0.28.0)(postcss@8.5.12) + + sass@1.85.0: + dependencies: + chokidar: 4.0.3 + immutable: 5.1.9 + source-map-js: 1.2.1 + optionalDependencies: + '@parcel/watcher': 2.6.0 + + sax@1.1.4: {} + + sax@1.6.1: {} + + schema-utils@4.3.3: + dependencies: + '@types/json-schema': 7.0.15 + ajv: 8.20.0 + ajv-formats: 2.1.1(ajv@8.20.0) + ajv-keywords: 5.1.0(ajv@8.20.0) + + select-hose@2.0.0: {} + + selfsigned@2.4.1: + dependencies: + '@types/node-forge': 1.3.14 + node-forge: 1.4.0 + + semver@5.7.2: + optional: true + + semver@6.3.1: {} + + semver@7.7.1: {} + + semver@7.8.5: {} + + send@0.19.2(supports-color@8.1.1): + dependencies: + debug: 2.6.9(supports-color@8.1.1) + depd: 2.0.0 + destroy: 1.2.0 + encodeurl: 2.0.0 + escape-html: 1.0.3 + etag: 1.8.1 + fresh: 0.5.2 + http-errors: 2.0.1 + mime: 1.6.0 + ms: 2.1.3 + on-finished: 2.4.1 + range-parser: 1.2.1 + statuses: 2.0.2 + transitivePeerDependencies: + - supports-color + + serialize-javascript@6.0.2: + dependencies: + randombytes: 2.1.0 + + serve-index@1.9.2(supports-color@8.1.1): + dependencies: + accepts: 1.3.8 + batch: 0.6.1 + debug: 2.6.9(supports-color@8.1.1) + escape-html: 1.0.3 + http-errors: 1.8.1 + mime-types: 2.1.35 + parseurl: 1.3.3 + transitivePeerDependencies: + - supports-color + + serve-static@1.16.3(supports-color@8.1.1): + dependencies: + encodeurl: 2.0.0 + escape-html: 1.0.3 + parseurl: 1.3.3 + send: 0.19.2(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + + setprototypeof@1.2.0: {} + + shallow-clone@3.0.1: + dependencies: + kind-of: 6.0.3 + + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 + + shebang-regex@3.0.0: {} + + shell-quote@1.10.0: {} + + side-channel-list@1.0.1: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + + side-channel-map@1.0.1: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + + side-channel-weakmap@1.0.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + side-channel-map: 1.0.1 + + side-channel@1.1.1: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + side-channel-list: 1.0.1 + side-channel-map: 1.0.1 + side-channel-weakmap: 1.0.2 + + signal-exit@3.0.7: {} + + signal-exit@4.1.0: {} + + sigstore@3.1.0(supports-color@8.1.1): + dependencies: + '@sigstore/bundle': 3.1.0 + '@sigstore/core': 2.0.0 + '@sigstore/protobuf-specs': 0.4.3 + '@sigstore/sign': 3.1.0(supports-color@8.1.1) + '@sigstore/tuf': 3.1.1(supports-color@8.1.1) + '@sigstore/verify': 2.1.1 + transitivePeerDependencies: + - supports-color + + simple-plist@1.3.1: + dependencies: + bplist-creator: 0.1.0 + bplist-parser: 0.3.1 + plist: 3.1.1 + + sisteransi@1.0.5: {} + + slash@5.1.0: {} + + slice-ansi@4.0.0: + dependencies: + ansi-styles: 4.3.0 + astral-regex: 2.0.0 + is-fullwidth-code-point: 3.0.0 + + slice-ansi@5.0.0: + dependencies: + ansi-styles: 6.2.3 + is-fullwidth-code-point: 4.0.0 + + slice-ansi@7.1.2: + dependencies: + ansi-styles: 6.2.3 + is-fullwidth-code-point: 5.1.0 + + smart-buffer@4.2.0: {} + + socket.io-adapter@2.5.8(supports-color@8.1.1): + dependencies: + debug: 4.4.3(supports-color@8.1.1) + ws: 8.21.1 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + socket.io-parser@4.2.7(supports-color@8.1.1): + dependencies: + '@socket.io/component-emitter': 3.1.2 + debug: 4.4.3(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + + socket.io@4.8.3(supports-color@8.1.1): + dependencies: + accepts: 1.3.8 + base64id: 2.0.0 + cors: 2.8.6 + debug: 4.4.3(supports-color@8.1.1) + engine.io: 6.6.9(supports-color@8.1.1) + socket.io-adapter: 2.5.8(supports-color@8.1.1) + socket.io-parser: 4.2.7(supports-color@8.1.1) + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + sockjs@0.3.24: + dependencies: + faye-websocket: 0.11.4 + uuid: 8.3.2 + websocket-driver: 0.7.5 + + socks-proxy-agent@8.0.5(supports-color@8.1.1): + dependencies: + agent-base: 7.1.4 + debug: 4.4.3(supports-color@8.1.1) + socks: 2.8.9 + transitivePeerDependencies: + - supports-color + + socks@2.8.9: + dependencies: + ip-address: 10.3.1 + smart-buffer: 4.2.0 + + source-map-js@1.2.1: {} + + source-map-loader@5.0.0(webpack@5.105.0(esbuild@0.28.0)(postcss@8.5.12)): + dependencies: + iconv-lite: 0.6.3 + source-map-js: 1.2.1 + webpack: 5.105.0(esbuild@0.28.0)(postcss@8.5.12) + + source-map-support@0.5.21: + dependencies: + buffer-from: 1.1.2 + source-map: 0.6.1 + + source-map@0.6.1: {} + + source-map@0.7.4: {} + + spdx-correct@3.2.0: + dependencies: + spdx-expression-parse: 3.0.1 + spdx-license-ids: 3.0.23 + + spdx-exceptions@2.5.0: {} + + spdx-expression-parse@3.0.1: + dependencies: + spdx-exceptions: 2.5.0 + spdx-license-ids: 3.0.23 + + spdx-license-ids@3.0.23: {} + + spdy-transport@3.0.0(supports-color@8.1.1): + dependencies: + debug: 4.4.3(supports-color@8.1.1) + detect-node: 2.1.0 + hpack.js: 2.1.6 + obuf: 1.1.2 + readable-stream: 3.6.2 + wbuf: 1.7.3 + transitivePeerDependencies: + - supports-color + + spdy@4.0.2(supports-color@8.1.1): + dependencies: + debug: 4.4.3(supports-color@8.1.1) + handle-thing: 2.0.1 + http-deceiver: 1.2.7 + select-hose: 2.0.0 + spdy-transport: 3.0.0(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + + split2@4.2.0: {} + + ssri@12.0.0: + dependencies: + minipass: 7.1.3 + + statuses@1.5.0: {} + + statuses@2.0.2: {} + + stream-buffers@2.2.0: {} + + streamroller@3.1.5(supports-color@8.1.1): + dependencies: + date-format: 4.0.14 + debug: 4.4.3(supports-color@8.1.1) + fs-extra: 8.1.0 + transitivePeerDependencies: + - supports-color + + string-width@4.2.3: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + string-width@5.1.2: + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.2.0 + + string-width@7.2.0: + dependencies: + emoji-regex: 10.6.0 + get-east-asian-width: 1.6.0 + strip-ansi: 7.2.0 + + string_decoder@1.1.1: + dependencies: + safe-buffer: 5.1.2 + + string_decoder@1.3.0: + dependencies: + safe-buffer: 5.2.1 + + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + strip-ansi@7.2.0: + dependencies: + ansi-regex: 6.2.2 + + supports-color@7.2.0: + dependencies: + has-flag: 4.0.0 + + supports-color@8.1.1: + dependencies: + has-flag: 4.0.0 + + supports-preserve-symlinks-flag@1.0.0: {} + + symbol-observable@4.0.0: {} + + tapable@2.3.3: {} + + tar@6.2.1: + dependencies: + chownr: 2.0.0 + fs-minipass: 2.1.0 + minipass: 5.0.0 + minizlib: 2.1.2 + mkdirp: 1.0.4 + yallist: 4.0.0 + + tar@7.5.22: + dependencies: + '@isaacs/fs-minipass': 4.0.1 + chownr: 3.0.0 + minipass: 7.1.3 + minizlib: 3.1.0 + yallist: 5.0.0 + + terser-webpack-plugin@5.6.1(esbuild@0.28.0)(postcss@8.5.12)(webpack@5.105.0(esbuild@0.28.0)(postcss@8.5.12)): + dependencies: + '@jridgewell/trace-mapping': 0.3.31 + jest-worker: 27.5.1 + schema-utils: 4.3.3 + terser: 5.39.0 + webpack: 5.105.0(esbuild@0.28.0)(postcss@8.5.12) + optionalDependencies: + esbuild: 0.28.0 + postcss: 8.5.12 + + terser@5.39.0: + dependencies: + '@jridgewell/source-map': 0.3.11 + acorn: 8.18.0 + commander: 2.20.3 + source-map-support: 0.5.21 + + thingies@2.6.1(tslib@2.8.1): + dependencies: + tslib: 2.8.1 + + three@0.185.1: {} + + through2@4.0.2: + dependencies: + readable-stream: 3.6.2 + + thunky@1.1.0: {} + + tinyglobby@0.2.17: + dependencies: + fdir: 6.5.0(picomatch@4.0.5) + picomatch: 4.0.5 + + tmp@0.2.7: {} + + to-regex-range@5.0.1: + dependencies: + is-number: 7.0.0 + + toidentifier@1.0.1: {} + + tree-dump@1.1.0(tslib@2.8.1): + dependencies: + tslib: 2.8.1 + + tree-kill@1.2.2: {} + + tslib@2.8.1: {} + + tuf-js@3.1.0(supports-color@8.1.1): + dependencies: + '@tufjs/models': 3.0.1 + debug: 4.4.3(supports-color@8.1.1) + make-fetch-happen: 14.0.3(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + + type-is@1.6.18: + dependencies: + media-typer: 0.3.0 + mime-types: 2.1.35 + + typed-assert@1.0.9: {} + + typescript@5.5.4: {} + + ua-parser-js@0.7.41: {} + + undici-types@8.3.0: {} + + unicode-canonical-property-names-ecmascript@2.0.1: {} + + unicode-match-property-ecmascript@2.0.0: + dependencies: + unicode-canonical-property-names-ecmascript: 2.0.1 + unicode-property-aliases-ecmascript: 2.2.0 + + unicode-match-property-value-ecmascript@2.2.1: {} + + unicode-property-aliases-ecmascript@2.2.0: {} + + unicorn-magic@0.3.0: {} + + unique-filename@4.0.0: + dependencies: + unique-slug: 5.0.0 + + unique-slug@5.0.0: + dependencies: + imurmurhash: 0.1.4 + + universalify@0.1.2: {} + + universalify@2.0.1: {} + + unpipe@1.0.0: {} + + untildify@4.0.0: {} + + update-browserslist-db@1.2.3(browserslist@4.28.7): + dependencies: + browserslist: 4.28.7 + escalade: 3.2.0 + picocolors: 1.1.1 + + util-deprecate@1.0.2: {} + + utils-merge@1.0.1: {} + + uuid@7.0.3: {} + + uuid@8.3.2: {} + + validate-npm-package-license@3.0.4: + dependencies: + spdx-correct: 3.2.0 + spdx-expression-parse: 3.0.1 + + validate-npm-package-name@6.0.2: {} + + vary@1.1.2: {} + + vite@6.4.2(@types/node@26.1.2)(jiti@1.21.7)(less@4.2.2)(sass@1.85.0)(terser@5.39.0): + dependencies: + esbuild: 0.25.12 + fdir: 6.5.0(picomatch@4.0.5) + picomatch: 4.0.5 + postcss: 8.5.23 + rollup: 4.62.3 + tinyglobby: 0.2.17 + optionalDependencies: + '@types/node': 26.1.2 + fsevents: 2.3.3 + jiti: 1.21.7 + less: 4.2.2 + sass: 1.85.0 + terser: 5.39.0 + + void-elements@2.0.1: {} + + watchpack@2.4.2: + dependencies: + glob-to-regexp: 0.4.1 + graceful-fs: 4.2.11 + + watchpack@2.5.2: + dependencies: + graceful-fs: 4.2.11 + + wbuf@1.7.3: + dependencies: + minimalistic-assert: 1.0.1 + + wcwidth@1.0.1: + dependencies: + defaults: 1.0.4 + + weak-lru-cache@1.2.2: + optional: true + + webpack-dev-middleware@7.4.2(tslib@2.8.1)(webpack@5.105.0(esbuild@0.28.0)(postcss@8.5.12)): + dependencies: + colorette: 2.0.20 + memfs: 4.64.0(tslib@2.8.1) + mime-types: 2.1.35 + on-finished: 2.4.1 + range-parser: 1.3.0 + schema-utils: 4.3.3 + optionalDependencies: + webpack: 5.105.0(esbuild@0.28.0)(postcss@8.5.12) + transitivePeerDependencies: + - tslib + + webpack-dev-server@5.2.2(debug@4.4.3(supports-color@8.1.1))(supports-color@8.1.1)(tslib@2.8.1)(webpack@5.105.0(esbuild@0.28.0)(postcss@8.5.12)): + dependencies: + '@types/bonjour': 3.5.13 + '@types/connect-history-api-fallback': 1.5.4 + '@types/express': 4.17.25 + '@types/express-serve-static-core': 4.19.9 + '@types/serve-index': 1.9.4 + '@types/serve-static': 1.15.10 + '@types/sockjs': 0.3.36 + '@types/ws': 8.18.1 + ansi-html-community: 0.0.8 + bonjour-service: 1.4.3 + chokidar: 3.6.0 + colorette: 2.0.20 + compression: 1.8.1(supports-color@8.1.1) + connect-history-api-fallback: 2.0.0 + express: 4.22.2(supports-color@8.1.1) + graceful-fs: 4.2.11 + http-proxy-middleware: 2.0.10(@types/express@4.17.25)(debug@4.4.3(supports-color@8.1.1)) + ipaddr.js: 2.4.0 + launch-editor: 2.14.1 + open: 10.1.0 + p-retry: 6.2.1 + schema-utils: 4.3.3 + selfsigned: 2.4.1 + serve-index: 1.9.2(supports-color@8.1.1) + sockjs: 0.3.24 + spdy: 4.0.2(supports-color@8.1.1) + webpack-dev-middleware: 7.4.2(tslib@2.8.1)(webpack@5.105.0(esbuild@0.28.0)(postcss@8.5.12)) + ws: 8.21.1 + optionalDependencies: + webpack: 5.105.0(esbuild@0.28.0)(postcss@8.5.12) + transitivePeerDependencies: + - bufferutil + - debug + - supports-color + - tslib + - utf-8-validate + + webpack-merge@6.0.1: + dependencies: + clone-deep: 4.0.1 + flat: 5.0.2 + wildcard: 2.0.1 + + webpack-sources@3.5.1: {} + + webpack-subresource-integrity@5.1.0(webpack@5.105.0(esbuild@0.28.0)(postcss@8.5.12)): + dependencies: + typed-assert: 1.0.9 + webpack: 5.105.0(esbuild@0.28.0)(postcss@8.5.12) + + webpack@5.105.0(esbuild@0.28.0)(postcss@8.5.12): + dependencies: + '@types/eslint-scope': 3.7.7 + '@types/estree': 1.0.9 + '@types/json-schema': 7.0.15 + '@webassemblyjs/ast': 1.14.1 + '@webassemblyjs/wasm-edit': 1.14.1 + '@webassemblyjs/wasm-parser': 1.14.1 + acorn: 8.18.0 + acorn-import-phases: 1.0.4(acorn@8.18.0) + browserslist: 4.28.7 + chrome-trace-event: 1.0.4 + enhanced-resolve: 5.24.3 + es-module-lexer: 2.3.1 + eslint-scope: 5.1.1 + events: 3.3.0 + glob-to-regexp: 0.4.1 + graceful-fs: 4.2.11 + json-parse-even-better-errors: 2.3.1 + loader-runner: 4.3.2 + mime-types: 2.1.35 + neo-async: 2.6.2 + schema-utils: 4.3.3 + tapable: 2.3.3 + terser-webpack-plugin: 5.6.1(esbuild@0.28.0)(postcss@8.5.12)(webpack@5.105.0(esbuild@0.28.0)(postcss@8.5.12)) + watchpack: 2.5.2 + webpack-sources: 3.5.1 + transitivePeerDependencies: + - '@minify-html/node' + - '@swc/core' + - '@swc/css' + - '@swc/html' + - clean-css + - cssnano + - csso + - esbuild + - html-minifier-terser + - lightningcss + - postcss + - uglify-js + + websocket-driver@0.7.5: + dependencies: + http-parser-js: 0.5.10 + safe-buffer: 5.2.1 + websocket-extensions: 0.1.4 + + websocket-extensions@0.1.4: {} + + which@1.3.1: + dependencies: + isexe: 2.0.0 + + which@2.0.2: + dependencies: + isexe: 2.0.0 + + which@5.0.0: + dependencies: + isexe: 3.1.5 + + wildcard@2.0.1: {} + + wrap-ansi@6.2.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + wrap-ansi@7.0.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + wrap-ansi@8.1.0: + dependencies: + ansi-styles: 6.2.3 + string-width: 5.1.2 + strip-ansi: 7.2.0 + + wrap-ansi@9.0.2: + dependencies: + ansi-styles: 6.2.3 + string-width: 7.2.0 + strip-ansi: 7.2.0 + + wrappy@1.0.2: {} + + ws@8.21.1: {} + + xcode@3.0.1: + dependencies: + simple-plist: 1.3.1 + uuid: 7.0.3 + + xml2js@0.6.2: + dependencies: + sax: 1.6.1 + xmlbuilder: 11.0.1 + + xmlbuilder@11.0.1: {} + + xmlbuilder@15.1.1: {} + + y18n@5.0.8: {} + + yallist@3.1.1: {} + + yallist@4.0.0: {} + + yallist@5.0.0: {} + + yargs-parser@20.2.9: {} + + yargs-parser@21.1.1: {} + + yargs@16.2.2: + dependencies: + cliui: 7.0.4 + escalade: 3.2.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 20.2.9 + + yargs@17.7.2: + dependencies: + cliui: 8.0.1 + escalade: 3.2.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + + yargs@17.7.3: + dependencies: + cliui: 8.0.1 + escalade: 3.2.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + + yauzl@2.10.0: + dependencies: + buffer-crc32: 0.2.13 + fd-slicer: 1.1.0 + + yocto-queue@1.2.2: {} + + yoctocolors-cjs@2.1.3: {} + + zone.js@0.15.1: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml new file mode 100644 index 0000000..f1c125c --- /dev/null +++ b/pnpm-workspace.yaml @@ -0,0 +1,5 @@ +allowBuilds: + '@parcel/watcher': set this to true or false + esbuild: set this to true or false + lmdb: set this to true or false + msgpackr-extract: set this to true or false diff --git a/public/404.html b/public/404.html new file mode 100644 index 0000000..e11d0fd --- /dev/null +++ b/public/404.html @@ -0,0 +1,31 @@ + + + + + + Cheems Bonk Game - Redirecting + + + + +

Redirecting... Click here if not redirected.

+ + diff --git a/public/data/cheems.json b/public/data/cheems.json new file mode 100644 index 0000000..c8fda6d --- /dev/null +++ b/public/data/cheems.json @@ -0,0 +1,115 @@ +[ + { + "id": "cheems_normal", + "nameKey": "cheems_normal", + "img": "normal.png", + "hitImg": "normal.png", + "default": true, + "storageKey": "c1", + "description": "cheems_normal_desc" + }, + { + "id": "cheems_little", + "nameKey": "cheems_little", + "img": "little.png", + "hitImg": "little.png", + "storageKey": "c2", + "description": "cheems_little_desc" + }, + { + "id": "cheems_adult", + "nameKey": "cheems_adult", + "img": "adult.png", + "hitImg": "adult.png", + "storageKey": "c3", + "description": "cheems_adult_desc" + }, + { + "id": "cheems_kid", + "nameKey": "cheems_kid", + "img": "kid.png", + "hitImg": "kid.png", + "storageKey": "c4", + "description": "cheems_kid_desc" + }, + { + "id": "cheems_mamado", + "nameKey": "cheems_mamado", + "img": "mamado.png", + "hitImg": "mamado.png", + "storageKey": "c5", + "description": "cheems_mamado_desc" + }, + { + "id": "cheems_pixelart", + "nameKey": "cheems_pixelart", + "img": "pixelart.png", + "hitImg": "pixelart.png", + "storageKey": "c6", + "description": "cheems_pixelart_desc" + }, + { + "id": "cheems_elegant", + "nameKey": "cheems_elegant", + "img": "elegant.png", + "hitImg": "elegant.png", + "storageKey": "c7", + "description": "cheems_elegant_desc" + }, + { + "id": "cheems_3d", + "nameKey": "cheems_3d", + "img": "3d.png", + "hitImg": "3d.png", + "storageKey": "c8", + "description": "cheems_3d_desc" + }, + { + "id": "cheems_black", + "nameKey": "cheems_black", + "img": "black.png", + "hitImg": "black.png", + "storageKey": "c9", + "description": "cheems_black_desc" + }, + { + "id": "cheems_minecraft", + "nameKey": "cheems_minecraft", + "img": "cubes.png", + "hitImg": "cubes.png", + "storageKey": "c10", + "description": "cheems_minecraft_desc" + }, + { + "id": "cheems_not_a_dog", + "nameKey": "cheems_not_a_dog", + "img": "not_a_dog.png", + "hitImg": "not_a_dog.png", + "storageKey": "c11", + "description": "cheems_not_a_dog_desc" + }, + { + "id": "cheems_not_a_plumber", + "nameKey": "cheems_not_a_plumber", + "img": "not_a_plumber.png", + "hitImg": "not_a_plumber.png", + "storageKey": "c12", + "description": "cheems_not_a_plumber_desc" + }, + { + "id": "cheems_not_ai", + "nameKey": "cheems_not_ai", + "img": "not_ai.png", + "hitImg": "not_ai.png", + "storageKey": "c13", + "description": "cheems_not_ai_desc" + }, + { + "id": "cheems_realistic", + "nameKey": "cheems_realistic", + "img": "realistic.png", + "hitImg": "realistic.png", + "storageKey": "c14", + "description": "cheems_realistic_desc" + } +] \ No newline at end of file diff --git a/public/data/closet.json b/public/data/closet.json new file mode 100644 index 0000000..3854dca --- /dev/null +++ b/public/data/closet.json @@ -0,0 +1,64 @@ +{ + "cheems": [ + "cheems_normal", + "cheems_little", + "cheems_adult", + "cheems_kid", + "cheems_mamado", + "cheems_pixelart", + "cheems_elegant", + "cheems_3d", + "cheems_black", + "cheems_minecraft", + "cheems_not_a_dog", + "cheems_not_a_plumber", + "cheems_not_ai", + "cheems_realistic" + ], + "sounds": [ + "sfx_1", + "sfx_2", + "sfx_3", + "sfx_4", + "sfx_5", + "sfx_6", + "sfx_7", + "sfx_8", + "sfx_9", + "sfx_10", + "sfx_11", + "sfx_12" + ], + "music": [ + "music_0", + "music_1", + "music_2", + "music_3", + "music_4", + "music_5", + "music_6", + "music_7", + "music_8", + "music_9", + "music_10", + "music_11", + "music_12", + "music_13", + "music_14", + "music_15", + "music_16", + "music_17", + "music_18", + "music_19", + "music_20", + "music_21", + "music_22", + "music_23", + "music_24", + "music_25", + "music_26", + "music_27", + "music_28", + "music_29" + ] +} \ No newline at end of file diff --git a/public/data/minigames.json b/public/data/minigames.json new file mode 100644 index 0000000..af7bbaa --- /dev/null +++ b/public/data/minigames.json @@ -0,0 +1,72 @@ +[ + { + "id": "block_breaker", + "name": "Merge Diggers", + "points": 100, + "mgPoints": 1, + "levelMgPoints": 2 + }, + { + "id": "attack_hole", + "name": "Attack Hole", + "points": 25000, + "mgPoints": 10, + "levelMgPoints": 1 + }, + { + "id": "doge_rescue", + "name": "Doge Rescue", + "points": 0, + "mgPoints": 0, + "levelMgPoints": 3 + }, + { + "id": "flappy_dunk", + "name": "Flappy Dunk", + "points": 10, + "mgPoints": 5, + "levelMgPoints": 5 + }, + { + "id": "helix_jump", + "name": "Helix Jump", + "points": 1000, + "mgPoints": 10, + "levelMgPoints": 1 + }, + { + "id": "magic_sort", + "name": "Magic Sort", + "points": 10, + "mgPoints": 0, + "levelMgPoints": 1 + }, + { + "id": "mob_control", + "name": "Mob Control", + "points": 100, + "mgPoints": 1, + "levelMgPoints": 2 + }, + { + "id": "paper_io", + "name": "Paper.io", + "points": 1000, + "mgPoints": 1, + "levelMgPoints": 0 + }, + { + "id": "spiral_roll", + "name": "Spiral Roll", + "points": 1000, + "mgPoints": 1, + "levelMgPoints": 1 + }, + { + "id": "stack_colors", + "name": "Stack Colors", + "points": 100, + "mgPoints": 1, + "levelMgPoints": 2 + } +] diff --git a/public/data/music.json b/public/data/music.json new file mode 100644 index 0000000..8e0362f --- /dev/null +++ b/public/data/music.json @@ -0,0 +1,302 @@ +[ + { + "id": "music_0", + "nameKey": "music_0", + "file": "", + "basePath": "sound/music/", + "default": true, + "storageKey": "m0", + "description": "music_0_desc", + "cover": "img/music/no_image.png" + }, + { + "id": "music_1", + "nameKey": "music_1", + "file": "A_Jazz_Piano.ogg", + "basePath": "sound/music/", + "default": true, + "storageKey": "m1", + "description": "music_1_desc", + "cover": "img/music/no_image.png" + }, + { + "id": "music_2", + "nameKey": "music_2", + "file": "Jack_Bootleg.ogg", + "basePath": "sound/music/", + "default": false, + "storageKey": "m2", + "description": "music_2_desc", + "cover": "img/music/jack_bootleg.png" + }, + { + "id": "music_3", + "nameKey": "music_3", + "file": "Magic_night.ogg", + "basePath": "sound/music/", + "default": false, + "storageKey": "m3", + "description": "music_3_desc", + "cover": "img/music/magic_night.png" + }, + { + "id": "music_4", + "nameKey": "music_4", + "file": "Minimalism_No9.ogg", + "basePath": "sound/music/", + "default": false, + "storageKey": "m4", + "description": "music_4_desc", + "cover": "img/music/minimalism_no9.png" + }, + { + "id": "music_5", + "nameKey": "music_5", + "file": "Minimalism_No10.ogg", + "basePath": "sound/music/", + "default": false, + "storageKey": "m5", + "description": "music_5_desc", + "cover": "img/music/minimalism_no10.png" + }, + { + "id": "music_6", + "nameKey": "music_6", + "file": "When_you_smile.ogg", + "basePath": "sound/music/", + "default": false, + "storageKey": "m6", + "description": "music_6_desc", + "cover": "img/music/when_you_smile.png" + }, + { + "id": "music_7", + "nameKey": "music_7", + "file": "TETRIS (Joey iLLah Bootleg) (Final).wav", + "basePath": "sound/music/", + "default": false, + "storageKey": "m7", + "description": "music_7_desc", + "cover": "img/music/tetris_bootleg.png" + }, + { + "id": "music_8", + "nameKey": "music_8", + "file": "separation-185196.mp3", + "basePath": "sound/music/", + "default": false, + "storageKey": "m8", + "description": "music_8_desc", + "cover": "img/music/no_image.png" + }, + { + "id": "music_9", + "nameKey": "music_9", + "file": "electro-summer-positive-party-141081.mp3", + "basePath": "sound/music/", + "default": false, + "storageKey": "m9", + "description": "music_9_desc", + "cover": "img/music/electro_summer_positive_party.png" + }, + { + "id": "music_10", + "nameKey": "music_10", + "file": "titanium-170190.mp3", + "basePath": "sound/music/", + "default": false, + "storageKey": "m10", + "description": "music_10_desc", + "cover": "img/music/titanium.png" + }, + { + "id": "music_11", + "nameKey": "music_11", + "file": "believe-me-143530.mp3", + "basePath": "sound/music/", + "default": false, + "storageKey": "m11", + "description": "music_11_desc", + "cover": "img/music/believe_me.png" + }, + { + "id": "music_12", + "nameKey": "music_12", + "file": "city-streets-background-version-166003.mp3", + "basePath": "sound/music/", + "default": false, + "storageKey": "m12", + "description": "music_12_desc", + "cover": "img/music/city_streets.png" + }, + { + "id": "music_13", + "nameKey": "music_13", + "file": "coffee-shop-189585.mp3", + "basePath": "sound/music/", + "default": false, + "storageKey": "m13", + "description": "music_13_desc", + "cover": "img/music/no_image.png" + }, + { + "id": "music_14", + "nameKey": "music_14", + "file": "trap-future-bass-royalty-free-music-167020.mp3", + "basePath": "sound/music/", + "default": false, + "storageKey": "m14", + "description": "music_14_desc", + "cover": "img/music/trap_future_bass.png" + }, + { + "id": "music_15", + "nameKey": "music_15", + "file": "bonk_the_amber.mp3", + "basePath": "sound/music/", + "default": false, + "storageKey": "m15", + "description": "music_15_desc", + "cover": "img/music/bonk_the_amber.png" + }, + { + "id": "music_16", + "nameKey": "music_16", + "file": "bonk_the_avatar.mp3", + "basePath": "sound/music/", + "default": false, + "storageKey": "m16", + "description": "music_16_desc", + "cover": "img/music/bonk_the_avatar.png" + }, + { + "id": "music_17", + "nameKey": "music_17", + "file": "bonus_level_bounce.mp3", + "basePath": "sound/music/", + "default": false, + "storageKey": "m17", + "description": "music_17_desc", + "cover": "img/music/bonus_level_bounce.png" + }, + { + "id": "music_18", + "nameKey": "music_18", + "file": "button_smash_routine.mp3", + "basePath": "sound/music/", + "default": false, + "storageKey": "m18", + "description": "music_18_desc", + "cover": "img/music/button_smash_routine.png" + }, + { + "id": "music_19", + "nameKey": "music_19", + "file": "cheems-chan_bonk.mp3", + "basePath": "sound/music/", + "default": false, + "storageKey": "m19", + "description": "music_19_desc", + "cover": "img/music/cheems_chan_bonk.png" + }, + { + "id": "music_20", + "nameKey": "music_20", + "file": "click_for_a_bonk.mp3", + "basePath": "sound/music/", + "default": false, + "storageKey": "m20", + "description": "music_20_desc", + "cover": "img/music/click_for_a_bonk.png" + }, + { + "id": "music_21", + "nameKey": "music_21", + "file": "hardwood_strike.mp3", + "basePath": "sound/music/", + "default": false, + "storageKey": "m21", + "description": "music_21_desc", + "cover": "img/music/hardwood_strike.png" + }, + { + "id": "music_22", + "nameKey": "music_22", + "file": "perfect_round.mp3", + "basePath": "sound/music/", + "default": false, + "storageKey": "m22", + "description": "music_22_desc", + "cover": "img/music/perfect_round.png" + }, + { + "id": "music_23", + "nameKey": "music_23", + "file": "pocket_change_victory.mp3", + "basePath": "sound/music/", + "default": false, + "storageKey": "m23", + "description": "music_23_desc", + "cover": "img/music/pocket_change_victory.png" + }, + { + "id": "music_24", + "nameKey": "music_24", + "file": "quick_loot_run.mp3", + "basePath": "sound/music/", + "default": false, + "storageKey": "m24", + "description": "music_24_desc", + "cover": "img/music/quick_loot_run.png" + }, + { + "id": "music_25", + "nameKey": "music_25", + "file": "target_in_the_sight.mp3", + "basePath": "sound/music/", + "default": false, + "storageKey": "m25", + "description": "music_25_desc", + "cover": "img/music/target_in_the_sight.png" + }, + { + "id": "music_26", + "nameKey": "music_26", + "file": "the_hammer_falls.mp3", + "basePath": "sound/music/", + "default": false, + "storageKey": "m26", + "description": "music_26_desc", + "cover": "img/music/the_hammer_falls.png" + }, + { + "id": "music_27", + "nameKey": "music_27", + "file": "the_late_commute.mp3", + "basePath": "sound/music/", + "default": false, + "storageKey": "m27", + "description": "music_27_desc", + "cover": "img/music/the_late_commute.png" + }, + { + "id": "music_28", + "nameKey": "music_28", + "file": "the_unwritten_page.mp3", + "basePath": "sound/music/", + "default": false, + "storageKey": "m28", + "description": "music_28_desc", + "cover": "img/music/the_unwritten_page_bage.png" + }, + { + "id": "music_29", + "nameKey": "music_29", + "file": "where_the_path_bends.mp3", + "basePath": "sound/music/", + "default": false, + "storageKey": "m29", + "description": "music_29_desc", + "cover": "img/music/where_the_path_bends.png" + } +] \ No newline at end of file diff --git a/public/data/shop.json b/public/data/shop.json new file mode 100644 index 0000000..0339e2f --- /dev/null +++ b/public/data/shop.json @@ -0,0 +1,868 @@ +[ + { + "_comment": "--- Currencies ---" + }, + { + "id": "dogecoin_1", + "type": "dogecoin", + "nameKey": "shop_dogecoin_special_name", + "descKey": "shop_dogecoin_special_desc", + "cost": "${daily_price} / 2", + "costCoins": 0, + "coinsGiven": 1, + "multiplier": 1, + "durationMin": 0, + "icon": "img/dogecoin-min.png", + "dailyLimit": "${daily_price_4} / 100 + 1" + }, + { + "id": "dogecoin_2", + "type": "dogecoin", + "nameKey": "shop_dogecoin_1_name", + "descKey": "shop_dogecoin_1_desc", + "cost": "${daily_price}", + "costCoins": 0, + "coinsGiven": 1, + "multiplier": 1, + "durationMin": 0, + "icon": "img/dogecoin-min.png", + "dailyLimit": 0 + }, + { + "id": "dogecoin_3", + "type": "dogecoin", + "nameKey": "shop_dogecoin_2_name", + "descKey": "shop_dogecoin_2_desc", + "cost": "${daily_price} * 1.8", + "costCoins": 0, + "coinsGiven": 2, + "multiplier": 1, + "durationMin": 0, + "icon": "img/dogecoin-min.png", + "dailyLimit": 0 + }, + { + "id": "dogecoin_4", + "type": "dogecoin", + "nameKey": "shop_dogecoin_5_name", + "descKey": "shop_dogecoin_5_desc", + "cost": "${daily_price} * 10 - ${daily_price} - ${daily_price_2}", + "costCoins": 0, + "coinsGiven": 5, + "multiplier": 1, + "durationMin": 0, + "icon": "img/dogecoin-min.png", + "dailyLimit": "${daily_price_4} / 10 + 1" + }, + { + "id": "dogecoin_5", + "type": "dogecoin", + "nameKey": "shop_dogecoin_10_name", + "descKey": "shop_dogecoin_10_desc", + "cost": "${daily_price} * 10 - ${daily_price} - ${daily_price_3} * 2", + "costCoins": 0, + "coinsGiven": 10, + "multiplier": 1, + "durationMin": 0, + "icon": "img/dogecoin-min.png", + "dailyLimit": "${daily_price_2} / 10 + 1" + }, + { + "id": "dogecoin_6", + "type": "dogecoin", + "nameKey": "shop_dogecoin_20_name", + "descKey": "shop_dogecoin_20_desc", + "cost": "${daily_price} * 20 - ${daily_price} - ${daily_price_4} * 2", + "costCoins": 0, + "coinsGiven": 20, + "multiplier": 1, + "durationMin": 0, + "icon": "img/dogecoin-min.png", + "dailyLimit": "${daily_price_3} / 10 + 1" + }, + { + "id": "curr_dgc_to_mg", + "type": "currency", + "nameKey": "shop_curr_dgc_to_mg_name", + "descKey": "shop_curr_dgc_to_mg_desc", + "cost": 0, + "costCoins": 1, + "costMinigames": 0, + "minigameCoinsGiven": 10, + "icon": "img/icons/play-svgrepo-com.svg" + }, + { + "id": "curr_mg_to_dgc", + "type": "currency", + "nameKey": "shop_curr_mg_to_dgc_name", + "descKey": "shop_curr_mg_to_dgc_desc", + "cost": 0, + "costCoins": 0, + "costMinigames": 10, + "coinsGiven": 1, + "icon": "img/dogecoin-min.png" + }, + { + "_comment": "--- Boosters ---" + }, + { + "id": "boost_2x_free", + "type": "booster", + "nameKey": "shop_boost_2x_5m_name", + "descKey": "shop_boost_2x_5m_desc", + "cost": 0, + "costCoins": 0, + "multiplier": 2, + "durationMin": 5, + "icon": "img/icons/trophy-svgrepo-com.svg", + "dailyLimit": "${daily_price} / 100 + 1" + }, + { + "id": "boost_3x_free", + "type": "booster", + "nameKey": "shop_boost_3x_5m_name", + "descKey": "shop_boost_3x_5m_desc", + "cost": 0, + "costCoins": 0, + "multiplier": 3, + "durationMin": 5, + "icon": "img/icons/trophy-svgrepo-com.svg", + "dailyLimit": "${daily_price_2} / 100 + 1" + }, + { + "id": "boost_10x_free", + "type": "booster", + "nameKey": "shop_boost_10x_3m_name", + "descKey": "shop_boost_10x_3m_desc", + "cost": 0, + "costCoins": 0, + "multiplier": 10, + "durationMin": 3, + "icon": "img/icons/trophy-svgrepo-com.svg", + "dailyLimit": "${daily_price_3} / 100 + 1" + }, + { + "id": "boost_2x_5m", + "type": "booster", + "nameKey": "shop_boost_2x_5m_name", + "descKey": "shop_boost_2x_5m_desc", + "cost": 1000, + "costCoins": 0, + "multiplier": 2, + "durationMin": 5, + "icon": "img/icons/trophy-svgrepo-com.svg", + "dailyLimit": 0 + }, + { + "id": "boost_2x_10m", + "type": "booster", + "nameKey": "shop_boost_2x_10m_name", + "descKey": "shop_boost_2x_10m_desc", + "cost": 1800, + "costCoins": 0, + "multiplier": 2, + "durationMin": 10, + "icon": "img/icons/trophy-svgrepo-com.svg", + "dailyLimit": 0 + }, + { + "id": "boost_2x_20m", + "type": "booster", + "nameKey": "shop_boost_2x_20m_name", + "descKey": "shop_boost_2x_20m_desc", + "cost": 3000, + "costCoins": 0, + "multiplier": 2, + "durationMin": 20, + "icon": "img/icons/trophy-svgrepo-com.svg", + "dailyLimit": 0 + }, + { + "id": "boost_3x_5m", + "type": "booster", + "nameKey": "shop_boost_3x_5m_name", + "descKey": "shop_boost_3x_5m_desc", + "cost": 0, + "costCoins": 150, + "multiplier": 3, + "durationMin": 5, + "icon": "img/icons/trophy-svgrepo-com.svg", + "dailyLimit": 0 + }, + { + "id": "boost_3x_10m", + "type": "booster", + "nameKey": "shop_boost_3x_10m_name", + "descKey": "shop_boost_3x_10m_desc", + "cost": 0, + "costCoins": 250, + "multiplier": 3, + "durationMin": 10, + "icon": "img/icons/trophy-svgrepo-com.svg", + "dailyLimit": 0 + }, + { + "id": "boost_3x_20m", + "type": "booster", + "nameKey": "shop_boost_3x_20m_name", + "descKey": "shop_boost_3x_20m_desc", + "cost": 0, + "costCoins": 450, + "multiplier": 3, + "durationMin": 20, + "icon": "img/icons/trophy-svgrepo-com.svg", + "dailyLimit": 0 + }, + { + "_comment": "--- Characters ---" + }, + { + "id": "cheems_little", + "type": "cheems", + "nameKey": "cheems_little", + "cost": 0, + "costCoins": 500, + "costMinigames": 0, + "icon": "img/cheems/little.png", + "oneTimePurchase": true + }, + { + "id": "cheems_adult", + "type": "cheems", + "nameKey": "cheems_adult", + "cost": 0, + "costCoins": 800, + "costMinigames": 0, + "icon": "img/cheems/adult.png", + "oneTimePurchase": true + }, + { + "id": "cheems_kid", + "type": "cheems", + "nameKey": "cheems_kid", + "cost": 0, + "costCoins": 1000, + "costMinigames": 0, + "icon": "img/cheems/kid.png", + "oneTimePurchase": true + }, + { + "id": "cheems_mamado", + "type": "cheems", + "nameKey": "cheems_mamado", + "cost": 0, + "costCoins": 2000, + "costMinigames": 0, + "icon": "img/cheems/mamado.png", + "oneTimePurchase": true + }, + { + "id": "cheems_pixelart", + "type": "cheems", + "nameKey": "cheems_pixelart", + "cost": 0, + "costCoins": 3000, + "costMinigames": 0, + "icon": "img/cheems/pixelart.png", + "oneTimePurchase": true + }, + { + "id": "cheems_elegant", + "type": "cheems", + "nameKey": "cheems_elegant", + "cost": 0, + "costCoins": 3500, + "costMinigames": 0, + "icon": "img/cheems/elegant.png", + "oneTimePurchase": true + }, + { + "id": "cheems_3d", + "type": "cheems", + "nameKey": "cheems_3d", + "cost": 0, + "costCoins": 2500, + "costMinigames": 0, + "icon": "img/cheems/3d.png", + "oneTimePurchase": true + }, + { + "id": "cheems_black", + "type": "cheems", + "nameKey": "cheems_black", + "cost": 0, + "costCoins": 2800, + "costMinigames": 0, + "icon": "img/cheems/black.png", + "oneTimePurchase": true + }, + { + "id": "cheems_not_ai", + "type": "cheems", + "nameKey": "cheems_not_ai", + "cost": 0, + "costCoins": 2600, + "costMinigames": 0, + "icon": "img/cheems/not_ai.png", + "oneTimePurchase": true + }, + { + "id": "cheems_realistic", + "type": "cheems", + "nameKey": "cheems_realistic", + "cost": 0, + "costCoins": 5000, + "costMinigames": 0, + "icon": "img/cheems/realistic.png", + "oneTimePurchase": true + }, + { + "id": "cheems_not_a_dog", + "type": "cheems", + "nameKey": "cheems_not_a_dog", + "cost": 0, + "costCoins": 3200, + "costMinigames": 0, + "icon": "img/cheems/not_a_dog.png", + "oneTimePurchase": true + }, + { + "id": "cheems_not_a_plumber", + "type": "cheems", + "nameKey": "cheems_not_a_plumber", + "cost": 0, + "costCoins": 4500, + "costMinigames": 3000, + "icon": "img/cheems/not_a_plumber.png", + "oneTimePurchase": true + }, + { + "id": "cheems_minecraft", + "type": "cheems", + "nameKey": "cheems_minecraft", + "cost": 0, + "costCoins": 3500, + "costMinigames": 2500, + "icon": "img/cheems/cubes.png", + "oneTimePurchase": true + }, + { + "_comment": "--- Sounds ---" + }, + { + "id": "sfx_2", + "type": "sound", + "nameKey": "sfx_2", + "cost": 0, + "costCoins": 1200, + "costMinigames": 2000, + "icon": "img/icons/sound-svgrepo-com.svg", + "oneTimePurchase": true + }, + { + "id": "sfx_3", + "type": "sound", + "nameKey": "sfx_3", + "cost": 0, + "costCoins": 1200, + "costMinigames": 2000, + "icon": "img/icons/sound-svgrepo-com.svg", + "oneTimePurchase": true + }, + { + "id": "sfx_4", + "type": "sound", + "nameKey": "sfx_4", + "cost": 0, + "costCoins": 1500, + "costMinigames": 2500, + "icon": "img/icons/sound-svgrepo-com.svg", + "oneTimePurchase": true + }, + { + "id": "sfx_5", + "type": "sound", + "nameKey": "sfx_5", + "cost": 0, + "costCoins": 1500, + "costMinigames": 2500, + "icon": "img/icons/sound-svgrepo-com.svg", + "oneTimePurchase": true + }, + { + "id": "sfx_6", + "type": "sound", + "nameKey": "sfx_6", + "cost": 0, + "costCoins": 800, + "costMinigames": 1500, + "icon": "img/icons/sound-svgrepo-com.svg", + "oneTimePurchase": true + }, + { + "id": "sfx_7", + "type": "sound", + "nameKey": "sfx_7", + "cost": 0, + "costCoins": 1200, + "costMinigames": 2000, + "icon": "img/icons/sound-svgrepo-com.svg", + "oneTimePurchase": true + }, + { + "id": "sfx_8", + "type": "sound", + "nameKey": "sfx_8", + "cost": 0, + "costCoins": 400, + "costMinigames": 0, + "icon": "img/icons/sound-svgrepo-com.svg", + "oneTimePurchase": true + }, + { + "id": "sfx_9", + "type": "sound", + "nameKey": "sfx_9", + "cost": 0, + "costCoins": 500, + "costMinigames": 0, + "icon": "img/icons/sound-svgrepo-com.svg", + "oneTimePurchase": true + }, + { + "id": "sfx_10", + "type": "sound", + "nameKey": "sfx_10", + "cost": 0, + "costCoins": 500, + "costMinigames": 0, + "icon": "img/icons/sound-svgrepo-com.svg", + "oneTimePurchase": true + }, + { + "id": "sfx_11", + "type": "sound", + "nameKey": "sfx_11", + "cost": 0, + "costCoins": 500, + "costMinigames": 0, + "icon": "img/icons/sound-svgrepo-com.svg", + "oneTimePurchase": true + }, + { + "id": "sfx_12", + "type": "sound", + "nameKey": "sfx_12", + "cost": 0, + "costCoins": 1000, + "costMinigames": 0, + "icon": "img/icons/sound-svgrepo-com.svg", + "oneTimePurchase": true + }, + { + "_comment": "--- Music ---" + }, + { + "id": "music_2", + "type": "music", + "nameKey": "music_2", + "cost": 0, + "costCoins": 1200, + "costMinigames": 0, + "icon": "img/icons/music-svgrepo-com.svg", + "oneTimePurchase": true + }, + { + "id": "music_3", + "type": "music", + "nameKey": "music_3", + "cost": 0, + "costCoins": 600, + "costMinigames": 0, + "icon": "img/icons/music-svgrepo-com.svg", + "oneTimePurchase": true + }, + { + "id": "music_4", + "type": "music", + "nameKey": "music_4", + "cost": 0, + "costCoins": 600, + "costMinigames": 0, + "icon": "img/icons/music-svgrepo-com.svg", + "oneTimePurchase": true + }, + { + "id": "music_5", + "type": "music", + "nameKey": "music_5", + "cost": 0, + "costCoins": 600, + "costMinigames": 0, + "icon": "img/icons/music-svgrepo-com.svg", + "oneTimePurchase": true + }, + { + "id": "music_6", + "type": "music", + "nameKey": "music_6", + "cost": 0, + "costCoins": 600, + "costMinigames": 0, + "icon": "img/icons/music-svgrepo-com.svg", + "oneTimePurchase": true + }, + { + "id": "music_7", + "type": "music", + "nameKey": "music_7", + "cost": 0, + "costCoins": 1500, + "costMinigames": 3000, + "icon": "img/icons/music-svgrepo-com.svg", + "oneTimePurchase": true + }, + { + "id": "music_8", + "type": "music", + "nameKey": "music_8", + "cost": 0, + "costCoins": 600, + "costMinigames": 0, + "icon": "img/icons/music-svgrepo-com.svg", + "oneTimePurchase": true + }, + { + "id": "music_9", + "type": "music", + "nameKey": "music_9", + "cost": 0, + "costCoins": 900, + "costMinigames": 0, + "icon": "img/icons/music-svgrepo-com.svg", + "oneTimePurchase": true + }, + { + "id": "music_10", + "type": "music", + "nameKey": "music_10", + "cost": 0, + "costCoins": 900, + "costMinigames": 0, + "icon": "img/icons/music-svgrepo-com.svg", + "oneTimePurchase": true + }, + { + "id": "music_11", + "type": "music", + "nameKey": "music_11", + "cost": 0, + "costCoins": 900, + "costMinigames": 0, + "icon": "img/icons/music-svgrepo-com.svg", + "oneTimePurchase": true + }, + { + "id": "music_12", + "type": "music", + "nameKey": "music_12", + "cost": 0, + "costCoins": 600, + "costMinigames": 0, + "icon": "img/icons/music-svgrepo-com.svg", + "oneTimePurchase": true + }, + { + "id": "music_13", + "type": "music", + "nameKey": "music_13", + "cost": 0, + "costCoins": 600, + "costMinigames": 0, + "icon": "img/icons/music-svgrepo-com.svg", + "oneTimePurchase": true + }, + { + "id": "music_14", + "type": "music", + "nameKey": "music_14", + "cost": 0, + "costCoins": 900, + "costMinigames": 0, + "icon": "img/icons/music-svgrepo-com.svg", + "oneTimePurchase": true + }, + { + "id": "music_15", + "type": "music", + "nameKey": "music_15", + "cost": 0, + "costCoins": 1200, + "costMinigames": 0, + "icon": "img/icons/music-svgrepo-com.svg", + "oneTimePurchase": true + }, + { + "id": "music_16", + "type": "music", + "nameKey": "music_16", + "cost": 0, + "costCoins": 1200, + "costMinigames": 0, + "icon": "img/icons/music-svgrepo-com.svg", + "oneTimePurchase": true + }, + { + "id": "music_17", + "type": "music", + "nameKey": "music_17", + "cost": 0, + "costCoins": 1200, + "costMinigames": 2500, + "icon": "img/icons/music-svgrepo-com.svg", + "oneTimePurchase": true + }, + { + "id": "music_18", + "type": "music", + "nameKey": "music_18", + "cost": 0, + "costCoins": 1200, + "costMinigames": 2500, + "icon": "img/icons/music-svgrepo-com.svg", + "oneTimePurchase": true + }, + { + "id": "music_19", + "type": "music", + "nameKey": "music_19", + "cost": 0, + "costCoins": 1200, + "costMinigames": 2500, + "icon": "img/icons/music-svgrepo-com.svg", + "oneTimePurchase": true + }, + { + "id": "music_20", + "type": "music", + "nameKey": "music_20", + "cost": 0, + "costCoins": 1200, + "costMinigames": 0, + "icon": "img/icons/music-svgrepo-com.svg", + "oneTimePurchase": true + }, + { + "id": "music_21", + "type": "music", + "nameKey": "music_21", + "cost": 0, + "costCoins": 1200, + "costMinigames": 0, + "icon": "img/icons/music-svgrepo-com.svg", + "oneTimePurchase": true + }, + { + "id": "music_22", + "type": "music", + "nameKey": "music_22", + "cost": 0, + "costCoins": 1200, + "costMinigames": 2500, + "icon": "img/icons/music-svgrepo-com.svg", + "oneTimePurchase": true + }, + { + "id": "music_23", + "type": "music", + "nameKey": "music_23", + "cost": 0, + "costCoins": 1200, + "costMinigames": 2500, + "icon": "img/icons/music-svgrepo-com.svg", + "oneTimePurchase": true + }, + { + "id": "music_24", + "type": "music", + "nameKey": "music_24", + "cost": 0, + "costCoins": 1200, + "costMinigames": 2500, + "icon": "img/icons/music-svgrepo-com.svg", + "oneTimePurchase": true + }, + { + "id": "music_25", + "type": "music", + "nameKey": "music_25", + "cost": 0, + "costCoins": 1200, + "costMinigames": 0, + "icon": "img/icons/music-svgrepo-com.svg", + "oneTimePurchase": true + }, + { + "id": "music_26", + "type": "music", + "nameKey": "music_26", + "cost": 0, + "costCoins": 1200, + "costMinigames": 0, + "icon": "img/icons/music-svgrepo-com.svg", + "oneTimePurchase": true + }, + { + "id": "music_27", + "type": "music", + "nameKey": "music_27", + "cost": 0, + "costCoins": 1200, + "costMinigames": 0, + "icon": "img/icons/music-svgrepo-com.svg", + "oneTimePurchase": true + }, + { + "id": "music_28", + "type": "music", + "nameKey": "music_28", + "cost": 0, + "costCoins": 1200, + "costMinigames": 0, + "icon": "img/icons/music-svgrepo-com.svg", + "oneTimePurchase": true + }, + { + "id": "music_29", + "type": "music", + "nameKey": "music_29", + "cost": 0, + "costCoins": 1200, + "costMinigames": 0, + "icon": "img/icons/music-svgrepo-com.svg", + "oneTimePurchase": true + }, + { + "_comment": "--- Minigames ---" + }, + { + "id": "minigame_block_breaker", + "type": "minigame", + "targetId": "block_breaker", + "nameKey": "shop_minigame_block_breaker_name", + "descKey": "shop_minigame_block_breaker_desc", + "cost": 0, + "costCoins": 1500, + "costMinigames": 3500, + "icon": "img/icons/play-svgrepo-com.svg", + "oneTimePurchase": true + }, + { + "id": "minigame_attack_hole", + "type": "minigame", + "targetId": "attack_hole", + "nameKey": "shop_minigame_attack_hole_name", + "descKey": "shop_minigame_attack_hole_desc", + "cost": 0, + "costCoins": 2500, + "costMinigames": 2000, + "icon": "img/icons/play-svgrepo-com.svg", + "oneTimePurchase": true + }, + { + "id": "minigame_doge_rescue", + "type": "minigame", + "targetId": "doge_rescue", + "nameKey": "shop_minigame_doge_rescue_name", + "descKey": "shop_minigame_doge_rescue_desc", + "cost": 0, + "costCoins": 500, + "costMinigames": 4000, + "icon": "img/icons/play-svgrepo-com.svg", + "oneTimePurchase": true + }, + { + "id": "minigame_flappy_dunk", + "type": "minigame", + "targetId": "flappy_dunk", + "nameKey": "shop_minigame_flappy_dunk_name", + "descKey": "shop_minigame_flappy_dunk_desc", + "cost": 0, + "costCoins": 2000, + "costMinigames": 3000, + "icon": "img/icons/play-svgrepo-com.svg", + "oneTimePurchase": true + }, + { + "id": "minigame_helix_jump", + "type": "minigame", + "targetId": "helix_jump", + "nameKey": "shop_minigame_helix_jump_name", + "descKey": "shop_minigame_helix_jump_desc", + "cost": 0, + "costCoins": 1000, + "costMinigames": 4500, + "icon": "img/icons/play-svgrepo-com.svg", + "oneTimePurchase": true + }, + { + "id": "minigame_magic_sort", + "type": "minigame", + "targetId": "magic_sort", + "nameKey": "shop_minigame_magic_sort_name", + "descKey": "shop_minigame_magic_sort_desc", + "cost": 0, + "costCoins": 1000, + "costMinigames": 5000, + "icon": "img/icons/play-svgrepo-com.svg", + "oneTimePurchase": true + }, + { + "id": "minigame_mob_control", + "type": "minigame", + "targetId": "mob_control", + "nameKey": "shop_minigame_mob_control_name", + "descKey": "shop_minigame_mob_control_desc", + "cost": 0, + "costCoins": 1500, + "costMinigames": 3500, + "icon": "img/icons/play-svgrepo-com.svg", + "oneTimePurchase": true + }, + { + "id": "minigame_paper_io", + "type": "minigame", + "targetId": "paper_io", + "nameKey": "shop_minigame_paper_io_name", + "descKey": "shop_minigame_paper_io_desc", + "cost": 0, + "costCoins": 3000, + "costMinigames": 5000, + "icon": "img/icons/play-svgrepo-com.svg", + "oneTimePurchase": true + }, + { + "id": "minigame_spiral_roll", + "type": "minigame", + "targetId": "spiral_roll", + "nameKey": "shop_minigame_spiral_roll_name", + "descKey": "shop_minigame_spiral_roll_desc", + "cost": 0, + "costCoins": 1000, + "costMinigames": 4500, + "icon": "img/icons/play-svgrepo-com.svg", + "oneTimePurchase": true + }, + { + "id": "minigame_stack_colors", + "type": "minigame", + "targetId": "stack_colors", + "nameKey": "shop_minigame_stack_colors_name", + "descKey": "shop_minigame_stack_colors_desc", + "cost": 0, + "costCoins": 500, + "costMinigames": 2500, + "icon": "img/icons/play-svgrepo-com.svg", + "oneTimePurchase": true + } +] \ No newline at end of file diff --git a/public/data/sound_effects.json b/public/data/sound_effects.json new file mode 100644 index 0000000..3744054 --- /dev/null +++ b/public/data/sound_effects.json @@ -0,0 +1,94 @@ +[ + { + "id": "sfx_1", + "nameKey": "sfx_1", + "file": "sfx/hit.ogg", + "default": true, + "storageKey": "s1", + "description": "sfx_1_desc" + }, + { + "id": "sfx_2", + "nameKey": "sfx_2", + "file": "sfx/hurt-minecraft.ogg", + "storageKey": "s2", + "description": "sfx_2_desc" + }, + { + "id": "sfx_3", + "nameKey": "sfx_3", + "file": "sfx/hurt-roblox.ogg", + "storageKey": "s3", + "description": "sfx_3_desc" + }, + { + "id": "sfx_4", + "nameKey": "sfx_4", + "files": [ + "sfx/levelup1.ogg", + "sfx/levelup2.ogg" + ], + "storageKey": "s4", + "description": "sfx_4_desc" + }, + { + "id": "sfx_5", + "nameKey": "sfx_5", + "files": [ + "sfx/discord-connect.ogg", + "sfx/discord-disconnect.ogg", + "sfx/discord-msg.ogg" + ], + "storageKey": "s5", + "description": "sfx_5_desc" + }, + { + "id": "sfx_6", + "nameKey": "sfx_6", + "file": "sfx/hello.ogg", + "storageKey": "s6", + "description": "sfx_6_desc" + }, + { + "id": "sfx_7", + "nameKey": "sfx_7", + "file": "sfx/hit-minecraft.ogg", + "storageKey": "s7", + "description": "sfx_7_desc" + }, + { + "id": "sfx_8", + "nameKey": "sfx_8", + "file": "sfx/no.ogg", + "storageKey": "s8", + "description": "sfx_8_desc" + }, + { + "id": "sfx_9", + "nameKey": "sfx_9", + "file": "sfx/pato.ogg", + "storageKey": "s9", + "description": "sfx_9_desc" + }, + { + "id": "sfx_10", + "nameKey": "sfx_10", + "file": "sfx/peluche.ogg", + "storageKey": "s10", + "description": "sfx_10_desc" + }, + { + "id": "sfx_11", + "nameKey": "sfx_11", + "file": "sfx/splat.ogg", + "storageKey": "s11", + "description": "sfx_11_desc" + }, + { + "id": "sfx_12", + "nameKey": "sfx_12", + "file": "sfx/windows-error.ogg", + "storageKey": "s12", + "description": "sfx_12_desc" + } +] \ No newline at end of file diff --git a/public/games/attack_hole/assets/big_grenade_bomb.png b/public/games/attack_hole/assets/big_grenade_bomb.png new file mode 100644 index 0000000..108e6f9 Binary files /dev/null and b/public/games/attack_hole/assets/big_grenade_bomb.png differ diff --git a/public/games/attack_hole/assets/fire_grenade_bomb.png b/public/games/attack_hole/assets/fire_grenade_bomb.png new file mode 100644 index 0000000..fc1c00f Binary files /dev/null and b/public/games/attack_hole/assets/fire_grenade_bomb.png differ diff --git a/public/games/attack_hole/assets/flash_grenade_bomb.png b/public/games/attack_hole/assets/flash_grenade_bomb.png new file mode 100644 index 0000000..39cedfb Binary files /dev/null and b/public/games/attack_hole/assets/flash_grenade_bomb.png differ diff --git a/public/games/attack_hole/assets/grenade_bomb.png b/public/games/attack_hole/assets/grenade_bomb.png new file mode 100644 index 0000000..a3559d8 Binary files /dev/null and b/public/games/attack_hole/assets/grenade_bomb.png differ diff --git a/public/games/attack_hole/assets/gun_bullet.png b/public/games/attack_hole/assets/gun_bullet.png new file mode 100644 index 0000000..eb2d3c3 Binary files /dev/null and b/public/games/attack_hole/assets/gun_bullet.png differ diff --git a/public/games/attack_hole/assets/magnum_bullet.png b/public/games/attack_hole/assets/magnum_bullet.png new file mode 100644 index 0000000..8663fe8 Binary files /dev/null and b/public/games/attack_hole/assets/magnum_bullet.png differ diff --git a/public/games/attack_hole/assets/rocket_bullet.png b/public/games/attack_hole/assets/rocket_bullet.png new file mode 100644 index 0000000..232c7de Binary files /dev/null and b/public/games/attack_hole/assets/rocket_bullet.png differ diff --git a/public/games/attack_hole/assets/shotgun_bullet.png b/public/games/attack_hole/assets/shotgun_bullet.png new file mode 100644 index 0000000..1017d2e Binary files /dev/null and b/public/games/attack_hole/assets/shotgun_bullet.png differ diff --git a/public/games/attack_hole/assets/sniper_bullet.png b/public/games/attack_hole/assets/sniper_bullet.png new file mode 100644 index 0000000..2fbf131 Binary files /dev/null and b/public/games/attack_hole/assets/sniper_bullet.png differ diff --git a/public/games/attack_hole/assets/tmp_bullet.png b/public/games/attack_hole/assets/tmp_bullet.png new file mode 100644 index 0000000..5901c19 Binary files /dev/null and b/public/games/attack_hole/assets/tmp_bullet.png differ diff --git a/public/games/attack_hole/data/items.json b/public/games/attack_hole/data/items.json new file mode 100644 index 0000000..de3fc8f --- /dev/null +++ b/public/games/attack_hole/data/items.json @@ -0,0 +1,82 @@ +[ + { + "id": "gun", + "emojiCounter": "🔫", + "model": "games/attack_hole/data/models/gun.geo.json", + "texture": "games/attack_hole/assets/gun_bullet.png", + "points": 10, + "category": "ammo" + }, + { + "id": "magnum", + "emojiCounter": "🤠", + "model": "games/attack_hole/data/models/magnum.geo.json", + "texture": "games/attack_hole/assets/magnum_bullet.png", + "points": 50, + "category": "ammo" + }, + { + "id": "tmp", + "emojiCounter": "🪖", + "model": "games/attack_hole/data/models/tmp.geo.json", + "texture": "games/attack_hole/assets/tmp_bullet.png", + "points": 5, + "category": "ammo" + }, + { + "id": "shotgun", + "emojiCounter": "🪤", + "model": "games/attack_hole/data/models/shotgun.geo.json", + "texture": "games/attack_hole/assets/shotgun_bullet.png", + "points": 25, + "category": "ammo" + }, + { + "id": "sniper", + "emojiCounter": "🎯", + "model": "games/attack_hole/data/models/sniper.geo.json", + "texture": "games/attack_hole/assets/sniper_bullet.png", + "points": 35, + "category": "ammo" + }, + { + "id": "rocket", + "emojiCounter": "🚀", + "model": "games/attack_hole/data/models/rocket.geo.json", + "texture": "games/attack_hole/assets/rocket_bullet.png", + "points": 100, + "category": "ammo" + }, + { + "id": "grenade", + "emojiCounter": "💣", + "model": "games/attack_hole/data/models/grenade.geo.json", + "texture": "games/attack_hole/assets/grenade_bomb.png", + "points": 60, + "category": "bomb" + }, + { + "id": "flash_grenade", + "emojiCounter": "⚡", + "model": "games/attack_hole/data/models/flash_grenade.geo.json", + "texture": "games/attack_hole/assets/flash_grenade_bomb.png", + "points": 50, + "category": "bomb" + }, + { + "id": "fire_grenade", + "emojiCounter": "🔥", + "model": "games/attack_hole/data/models/fire_grenade.geo.json", + "texture": "games/attack_hole/assets/fire_grenade_bomb.png", + "points": 70, + "category": "bomb" + }, + { + "id": "big_grenade", + "emojiCounter": "💥", + "model": "games/attack_hole/data/models/big_grenade.geo.json", + "texture": "games/attack_hole/assets/big_grenade_bomb.png", + "points": 150, + "category": "bomb" + } +] diff --git a/public/games/attack_hole/data/levels.json b/public/games/attack_hole/data/levels.json new file mode 100644 index 0000000..986bc46 --- /dev/null +++ b/public/games/attack_hole/data/levels.json @@ -0,0 +1,380 @@ +[ + { + "id": "level_1", + "time": 40, + "HoleSizeIncreasePercentage": 100, + "floorSize": 100, + "ammoGrouping": "grouped", + "floorPrimaryColor": "rgba(224, 224, 224, 1)", + "floorSecondaryColor": "rgba(180, 180, 180, 1)", + "floorPattern": "squares", + "wallPrimaryColor": "rgba(255, 255, 255, 1)", + "wallSecondaryColor": "rgba(200, 200, 200, 1)", + "wallPattern": "none", + "wallLife": 1000, + "ammo": { + "gun": [60, 80], + "tmp": [100, 120] + } + }, + { + "id": "level_2", + "time": 45, + "HoleSizeIncreasePercentage": 120, + "floorSize": 120, + "ammoGrouping": "near", + "floorPrimaryColor": "rgba(50, 150, 50, 1)", + "floorSecondaryColor": "rgba(30, 100, 30, 1)", + "floorPattern": "triangles", + "wallPrimaryColor": "rgba(100, 50, 50, 1)", + "wallSecondaryColor": "rgba(50, 20, 20, 1)", + "wallPattern": "squares", + "wallLife": 1500, + "ammo": { + "gun": [50, 70], + "shotgun": [50, 70] + } + }, + { + "id": "level_3", + "time": 50, + "HoleSizeIncreasePercentage": 140, + "floorSize": 140, + "ammoGrouping": "random", + "floorPrimaryColor": "rgba(10, 20, 40, 1)", + "floorSecondaryColor": "rgba(5, 10, 20, 1)", + "floorPattern": "pentagons", + "wallPrimaryColor": "rgba(40, 40, 40, 1)", + "wallSecondaryColor": "rgba(20, 20, 20, 1)", + "wallPattern": "hexagons", + "wallLife": 2500, + "ammo": { + "tmp": [100, 150], + "shotgun": [40, 60], + "magnum": [25, 40] + } + }, + { + "id": "level_4", + "time": 55, + "HoleSizeIncreasePercentage": 160, + "floorSize": 160, + "ammoGrouping": "grouped", + "floorPrimaryColor": "rgba(80, 0, 0, 1)", + "floorSecondaryColor": "rgba(40, 0, 0, 1)", + "floorPattern": "none", + "wallPrimaryColor": "rgba(120, 20, 20, 1)", + "wallSecondaryColor": "rgba(60, 10, 10, 1)", + "wallPattern": "stars", + "wallLife": 3500, + "ammo": { + "gun": [100, 150], + "sniper": [40, 60], + "magnum": [30, 50] + } + }, + { + "id": "level_5", + "time": 60, + "HoleSizeIncreasePercentage": 180, + "floorSize": 180, + "ammoGrouping": "near", + "floorPrimaryColor": "rgba(150, 150, 50, 1)", + "floorSecondaryColor": "rgba(100, 100, 30, 1)", + "floorPattern": "hexagons", + "wallPrimaryColor": "rgba(80, 80, 80, 1)", + "wallSecondaryColor": "rgba(40, 40, 40, 1)", + "wallPattern": "none", + "wallLife": 5000, + "ammo": { + "shotgun": [50, 80], + "sniper": [50, 70], + "flash_grenade": [45, 60] + } + }, + { + "id": "level_6", + "time": 65, + "HoleSizeIncreasePercentage": 200, + "floorSize": 200, + "ammoGrouping": "random", + "floorPrimaryColor": "rgba(30, 30, 30, 1)", + "floorSecondaryColor": "rgba(15, 15, 15, 1)", + "floorPattern": "squares", + "wallPrimaryColor": "rgba(200, 200, 200, 1)", + "wallSecondaryColor": "rgba(150, 150, 150, 1)", + "wallPattern": "triangles", + "wallLife": 6500, + "ammo": { + "magnum": [50, 70], + "grenade": [40, 60], + "shotgun": [70, 90] + } + }, + { + "id": "level_7", + "time": 70, + "HoleSizeIncreasePercentage": 220, + "floorSize": 250, + "ammoGrouping": "grouped", + "floorPrimaryColor": "rgba(0, 100, 150, 1)", + "floorSecondaryColor": "rgba(0, 50, 80, 1)", + "floorPattern": "stars", + "wallPrimaryColor": "rgba(0, 150, 200, 1)", + "wallSecondaryColor": "rgba(0, 80, 120, 1)", + "wallPattern": "pentagons", + "wallLife": 8000, + "ammo": { + "sniper": [60, 80], + "fire_grenade": [50, 70], + "grenade": [50, 70] + } + }, + { + "id": "level_8", + "time": 75, + "HoleSizeIncreasePercentage": 250, + "floorSize": 300, + "ammoGrouping": "near", + "floorPrimaryColor": "rgba(60, 20, 80, 1)", + "floorSecondaryColor": "rgba(30, 10, 40, 1)", + "floorPattern": "none", + "wallPrimaryColor": "rgba(100, 40, 120, 1)", + "wallSecondaryColor": "rgba(50, 20, 60, 1)", + "wallPattern": "squares", + "wallLife": 10000, + "ammo": { + "rocket": [30, 40], + "big_grenade": [30, 40], + "magnum": [60, 80] + } + }, + { + "id": "level_9", + "time": 80, + "HoleSizeIncreasePercentage": 280, + "floorSize": 350, + "ammoGrouping": "random", + "floorPrimaryColor": "rgba(200, 100, 0, 1)", + "floorSecondaryColor": "rgba(120, 60, 0, 1)", + "floorPattern": "pentagons", + "wallPrimaryColor": "rgba(255, 150, 0, 1)", + "wallSecondaryColor": "rgba(180, 90, 0, 1)", + "wallPattern": "none", + "wallLife": 12000, + "ammo": { + "big_grenade": [40, 60], + "fire_grenade": [60, 80], + "sniper": [60, 80] + } + }, + { + "id": "level_10", + "time": 85, + "HoleSizeIncreasePercentage": 310, + "floorSize": 400, + "ammoGrouping": "grouped", + "floorPrimaryColor": "rgba(0, 0, 0, 1)", + "floorSecondaryColor": "rgba(20, 0, 0, 1)", + "floorPattern": "hexagons", + "wallPrimaryColor": "rgba(50, 0, 0, 1)", + "wallSecondaryColor": "rgba(25, 0, 0, 1)", + "wallPattern": "triangles", + "wallLife": 15000, + "ammo": { + "rocket": [50, 70], + "big_grenade": [50, 70], + "magnum": [60, 80] + } + }, + { + "id": "level_11", + "time": 90, + "HoleSizeIncreasePercentage": 340, + "floorSize": 450, + "ammoGrouping": "near", + "floorPrimaryColor": "rgba(40, 120, 40, 1)", + "floorSecondaryColor": "rgba(20, 60, 20, 1)", + "floorPattern": "squares", + "wallPrimaryColor": "rgba(60, 180, 60, 1)", + "wallSecondaryColor": "rgba(30, 90, 30, 1)", + "wallPattern": "stars", + "wallLife": 18000, + "ammo": { + "rocket": [60, 80], + "big_grenade": [60, 80], + "fire_grenade": [50, 70] + } + }, + { + "id": "level_12", + "time": 95, + "HoleSizeIncreasePercentage": 370, + "floorSize": 500, + "ammoGrouping": "random", + "floorPrimaryColor": "rgba(100, 100, 200, 1)", + "floorSecondaryColor": "rgba(50, 50, 100, 1)", + "floorPattern": "none", + "wallPrimaryColor": "rgba(150, 150, 255, 1)", + "wallSecondaryColor": "rgba(75, 75, 125, 1)", + "wallPattern": "pentagons", + "wallLife": 22000, + "ammo": { + "rocket": [80, 100], + "big_grenade": [80, 100], + "sniper": [70, 90] + } + }, + { + "id": "level_13", + "time": 100, + "HoleSizeIncreasePercentage": 400, + "floorSize": 550, + "ammoGrouping": "grouped", + "floorPrimaryColor": "rgba(180, 180, 180, 1)", + "floorSecondaryColor": "rgba(90, 90, 90, 1)", + "floorPattern": "squares", + "wallPrimaryColor": "rgba(220, 220, 220, 1)", + "wallSecondaryColor": "rgba(110, 110, 110, 1)", + "wallPattern": "none", + "wallLife": 26000, + "ammo": { + "rocket": [100, 120], + "big_grenade": [90, 110], + "fire_grenade": [50, 70] + } + }, + { + "id": "level_14", + "time": 105, + "HoleSizeIncreasePercentage": 450, + "floorSize": 600, + "ammoGrouping": "near", + "floorPrimaryColor": "rgba(120, 0, 120, 1)", + "floorSecondaryColor": "rgba(60, 0, 60, 1)", + "floorPattern": "hexagons", + "wallPrimaryColor": "rgba(180, 0, 180, 1)", + "wallSecondaryColor": "rgba(90, 0, 90, 1)", + "wallPattern": "squares", + "wallLife": 30000, + "ammo": { + "big_grenade": [110, 130], + "rocket": [110, 130], + "magnum": [60, 80] + } + }, + { + "id": "level_15", + "time": 110, + "HoleSizeIncreasePercentage": 500, + "floorSize": 650, + "ammoGrouping": "random", + "floorPrimaryColor": "rgba(255, 200, 0, 1)", + "floorSecondaryColor": "rgba(150, 120, 0, 1)", + "floorPattern": "stars", + "wallPrimaryColor": "rgba(255, 255, 0, 1)", + "wallSecondaryColor": "rgba(180, 180, 0, 1)", + "wallPattern": "triangles", + "wallLife": 35000, + "ammo": { + "big_grenade": [130, 150], + "rocket": [120, 140], + "fire_grenade": [60, 80] + } + }, + { + "id": "level_16", + "time": 115, + "HoleSizeIncreasePercentage": 550, + "floorSize": 700, + "ammoGrouping": "grouped", + "floorPrimaryColor": "rgba(0, 150, 100, 1)", + "floorSecondaryColor": "rgba(0, 80, 50, 1)", + "floorPattern": "pentagons", + "wallPrimaryColor": "rgba(0, 200, 150, 1)", + "wallSecondaryColor": "rgba(0, 100, 75, 1)", + "wallPattern": "hexagons", + "wallLife": 40000, + "ammo": { + "big_grenade": [150, 170], + "rocket": [140, 160], + "grenade": [70, 90] + } + }, + { + "id": "level_17", + "time": 120, + "HoleSizeIncreasePercentage": 600, + "floorSize": 800, + "ammoGrouping": "near", + "floorPrimaryColor": "rgba(80, 80, 120, 1)", + "floorSecondaryColor": "rgba(40, 40, 60, 1)", + "floorPattern": "none", + "wallPrimaryColor": "rgba(100, 100, 150, 1)", + "wallSecondaryColor": "rgba(50, 50, 75, 1)", + "wallPattern": "stars", + "wallLife": 45000, + "ammo": { + "big_grenade": [170, 190], + "rocket": [160, 180], + "fire_grenade": [60, 80] + } + }, + { + "id": "level_18", + "time": 130, + "HoleSizeIncreasePercentage": 700, + "floorSize": 900, + "ammoGrouping": "random", + "floorPrimaryColor": "rgba(180, 50, 50, 1)", + "floorSecondaryColor": "rgba(90, 25, 25, 1)", + "floorPattern": "triangles", + "wallPrimaryColor": "rgba(220, 80, 80, 1)", + "wallSecondaryColor": "rgba(110, 40, 40, 1)", + "wallPattern": "none", + "wallLife": 50000, + "ammo": { + "big_grenade": [200, 220], + "rocket": [170, 190], + "flash_grenade": [80, 100] + } + }, + { + "id": "level_19", + "time": 140, + "HoleSizeIncreasePercentage": 800, + "floorSize": 1000, + "ammoGrouping": "grouped", + "floorPrimaryColor": "rgba(40, 40, 40, 1)", + "floorSecondaryColor": "rgba(20, 20, 20, 1)", + "floorPattern": "hexagons", + "wallPrimaryColor": "rgba(255, 255, 255, 1)", + "wallSecondaryColor": "rgba(150, 150, 150, 1)", + "wallPattern": "squares", + "wallLife": 55000, + "ammo": { + "big_grenade": [220, 240], + "rocket": [180, 200], + "fire_grenade": [70, 90] + } + }, + { + "id": "level_20", + "time": 150, + "HoleSizeIncreasePercentage": 1000, + "floorSize": 1200, + "ammoGrouping": "near", + "floorPrimaryColor": "rgba(255, 0, 0, 1)", + "floorSecondaryColor": "rgba(100, 0, 0, 1)", + "floorPattern": "stars", + "wallPrimaryColor": "rgba(0, 0, 0, 1)", + "wallSecondaryColor": "rgba(30, 30, 30, 1)", + "wallPattern": "none", + "wallLife": 60000, + "ammo": { + "big_grenade": [250, 280], + "rocket": [200, 220], + "fire_grenade": [50, 70] + } + } +] \ No newline at end of file diff --git a/public/games/attack_hole/data/models/big_grenade.geo.json b/public/games/attack_hole/data/models/big_grenade.geo.json new file mode 100644 index 0000000..8538745 --- /dev/null +++ b/public/games/attack_hole/data/models/big_grenade.geo.json @@ -0,0 +1,59 @@ +{ + "format_version": "1.12.0", + "minecraft:geometry": [ + { + "description": { + "identifier": "geometry.big_grenade", + "texture_width": 32, + "texture_height": 32, + "visible_bounds_width": 2, + "visible_bounds_height": 2.5, + "visible_bounds_offset": [0, 0.75, 0] + }, + "bones": [ + { + "name": "bb_main", + "pivot": [0, 0, 0], + "cubes": [ + { + "origin": [-3, 0, -3], + "size": [6, 7, 6], + "uv": { + "north": {"uv": [0, 7], "uv_size": [6, 7]}, + "east": {"uv": [6, 0], "uv_size": [6, 7]}, + "south": {"uv": [6, 7], "uv_size": [6, 7]}, + "west": {"uv": [0, 0], "uv_size": [6, 7]}, + "up": {"uv": [12, 0], "uv_size": [6, 6]}, + "down": {"uv": [12, 12], "uv_size": [6, -6]} + } + }, + { + "origin": [-1.5, 7, -1.5], + "size": [3, 2, 3], + "uv": { + "north": {"uv": [3, 17], "uv_size": [3, 2]}, + "east": {"uv": [6, 16], "uv_size": [3, 2]}, + "south": {"uv": [6, 14], "uv_size": [3, 2]}, + "west": {"uv": [0, 17], "uv_size": [3, 2]}, + "up": {"uv": [0, 14], "uv_size": [3, 3]}, + "down": {"uv": [3, 17], "uv_size": [3, -3]} + } + }, + { + "origin": [-1.5, 8, -2.5], + "size": [1, 4, 2], + "uv": { + "north": {"uv": [12, 12], "uv_size": [1, 4]}, + "east": {"uv": [13, 12], "uv_size": [2, 4]}, + "south": {"uv": [9, 14], "uv_size": [1, 4]}, + "west": {"uv": [10, 17], "uv_size": [2, 4]}, + "up": {"uv": [16, 12], "uv_size": [1, 2]}, + "down": {"uv": [17, 14], "uv_size": [1, -2]} + } + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/public/games/attack_hole/data/models/fire_grenade.geo.json b/public/games/attack_hole/data/models/fire_grenade.geo.json new file mode 100644 index 0000000..a3fc1ba --- /dev/null +++ b/public/games/attack_hole/data/models/fire_grenade.geo.json @@ -0,0 +1,59 @@ +{ + "format_version": "1.12.0", + "minecraft:geometry": [ + { + "description": { + "identifier": "geometry.fire_grenade", + "texture_width": 32, + "texture_height": 32, + "visible_bounds_width": 2, + "visible_bounds_height": 2.5, + "visible_bounds_offset": [0, 0.75, 0] + }, + "bones": [ + { + "name": "bb_main", + "pivot": [0, 0, 0], + "cubes": [ + { + "origin": [-2, 0, -2], + "size": [4, 2, 4], + "uv": { + "north": {"uv": [28, 6], "uv_size": [4, 2]}, + "east": {"uv": [24, 4], "uv_size": [4, 2]}, + "south": {"uv": [28, 4], "uv_size": [4, 2]}, + "west": {"uv": [24, 6], "uv_size": [4, 2]}, + "up": {"uv": [28, 0], "uv_size": [4, 4]}, + "down": {"uv": [24, 4], "uv_size": [4, -4]} + } + }, + { + "origin": [-2.5, 2, -2.5], + "size": [5, 5, 5], + "uv": { + "north": {"uv": [6, 6], "uv_size": [6, 6]}, + "east": {"uv": [0, 6], "uv_size": [6, 6]}, + "south": {"uv": [12, 0], "uv_size": [6, 6]}, + "west": {"uv": [12, 6], "uv_size": [6, 6]}, + "up": {"uv": [0, 0], "uv_size": [5.8, 5.8]}, + "down": {"uv": [6, 6], "uv_size": [6, -6]} + } + }, + { + "origin": [-1, 7, -1], + "size": [2, 2, 2], + "uv": { + "north": {"uv": [2, 17], "uv_size": [2, 2]}, + "east": {"uv": [4, 17], "uv_size": [2, 2]}, + "south": {"uv": [6, 17], "uv_size": [2, 2]}, + "west": {"uv": [0, 17], "uv_size": [2, 2]}, + "up": {"uv": [2, 15], "uv_size": [2, 2]}, + "down": {"uv": [0, 17], "uv_size": [2, -2]} + } + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/public/games/attack_hole/data/models/flash_grenade.geo.json b/public/games/attack_hole/data/models/flash_grenade.geo.json new file mode 100644 index 0000000..dac814d --- /dev/null +++ b/public/games/attack_hole/data/models/flash_grenade.geo.json @@ -0,0 +1,59 @@ +{ + "format_version": "1.12.0", + "minecraft:geometry": [ + { + "description": { + "identifier": "geometry.flash_grenade", + "texture_width": 32, + "texture_height": 32, + "visible_bounds_width": 2, + "visible_bounds_height": 2.5, + "visible_bounds_offset": [0, 0.75, 0] + }, + "bones": [ + { + "name": "bb_main", + "pivot": [0, 0, 0], + "cubes": [ + { + "origin": [-2, 0, -2], + "size": [4, 8, 4], + "uv": { + "north": {"uv": [4, 0], "uv_size": [4, 10]}, + "east": {"uv": [8, 0], "uv_size": [4, 10]}, + "south": {"uv": [12, 0], "uv_size": [4, 10]}, + "west": {"uv": [0, 0], "uv_size": [4, 10]}, + "up": {"uv": [20, 0], "uv_size": [4, 4]}, + "down": {"uv": [16, 4], "uv_size": [4, -4]} + } + }, + { + "origin": [-1, 8, -1], + "size": [2, 1, 2], + "uv": { + "north": {"uv": [2, 12], "uv_size": [2, 1]}, + "east": {"uv": [4, 12], "uv_size": [2, 1]}, + "south": {"uv": [6, 13], "uv_size": [2, -1]}, + "west": {"uv": [0, 12], "uv_size": [2, 1]}, + "up": {"uv": [2, 10], "uv_size": [2, 2]}, + "down": {"uv": [0, 12], "uv_size": [2, -2]} + } + }, + { + "origin": [-1, 9, -2.5], + "size": [1, 3, 1], + "uv": { + "north": {"uv": [1, 16], "uv_size": [1, 3]}, + "east": {"uv": [2, 16], "uv_size": [1, 3]}, + "south": {"uv": [3, 16], "uv_size": [1, 3]}, + "west": {"uv": [0, 16], "uv_size": [1, 3]}, + "up": {"uv": [1, 15], "uv_size": [1, 1]}, + "down": {"uv": [2, 16], "uv_size": [1, -1]} + } + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/public/games/attack_hole/data/models/grenade.geo.json b/public/games/attack_hole/data/models/grenade.geo.json new file mode 100644 index 0000000..698fcdf --- /dev/null +++ b/public/games/attack_hole/data/models/grenade.geo.json @@ -0,0 +1,59 @@ +{ + "format_version": "1.12.0", + "minecraft:geometry": [ + { + "description": { + "identifier": "geometry.grenade", + "texture_width": 32, + "texture_height": 32, + "visible_bounds_width": 2, + "visible_bounds_height": 2.5, + "visible_bounds_offset": [0, 0.75, 0] + }, + "bones": [ + { + "name": "bb_main", + "pivot": [0, 0, 0], + "cubes": [ + { + "origin": [-2, 0, -2], + "size": [4, 5, 4], + "uv": { + "north": {"uv": [4, 0], "uv_size": [4, 6]}, + "east": {"uv": [8, 0], "uv_size": [4, 6]}, + "south": {"uv": [12, 0], "uv_size": [4, 6]}, + "west": {"uv": [0, 0], "uv_size": [4, 6]}, + "up": {"uv": [4, 6], "uv_size": [4, 4]}, + "down": {"uv": [0, 10], "uv_size": [4, -4]} + } + }, + { + "origin": [-1, 5, -1], + "size": [2, 1, 2], + "uv": { + "north": {"uv": [4, 20], "uv_size": [2, 1]}, + "east": {"uv": [0, 20], "uv_size": [2, 1]}, + "south": {"uv": [6, 20], "uv_size": [2, 1]}, + "west": {"uv": [2, 20], "uv_size": [2, 1]}, + "up": {"uv": [0, 21], "uv_size": [2, 2]}, + "down": {"uv": [2, 23], "uv_size": [2, -2]} + } + }, + { + "origin": [-1, 5, -2], + "size": [1, 3, 1], + "uv": { + "north": {"uv": [11, 20], "uv_size": [1, 3]}, + "east": {"uv": [10, 20], "uv_size": [1, 3]}, + "south": {"uv": [9, 20], "uv_size": [1, 3]}, + "west": {"uv": [12, 20], "uv_size": [1, 3]}, + "up": {"uv": [14, 20], "uv_size": [1, 1]}, + "down": {"uv": [13, 21], "uv_size": [1, -1]} + } + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/public/games/attack_hole/data/models/gun.geo.json b/public/games/attack_hole/data/models/gun.geo.json new file mode 100644 index 0000000..9156c69 --- /dev/null +++ b/public/games/attack_hole/data/models/gun.geo.json @@ -0,0 +1,47 @@ +{ + "format_version": "1.12.0", + "minecraft:geometry": [ + { + "description": { + "identifier": "geometry.bullet_gun", + "texture_width": 16, + "texture_height": 16, + "visible_bounds_width": 2, + "visible_bounds_height": 2.5, + "visible_bounds_offset": [0, 0.75, 0] + }, + "bones": [ + { + "name": "bb_main", + "pivot": [0, 0, 0], + "cubes": [ + { + "origin": [-1, 0, -1], + "size": [2, 3, 2], + "uv": { + "north": {"uv": [0, 0], "uv_size": [2, 3]}, + "east": {"uv": [2, 0], "uv_size": [2, 3]}, + "south": {"uv": [0, 3], "uv_size": [2, 3]}, + "west": {"uv": [2, 3], "uv_size": [2, 3]}, + "up": {"uv": [4, 0], "uv_size": [2, 2]}, + "down": {"uv": [4, 4], "uv_size": [2, -2]} + } + }, + { + "origin": [-0.75, 3, -0.75], + "size": [1.5, 2, 1.5], + "uv": { + "north": {"uv": [4, 4], "uv_size": [2, 2]}, + "east": {"uv": [0, 6], "uv_size": [2, 2]}, + "south": {"uv": [6, 0], "uv_size": [2, 2]}, + "west": {"uv": [2, 6], "uv_size": [2, 2]}, + "up": {"uv": [6, 2], "uv_size": [2, 2]}, + "down": {"uv": [4, 8], "uv_size": [2, -2]} + } + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/public/games/attack_hole/data/models/magnum.geo.json b/public/games/attack_hole/data/models/magnum.geo.json new file mode 100644 index 0000000..e3ccaeb --- /dev/null +++ b/public/games/attack_hole/data/models/magnum.geo.json @@ -0,0 +1,47 @@ +{ + "format_version": "1.12.0", + "minecraft:geometry": [ + { + "description": { + "identifier": "geometry.bullet_magnum", + "texture_width": 16, + "texture_height": 16, + "visible_bounds_width": 2, + "visible_bounds_height": 2.5, + "visible_bounds_offset": [0, 0.75, 0] + }, + "bones": [ + { + "name": "bb_main", + "pivot": [0.41667, 5, 0.41667], + "cubes": [ + { + "origin": [-1.5, 0, -1.5], + "size": [3, 4, 3], + "uv": { + "north": {"uv": [0, 0], "uv_size": [3, 4]}, + "east": {"uv": [3, 0], "uv_size": [3, 4]}, + "south": {"uv": [0, 4], "uv_size": [3, 4]}, + "west": {"uv": [3, 4], "uv_size": [3, 4]}, + "up": {"uv": [6, 0], "uv_size": [3, 3]}, + "down": {"uv": [6, 6], "uv_size": [3, -3]} + } + }, + { + "origin": [-1.25, 4, -1.25], + "size": [2.5, 2, 2.5], + "uv": { + "north": {"uv": [3, 8], "uv_size": [3, 2]}, + "east": {"uv": [9, 0], "uv_size": [3, 2]}, + "south": {"uv": [9, 2], "uv_size": [3, 2]}, + "west": {"uv": [9, 4], "uv_size": [3, 2]}, + "up": {"uv": [6, 6], "uv_size": [3, 3]}, + "down": {"uv": [0, 11], "uv_size": [3, -3]} + } + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/public/games/attack_hole/data/models/rocket.geo.json b/public/games/attack_hole/data/models/rocket.geo.json new file mode 100644 index 0000000..157410f --- /dev/null +++ b/public/games/attack_hole/data/models/rocket.geo.json @@ -0,0 +1,95 @@ +{ + "format_version": "1.12.0", + "minecraft:geometry": [ + { + "description": { + "identifier": "geometry.rocket", + "texture_width": 32, + "texture_height": 32, + "visible_bounds_width": 2, + "visible_bounds_height": 2.5, + "visible_bounds_offset": [0, 0.75, 0] + }, + "bones": [ + { + "name": "bb_main", + "pivot": [0, 0, 0], + "cubes": [ + { + "origin": [-1, 0, -1], + "size": [2, 3, 2], + "uv": { + "north": {"uv": [24, 16], "uv_size": [2, 3]}, + "east": {"uv": [22, 16], "uv_size": [2, 3]}, + "south": {"uv": [20, 16], "uv_size": [2, 3]}, + "west": {"uv": [26, 16], "uv_size": [2, 3]}, + "up": {"uv": [20, 19], "uv_size": [2, 2]}, + "down": {"uv": [22, 21], "uv_size": [2, -2]} + } + }, + { + "origin": [-2.5, 0, -0.5], + "size": [5, 3, 1], + "uv": { + "north": {"uv": [5, 16], "uv_size": [5, 3]}, + "east": {"uv": [1, 19], "uv_size": [1, 3]}, + "south": {"uv": [0, 16], "uv_size": [5, 3]}, + "west": {"uv": [0, 19], "uv_size": [1, 3]}, + "up": {"uv": [2, 19], "uv_size": [5, 1]}, + "down": {"uv": [2, 21], "uv_size": [5, -1]} + } + }, + { + "origin": [-0.5, 0, -2.5], + "size": [1, 3, 5], + "uv": { + "north": {"uv": [11, 19], "uv_size": [1, 3]}, + "east": {"uv": [10, 16], "uv_size": [5, 3]}, + "south": {"uv": [10, 19], "uv_size": [1, 3]}, + "west": {"uv": [15, 16], "uv_size": [5, 3]}, + "up": {"uv": [12, 19], "uv_size": [1, 5]}, + "down": {"uv": [13, 24], "uv_size": [1, -5]} + } + }, + { + "origin": [-1.5, 3, -1.5], + "size": [3, 10, 3], + "uv": { + "north": {"uv": [3, 0], "uv_size": [3, 10]}, + "east": {"uv": [6, 0], "uv_size": [3, 10]}, + "south": {"uv": [9, 0], "uv_size": [3, 10]}, + "west": {"uv": [0, 0], "uv_size": [3, 10]}, + "up": {"uv": [0, 10], "uv_size": [3, 3]}, + "down": {"uv": [3, 13], "uv_size": [3, -3]} + } + }, + { + "origin": [-1, 13, -1], + "size": [2, 3, 2], + "uv": { + "north": {"uv": [13, 0], "uv_size": [2, 3]}, + "east": {"uv": [15, 0], "uv_size": [2, 3]}, + "south": {"uv": [17, 0], "uv_size": [2, 3]}, + "west": {"uv": [19, 0], "uv_size": [2, 3]}, + "up": {"uv": [15, 3], "uv_size": [2, 2]}, + "down": {"uv": [13, 5], "uv_size": [2, -2]} + } + }, + { + "origin": [-0.5, 16, -0.5], + "size": [1, 2, 1], + "uv": { + "north": {"uv": [26, 0], "uv_size": [1, 2]}, + "east": {"uv": [25, 0], "uv_size": [1, 2]}, + "south": {"uv": [24, 0], "uv_size": [1, 2]}, + "west": {"uv": [23, 0], "uv_size": [1, 2]}, + "up": {"uv": [28, 0], "uv_size": [1, 1]}, + "down": {"uv": [27, 1], "uv_size": [1, -1]} + } + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/public/games/attack_hole/data/models/shotgun.geo.json b/public/games/attack_hole/data/models/shotgun.geo.json new file mode 100644 index 0000000..d4b5475 --- /dev/null +++ b/public/games/attack_hole/data/models/shotgun.geo.json @@ -0,0 +1,47 @@ +{ + "format_version": "1.12.0", + "minecraft:geometry": [ + { + "description": { + "identifier": "geometry.bullet_shotgun", + "texture_width": 16, + "texture_height": 16, + "visible_bounds_width": 2, + "visible_bounds_height": 2.5, + "visible_bounds_offset": [0, 0.75, 0] + }, + "bones": [ + { + "name": "bb_main", + "pivot": [0, 3, 0], + "cubes": [ + { + "origin": [-2, 0, -2], + "size": [4, 2, 4], + "uv": { + "north": {"uv": [9, 3], "uv_size": [3, 2]}, + "east": {"uv": [9, 5], "uv_size": [3, 2]}, + "south": {"uv": [6, 9], "uv_size": [3, 2]}, + "west": {"uv": [9, 7], "uv_size": [3, 2]}, + "up": {"uv": [6, 0], "uv_size": [3, 3]}, + "down": {"uv": [6, 6], "uv_size": [3, -3]} + } + }, + { + "origin": [-1.5, 2, -1.5], + "size": [3, 6, 3], + "uv": { + "north": {"uv": [0, 0], "uv_size": [3, 5]}, + "east": {"uv": [3, 0], "uv_size": [3, 5]}, + "south": {"uv": [0, 5], "uv_size": [3, 5]}, + "west": {"uv": [3, 5], "uv_size": [3, 5]}, + "up": {"uv": [6, 6], "uv_size": [3, 3]}, + "down": {"uv": [9, 3], "uv_size": [3, -3]} + } + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/public/games/attack_hole/data/models/sniper.geo.json b/public/games/attack_hole/data/models/sniper.geo.json new file mode 100644 index 0000000..0710ff5 --- /dev/null +++ b/public/games/attack_hole/data/models/sniper.geo.json @@ -0,0 +1,47 @@ +{ + "format_version": "1.12.0", + "minecraft:geometry": [ + { + "description": { + "identifier": "geometry.bullet_sniper", + "texture_width": 16, + "texture_height": 16, + "visible_bounds_width": 2, + "visible_bounds_height": 2.5, + "visible_bounds_offset": [0, 0.75, 0] + }, + "bones": [ + { + "name": "bb_main", + "pivot": [0, 0, 0], + "cubes": [ + { + "origin": [-1, 0, -1], + "size": [2, 6, 2], + "uv": { + "north": {"uv": [0, 0], "uv_size": [2, 6]}, + "east": {"uv": [2, 0], "uv_size": [2, 6]}, + "south": {"uv": [4, 0], "uv_size": [2, 6]}, + "west": {"uv": [6, 0], "uv_size": [2, 6]}, + "up": {"uv": [0, 8], "uv_size": [2, 2]}, + "down": {"uv": [0, 12], "uv_size": [2, -2]} + } + }, + { + "origin": [-0.5, 6, -0.5], + "size": [1, 3, 1], + "uv": { + "north": {"uv": [4, 6], "uv_size": [1, 3]}, + "east": {"uv": [5, 6], "uv_size": [1, 3]}, + "south": {"uv": [6, 6], "uv_size": [1, 3]}, + "west": {"uv": [3, 6], "uv_size": [1, 3]}, + "up": {"uv": [2, 7], "uv_size": [1, 1]}, + "down": {"uv": [2, 7], "uv_size": [1, -1]} + } + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/public/games/attack_hole/data/models/tmp.geo.json b/public/games/attack_hole/data/models/tmp.geo.json new file mode 100644 index 0000000..79f17ed --- /dev/null +++ b/public/games/attack_hole/data/models/tmp.geo.json @@ -0,0 +1,47 @@ +{ + "format_version": "1.12.0", + "minecraft:geometry": [ + { + "description": { + "identifier": "geometry.bullet_tmp", + "texture_width": 16, + "texture_height": 16, + "visible_bounds_width": 2, + "visible_bounds_height": 2.5, + "visible_bounds_offset": [0, 0.75, 0] + }, + "bones": [ + { + "name": "bb_main", + "pivot": [0, 0, 0], + "cubes": [ + { + "origin": [-0.75, 0, -0.75], + "size": [1.5, 4, 1.5], + "uv": { + "north": {"uv": [0, 0], "uv_size": [1.5, 4]}, + "east": {"uv": [3, 0], "uv_size": [1.5, 4]}, + "south": {"uv": [1.5, 0], "uv_size": [1.5, 4]}, + "west": {"uv": [4.5, 0], "uv_size": [1.5, 4]}, + "up": {"uv": [0, 5], "uv_size": [1.5, 1.5]}, + "down": {"uv": [0, 8], "uv_size": [1.5, -1.5]} + } + }, + { + "origin": [-0.75, 4, -0.75], + "size": [1.5, 1.5, 1.5], + "uv": { + "north": {"uv": [6, 3], "uv_size": [1.5, 1.5]}, + "east": {"uv": [6, 4.5], "uv_size": [1.5, 1.5]}, + "south": {"uv": [6, 1.5], "uv_size": [1.5, 1.5]}, + "west": {"uv": [6, 0], "uv_size": [1.5, 1.5]}, + "up": {"uv": [3.5, 6], "uv_size": [1.5, 1.5]}, + "down": {"uv": [2, 7.5], "uv_size": [1.5, -1.5]} + } + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/public/games/block_breaker/assets/blocks/amethyst_block.png b/public/games/block_breaker/assets/blocks/amethyst_block.png new file mode 100644 index 0000000..4e3e8b1 Binary files /dev/null and b/public/games/block_breaker/assets/blocks/amethyst_block.png differ diff --git a/public/games/block_breaker/assets/blocks/ancient_debris_side.png b/public/games/block_breaker/assets/blocks/ancient_debris_side.png new file mode 100644 index 0000000..498d98a Binary files /dev/null and b/public/games/block_breaker/assets/blocks/ancient_debris_side.png differ diff --git a/public/games/block_breaker/assets/blocks/barrel_side.png b/public/games/block_breaker/assets/blocks/barrel_side.png new file mode 100644 index 0000000..f2d4b7f Binary files /dev/null and b/public/games/block_breaker/assets/blocks/barrel_side.png differ diff --git a/public/games/block_breaker/assets/blocks/basalt_side.png b/public/games/block_breaker/assets/blocks/basalt_side.png new file mode 100644 index 0000000..b9e2ace Binary files /dev/null and b/public/games/block_breaker/assets/blocks/basalt_side.png differ diff --git a/public/games/block_breaker/assets/blocks/bedrock.png b/public/games/block_breaker/assets/blocks/bedrock.png new file mode 100644 index 0000000..e2df190 Binary files /dev/null and b/public/games/block_breaker/assets/blocks/bedrock.png differ diff --git a/public/games/block_breaker/assets/blocks/bee_nest_front.png b/public/games/block_breaker/assets/blocks/bee_nest_front.png new file mode 100644 index 0000000..6810ce9 Binary files /dev/null and b/public/games/block_breaker/assets/blocks/bee_nest_front.png differ diff --git a/public/games/block_breaker/assets/blocks/bee_nest_front_honey.png b/public/games/block_breaker/assets/blocks/bee_nest_front_honey.png new file mode 100644 index 0000000..429fe06 Binary files /dev/null and b/public/games/block_breaker/assets/blocks/bee_nest_front_honey.png differ diff --git a/public/games/block_breaker/assets/blocks/beehive_front.png b/public/games/block_breaker/assets/blocks/beehive_front.png new file mode 100644 index 0000000..09cd1fb Binary files /dev/null and b/public/games/block_breaker/assets/blocks/beehive_front.png differ diff --git a/public/games/block_breaker/assets/blocks/beehive_front_honey.png b/public/games/block_breaker/assets/blocks/beehive_front_honey.png new file mode 100644 index 0000000..662e320 Binary files /dev/null and b/public/games/block_breaker/assets/blocks/beehive_front_honey.png differ diff --git a/public/games/block_breaker/assets/blocks/blackstone.png b/public/games/block_breaker/assets/blocks/blackstone.png new file mode 100644 index 0000000..5f94c21 Binary files /dev/null and b/public/games/block_breaker/assets/blocks/blackstone.png differ diff --git a/public/games/block_breaker/assets/blocks/bookshelf.png b/public/games/block_breaker/assets/blocks/bookshelf.png new file mode 100644 index 0000000..5d2afaf Binary files /dev/null and b/public/games/block_breaker/assets/blocks/bookshelf.png differ diff --git a/public/games/block_breaker/assets/blocks/calcite.png b/public/games/block_breaker/assets/blocks/calcite.png new file mode 100644 index 0000000..4c2b0dd Binary files /dev/null and b/public/games/block_breaker/assets/blocks/calcite.png differ diff --git a/public/games/block_breaker/assets/blocks/chest_front.png b/public/games/block_breaker/assets/blocks/chest_front.png new file mode 100644 index 0000000..60ab981 Binary files /dev/null and b/public/games/block_breaker/assets/blocks/chest_front.png differ diff --git a/public/games/block_breaker/assets/blocks/chiseled_bookshelf_occupied.png b/public/games/block_breaker/assets/blocks/chiseled_bookshelf_occupied.png new file mode 100644 index 0000000..22a0f74 Binary files /dev/null and b/public/games/block_breaker/assets/blocks/chiseled_bookshelf_occupied.png differ diff --git a/public/games/block_breaker/assets/blocks/clay.png b/public/games/block_breaker/assets/blocks/clay.png new file mode 100644 index 0000000..b350cef Binary files /dev/null and b/public/games/block_breaker/assets/blocks/clay.png differ diff --git a/public/games/block_breaker/assets/blocks/coal_ore.png b/public/games/block_breaker/assets/blocks/coal_ore.png new file mode 100644 index 0000000..2a21d2b Binary files /dev/null and b/public/games/block_breaker/assets/blocks/coal_ore.png differ diff --git a/public/games/block_breaker/assets/blocks/coarse_dirt.png b/public/games/block_breaker/assets/blocks/coarse_dirt.png new file mode 100644 index 0000000..39211f1 Binary files /dev/null and b/public/games/block_breaker/assets/blocks/coarse_dirt.png differ diff --git a/public/games/block_breaker/assets/blocks/cobbled_deepslate.png b/public/games/block_breaker/assets/blocks/cobbled_deepslate.png new file mode 100644 index 0000000..50fe34e Binary files /dev/null and b/public/games/block_breaker/assets/blocks/cobbled_deepslate.png differ diff --git a/public/games/block_breaker/assets/blocks/cobblestone.png b/public/games/block_breaker/assets/blocks/cobblestone.png new file mode 100644 index 0000000..7b9837a Binary files /dev/null and b/public/games/block_breaker/assets/blocks/cobblestone.png differ diff --git a/public/games/block_breaker/assets/blocks/cobblestone_mossy.png b/public/games/block_breaker/assets/blocks/cobblestone_mossy.png new file mode 100644 index 0000000..153397a Binary files /dev/null and b/public/games/block_breaker/assets/blocks/cobblestone_mossy.png differ diff --git a/public/games/block_breaker/assets/blocks/command_block_back_mipmap.png b/public/games/block_breaker/assets/blocks/command_block_back_mipmap.png new file mode 100644 index 0000000..3d9ec3a Binary files /dev/null and b/public/games/block_breaker/assets/blocks/command_block_back_mipmap.png differ diff --git a/public/games/block_breaker/assets/blocks/copper_block.png b/public/games/block_breaker/assets/blocks/copper_block.png new file mode 100644 index 0000000..f7ce8b4 Binary files /dev/null and b/public/games/block_breaker/assets/blocks/copper_block.png differ diff --git a/public/games/block_breaker/assets/blocks/copper_chest_inventory_front.png b/public/games/block_breaker/assets/blocks/copper_chest_inventory_front.png new file mode 100644 index 0000000..db0c0b6 Binary files /dev/null and b/public/games/block_breaker/assets/blocks/copper_chest_inventory_front.png differ diff --git a/public/games/block_breaker/assets/blocks/copper_ore.png b/public/games/block_breaker/assets/blocks/copper_ore.png new file mode 100644 index 0000000..c7aea0c Binary files /dev/null and b/public/games/block_breaker/assets/blocks/copper_ore.png differ diff --git a/public/games/block_breaker/assets/blocks/crafting_table_front.png b/public/games/block_breaker/assets/blocks/crafting_table_front.png new file mode 100644 index 0000000..5bdd5d4 Binary files /dev/null and b/public/games/block_breaker/assets/blocks/crafting_table_front.png differ diff --git a/public/games/block_breaker/assets/blocks/crimson_nylium_side.png b/public/games/block_breaker/assets/blocks/crimson_nylium_side.png new file mode 100644 index 0000000..60d4790 Binary files /dev/null and b/public/games/block_breaker/assets/blocks/crimson_nylium_side.png differ diff --git a/public/games/block_breaker/assets/blocks/crying_obsidian.png b/public/games/block_breaker/assets/blocks/crying_obsidian.png new file mode 100644 index 0000000..1ec4b2c Binary files /dev/null and b/public/games/block_breaker/assets/blocks/crying_obsidian.png differ diff --git a/public/games/block_breaker/assets/blocks/deepslate.png b/public/games/block_breaker/assets/blocks/deepslate.png new file mode 100644 index 0000000..b07b09d Binary files /dev/null and b/public/games/block_breaker/assets/blocks/deepslate.png differ diff --git a/public/games/block_breaker/assets/blocks/deepslate_coal_ore.png b/public/games/block_breaker/assets/blocks/deepslate_coal_ore.png new file mode 100644 index 0000000..3b9768c Binary files /dev/null and b/public/games/block_breaker/assets/blocks/deepslate_coal_ore.png differ diff --git a/public/games/block_breaker/assets/blocks/deepslate_copper_ore.png b/public/games/block_breaker/assets/blocks/deepslate_copper_ore.png new file mode 100644 index 0000000..6dc547d Binary files /dev/null and b/public/games/block_breaker/assets/blocks/deepslate_copper_ore.png differ diff --git a/public/games/block_breaker/assets/blocks/deepslate_diamond_ore.png b/public/games/block_breaker/assets/blocks/deepslate_diamond_ore.png new file mode 100644 index 0000000..86772d0 Binary files /dev/null and b/public/games/block_breaker/assets/blocks/deepslate_diamond_ore.png differ diff --git a/public/games/block_breaker/assets/blocks/deepslate_emerald_ore.png b/public/games/block_breaker/assets/blocks/deepslate_emerald_ore.png new file mode 100644 index 0000000..31720fd Binary files /dev/null and b/public/games/block_breaker/assets/blocks/deepslate_emerald_ore.png differ diff --git a/public/games/block_breaker/assets/blocks/deepslate_gold_ore.png b/public/games/block_breaker/assets/blocks/deepslate_gold_ore.png new file mode 100644 index 0000000..be52acb Binary files /dev/null and b/public/games/block_breaker/assets/blocks/deepslate_gold_ore.png differ diff --git a/public/games/block_breaker/assets/blocks/deepslate_iron_ore.png b/public/games/block_breaker/assets/blocks/deepslate_iron_ore.png new file mode 100644 index 0000000..96c170e Binary files /dev/null and b/public/games/block_breaker/assets/blocks/deepslate_iron_ore.png differ diff --git a/public/games/block_breaker/assets/blocks/deepslate_lapis_ore.png b/public/games/block_breaker/assets/blocks/deepslate_lapis_ore.png new file mode 100644 index 0000000..0e9c8cc Binary files /dev/null and b/public/games/block_breaker/assets/blocks/deepslate_lapis_ore.png differ diff --git a/public/games/block_breaker/assets/blocks/deepslate_redstone_ore.png b/public/games/block_breaker/assets/blocks/deepslate_redstone_ore.png new file mode 100644 index 0000000..6a1419a Binary files /dev/null and b/public/games/block_breaker/assets/blocks/deepslate_redstone_ore.png differ diff --git a/public/games/block_breaker/assets/blocks/diamond_block.png b/public/games/block_breaker/assets/blocks/diamond_block.png new file mode 100644 index 0000000..be41339 Binary files /dev/null and b/public/games/block_breaker/assets/blocks/diamond_block.png differ diff --git a/public/games/block_breaker/assets/blocks/diamond_ore.png b/public/games/block_breaker/assets/blocks/diamond_ore.png new file mode 100644 index 0000000..5182e1c Binary files /dev/null and b/public/games/block_breaker/assets/blocks/diamond_ore.png differ diff --git a/public/games/block_breaker/assets/blocks/dirt.png b/public/games/block_breaker/assets/blocks/dirt.png new file mode 100644 index 0000000..2af9958 Binary files /dev/null and b/public/games/block_breaker/assets/blocks/dirt.png differ diff --git a/public/games/block_breaker/assets/blocks/dirt_podzol_side.png b/public/games/block_breaker/assets/blocks/dirt_podzol_side.png new file mode 100644 index 0000000..89a328b Binary files /dev/null and b/public/games/block_breaker/assets/blocks/dirt_podzol_side.png differ diff --git a/public/games/block_breaker/assets/blocks/dirt_with_roots.png b/public/games/block_breaker/assets/blocks/dirt_with_roots.png new file mode 100644 index 0000000..b28f0a3 Binary files /dev/null and b/public/games/block_breaker/assets/blocks/dirt_with_roots.png differ diff --git a/public/games/block_breaker/assets/blocks/dripstone_block.png b/public/games/block_breaker/assets/blocks/dripstone_block.png new file mode 100644 index 0000000..c3fbb5b Binary files /dev/null and b/public/games/block_breaker/assets/blocks/dripstone_block.png differ diff --git a/public/games/block_breaker/assets/blocks/emerald_block.png b/public/games/block_breaker/assets/blocks/emerald_block.png new file mode 100644 index 0000000..80e9c00 Binary files /dev/null and b/public/games/block_breaker/assets/blocks/emerald_block.png differ diff --git a/public/games/block_breaker/assets/blocks/emerald_ore.png b/public/games/block_breaker/assets/blocks/emerald_ore.png new file mode 100644 index 0000000..425191c Binary files /dev/null and b/public/games/block_breaker/assets/blocks/emerald_ore.png differ diff --git a/public/games/block_breaker/assets/blocks/end_stone.png b/public/games/block_breaker/assets/blocks/end_stone.png new file mode 100644 index 0000000..4825c91 Binary files /dev/null and b/public/games/block_breaker/assets/blocks/end_stone.png differ diff --git a/public/games/block_breaker/assets/blocks/ender_chest_front.png b/public/games/block_breaker/assets/blocks/ender_chest_front.png new file mode 100644 index 0000000..08776b3 Binary files /dev/null and b/public/games/block_breaker/assets/blocks/ender_chest_front.png differ diff --git a/public/games/block_breaker/assets/blocks/exposed_copper.png b/public/games/block_breaker/assets/blocks/exposed_copper.png new file mode 100644 index 0000000..d265f4b Binary files /dev/null and b/public/games/block_breaker/assets/blocks/exposed_copper.png differ diff --git a/public/games/block_breaker/assets/blocks/exposed_copper_chest_inventory_front.png b/public/games/block_breaker/assets/blocks/exposed_copper_chest_inventory_front.png new file mode 100644 index 0000000..5ecfeab Binary files /dev/null and b/public/games/block_breaker/assets/blocks/exposed_copper_chest_inventory_front.png differ diff --git a/public/games/block_breaker/assets/blocks/gilded_blackstone.png b/public/games/block_breaker/assets/blocks/gilded_blackstone.png new file mode 100644 index 0000000..db5c616 Binary files /dev/null and b/public/games/block_breaker/assets/blocks/gilded_blackstone.png differ diff --git a/public/games/block_breaker/assets/blocks/glowing_obsidian.png b/public/games/block_breaker/assets/blocks/glowing_obsidian.png new file mode 100644 index 0000000..88e1cfb Binary files /dev/null and b/public/games/block_breaker/assets/blocks/glowing_obsidian.png differ diff --git a/public/games/block_breaker/assets/blocks/glowstone.png b/public/games/block_breaker/assets/blocks/glowstone.png new file mode 100644 index 0000000..3ff68e2 Binary files /dev/null and b/public/games/block_breaker/assets/blocks/glowstone.png differ diff --git a/public/games/block_breaker/assets/blocks/gold_block.png b/public/games/block_breaker/assets/blocks/gold_block.png new file mode 100644 index 0000000..c74092a Binary files /dev/null and b/public/games/block_breaker/assets/blocks/gold_block.png differ diff --git a/public/games/block_breaker/assets/blocks/gold_ore.png b/public/games/block_breaker/assets/blocks/gold_ore.png new file mode 100644 index 0000000..cb1c9cc Binary files /dev/null and b/public/games/block_breaker/assets/blocks/gold_ore.png differ diff --git a/public/games/block_breaker/assets/blocks/grass_block_snow.png b/public/games/block_breaker/assets/blocks/grass_block_snow.png new file mode 100644 index 0000000..5fe3e02 Binary files /dev/null and b/public/games/block_breaker/assets/blocks/grass_block_snow.png differ diff --git a/public/games/block_breaker/assets/blocks/grass_path_side.png b/public/games/block_breaker/assets/blocks/grass_path_side.png new file mode 100644 index 0000000..c354996 Binary files /dev/null and b/public/games/block_breaker/assets/blocks/grass_path_side.png differ diff --git a/public/games/block_breaker/assets/blocks/grass_side_carried.png b/public/games/block_breaker/assets/blocks/grass_side_carried.png new file mode 100644 index 0000000..30663bf Binary files /dev/null and b/public/games/block_breaker/assets/blocks/grass_side_carried.png differ diff --git a/public/games/block_breaker/assets/blocks/gravel.png b/public/games/block_breaker/assets/blocks/gravel.png new file mode 100644 index 0000000..dd006d4 Binary files /dev/null and b/public/games/block_breaker/assets/blocks/gravel.png differ diff --git a/public/games/block_breaker/assets/blocks/honey_side.png b/public/games/block_breaker/assets/blocks/honey_side.png new file mode 100644 index 0000000..071ca42 Binary files /dev/null and b/public/games/block_breaker/assets/blocks/honey_side.png differ diff --git a/public/games/block_breaker/assets/blocks/ice.png b/public/games/block_breaker/assets/blocks/ice.png new file mode 100644 index 0000000..9b08668 Binary files /dev/null and b/public/games/block_breaker/assets/blocks/ice.png differ diff --git a/public/games/block_breaker/assets/blocks/ice_packed.png b/public/games/block_breaker/assets/blocks/ice_packed.png new file mode 100644 index 0000000..9aa4da6 Binary files /dev/null and b/public/games/block_breaker/assets/blocks/ice_packed.png differ diff --git a/public/games/block_breaker/assets/blocks/iron_block.png b/public/games/block_breaker/assets/blocks/iron_block.png new file mode 100644 index 0000000..b4d5e53 Binary files /dev/null and b/public/games/block_breaker/assets/blocks/iron_block.png differ diff --git a/public/games/block_breaker/assets/blocks/iron_ore.png b/public/games/block_breaker/assets/blocks/iron_ore.png new file mode 100644 index 0000000..8fa6857 Binary files /dev/null and b/public/games/block_breaker/assets/blocks/iron_ore.png differ diff --git a/public/games/block_breaker/assets/blocks/lapis_block.png b/public/games/block_breaker/assets/blocks/lapis_block.png new file mode 100644 index 0000000..f2fc093 Binary files /dev/null and b/public/games/block_breaker/assets/blocks/lapis_block.png differ diff --git a/public/games/block_breaker/assets/blocks/lapis_ore.png b/public/games/block_breaker/assets/blocks/lapis_ore.png new file mode 100644 index 0000000..7c212c3 Binary files /dev/null and b/public/games/block_breaker/assets/blocks/lapis_ore.png differ diff --git a/public/games/block_breaker/assets/blocks/magma.png b/public/games/block_breaker/assets/blocks/magma.png new file mode 100644 index 0000000..4f3ed73 Binary files /dev/null and b/public/games/block_breaker/assets/blocks/magma.png differ diff --git a/public/games/block_breaker/assets/blocks/mud.png b/public/games/block_breaker/assets/blocks/mud.png new file mode 100644 index 0000000..104d291 Binary files /dev/null and b/public/games/block_breaker/assets/blocks/mud.png differ diff --git a/public/games/block_breaker/assets/blocks/muddy_mangrove_roots_side.png b/public/games/block_breaker/assets/blocks/muddy_mangrove_roots_side.png new file mode 100644 index 0000000..9436714 Binary files /dev/null and b/public/games/block_breaker/assets/blocks/muddy_mangrove_roots_side.png differ diff --git a/public/games/block_breaker/assets/blocks/mycelium_side.png b/public/games/block_breaker/assets/blocks/mycelium_side.png new file mode 100644 index 0000000..3e65e6e Binary files /dev/null and b/public/games/block_breaker/assets/blocks/mycelium_side.png differ diff --git a/public/games/block_breaker/assets/blocks/nether_brick.png b/public/games/block_breaker/assets/blocks/nether_brick.png new file mode 100644 index 0000000..90c6e33 Binary files /dev/null and b/public/games/block_breaker/assets/blocks/nether_brick.png differ diff --git a/public/games/block_breaker/assets/blocks/nether_gold_ore.png b/public/games/block_breaker/assets/blocks/nether_gold_ore.png new file mode 100644 index 0000000..7029bc0 Binary files /dev/null and b/public/games/block_breaker/assets/blocks/nether_gold_ore.png differ diff --git a/public/games/block_breaker/assets/blocks/nether_wart_block.png b/public/games/block_breaker/assets/blocks/nether_wart_block.png new file mode 100644 index 0000000..27052ea Binary files /dev/null and b/public/games/block_breaker/assets/blocks/nether_wart_block.png differ diff --git a/public/games/block_breaker/assets/blocks/netherite_block.png b/public/games/block_breaker/assets/blocks/netherite_block.png new file mode 100644 index 0000000..60957f0 Binary files /dev/null and b/public/games/block_breaker/assets/blocks/netherite_block.png differ diff --git a/public/games/block_breaker/assets/blocks/netherrack.png b/public/games/block_breaker/assets/blocks/netherrack.png new file mode 100644 index 0000000..d324e2f Binary files /dev/null and b/public/games/block_breaker/assets/blocks/netherrack.png differ diff --git a/public/games/block_breaker/assets/blocks/obsidian.png b/public/games/block_breaker/assets/blocks/obsidian.png new file mode 100644 index 0000000..9ebf440 Binary files /dev/null and b/public/games/block_breaker/assets/blocks/obsidian.png differ diff --git a/public/games/block_breaker/assets/blocks/oxidized_copper.png b/public/games/block_breaker/assets/blocks/oxidized_copper.png new file mode 100644 index 0000000..0ad69bc Binary files /dev/null and b/public/games/block_breaker/assets/blocks/oxidized_copper.png differ diff --git a/public/games/block_breaker/assets/blocks/oxidized_copper_chest_inventory_front.png b/public/games/block_breaker/assets/blocks/oxidized_copper_chest_inventory_front.png new file mode 100644 index 0000000..25861dc Binary files /dev/null and b/public/games/block_breaker/assets/blocks/oxidized_copper_chest_inventory_front.png differ diff --git a/public/games/block_breaker/assets/blocks/packed_mud.png b/public/games/block_breaker/assets/blocks/packed_mud.png new file mode 100644 index 0000000..c1539af Binary files /dev/null and b/public/games/block_breaker/assets/blocks/packed_mud.png differ diff --git a/public/games/block_breaker/assets/blocks/quartz_ore.png b/public/games/block_breaker/assets/blocks/quartz_ore.png new file mode 100644 index 0000000..9036e38 Binary files /dev/null and b/public/games/block_breaker/assets/blocks/quartz_ore.png differ diff --git a/public/games/block_breaker/assets/blocks/raw_copper_block.png b/public/games/block_breaker/assets/blocks/raw_copper_block.png new file mode 100644 index 0000000..204a822 Binary files /dev/null and b/public/games/block_breaker/assets/blocks/raw_copper_block.png differ diff --git a/public/games/block_breaker/assets/blocks/raw_gold_block.png b/public/games/block_breaker/assets/blocks/raw_gold_block.png new file mode 100644 index 0000000..57472f7 Binary files /dev/null and b/public/games/block_breaker/assets/blocks/raw_gold_block.png differ diff --git a/public/games/block_breaker/assets/blocks/raw_iron_block.png b/public/games/block_breaker/assets/blocks/raw_iron_block.png new file mode 100644 index 0000000..e99a2b3 Binary files /dev/null and b/public/games/block_breaker/assets/blocks/raw_iron_block.png differ diff --git a/public/games/block_breaker/assets/blocks/red_nether_brick.png b/public/games/block_breaker/assets/blocks/red_nether_brick.png new file mode 100644 index 0000000..0057946 Binary files /dev/null and b/public/games/block_breaker/assets/blocks/red_nether_brick.png differ diff --git a/public/games/block_breaker/assets/blocks/redstone_block.png b/public/games/block_breaker/assets/blocks/redstone_block.png new file mode 100644 index 0000000..0cc3ddf Binary files /dev/null and b/public/games/block_breaker/assets/blocks/redstone_block.png differ diff --git a/public/games/block_breaker/assets/blocks/redstone_ore.png b/public/games/block_breaker/assets/blocks/redstone_ore.png new file mode 100644 index 0000000..b708697 Binary files /dev/null and b/public/games/block_breaker/assets/blocks/redstone_ore.png differ diff --git a/public/games/block_breaker/assets/blocks/reinforced_deepslate_side.png b/public/games/block_breaker/assets/blocks/reinforced_deepslate_side.png new file mode 100644 index 0000000..934776f Binary files /dev/null and b/public/games/block_breaker/assets/blocks/reinforced_deepslate_side.png differ diff --git a/public/games/block_breaker/assets/blocks/sand.png b/public/games/block_breaker/assets/blocks/sand.png new file mode 100644 index 0000000..c93e4a3 Binary files /dev/null and b/public/games/block_breaker/assets/blocks/sand.png differ diff --git a/public/games/block_breaker/assets/blocks/sandstone_carved.png b/public/games/block_breaker/assets/blocks/sandstone_carved.png new file mode 100644 index 0000000..c5c469e Binary files /dev/null and b/public/games/block_breaker/assets/blocks/sandstone_carved.png differ diff --git a/public/games/block_breaker/assets/blocks/sandstone_normal.png b/public/games/block_breaker/assets/blocks/sandstone_normal.png new file mode 100644 index 0000000..aa6a922 Binary files /dev/null and b/public/games/block_breaker/assets/blocks/sandstone_normal.png differ diff --git a/public/games/block_breaker/assets/blocks/sandstone_smooth.png b/public/games/block_breaker/assets/blocks/sandstone_smooth.png new file mode 100644 index 0000000..6ae4443 Binary files /dev/null and b/public/games/block_breaker/assets/blocks/sandstone_smooth.png differ diff --git a/public/games/block_breaker/assets/blocks/sculk_catalyst_top.png b/public/games/block_breaker/assets/blocks/sculk_catalyst_top.png new file mode 100644 index 0000000..00ee9fa Binary files /dev/null and b/public/games/block_breaker/assets/blocks/sculk_catalyst_top.png differ diff --git a/public/games/block_breaker/assets/blocks/sculk_shrieker_bottom.png b/public/games/block_breaker/assets/blocks/sculk_shrieker_bottom.png new file mode 100644 index 0000000..a3bf18f Binary files /dev/null and b/public/games/block_breaker/assets/blocks/sculk_shrieker_bottom.png differ diff --git a/public/games/block_breaker/assets/blocks/slime.png b/public/games/block_breaker/assets/blocks/slime.png new file mode 100644 index 0000000..93c4010 Binary files /dev/null and b/public/games/block_breaker/assets/blocks/slime.png differ diff --git a/public/games/block_breaker/assets/blocks/snow.png b/public/games/block_breaker/assets/blocks/snow.png new file mode 100644 index 0000000..2b83227 Binary files /dev/null and b/public/games/block_breaker/assets/blocks/snow.png differ diff --git a/public/games/block_breaker/assets/blocks/soul_sand.png b/public/games/block_breaker/assets/blocks/soul_sand.png new file mode 100644 index 0000000..c6ea8cd Binary files /dev/null and b/public/games/block_breaker/assets/blocks/soul_sand.png differ diff --git a/public/games/block_breaker/assets/blocks/soul_soil.png b/public/games/block_breaker/assets/blocks/soul_soil.png new file mode 100644 index 0000000..6604561 Binary files /dev/null and b/public/games/block_breaker/assets/blocks/soul_soil.png differ diff --git a/public/games/block_breaker/assets/blocks/stone.png b/public/games/block_breaker/assets/blocks/stone.png new file mode 100644 index 0000000..618435e Binary files /dev/null and b/public/games/block_breaker/assets/blocks/stone.png differ diff --git a/public/games/block_breaker/assets/blocks/stone_andesite.png b/public/games/block_breaker/assets/blocks/stone_andesite.png new file mode 100644 index 0000000..b418fe2 Binary files /dev/null and b/public/games/block_breaker/assets/blocks/stone_andesite.png differ diff --git a/public/games/block_breaker/assets/blocks/stone_diorite.png b/public/games/block_breaker/assets/blocks/stone_diorite.png new file mode 100644 index 0000000..5eb65d0 Binary files /dev/null and b/public/games/block_breaker/assets/blocks/stone_diorite.png differ diff --git a/public/games/block_breaker/assets/blocks/stone_granite.png b/public/games/block_breaker/assets/blocks/stone_granite.png new file mode 100644 index 0000000..36c32e0 Binary files /dev/null and b/public/games/block_breaker/assets/blocks/stone_granite.png differ diff --git a/public/games/block_breaker/assets/blocks/stonebrick.png b/public/games/block_breaker/assets/blocks/stonebrick.png new file mode 100644 index 0000000..3f2c93f Binary files /dev/null and b/public/games/block_breaker/assets/blocks/stonebrick.png differ diff --git a/public/games/block_breaker/assets/blocks/sulfur.png b/public/games/block_breaker/assets/blocks/sulfur.png new file mode 100644 index 0000000..065e56f Binary files /dev/null and b/public/games/block_breaker/assets/blocks/sulfur.png differ diff --git a/public/games/block_breaker/assets/blocks/suspicious_gravel_0.png b/public/games/block_breaker/assets/blocks/suspicious_gravel_0.png new file mode 100644 index 0000000..dc91b68 Binary files /dev/null and b/public/games/block_breaker/assets/blocks/suspicious_gravel_0.png differ diff --git a/public/games/block_breaker/assets/blocks/suspicious_sand_0.png b/public/games/block_breaker/assets/blocks/suspicious_sand_0.png new file mode 100644 index 0000000..d870c69 Binary files /dev/null and b/public/games/block_breaker/assets/blocks/suspicious_sand_0.png differ diff --git a/public/games/block_breaker/assets/blocks/tnt_side.png b/public/games/block_breaker/assets/blocks/tnt_side.png new file mode 100644 index 0000000..b387870 Binary files /dev/null and b/public/games/block_breaker/assets/blocks/tnt_side.png differ diff --git a/public/games/block_breaker/assets/blocks/tuff.png b/public/games/block_breaker/assets/blocks/tuff.png new file mode 100644 index 0000000..0880433 Binary files /dev/null and b/public/games/block_breaker/assets/blocks/tuff.png differ diff --git a/public/games/block_breaker/assets/blocks/warped_nylium_side.png b/public/games/block_breaker/assets/blocks/warped_nylium_side.png new file mode 100644 index 0000000..accb58c Binary files /dev/null and b/public/games/block_breaker/assets/blocks/warped_nylium_side.png differ diff --git a/public/games/block_breaker/assets/blocks/weathered_copper.png b/public/games/block_breaker/assets/blocks/weathered_copper.png new file mode 100644 index 0000000..10d24e1 Binary files /dev/null and b/public/games/block_breaker/assets/blocks/weathered_copper.png differ diff --git a/public/games/block_breaker/assets/blocks/weathered_copper_chest_inventory_front.png b/public/games/block_breaker/assets/blocks/weathered_copper_chest_inventory_front.png new file mode 100644 index 0000000..6c25ae2 Binary files /dev/null and b/public/games/block_breaker/assets/blocks/weathered_copper_chest_inventory_front.png differ diff --git a/public/games/block_breaker/assets/blocks/wool_colored_black.png b/public/games/block_breaker/assets/blocks/wool_colored_black.png new file mode 100644 index 0000000..4ee0ded Binary files /dev/null and b/public/games/block_breaker/assets/blocks/wool_colored_black.png differ diff --git a/public/games/block_breaker/assets/blocks/wool_colored_brown.png b/public/games/block_breaker/assets/blocks/wool_colored_brown.png new file mode 100644 index 0000000..83b19f2 Binary files /dev/null and b/public/games/block_breaker/assets/blocks/wool_colored_brown.png differ diff --git a/public/games/block_breaker/assets/blocks/wool_colored_cyan.png b/public/games/block_breaker/assets/blocks/wool_colored_cyan.png new file mode 100644 index 0000000..3eb475d Binary files /dev/null and b/public/games/block_breaker/assets/blocks/wool_colored_cyan.png differ diff --git a/public/games/block_breaker/assets/blocks/wool_colored_gray.png b/public/games/block_breaker/assets/blocks/wool_colored_gray.png new file mode 100644 index 0000000..89a4398 Binary files /dev/null and b/public/games/block_breaker/assets/blocks/wool_colored_gray.png differ diff --git a/public/games/block_breaker/assets/blocks/wool_colored_green.png b/public/games/block_breaker/assets/blocks/wool_colored_green.png new file mode 100644 index 0000000..5475c8d Binary files /dev/null and b/public/games/block_breaker/assets/blocks/wool_colored_green.png differ diff --git a/public/games/block_breaker/assets/blocks/wool_colored_light_blue.png b/public/games/block_breaker/assets/blocks/wool_colored_light_blue.png new file mode 100644 index 0000000..2ee487a Binary files /dev/null and b/public/games/block_breaker/assets/blocks/wool_colored_light_blue.png differ diff --git a/public/games/block_breaker/assets/blocks/wool_colored_lime.png b/public/games/block_breaker/assets/blocks/wool_colored_lime.png new file mode 100644 index 0000000..dc3da54 Binary files /dev/null and b/public/games/block_breaker/assets/blocks/wool_colored_lime.png differ diff --git a/public/games/block_breaker/assets/blocks/wool_colored_magenta.png b/public/games/block_breaker/assets/blocks/wool_colored_magenta.png new file mode 100644 index 0000000..abbf348 Binary files /dev/null and b/public/games/block_breaker/assets/blocks/wool_colored_magenta.png differ diff --git a/public/games/block_breaker/assets/blocks/wool_colored_orange.png b/public/games/block_breaker/assets/blocks/wool_colored_orange.png new file mode 100644 index 0000000..bd12539 Binary files /dev/null and b/public/games/block_breaker/assets/blocks/wool_colored_orange.png differ diff --git a/public/games/block_breaker/assets/blocks/wool_colored_pink.png b/public/games/block_breaker/assets/blocks/wool_colored_pink.png new file mode 100644 index 0000000..a2204f6 Binary files /dev/null and b/public/games/block_breaker/assets/blocks/wool_colored_pink.png differ diff --git a/public/games/block_breaker/assets/blocks/wool_colored_purple.png b/public/games/block_breaker/assets/blocks/wool_colored_purple.png new file mode 100644 index 0000000..448076d Binary files /dev/null and b/public/games/block_breaker/assets/blocks/wool_colored_purple.png differ diff --git a/public/games/block_breaker/assets/blocks/wool_colored_red.png b/public/games/block_breaker/assets/blocks/wool_colored_red.png new file mode 100644 index 0000000..8e9d27d Binary files /dev/null and b/public/games/block_breaker/assets/blocks/wool_colored_red.png differ diff --git a/public/games/block_breaker/assets/blocks/wool_colored_silver.png b/public/games/block_breaker/assets/blocks/wool_colored_silver.png new file mode 100644 index 0000000..9d6fea8 Binary files /dev/null and b/public/games/block_breaker/assets/blocks/wool_colored_silver.png differ diff --git a/public/games/block_breaker/assets/blocks/wool_colored_white.png b/public/games/block_breaker/assets/blocks/wool_colored_white.png new file mode 100644 index 0000000..23ba5a3 Binary files /dev/null and b/public/games/block_breaker/assets/blocks/wool_colored_white.png differ diff --git a/public/games/block_breaker/assets/blocks/wool_colored_yellow.png b/public/games/block_breaker/assets/blocks/wool_colored_yellow.png new file mode 100644 index 0000000..c3735de Binary files /dev/null and b/public/games/block_breaker/assets/blocks/wool_colored_yellow.png differ diff --git a/public/games/block_breaker/assets/items/copper_pickaxe.png b/public/games/block_breaker/assets/items/copper_pickaxe.png new file mode 100644 index 0000000..a0f2d9c Binary files /dev/null and b/public/games/block_breaker/assets/items/copper_pickaxe.png differ diff --git a/public/games/block_breaker/assets/items/copper_shovel.png b/public/games/block_breaker/assets/items/copper_shovel.png new file mode 100644 index 0000000..fa41a5d Binary files /dev/null and b/public/games/block_breaker/assets/items/copper_shovel.png differ diff --git a/public/games/block_breaker/assets/items/diamond_pickaxe.png b/public/games/block_breaker/assets/items/diamond_pickaxe.png new file mode 100644 index 0000000..7181c98 Binary files /dev/null and b/public/games/block_breaker/assets/items/diamond_pickaxe.png differ diff --git a/public/games/block_breaker/assets/items/diamond_shovel.png b/public/games/block_breaker/assets/items/diamond_shovel.png new file mode 100644 index 0000000..a3bb990 Binary files /dev/null and b/public/games/block_breaker/assets/items/diamond_shovel.png differ diff --git a/public/games/block_breaker/assets/items/gold_pickaxe.png b/public/games/block_breaker/assets/items/gold_pickaxe.png new file mode 100644 index 0000000..8634664 Binary files /dev/null and b/public/games/block_breaker/assets/items/gold_pickaxe.png differ diff --git a/public/games/block_breaker/assets/items/gold_shovel.png b/public/games/block_breaker/assets/items/gold_shovel.png new file mode 100644 index 0000000..66ff882 Binary files /dev/null and b/public/games/block_breaker/assets/items/gold_shovel.png differ diff --git a/public/games/block_breaker/assets/items/iron_pickaxe.png b/public/games/block_breaker/assets/items/iron_pickaxe.png new file mode 100644 index 0000000..3fa7098 Binary files /dev/null and b/public/games/block_breaker/assets/items/iron_pickaxe.png differ diff --git a/public/games/block_breaker/assets/items/iron_shovel.png b/public/games/block_breaker/assets/items/iron_shovel.png new file mode 100644 index 0000000..32163ce Binary files /dev/null and b/public/games/block_breaker/assets/items/iron_shovel.png differ diff --git a/public/games/block_breaker/assets/items/netherite_pickaxe.png b/public/games/block_breaker/assets/items/netherite_pickaxe.png new file mode 100644 index 0000000..088283b Binary files /dev/null and b/public/games/block_breaker/assets/items/netherite_pickaxe.png differ diff --git a/public/games/block_breaker/assets/items/netherite_shovel.png b/public/games/block_breaker/assets/items/netherite_shovel.png new file mode 100644 index 0000000..9517e2a Binary files /dev/null and b/public/games/block_breaker/assets/items/netherite_shovel.png differ diff --git a/public/games/block_breaker/assets/items/stone_pickaxe.png b/public/games/block_breaker/assets/items/stone_pickaxe.png new file mode 100644 index 0000000..f352d1b Binary files /dev/null and b/public/games/block_breaker/assets/items/stone_pickaxe.png differ diff --git a/public/games/block_breaker/assets/items/stone_shovel.png b/public/games/block_breaker/assets/items/stone_shovel.png new file mode 100644 index 0000000..bbfef79 Binary files /dev/null and b/public/games/block_breaker/assets/items/stone_shovel.png differ diff --git a/public/games/block_breaker/assets/items/wood_pickaxe.png b/public/games/block_breaker/assets/items/wood_pickaxe.png new file mode 100644 index 0000000..b56858a Binary files /dev/null and b/public/games/block_breaker/assets/items/wood_pickaxe.png differ diff --git a/public/games/block_breaker/assets/items/wood_shovel.png b/public/games/block_breaker/assets/items/wood_shovel.png new file mode 100644 index 0000000..c20b070 Binary files /dev/null and b/public/games/block_breaker/assets/items/wood_shovel.png differ diff --git a/public/games/block_breaker/data/blocks.json b/public/games/block_breaker/data/blocks.json new file mode 100644 index 0000000..6564a76 --- /dev/null +++ b/public/games/block_breaker/data/blocks.json @@ -0,0 +1,133 @@ +{ + "air": { "hp": 0, "solid": false, "src": null, "desired_tools": [] }, + "dirt": { "hp": 5, "solid": true, "src": "blocks/dirt.png", "desired_tools": ["shovel"] }, + "grass": { "hp": 6, "solid": true, "src": "blocks/grass_side_carried.png", "desired_tools": ["shovel"] }, + "gravel": { "hp": 10, "solid": true, "src": "blocks/gravel.png", "desired_tools": ["shovel"] }, + "sand": { "hp": 5, "solid": true, "src": "blocks/sand.png", "desired_tools": ["shovel"] }, + "coarse_dirt": { "hp": 7, "solid": true, "src": "blocks/coarse_dirt.png", "desired_tools": ["shovel"] }, + "clay": { "hp": 8, "solid": true, "src": "blocks/clay.png", "desired_tools": ["shovel"] }, + "mud": { "hp": 8, "solid": true, "src": "blocks/mud.png", "desired_tools": ["shovel"] }, + "packed_mud": { "hp": 12, "solid": true, "src": "blocks/packed_mud.png", "desired_tools": ["pickaxe"] }, + "dirt_podzol_side": { "hp": 8, "solid": true, "src": "blocks/dirt_podzol_side.png", "desired_tools": ["shovel"] }, + "dirt_with_roots": { "hp": 8, "solid": true, "src": "blocks/dirt_with_roots.png", "desired_tools": ["shovel"] }, + "grass_block_snow": { "hp": 8, "solid": true, "src": "blocks/grass_block_snow.png", "desired_tools": ["shovel"] }, + "grass_path_side": { "hp": 6, "solid": true, "src": "blocks/grass_path_side.png", "desired_tools": ["shovel"] }, + "mycelium_side": { "hp": 10, "solid": true, "src": "blocks/mycelium_side.png", "desired_tools": ["shovel"] }, + "crimson_nylium_side": { "hp": 12, "solid": true, "src": "blocks/crimson_nylium_side.png", "desired_tools": ["pickaxe"] }, + "warped_nylium_side": { "hp": 12, "solid": true, "src": "blocks/warped_nylium_side.png", "desired_tools": ["pickaxe"] }, + "snow": { "hp": 4, "solid": true, "src": "blocks/snow.png", "desired_tools": ["shovel"] }, + "ice": { "hp": 8, "solid": true, "src": "blocks/ice.png", "desired_tools": ["pickaxe"] }, + "ice_packed": { "hp": 15, "solid": true, "src": "blocks/ice_packed.png", "desired_tools": ["pickaxe"] }, + "soul_sand": { "hp": 10, "solid": true, "src": "blocks/soul_sand.png", "desired_tools": ["shovel"] }, + "soul_soil": { "hp": 10, "solid": true, "src": "blocks/soul_soil.png", "desired_tools": ["shovel"] }, + "suspicious_gravel": { "hp": 10, "solid": true, "src": "blocks/suspicious_gravel_0.png", "desired_tools": ["shovel"], "prize": 40 }, + "suspicious_sand": { "hp": 10, "solid": true, "src": "blocks/suspicious_sand_0.png", "desired_tools": ["shovel"], "prize": 40 }, + "stone": { "hp": 20, "solid": true, "src": "blocks/stone.png", "desired_tools": ["pickaxe"] }, + "diorite": { "hp": 22, "solid": true, "src": "blocks/stone_diorite.png", "desired_tools": ["pickaxe"] }, + "granite": { "hp": 22, "solid": true, "src": "blocks/stone_granite.png", "desired_tools": ["pickaxe"] }, + "andesite": { "hp": 22, "solid": true, "src": "blocks/stone_andesite.png", "desired_tools": ["pickaxe"] }, + "cobblestone": { "hp": 30, "solid": true, "src": "blocks/cobblestone.png", "desired_tools": ["pickaxe"] }, + "cobblestone_mossy": { "hp": 30, "solid": true, "src": "blocks/cobblestone_mossy.png", "desired_tools": ["pickaxe"] }, + "stonebrick": { "hp": 35, "solid": true, "src": "blocks/stonebrick.png", "desired_tools": ["pickaxe"] }, + "tuff": { "hp": 25, "solid": true, "src": "blocks/tuff.png", "desired_tools": ["pickaxe"] }, + "calcite": { "hp": 25, "solid": true, "src": "blocks/calcite.png", "desired_tools": ["pickaxe"] }, + "dripstone_block": { "hp": 28, "solid": true, "src": "blocks/dripstone_block.png", "desired_tools": ["pickaxe"] }, + "sandstone_normal": { "hp": 20, "solid": true, "src": "blocks/sandstone_normal.png", "desired_tools": ["pickaxe"] }, + "sandstone_carved": { "hp": 25, "solid": true, "src": "blocks/sandstone_carved.png", "desired_tools": ["pickaxe"] }, + "sandstone_smooth": { "hp": 20, "solid": true, "src": "blocks/sandstone_smooth.png", "desired_tools": ["pickaxe"] }, + "end_stone": { "hp": 60, "solid": true, "src": "blocks/end_stone.png", "desired_tools": ["pickaxe"] }, + "netherrack": { "hp": 10, "solid": true, "src": "blocks/netherrack.png", "desired_tools": ["pickaxe"] }, + "nether_brick": { "hp": 40, "solid": true, "src": "blocks/nether_brick.png", "desired_tools": ["pickaxe"] }, + "red_nether_brick": { "hp": 40, "solid": true, "src": "blocks/red_nether_brick.png", "desired_tools": ["pickaxe"] }, + "basalt_side": { "hp": 35, "solid": true, "src": "blocks/basalt_side.png", "desired_tools": ["pickaxe"] }, + "blackstone": { "hp": 45, "solid": true, "src": "blocks/blackstone.png", "desired_tools": ["pickaxe"] }, + "gilded_blackstone": { "hp": 60, "solid": true, "src": "blocks/gilded_blackstone.png", "desired_tools": ["pickaxe"], "prize": 200 }, + "deepslate": { "hp": 80, "solid": true, "src": "blocks/deepslate.png", "desired_tools": ["pickaxe"] }, + "cobbled_deepslate": { "hp": 90, "solid": true, "src": "blocks/cobbled_deepslate.png", "desired_tools": ["pickaxe"] }, + "reinforced_deepslate_side": { "hp": 800, "solid": true, "src": "blocks/reinforced_deepslate_side.png", "desired_tools": ["pickaxe"] }, + "obsidian": { "hp": 200, "solid": true, "src": "blocks/obsidian.png", "desired_tools": ["pickaxe"] }, + "crying_obsidian": { "hp": 200, "solid": true, "src": "blocks/crying_obsidian.png", "desired_tools": ["pickaxe"] }, + "glowing_obsidian": { "hp": 200, "solid": true, "src": "blocks/glowing_obsidian.png", "desired_tools": ["pickaxe"] }, + "magma": { "hp": 30, "solid": true, "src": "blocks/magma.png", "desired_tools": ["pickaxe"] }, + "coal_ore": { "hp": 25, "solid": true, "src": "blocks/coal_ore.png", "desired_tools": ["pickaxe"], "prize": 40 }, + "deepslate_coal_ore": { "hp": 80, "solid": true, "src": "blocks/deepslate_coal_ore.png", "desired_tools": ["pickaxe"], "prize": 60 }, + "copper_ore": { "hp": 30, "solid": true, "src": "blocks/copper_ore.png", "desired_tools": ["pickaxe"], "prize": 50 }, + "deepslate_copper_ore": { "hp": 85, "solid": true, "src": "blocks/deepslate_copper_ore.png", "desired_tools": ["pickaxe"], "prize": 80 }, + "iron_ore": { "hp": 40, "solid": true, "src": "blocks/iron_ore.png", "desired_tools": ["pickaxe"], "prize": 70 }, + "deepslate_iron_ore": { "hp": 90, "solid": true, "src": "blocks/deepslate_iron_ore.png", "desired_tools": ["pickaxe"], "prize": 110 }, + "gold_ore": { "hp": 55, "solid": true, "src": "blocks/gold_ore.png", "desired_tools": ["pickaxe"], "prize": 120 }, + "deepslate_gold_ore": { "hp": 110, "solid": true, "src": "blocks/deepslate_gold_ore.png", "desired_tools": ["pickaxe"], "prize": 180 }, + "nether_gold_ore": { "hp": 25, "solid": true, "src": "blocks/nether_gold_ore.png", "desired_tools": ["pickaxe"], "prize": 100 }, + "redstone_ore": { "hp": 45, "solid": true, "src": "blocks/redstone_ore.png", "desired_tools": ["pickaxe"], "prize": 85 }, + "deepslate_redstone_ore": { "hp": 100, "solid": true, "src": "blocks/deepslate_redstone_ore.png", "desired_tools": ["pickaxe"], "prize": 130 }, + "lapis_ore": { "hp": 45, "solid": true, "src": "blocks/lapis_ore.png", "desired_tools": ["pickaxe"], "prize": 85 }, + "deepslate_lapis_ore": { "hp": 100, "solid": true, "src": "blocks/deepslate_lapis_ore.png", "desired_tools": ["pickaxe"], "prize": 130 }, + "diamond_ore": { "hp": 100, "solid": true, "src": "blocks/diamond_ore.png", "desired_tools": ["pickaxe"], "prize": 250 }, + "deepslate_diamond_ore": { "hp": 140, "solid": true, "src": "blocks/deepslate_diamond_ore.png", "desired_tools": ["pickaxe"], "prize": 400 }, + "emerald_ore": { "hp": 120, "solid": true, "src": "blocks/emerald_ore.png", "desired_tools": ["pickaxe"], "prize": 300 }, + "deepslate_emerald_ore": { "hp": 160, "solid": true, "src": "blocks/deepslate_emerald_ore.png", "desired_tools": ["pickaxe"], "prize": 450 }, + "quartz_ore": { "hp": 20, "solid": true, "src": "blocks/quartz_ore.png", "desired_tools": ["pickaxe"], "prize": 60 }, + "ancient_debris_side": { "hp": 250, "solid": true, "src": "blocks/ancient_debris_side.png", "desired_tools": ["pickaxe"], "prize": 750 }, + "amethyst_block": { "hp": 40, "solid": true, "src": "blocks/amethyst_block.png", "desired_tools": ["pickaxe"], "prize": 70 }, + "copper_block": { "hp": 50, "solid": true, "src": "blocks/copper_block.png", "desired_tools": ["pickaxe"] }, + "exposed_copper": { "hp": 50, "solid": true, "src": "blocks/exposed_copper.png", "desired_tools": ["pickaxe"] }, + "weathered_copper": { "hp": 50, "solid": true, "src": "blocks/weathered_copper.png", "desired_tools": ["pickaxe"] }, + "oxidized_copper": { "hp": 50, "solid": true, "src": "blocks/oxidized_copper.png", "desired_tools": ["pickaxe"] }, + "raw_copper_block": { "hp": 60, "solid": true, "src": "blocks/raw_copper_block.png", "desired_tools": ["pickaxe"], "prize": 150 }, + "raw_iron_block": { "hp": 80, "solid": true, "src": "blocks/raw_iron_block.png", "desired_tools": ["pickaxe"], "prize": 220 }, + "raw_gold_block": { "hp": 110, "solid": true, "src": "blocks/raw_gold_block.png", "desired_tools": ["pickaxe"], "prize": 300 }, + "iron_block": { "hp": 70, "solid": true, "src": "blocks/iron_block.png", "desired_tools": ["pickaxe"] }, + "gold_block": { "hp": 100, "solid": true, "src": "blocks/gold_block.png", "desired_tools": ["pickaxe"] }, + "diamond_block": { "hp": 200, "solid": true, "src": "blocks/diamond_block.png", "desired_tools": ["pickaxe"] }, + "emerald_block": { "hp": 220, "solid": true, "src": "blocks/emerald_block.png", "desired_tools": ["pickaxe"] }, + "lapis_block": { "hp": 80, "solid": true, "src": "blocks/lapis_block.png", "desired_tools": ["pickaxe"] }, + "redstone_block": { "hp": 90, "solid": true, "src": "blocks/redstone_block.png", "desired_tools": ["pickaxe"] }, + "netherite_block": { "hp": 400, "solid": true, "src": "blocks/netherite_block.png", "desired_tools": ["pickaxe"] }, + "glowstone": { "hp": 15, "solid": true, "src": "blocks/glowstone.png", "desired_tools": ["pickaxe"], "prize": 50 }, + "chest_50": { "hp": 1, "solid": true, "src": "blocks/chest_front.png", "prize": 50, "desired_tools": [] }, + "chest_100": { "hp": 1, "solid": true, "src": "blocks/chest_front.png", "prize": 100, "desired_tools": [] }, + "chest_250": { "hp": 1, "solid": true, "src": "blocks/chest_front.png", "prize": 250, "desired_tools": [] }, + "chest_500": { "hp": 1, "solid": true, "src": "blocks/chest_front.png", "prize": 500, "desired_tools": [] }, + "barrel_50": { "hp": 5, "solid": true, "src": "blocks/barrel_side.png", "desired_tools": [], "prize": 50 }, + "barrel_100": { "hp": 5, "solid": true, "src": "blocks/barrel_side.png", "desired_tools": [], "prize": 100 }, + "barrel_250": { "hp": 5, "solid": true, "src": "blocks/barrel_side.png", "desired_tools": [], "prize": 250 }, + "barrel_500": { "hp": 5, "solid": true, "src": "blocks/barrel_side.png", "desired_tools": [], "prize": 500 }, + "copper_chest_inventory_front": { "hp": 15, "solid": true, "src": "blocks/copper_chest_inventory_front.png", "prize": 300, "desired_tools": [] }, + "exposed_copper_chest_inventory_front": { "hp": 25, "solid": true, "src": "blocks/exposed_copper_chest_inventory_front.png", "prize": 400, "desired_tools": [] }, + "weathered_copper_chest_inventory_front": { "hp": 35, "solid": true, "src": "blocks/weathered_copper_chest_inventory_front.png", "prize": 500, "desired_tools": [] }, + "oxidized_copper_chest_inventory_front": { "hp": 45, "solid": true, "src": "blocks/oxidized_copper_chest_inventory_front.png", "prize": 600, "desired_tools": [] }, + "ender_chest_front": { "hp": 150, "solid": true, "src": "blocks/ender_chest_front.png", "prize": 2500, "desired_tools": [] }, + "bee_nest_front": { "hp": 15, "solid": true, "src": "blocks/bee_nest_front.png", "desired_tools": [], "prize": 120 }, + "bee_nest_front_honey": { "hp": 15, "solid": true, "src": "blocks/bee_nest_front_honey.png", "desired_tools": [], "prize": 180 }, + "beehive_front": { "hp": 20, "solid": true, "src": "blocks/beehive_front.png", "desired_tools": [], "prize": 150 }, + "beehive_front_honey": { "hp": 20, "solid": true, "src": "blocks/beehive_front_honey.png", "desired_tools": [], "prize": 220 }, + "honey_side": { "hp": 10, "solid": true, "src": "blocks/honey_side.png", "desired_tools": [] }, + "slime": { "hp": 10, "solid": true, "src": "blocks/slime.png", "desired_tools": [] }, + "tnt_side": { "hp": 1, "solid": true, "src": "blocks/tnt_side.png", "prize": 150, "desired_tools": [] }, + "command_block_back_mipmap": { "hp": 2500, "solid": true, "src": "blocks/command_block_back_mipmap.png", "desired_tools": [], "prize": 1500 }, + "sculk_catalyst_top": { "hp": 100, "solid": true, "src": "blocks/sculk_catalyst_top.png", "desired_tools": [] }, + "sculk_shrieker_bottom": { "hp": 100, "solid": true, "src": "blocks/sculk_shrieker_bottom.png", "desired_tools": [] }, + "bookshelf": { "hp": 15, "solid": true, "src": "blocks/bookshelf.png", "desired_tools": [], "prize": 100 }, + "chiseled_bookshelf_occupied": { "hp": 20, "solid": true, "src": "blocks/chiseled_bookshelf_occupied.png", "prize": 120, "desired_tools": [] }, + "crafting_table_front": { "hp": 15, "solid": true, "src": "blocks/crafting_table_front.png", "desired_tools": [] }, + "muddy_mangrove_roots_side": { "hp": 10, "solid": true, "src": "blocks/muddy_mangrove_roots_side.png", "desired_tools": ["shovel"] }, + "nether_wart_block": { "hp": 20, "solid": true, "src": "blocks/nether_wart_block.png", "desired_tools": [] }, + "sulfur": { "hp": 25, "solid": true, "src": "blocks/sulfur.png", "desired_tools": ["pickaxe"], "prize": 75 }, + "wool_colored_white": { "hp": 5, "solid": true, "src": "blocks/wool_colored_white.png", "desired_tools": [] }, + "wool_colored_orange": { "hp": 5, "solid": true, "src": "blocks/wool_colored_orange.png", "desired_tools": [] }, + "wool_colored_magenta": { "hp": 5, "solid": true, "src": "blocks/wool_colored_magenta.png", "desired_tools": [] }, + "wool_colored_light_blue": { "hp": 5, "solid": true, "src": "blocks/wool_colored_light_blue.png", "desired_tools": [] }, + "wool_colored_yellow": { "hp": 5, "solid": true, "src": "blocks/wool_colored_yellow.png", "desired_tools": [] }, + "wool_colored_lime": { "hp": 5, "solid": true, "src": "blocks/wool_colored_lime.png", "desired_tools": [] }, + "wool_colored_pink": { "hp": 5, "solid": true, "src": "blocks/wool_colored_pink.png", "desired_tools": [] }, + "wool_colored_gray": { "hp": 5, "solid": true, "src": "blocks/wool_colored_gray.png", "desired_tools": [] }, + "wool_colored_silver": { "hp": 5, "solid": true, "src": "blocks/wool_colored_silver.png", "desired_tools": [] }, + "wool_colored_cyan": { "hp": 5, "solid": true, "src": "blocks/wool_colored_cyan.png", "desired_tools": [] }, + "wool_colored_purple": { "hp": 5, "solid": true, "src": "blocks/wool_colored_purple.png", "desired_tools": [] }, + "wool_colored_blue": { "hp": 5, "solid": true, "src": "blocks/wool_colored_light_blue.png", "desired_tools": [] }, + "wool_colored_brown": { "hp": 5, "solid": true, "src": "blocks/wool_colored_brown.png", "desired_tools": [] }, + "wool_colored_green": { "hp": 5, "solid": true, "src": "blocks/wool_colored_green.png", "desired_tools": [] }, + "wool_colored_red": { "hp": 5, "solid": true, "src": "blocks/wool_colored_red.png", "desired_tools": [] }, + "wool_colored_black": { "hp": 5, "solid": true, "src": "blocks/wool_colored_black.png", "desired_tools": [] }, + "bedrock": { "hp": null, "solid": true, "unbreakable": true, "src": "blocks/bedrock.png", "desired_tools": [] } +} diff --git a/public/games/block_breaker/data/items.json b/public/games/block_breaker/data/items.json new file mode 100644 index 0000000..bb3174c --- /dev/null +++ b/public/games/block_breaker/data/items.json @@ -0,0 +1,20 @@ +{ + "shovel": [ + { "level": 1, "name": "Wood Shovel", "src": "items/wood_shovel.png", "damage": 1, "maxHits": 20, "price": 5 }, + { "level": 2, "name": "Stone Shovel", "src": "items/stone_shovel.png", "damage": 2, "maxHits": 40, "price": 15 }, + { "level": 3, "name": "Copper Shovel", "src": "items/copper_shovel.png", "damage": 3, "maxHits": 60, "price": 30 }, + { "level": 4, "name": "Iron Shovel", "src": "items/iron_shovel.png", "damage": 4, "maxHits": 80, "price": 50 }, + { "level": 5, "name": "Gold Shovel", "src": "items/gold_shovel.png", "damage": 15, "maxHits": 25, "price": 80 }, + { "level": 6, "name": "Diamond Shovel", "src": "items/diamond_shovel.png", "damage": 7, "maxHits": 100, "price": 200 }, + { "level": 7, "name": "Netherite Shovel", "src": "items/netherite_shovel.png", "damage": 10, "maxHits": 120, "price": 500 } + ], + "pickaxe": [ + { "level": 1, "name": "Wood Pickaxe", "src": "items/wood_pickaxe.png", "damage": 1, "maxHits": 20, "price": 5 }, + { "level": 2, "name": "Stone Pickaxe", "src": "items/stone_pickaxe.png", "damage": 2, "maxHits": 40, "price": 15 }, + { "level": 3, "name": "Copper Pickaxe", "src": "items/copper_pickaxe.png", "damage": 3, "maxHits": 60, "price": 30 }, + { "level": 4, "name": "Iron Pickaxe", "src": "items/iron_pickaxe.png", "damage": 4, "maxHits": 80, "price": 50 }, + { "level": 5, "name": "Gold Pickaxe", "src": "items/gold_pickaxe.png", "damage": 15, "maxHits": 25, "price": 80 }, + { "level": 6, "name": "Diamond Pickaxe", "src": "items/diamond_pickaxe.png", "damage": 7, "maxHits": 100, "price": 200 }, + { "level": 7, "name": "Netherite Pickaxe", "src": "items/netherite_pickaxe.png", "damage": 10, "maxHits": 120, "price": 500 } + ] +} diff --git a/public/games/block_breaker/data/level.json b/public/games/block_breaker/data/level.json new file mode 100644 index 0000000..f527477 --- /dev/null +++ b/public/games/block_breaker/data/level.json @@ -0,0 +1,953 @@ +{ + "levels": [ + { + "id": "overworld_plains", + "background_color": "#87CEEB", + "max_level": 0, + "random_pools": { + "rand_surface": ["grass", "dirt", "coarse_dirt"], + "rand_stone": ["stone", "andesite", "coal_ore", "iron_ore"], + "rand_deep": ["deepslate", "cobbled_deepslate", "diamond_ore", "lapis_ore"] + }, + "map": [ + ["grass", "grass", "air", "grass", "grass"], + ["dirt", "dirt", "tnt_side", "dirt", "dirt"], + ["rand_stone", "rand_stone", "rand_stone", "rand_stone", "rand_stone"], + ["rand_stone", "barrel_100", "rand_stone", "rand_stone", "rand_stone"], + ["rand_stone", "rand_stone", "rand_stone", "rand_stone", "rand_stone"], + ["stone", "stone", "stone", "stone", "stone"], + ["rand_deep", "rand_deep", "exposed_copper_chest_inventory_front", "rand_deep", "rand_deep"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["rand_deep", "air", "rand_deep", "rand_deep", "rand_deep"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["rand_deep", "weathered_copper_chest_inventory_front", "rand_deep", "rand_deep", "rand_deep"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["air", "air", "air", "air", "air"], + ["air", "chest_250", "air", "chest_500", "air"], + ["bedrock", "bedrock", "bedrock", "bedrock", "bedrock"] + ] + }, + { + "id": "sunny_beach", + "background_color": "#87CEEB", + "max_level": 0, + "random_pools": { + "rand_sand": ["sand", "suspicious_sand"], + "rand_stone": ["stone", "coal_ore", "iron_ore", "copper_ore"], + "rand_deep": ["deepslate", "deepslate_gold_ore", "diamond_ore"] + }, + "map": [ + ["sand", "air", "sand", "sand", "sand"], + ["rand_sand", "rand_sand", "barrel_50", "rand_sand", "rand_sand"], + ["sandstone_normal", "sandstone_normal", "sandstone_normal", "sandstone_normal", "sandstone_normal"], + ["rand_stone", "rand_stone", "tnt_side", "rand_stone", "rand_stone"], + ["rand_stone", "rand_stone", "rand_stone", "rand_stone", "rand_stone"], + ["rand_stone", "oxidized_copper_chest_inventory_front", "rand_stone", "rand_stone", "rand_stone"], + ["stone", "stone", "stone", "stone", "stone"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["rand_deep", "air", "rand_deep", "rand_deep", "rand_deep"], + ["rand_deep", "rand_deep", "rand_deep", "barrel_250", "rand_deep"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["air", "air", "air", "air", "air"], + ["air", "chest_100", "chest_250", "copper_chest_inventory_front", "air"], + ["bedrock", "bedrock", "bedrock", "bedrock", "bedrock"] + ] + }, + { + "id": "snow_tundra", + "background_color": "#B0E0E6", + "max_level": 0, + "random_pools": { + "rand_snow": ["snow", "grass_block_snow"], + "rand_ice": ["ice", "ice_packed", "stone", "iron_ore"], + "rand_deep": ["deepslate", "deepslate_iron_ore", "deepslate_diamond_ore"] + }, + "map": [ + ["rand_snow", "rand_snow", "air", "rand_snow", "rand_snow"], + ["dirt", "dirt", "dirt", "tnt_side", "dirt"], + ["stone", "stone", "stone", "stone", "stone"], + ["rand_ice", "rand_ice", "barrel_100", "rand_ice", "rand_ice"], + ["rand_ice", "rand_ice", "rand_ice", "rand_ice", "rand_ice"], + ["stone", "stone", "stone", "stone", "stone"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["rand_deep", "exposed_copper_chest_inventory_front", "rand_deep", "rand_deep", "rand_deep"], + ["rand_deep", "rand_deep", "rand_deep", "air", "rand_deep"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["rand_deep", "rand_deep", "barrel_250", "rand_deep", "rand_deep"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["air", "air", "air", "air", "air"], + ["air", "chest_250", "chest_100", "chest_500", "air"], + ["bedrock", "bedrock", "bedrock", "bedrock", "bedrock"] + ] + }, + { + "id": "desert_archaeology", + "background_color": "#EDC9AF", + "max_level": 0, + "random_pools": { + "rand_sand": ["sand", "suspicious_sand"], + "rand_sandstone": ["sandstone_normal", "sandstone_carved", "sandstone_smooth"], + "rand_stone": ["stone", "iron_ore", "gold_ore"], + "rand_deep": ["deepslate", "deepslate_gold_ore", "deepslate_diamond_ore"] + }, + "map": [ + ["rand_sand", "rand_sand", "air", "rand_sand", "rand_sand"], + ["rand_sand", "rand_sand", "suspicious_sand", "tnt_side", "rand_sand"], + ["rand_sandstone", "rand_sandstone", "rand_sandstone", "rand_sandstone", "rand_sandstone"], + ["rand_sandstone", "barrel_100", "air", "rand_sandstone", "rand_sandstone"], + ["rand_stone", "rand_stone", "rand_stone", "rand_stone", "rand_stone"], + ["rand_stone", "exposed_copper_chest_inventory_front", "rand_stone", "rand_stone", "rand_stone"], + ["stone", "stone", "stone", "stone", "stone"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["rand_deep", "air", "air", "air", "rand_deep"], + ["rand_deep", "rand_deep", "barrel_250", "rand_deep", "rand_deep"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["air", "air", "air", "air", "air"], + ["air", "chest_250", "chest_500", "chest_250", "air"], + ["bedrock", "bedrock", "bedrock", "bedrock", "bedrock"] + ] + }, + { + "id": "nether_wastes", + "background_color": "#4A0E0E", + "max_level": 0, + "random_pools": { + "rand_nether": ["netherrack", "nether_gold_ore", "quartz_ore"], + "rand_soul": ["soul_sand", "soul_soil", "netherrack"], + "rand_blackstone": ["blackstone", "gilded_blackstone", "ancient_debris_side"] + }, + "map": [ + ["rand_nether", "air", "rand_nether", "rand_nether", "rand_nether"], + ["rand_nether", "rand_nether", "magma", "rand_nether", "tnt_side"], + ["rand_soul", "rand_soul", "rand_nether", "rand_soul", "rand_soul"], + ["rand_nether", "barrel_250", "air", "rand_nether", "rand_nether"], + ["rand_blackstone", "rand_blackstone", "rand_blackstone", "rand_blackstone", "rand_blackstone"], + ["rand_blackstone", "rand_blackstone", "weathered_copper_chest_inventory_front", "rand_blackstone", "rand_blackstone"], + ["rand_blackstone", "gilded_blackstone", "rand_blackstone", "gilded_blackstone", "rand_blackstone"], + ["rand_blackstone", "rand_blackstone", "rand_blackstone", "rand_blackstone", "rand_blackstone"], + ["rand_blackstone", "air", "air", "air", "rand_blackstone"], + ["rand_blackstone", "rand_blackstone", "barrel_500", "rand_blackstone", "rand_blackstone"], + ["ancient_debris_side", "rand_blackstone", "rand_blackstone", "rand_blackstone", "ancient_debris_side"], + ["rand_blackstone", "rand_blackstone", "rand_blackstone", "rand_blackstone", "rand_blackstone"], + ["air", "air", "air", "air", "air"], + ["air", "chest_500", "ender_chest_front", "chest_500", "air"], + ["bedrock", "bedrock", "bedrock", "bedrock", "bedrock"] + ] + }, + { + "id": "deep_dark_sculk", + "background_color": "#0A0E17", + "max_level": 0, + "random_pools": { + "rand_sculk": ["deepslate", "sculk_catalyst_top", "sculk_shrieker_bottom"], + "rand_deep": ["deepslate", "cobbled_deepslate", "deepslate_diamond_ore", "deepslate_emerald_ore"], + "rand_obsidian": ["obsidian", "crying_obsidian", "glowing_obsidian"] + }, + "map": [ + ["rand_sculk", "air", "rand_sculk", "air", "rand_sculk"], + ["rand_sculk", "rand_sculk", "tnt_side", "rand_sculk", "rand_sculk"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["rand_deep", "air", "barrel_500", "air", "rand_deep"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["rand_obsidian", "oxidized_copper_chest_inventory_front", "rand_obsidian", "rand_obsidian", "rand_obsidian"], + ["rand_obsidian", "rand_obsidian", "rand_obsidian", "rand_obsidian", "rand_obsidian"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["rand_obsidian", "air", "air", "air", "rand_obsidian"], + ["rand_obsidian", "rand_obsidian", "barrel_500", "rand_obsidian", "rand_obsidian"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["rand_obsidian", "rand_obsidian", "rand_obsidian", "rand_obsidian", "rand_obsidian"], + ["air", "air", "air", "air", "air"], + ["air", "chest_500", "ender_chest_front", "chest_500", "air"], + ["bedrock", "bedrock", "bedrock", "bedrock", "bedrock"] + ] + }, + + { + "id": "muddy_swamp", + "background_color": "#556B2F", + "max_level": 0, + "random_pools": { + "rand_mud": ["mud", "packed_mud"], + "rand_roots": ["muddy_mangrove_roots_side", "clay"], + "rand_stone": ["stone", "coal_ore", "copper_ore"], + "rand_deep": ["deepslate", "deepslate_copper_ore", "deepslate_coal_ore"] + }, + "map": [ + ["rand_mud", "air", "rand_mud", "rand_mud", "rand_mud"], + ["rand_mud", "rand_mud", "tnt_side", "rand_mud", "rand_roots"], + ["rand_roots", "rand_roots", "rand_roots", "rand_roots", "rand_roots"], + ["rand_stone", "barrel_100", "air", "rand_stone", "rand_stone"], + ["rand_stone", "rand_stone", "rand_stone", "rand_stone", "rand_stone"], + ["rand_stone", "rand_stone", "exposed_copper_chest_inventory_front", "rand_stone", "rand_stone"], + ["stone", "stone", "stone", "stone", "stone"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["rand_deep", "air", "rand_deep", "rand_deep", "rand_deep"], + ["rand_deep", "rand_deep", "rand_deep", "barrel_250", "rand_deep"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["air", "air", "air", "air", "air"], + ["air", "chest_250", "air", "chest_500", "air"], + ["bedrock", "bedrock", "bedrock", "bedrock", "bedrock"] + ] + }, + { + "id": "podzol_taiga", + "background_color": "#6B8E23", + "max_level": 0, + "random_pools": { + "rand_surface": ["dirt_podzol_side", "coarse_dirt"], + "rand_stone": ["stone", "cobblestone_mossy", "iron_ore"], + "rand_deep": ["deepslate", "deepslate_iron_ore", "deepslate_diamond_ore"] + }, + "map": [ + ["rand_surface", "rand_surface", "air", "rand_surface", "rand_surface"], + ["dirt", "dirt", "tnt_side", "dirt", "dirt"], + ["rand_stone", "rand_stone", "rand_stone", "rand_stone", "rand_stone"], + ["rand_stone", "barrel_100", "air", "rand_stone", "rand_stone"], + ["rand_stone", "rand_stone", "rand_stone", "rand_stone", "rand_stone"], + ["rand_stone", "weathered_copper_chest_inventory_front", "rand_stone", "rand_stone", "rand_stone"], + ["stone", "stone", "stone", "stone", "stone"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["rand_deep", "rand_deep", "air", "rand_deep", "rand_deep"], + ["rand_deep", "rand_deep", "barrel_250", "rand_deep", "rand_deep"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["air", "air", "air", "air", "air"], + ["air", "chest_500", "chest_250", "air", "air"], + ["bedrock", "bedrock", "bedrock", "bedrock", "bedrock"] + ] + }, + { + "id": "ice_cavern", + "background_color": "#8FD3FE", + "max_level": 0, + "random_pools": { + "rand_ice": ["ice_packed", "ice"], + "rand_diorite": ["diorite", "stone", "lapis_ore"], + "rand_deep": ["deepslate", "deepslate_lapis_ore", "diamond_ore"] + }, + "map": [ + ["rand_ice", "air", "rand_ice", "rand_ice", "rand_ice"], + ["rand_ice", "rand_ice", "tnt_side", "rand_ice", "rand_ice"], + ["rand_diorite", "rand_diorite", "rand_diorite", "rand_diorite", "rand_diorite"], + ["rand_diorite", "barrel_100", "air", "rand_diorite", "rand_diorite"], + ["rand_diorite", "rand_diorite", "rand_diorite", "rand_diorite", "rand_diorite"], + ["rand_diorite", "oxidized_copper_chest_inventory_front", "rand_diorite", "rand_diorite", "rand_diorite"], + ["stone", "stone", "stone", "stone", "stone"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["rand_deep", "air", "rand_deep", "rand_deep", "rand_deep"], + ["rand_deep", "rand_deep", "rand_deep", "barrel_500", "rand_deep"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["air", "air", "air", "air", "air"], + ["air", "chest_250", "ender_chest_front", "air", "air"], + ["bedrock", "bedrock", "bedrock", "bedrock", "bedrock"] + ] + }, + { + "id": "deep_cave", + "background_color": "#1A1A24", + "max_level": 0, + "random_pools": { + "rand_cave": ["dripstone_block", "cobblestone", "stone"], + "rand_ores": ["coal_ore", "iron_ore", "copper_ore"], + "rand_deep": ["deepslate", "cobbled_deepslate", "deepslate_redstone_ore"] + }, + "map": [ + ["rand_cave", "rand_cave", "air", "rand_cave", "rand_cave"], + ["rand_cave", "rand_cave", "tnt_side", "rand_cave", "rand_cave"], + ["rand_ores", "rand_ores", "rand_cave", "rand_ores", "rand_ores"], + ["rand_cave", "barrel_250", "air", "rand_cave", "rand_cave"], + ["rand_cave", "rand_cave", "rand_cave", "rand_cave", "rand_cave"], + ["stone", "stone", "exposed_copper_chest_inventory_front", "stone", "stone"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["rand_deep", "air", "air", "rand_deep", "rand_deep"], + ["rand_deep", "rand_deep", "barrel_250", "rand_deep", "rand_deep"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["air", "air", "air", "air", "air"], + ["air", "chest_500", "air", "chest_500", "air"], + ["bedrock", "bedrock", "bedrock", "bedrock", "bedrock"] + ] + }, + { + "id": "amethyst_geode", + "background_color": "#2D1E3A", + "max_level": 0, + "random_pools": { + "rand_crust": ["calcite", "tuff", "stone"], + "rand_geode": ["amethyst_block", "calcite"], + "rand_deep": ["deepslate", "amethyst_block", "diamond_ore"] + }, + "map": [ + ["rand_crust", "rand_crust", "air", "rand_crust", "rand_crust"], + ["rand_crust", "rand_crust", "tnt_side", "rand_crust", "rand_crust"], + ["rand_geode", "rand_geode", "amethyst_block", "rand_geode", "rand_geode"], + ["rand_geode", "barrel_250", "air", "rand_geode", "rand_geode"], + ["rand_geode", "rand_geode", "rand_geode", "rand_geode", "rand_geode"], + ["rand_crust", "weathered_copper_chest_inventory_front", "rand_crust", "rand_crust", "rand_crust"], + ["stone", "stone", "stone", "stone", "stone"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["rand_deep", "air", "rand_deep", "rand_deep", "rand_deep"], + ["rand_deep", "rand_deep", "barrel_500", "rand_deep", "rand_deep"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["air", "air", "air", "air", "air"], + ["air", "chest_250", "air", "copper_chest_inventory_front", "air"], + ["bedrock", "bedrock", "bedrock", "bedrock", "bedrock"] + ] + }, + { + "id": "end_dimension", + "background_color": "#190E2B", + "max_level": 0, + "random_pools": { + "rand_end": ["end_stone", "obsidian"], + "rand_obsidian": ["obsidian", "crying_obsidian", "glowing_obsidian"] + }, + "map": [ + ["rand_end", "air", "rand_end", "rand_end", "rand_end"], + ["rand_end", "rand_end", "tnt_side", "rand_end", "rand_end"], + ["rand_end", "rand_end", "rand_end", "rand_end", "rand_end"], + ["rand_obsidian", "barrel_500", "air", "rand_obsidian", "rand_obsidian"], + ["rand_obsidian", "rand_obsidian", "rand_obsidian", "rand_obsidian", "rand_obsidian"], + ["rand_obsidian", "oxidized_copper_chest_inventory_front", "rand_obsidian", "rand_obsidian", "rand_obsidian"], + ["rand_end", "rand_end", "rand_end", "rand_end", "rand_end"], + ["rand_end", "rand_end", "rand_end", "rand_end", "rand_end"], + ["rand_end", "air", "air", "rand_end", "rand_end"], + ["rand_obsidian", "rand_obsidian", "barrel_500", "rand_obsidian", "rand_obsidian"], + ["rand_obsidian", "rand_obsidian", "rand_obsidian", "rand_obsidian", "rand_obsidian"], + ["rand_obsidian", "rand_obsidian", "rand_obsidian", "rand_obsidian", "rand_obsidian"], + ["air", "air", "air", "air", "air"], + ["air", "ender_chest_front", "air", "chest_500", "air"], + ["bedrock", "bedrock", "bedrock", "bedrock", "bedrock"] + ] + }, + { + "id": "crimson_forest", + "background_color": "#5A0A0A", + "max_level": 0, + "random_pools": { + "rand_crimson": ["crimson_nylium_side", "nether_wart_block", "netherrack"], + "rand_mid": ["netherrack", "magma", "nether_gold_ore"], + "rand_deep": ["blackstone", "gilded_blackstone"] + }, + "map": [ + ["rand_crimson", "air", "rand_crimson", "rand_crimson", "rand_crimson"], + ["rand_crimson", "rand_crimson", "tnt_side", "rand_crimson", "rand_crimson"], + ["rand_mid", "rand_mid", "rand_mid", "rand_mid", "rand_mid"], + ["rand_mid", "barrel_250", "air", "rand_mid", "rand_mid"], + ["rand_mid", "rand_mid", "rand_mid", "rand_mid", "rand_mid"], + ["rand_mid", "exposed_copper_chest_inventory_front", "rand_mid", "rand_mid", "rand_mid"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["rand_deep", "air", "rand_deep", "rand_deep", "rand_deep"], + ["rand_deep", "rand_deep", "barrel_500", "rand_deep", "rand_deep"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["air", "air", "air", "air", "air"], + ["air", "chest_500", "air", "ender_chest_front", "air"], + ["bedrock", "bedrock", "bedrock", "bedrock", "bedrock"] + ] + }, + { + "id": "warped_forest", + "background_color": "#0A3A3A", + "max_level": 0, + "random_pools": { + "rand_warped": ["warped_nylium_side", "netherrack"], + "rand_mid": ["netherrack", "quartz_ore", "magma"], + "rand_deep": ["blackstone", "basalt_side", "ancient_debris_side"] + }, + "map": [ + ["rand_warped", "air", "rand_warped", "rand_warped", "rand_warped"], + ["rand_warped", "rand_warped", "tnt_side", "rand_warped", "rand_warped"], + ["rand_mid", "rand_mid", "rand_mid", "rand_mid", "rand_mid"], + ["rand_mid", "barrel_250", "air", "rand_mid", "rand_mid"], + ["rand_mid", "rand_mid", "rand_mid", "rand_mid", "rand_mid"], + ["rand_mid", "weathered_copper_chest_inventory_front", "rand_mid", "rand_mid", "rand_mid"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["rand_deep", "air", "air", "rand_deep", "rand_deep"], + ["rand_deep", "rand_deep", "barrel_500", "rand_deep", "rand_deep"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["air", "air", "air", "air", "air"], + ["air", "chest_500", "air", "chest_500", "air"], + ["bedrock", "bedrock", "bedrock", "bedrock", "bedrock"] + ] + }, + { + "id": "badlands_mesa", + "background_color": "#8B4513", + "max_level": 0, + "random_pools": { + "rand_mesa": ["sand", "sandstone_normal", "coarse_dirt"], + "rand_stone": ["stone", "gold_ore", "iron_ore"], + "rand_deep": ["deepslate", "deepslate_gold_ore", "diamond_ore"] + }, + "map": [ + ["rand_mesa", "air", "rand_mesa", "rand_mesa", "rand_mesa"], + ["rand_mesa", "rand_mesa", "tnt_side", "rand_mesa", "rand_mesa"], + ["sandstone_normal", "sandstone_carved", "sandstone_smooth", "sandstone_normal", "sandstone_normal"], + ["rand_stone", "barrel_100", "air", "rand_stone", "rand_stone"], + ["rand_stone", "rand_stone", "rand_stone", "rand_stone", "rand_stone"], + ["rand_stone", "oxidized_copper_chest_inventory_front", "rand_stone", "rand_stone", "rand_stone"], + ["stone", "stone", "stone", "stone", "stone"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["rand_deep", "air", "rand_deep", "rand_deep", "rand_deep"], + ["rand_deep", "rand_deep", "barrel_250", "rand_deep", "rand_deep"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["air", "air", "air", "air", "air"], + ["air", "chest_250", "air", "chest_500", "air"], + ["bedrock", "bedrock", "bedrock", "bedrock", "bedrock"] + ] + }, + { + "id": "lush_cave", + "background_color": "#2E4A2E", + "max_level": 0, + "random_pools": { + "rand_top": ["clay", "dirt_with_roots"], + "rand_moss": ["cobblestone_mossy", "stone", "emerald_ore"], + "rand_deep": ["deepslate", "deepslate_emerald_ore", "amethyst_block"] + }, + "map": [ + ["rand_top", "air", "rand_top", "rand_top", "rand_top"], + ["rand_top", "rand_top", "tnt_side", "rand_top", "rand_top"], + ["rand_moss", "rand_moss", "rand_moss", "rand_moss", "rand_moss"], + ["rand_moss", "barrel_100", "air", "rand_moss", "rand_moss"], + ["rand_moss", "rand_moss", "rand_moss", "rand_moss", "rand_moss"], + ["rand_moss", "exposed_copper_chest_inventory_front", "rand_moss", "rand_moss", "rand_moss"], + ["stone", "stone", "stone", "stone", "stone"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["rand_deep", "air", "air", "rand_deep", "rand_deep"], + ["rand_deep", "rand_deep", "barrel_250", "rand_deep", "rand_deep"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["air", "air", "air", "air", "air"], + ["air", "chest_500", "air", "chest_250", "air"], + ["bedrock", "bedrock", "bedrock", "bedrock", "bedrock"] + ] + }, + { + "id": "mushroom_island", + "background_color": "#A080A0", + "max_level": 0, + "random_pools": { + "rand_mush": ["mycelium_side", "dirt"], + "rand_stone": ["stone", "coal_ore", "iron_ore"], + "rand_deep": ["deepslate", "deepslate_diamond_ore", "deepslate_redstone_ore"] + }, + "map": [ + ["rand_mush", "air", "rand_mush", "rand_mush", "rand_mush"], + ["dirt", "dirt", "tnt_side", "dirt", "dirt"], + ["rand_stone", "rand_stone", "rand_stone", "rand_stone", "rand_stone"], + ["rand_stone", "barrel_100", "air", "rand_stone", "rand_stone"], + ["rand_stone", "rand_stone", "rand_stone", "rand_stone", "rand_stone"], + ["rand_stone", "weathered_copper_chest_inventory_front", "rand_stone", "rand_stone", "rand_stone"], + ["stone", "stone", "stone", "stone", "stone"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["rand_deep", "air", "rand_deep", "rand_deep", "rand_deep"], + ["rand_deep", "rand_deep", "barrel_500", "rand_deep", "rand_deep"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["air", "air", "air", "air", "air"], + ["air", "chest_250", "air", "chest_500", "air"], + ["bedrock", "bedrock", "bedrock", "bedrock", "bedrock"] + ] + }, + { + "id": "bee_meadow", + "background_color": "#FFD700", + "max_level": 0, + "random_pools": { + "rand_top": ["grass", "bee_nest_front", "honey_side"], + "rand_stone": ["stone", "coal_ore", "copper_ore"], + "rand_deep": ["deepslate", "deepslate_emerald_ore", "deepslate_copper_ore"] + }, + "map": [ + ["rand_top", "air", "rand_top", "rand_top", "rand_top"], + ["dirt", "dirt", "tnt_side", "dirt", "dirt"], + ["rand_stone", "rand_stone", "rand_stone", "rand_stone", "rand_stone"], + ["rand_stone", "barrel_50", "air", "rand_stone", "rand_stone"], + ["rand_stone", "rand_stone", "rand_stone", "rand_stone", "rand_stone"], + ["rand_stone", "oxidized_copper_chest_inventory_front", "rand_stone", "rand_stone", "rand_stone"], + ["stone", "stone", "stone", "stone", "stone"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["rand_deep", "air", "rand_deep", "rand_deep", "rand_deep"], + ["rand_deep", "rand_deep", "barrel_250", "rand_deep", "rand_deep"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["air", "air", "air", "air", "air"], + ["air", "chest_250", "air", "chest_100", "air"], + ["bedrock", "bedrock", "bedrock", "bedrock", "bedrock"] + ] + }, + + { + "id": "industrial_zone", + "background_color": "#505050", + "max_level": 0, + "random_pools": { + "rand_metal": ["iron_block", "raw_iron_block", "andesite"], + "rand_stone": ["stone", "stonebrick", "tuff"], + "rand_deep": ["cobbled_deepslate", "deepslate", "deepslate_iron_ore"] + }, + "map": [ + ["iron_block", "air", "iron_block", "iron_block", "iron_block"], + ["raw_iron_block", "raw_iron_block", "tnt_side", "raw_iron_block", "raw_iron_block"], + ["rand_metal", "rand_metal", "rand_metal", "rand_metal", "rand_metal"], + ["rand_stone", "barrel_100", "air", "rand_stone", "rand_stone"], + ["rand_stone", "rand_stone", "rand_stone", "rand_stone", "rand_stone"], + ["rand_stone", "weathered_copper_chest_inventory_front", "rand_stone", "rand_stone", "rand_stone"], + ["stone", "stone", "stone", "stone", "stone"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["rand_deep", "air", "rand_deep", "rand_deep", "rand_deep"], + ["rand_deep", "rand_deep", "barrel_250", "rand_deep", "rand_deep"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["air", "air", "air", "air", "air"], + ["air", "chest_250", "air", "chest_500", "air"], + ["bedrock", "bedrock", "bedrock", "bedrock", "bedrock"] + ] + }, + { + "id": "rainbow_wool_road", + "background_color": "#FFB6C1", + "max_level": 0, + "random_pools": { + "rand_warm": ["wool_colored_red", "wool_colored_orange", "wool_colored_yellow"], + "rand_cool": ["wool_colored_lime", "wool_colored_cyan", "wool_colored_blue"], + "rand_dark": ["wool_colored_purple", "wool_colored_magenta", "wool_colored_black"] + }, + "map": [ + ["rand_warm", "air", "rand_warm", "rand_warm", "rand_warm"], + ["rand_warm", "rand_warm", "tnt_side", "rand_warm", "rand_warm"], + ["rand_warm", "rand_warm", "rand_warm", "rand_warm", "rand_warm"], + ["rand_cool", "barrel_50", "air", "rand_cool", "rand_cool"], + ["rand_cool", "rand_cool", "rand_cool", "rand_cool", "rand_cool"], + ["rand_cool", "exposed_copper_chest_inventory_front", "rand_cool", "rand_cool", "rand_cool"], + ["wool_colored_white", "wool_colored_white", "wool_colored_white", "wool_colored_white", "wool_colored_white"], + ["rand_dark", "rand_dark", "rand_dark", "rand_dark", "rand_dark"], + ["rand_dark", "air", "rand_dark", "rand_dark", "rand_dark"], + ["rand_dark", "rand_dark", "barrel_100", "rand_dark", "rand_dark"], + ["rand_dark", "rand_dark", "rand_dark", "rand_dark", "rand_dark"], + ["rand_dark", "rand_dark", "rand_dark", "rand_dark", "rand_dark"], + ["air", "air", "air", "air", "air"], + ["air", "chest_100", "chest_250", "air", "air"], + ["bedrock", "bedrock", "bedrock", "bedrock", "bedrock"] + ] + }, + { + "id": "scholar_sanctum", + "background_color": "#D2B48C", + "max_level": 0, + "random_pools": { + "rand_books": ["bookshelf", "chiseled_bookshelf_occupied", "crafting_table_front"], + "rand_stone": ["stonebrick", "stone", "cobblestone"], + "rand_deep": ["deepslate", "cobbled_deepslate"] + }, + "map": [ + ["rand_books", "air", "rand_books", "rand_books", "rand_books"], + ["rand_books", "rand_books", "tnt_side", "rand_books", "rand_books"], + ["rand_books", "rand_books", "rand_books", "rand_books", "rand_books"], + ["rand_stone", "barrel_250", "air", "rand_stone", "rand_stone"], + ["rand_stone", "rand_stone", "rand_stone", "rand_stone", "rand_stone"], + ["rand_stone", "oxidized_copper_chest_inventory_front", "rand_stone", "rand_stone", "rand_stone"], + ["stonebrick", "stonebrick", "stonebrick", "stonebrick", "stonebrick"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["rand_deep", "air", "rand_deep", "rand_deep", "rand_deep"], + ["rand_deep", "rand_deep", "barrel_500", "rand_deep", "rand_deep"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["air", "air", "air", "air", "air"], + ["air", "chest_500", "air", "ender_chest_front", "air"], + ["bedrock", "bedrock", "bedrock", "bedrock", "bedrock"] + ] + }, + { + "id": "slime_honey_pit", + "background_color": "#98FB98", + "max_level": 0, + "random_pools": { + "rand_sticky": ["slime", "honey_side"], + "rand_mid": ["clay", "stone", "gold_ore"], + "rand_deep": ["deepslate", "deepslate_gold_ore"] + }, + "map": [ + ["rand_sticky", "air", "rand_sticky", "rand_sticky", "rand_sticky"], + ["rand_sticky", "rand_sticky", "tnt_side", "rand_sticky", "rand_sticky"], + ["rand_sticky", "rand_sticky", "rand_sticky", "rand_sticky", "rand_sticky"], + ["rand_mid", "barrel_100", "air", "rand_mid", "rand_mid"], + ["rand_mid", "rand_mid", "rand_mid", "rand_mid", "rand_mid"], + ["rand_mid", "weathered_copper_chest_inventory_front", "rand_mid", "rand_mid", "rand_mid"], + ["clay", "clay", "clay", "clay", "clay"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["rand_deep", "air", "rand_deep", "rand_deep", "rand_deep"], + ["rand_deep", "rand_deep", "barrel_250", "rand_deep", "rand_deep"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["air", "air", "air", "air", "air"], + ["air", "chest_250", "air", "chest_250", "air"], + ["bedrock", "bedrock", "bedrock", "bedrock", "bedrock"] + ] + }, + { + "id": "gemstone_grotto", + "background_color": "#E0FFFF", + "max_level": 0, + "random_pools": { + "rand_gem": ["diamond_block", "emerald_block", "lapis_block"], + "rand_mid": ["diamond_ore", "emerald_ore", "stone"], + "rand_deep": ["deepslate_diamond_ore", "deepslate_emerald_ore", "deepslate"] + }, + "map": [ + ["rand_gem", "air", "rand_gem", "rand_gem", "rand_gem"], + ["rand_gem", "rand_gem", "tnt_side", "rand_gem", "rand_gem"], + ["rand_gem", "rand_gem", "rand_gem", "rand_gem", "rand_gem"], + ["rand_mid", "barrel_250", "air", "rand_mid", "rand_mid"], + ["rand_mid", "rand_mid", "rand_mid", "rand_mid", "rand_mid"], + ["rand_mid", "exposed_copper_chest_inventory_front", "rand_mid", "rand_mid", "rand_mid"], + ["stone", "stone", "stone", "stone", "stone"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["rand_deep", "air", "rand_deep", "rand_deep", "rand_deep"], + ["rand_deep", "rand_deep", "barrel_500", "rand_deep", "rand_deep"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["air", "air", "air", "air", "air"], + ["air", "chest_500", "ender_chest_front", "air", "air"], + ["bedrock", "bedrock", "bedrock", "bedrock", "bedrock"] + ] + }, + { + "id": "volcanic_ash", + "background_color": "#2F4F4F", + "max_level": 0, + "random_pools": { + "rand_ash": ["basalt_side", "magma", "tuff"], + "rand_mid": ["tuff", "coal_ore", "stone"], + "rand_deep": ["blackstone", "ancient_debris_side", "obsidian"] + }, + "map": [ + ["rand_ash", "air", "rand_ash", "rand_ash", "rand_ash"], + ["rand_ash", "rand_ash", "tnt_side", "rand_ash", "rand_ash"], + ["rand_ash", "rand_ash", "rand_ash", "rand_ash", "rand_ash"], + ["rand_mid", "barrel_100", "air", "rand_mid", "rand_mid"], + ["rand_mid", "rand_mid", "rand_mid", "rand_mid", "rand_mid"], + ["rand_mid", "oxidized_copper_chest_inventory_front", "rand_mid", "rand_mid", "rand_mid"], + ["tuff", "tuff", "tuff", "tuff", "tuff"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["rand_deep", "air", "rand_deep", "rand_deep", "rand_deep"], + ["rand_deep", "rand_deep", "barrel_250", "rand_deep", "rand_deep"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["air", "air", "air", "air", "air"], + ["air", "chest_250", "air", "chest_500", "air"], + ["bedrock", "bedrock", "bedrock", "bedrock", "bedrock"] + ] + }, + { + "id": "ruined_citadel", + "background_color": "#708090", + "max_level": 0, + "random_pools": { + "rand_ruin": ["stonebrick", "cobblestone_mossy", "cobblestone"], + "rand_mid": ["stone", "andesite", "iron_ore"], + "rand_deep": ["deepslate", "cobbled_deepslate", "deepslate_iron_ore"] + }, + "map": [ + ["rand_ruin", "air", "rand_ruin", "rand_ruin", "rand_ruin"], + ["rand_ruin", "rand_ruin", "tnt_side", "rand_ruin", "rand_ruin"], + ["rand_ruin", "rand_ruin", "rand_ruin", "rand_ruin", "rand_ruin"], + ["rand_mid", "barrel_50", "air", "rand_mid", "rand_mid"], + ["rand_mid", "rand_mid", "rand_mid", "rand_mid", "rand_mid"], + ["rand_mid", "weathered_copper_chest_inventory_front", "rand_mid", "rand_mid", "rand_mid"], + ["stone", "stone", "stone", "stone", "stone"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["rand_deep", "air", "rand_deep", "rand_deep", "rand_deep"], + ["rand_deep", "rand_deep", "barrel_100", "rand_deep", "rand_deep"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["air", "air", "air", "air", "air"], + ["air", "chest_100", "chest_250", "air", "air"], + ["bedrock", "bedrock", "bedrock", "bedrock", "bedrock"] + ] + }, + { + "id": "netherite_factory", + "background_color": "#3B3B3B", + "max_level": 0, + "random_pools": { + "rand_hard": ["ancient_debris_side", "netherite_block", "obsidian"], + "rand_mid": ["blackstone", "gilded_blackstone", "basalt_side"], + "rand_deep": ["reinforced_deepslate_side", "obsidian", "crying_obsidian"] + }, + "map": [ + ["rand_hard", "air", "rand_hard", "rand_hard", "rand_hard"], + ["rand_hard", "rand_hard", "tnt_side", "rand_hard", "rand_hard"], + ["rand_hard", "rand_hard", "rand_hard", "rand_hard", "rand_hard"], + ["rand_mid", "barrel_500", "air", "rand_mid", "rand_mid"], + ["rand_mid", "rand_mid", "rand_mid", "rand_mid", "rand_mid"], + ["rand_mid", "oxidized_copper_chest_inventory_front", "rand_mid", "rand_mid", "rand_mid"], + ["blackstone", "blackstone", "blackstone", "blackstone", "blackstone"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["rand_deep", "air", "rand_deep", "rand_deep", "rand_deep"], + ["rand_deep", "rand_deep", "barrel_500", "rand_deep", "rand_deep"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["air", "air", "air", "air", "air"], + ["air", "ender_chest_front", "air", "ender_chest_front", "air"], + ["bedrock", "bedrock", "bedrock", "bedrock", "bedrock"] + ] + }, + { + "id": "obsidian_mirage", + "background_color": "#1A0033", + "max_level": 0, + "random_pools": { + "rand_obsidian": ["obsidian", "crying_obsidian", "glowing_obsidian"], + "rand_mid": ["amethyst_block", "calcite", "diorite"], + "rand_deep": ["deepslate", "cobbled_deepslate", "obsidian"] + }, + "map": [ + ["rand_obsidian", "air", "rand_obsidian", "rand_obsidian", "rand_obsidian"], + ["rand_obsidian", "rand_obsidian", "tnt_side", "rand_obsidian", "rand_obsidian"], + ["rand_obsidian", "rand_obsidian", "rand_obsidian", "rand_obsidian", "rand_obsidian"], + ["rand_mid", "barrel_250", "air", "rand_mid", "rand_mid"], + ["rand_mid", "rand_mid", "rand_mid", "rand_mid", "rand_mid"], + ["rand_mid", "exposed_copper_chest_inventory_front", "rand_mid", "rand_mid", "rand_mid"], + ["calcite", "calcite", "calcite", "calcite", "calcite"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["rand_deep", "air", "rand_deep", "rand_deep", "rand_deep"], + ["rand_deep", "rand_deep", "barrel_250", "rand_deep", "rand_deep"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["air", "air", "air", "air", "air"], + ["air", "chest_250", "chest_500", "air", "air"], + ["bedrock", "bedrock", "bedrock", "bedrock", "bedrock"] + ] + }, + { + "id": "copper_machinery", + "background_color": "#CD7F32", + "max_level": 0, + "random_pools": { + "rand_cop": ["copper_block", "exposed_copper", "raw_copper_block"], + "rand_mid": ["weathered_copper", "oxidized_copper", "stone"], + "rand_deep": ["deepslate", "deepslate_copper_ore", "deepslate_redstone_ore"] + }, + "map": [ + ["rand_cop", "air", "rand_cop", "rand_cop", "rand_cop"], + ["rand_cop", "rand_cop", "tnt_side", "rand_cop", "rand_cop"], + ["rand_cop", "rand_cop", "rand_cop", "rand_cop", "rand_cop"], + ["rand_mid", "barrel_100", "air", "rand_mid", "rand_mid"], + ["rand_mid", "rand_mid", "rand_mid", "rand_mid", "rand_mid"], + ["rand_mid", "weathered_copper_chest_inventory_front", "rand_mid", "rand_mid", "rand_mid"], + ["stone", "stone", "stone", "stone", "stone"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["rand_deep", "air", "rand_deep", "rand_deep", "rand_deep"], + ["rand_deep", "rand_deep", "barrel_250", "rand_deep", "rand_deep"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["air", "air", "air", "air", "air"], + ["air", "copper_chest_inventory_front", "chest_250", "air", "air"], + ["bedrock", "bedrock", "bedrock", "bedrock", "bedrock"] + ] + }, + { + "id": "chaos_realm", + "background_color": "#FF00FF", + "max_level": 0, + "random_pools": { + "rand_chaos1": ["wool_colored_magenta", "slime", "diamond_block", "magma", "bookshelf"], + "rand_chaos2": ["tuff", "end_stone", "crafting_table_front", "nether_wart_block", "honey_side"], + "rand_chaos3": ["gilded_blackstone", "raw_gold_block", "ice_packed", "suspicious_sand", "emerald_block"] + }, + "map": [ + ["rand_chaos1", "air", "rand_chaos1", "rand_chaos2", "rand_chaos3"], + ["rand_chaos3", "rand_chaos2", "tnt_side", "rand_chaos1", "rand_chaos2"], + ["rand_chaos2", "rand_chaos1", "rand_chaos3", "rand_chaos3", "rand_chaos1"], + ["rand_chaos1", "barrel_250", "air", "rand_chaos2", "rand_chaos3"], + ["rand_chaos3", "rand_chaos3", "rand_chaos1", "rand_chaos2", "rand_chaos1"], + ["rand_chaos2", "oxidized_copper_chest_inventory_front", "rand_chaos3", "rand_chaos1", "rand_chaos2"], + ["rand_chaos1", "rand_chaos2", "rand_chaos3", "rand_chaos1", "rand_chaos2"], + ["rand_chaos3", "rand_chaos1", "rand_chaos2", "rand_chaos3", "rand_chaos1"], + ["rand_chaos2", "air", "rand_chaos1", "rand_chaos3", "rand_chaos2"], + ["rand_chaos1", "rand_chaos3", "barrel_500", "rand_chaos2", "rand_chaos1"], + ["rand_chaos3", "rand_chaos2", "rand_chaos1", "rand_chaos3", "rand_chaos2"], + ["rand_chaos2", "rand_chaos1", "rand_chaos3", "rand_chaos1", "rand_chaos2"], + ["air", "air", "air", "air", "air"], + ["air", "chest_500", "chest_100", "ender_chest_front", "air"], + ["bedrock", "bedrock", "bedrock", "bedrock", "bedrock"] + ] + }, + + { + "id": "bonus_overworld_ores", + "background_color": "#FFD700", + "max_level": 0, + "random_pools": { + "rand_low": ["coal_ore", "copper_ore", "iron_ore"], + "rand_mid": ["gold_ore", "lapis_ore", "redstone_ore"], + "rand_high": ["diamond_ore", "emerald_ore"] + }, + "map": [ + ["rand_low", "rand_low", "rand_low", "rand_low", "rand_low"], + ["rand_low", "rand_low", "tnt_side", "rand_low", "rand_low"], + ["rand_low", "rand_low", "rand_low", "rand_low", "rand_low"], + ["rand_mid", "barrel_100", "rand_mid", "rand_mid", "rand_mid"], + ["rand_mid", "rand_mid", "rand_mid", "rand_mid", "rand_mid"], + ["rand_mid", "copper_chest_inventory_front", "rand_mid", "rand_mid", "rand_mid"], + ["rand_mid", "rand_mid", "rand_mid", "rand_mid", "rand_mid"], + ["rand_high", "rand_high", "rand_high", "rand_high", "rand_high"], + ["rand_high", "rand_high", "rand_high", "rand_high", "rand_high"], + ["rand_high", "rand_high", "barrel_250", "rand_high", "rand_high"], + ["rand_high", "rand_high", "rand_high", "rand_high", "rand_high"], + ["rand_high", "rand_high", "rand_high", "rand_high", "rand_high"], + ["air", "air", "air", "air", "air"], + ["chest_250", "chest_500", "chest_500", "chest_500", "chest_250"], + ["bedrock", "bedrock", "bedrock", "bedrock", "bedrock"] + ] + }, + { + "id": "bonus_deepslate_riches", + "background_color": "#B8860B", + "max_level": 0, + "random_pools": { + "rand_low": ["deepslate_coal_ore", "deepslate_copper_ore", "deepslate_iron_ore"], + "rand_mid": ["deepslate_gold_ore", "deepslate_lapis_ore", "deepslate_redstone_ore"], + "rand_high": ["deepslate_diamond_ore", "deepslate_emerald_ore"] + }, + "map": [ + ["rand_low", "rand_low", "rand_low", "rand_low", "rand_low"], + ["rand_low", "rand_low", "tnt_side", "rand_low", "rand_low"], + ["rand_low", "rand_low", "rand_low", "rand_low", "rand_low"], + ["rand_mid", "barrel_250", "rand_mid", "rand_mid", "rand_mid"], + ["rand_mid", "rand_mid", "rand_mid", "rand_mid", "rand_mid"], + ["rand_mid", "exposed_copper_chest_inventory_front", "rand_mid", "rand_mid", "rand_mid"], + ["rand_mid", "rand_mid", "rand_mid", "rand_mid", "rand_mid"], + ["rand_high", "rand_high", "rand_high", "rand_high", "rand_high"], + ["rand_high", "rand_high", "rand_high", "rand_high", "rand_high"], + ["rand_high", "rand_high", "barrel_500", "rand_high", "rand_high"], + ["rand_high", "rand_high", "rand_high", "rand_high", "rand_high"], + ["rand_high", "rand_high", "rand_high", "rand_high", "rand_high"], + ["air", "air", "air", "air", "air"], + ["chest_500", "ender_chest_front", "chest_500", "ender_chest_front", "chest_500"], + ["bedrock", "bedrock", "bedrock", "bedrock", "bedrock"] + ] + }, + { + "id": "bonus_nether_vault", + "background_color": "#FF4500", + "max_level": 0, + "random_pools": { + "rand_low": ["nether_gold_ore", "quartz_ore", "sulfur"], + "rand_mid": ["glowstone", "gilded_blackstone"], + "rand_high": ["ancient_debris_side"] + }, + "map": [ + ["rand_low", "rand_low", "rand_low", "rand_low", "rand_low"], + ["rand_low", "rand_low", "tnt_side", "rand_low", "rand_low"], + ["rand_low", "rand_low", "rand_low", "rand_low", "rand_low"], + ["rand_mid", "barrel_250", "rand_mid", "rand_mid", "rand_mid"], + ["rand_mid", "rand_mid", "rand_mid", "rand_mid", "rand_mid"], + ["rand_mid", "weathered_copper_chest_inventory_front", "rand_mid", "rand_mid", "rand_mid"], + ["rand_mid", "rand_mid", "rand_mid", "rand_mid", "rand_mid"], + ["rand_high", "rand_high", "rand_high", "rand_high", "rand_high"], + ["rand_high", "rand_high", "rand_high", "rand_high", "rand_high"], + ["rand_high", "rand_high", "barrel_500", "rand_high", "rand_high"], + ["rand_high", "rand_high", "rand_high", "rand_high", "rand_high"], + ["rand_high", "rand_high", "rand_high", "rand_high", "rand_high"], + ["air", "air", "air", "air", "air"], + ["ender_chest_front", "chest_500", "ender_chest_front", "chest_500", "ender_chest_front"], + ["bedrock", "bedrock", "bedrock", "bedrock", "bedrock"] + ] + }, + { + "id": "bonus_raw_metal_stash", + "background_color": "#DAA520", + "max_level": 0, + "random_pools": { + "rand_cop": ["raw_copper_block", "amethyst_block"], + "rand_iron": ["raw_iron_block"], + "rand_gold": ["raw_gold_block"] + }, + "map": [ + ["rand_cop", "rand_cop", "rand_cop", "rand_cop", "rand_cop"], + ["rand_cop", "rand_cop", "tnt_side", "rand_cop", "rand_cop"], + ["rand_cop", "rand_cop", "rand_cop", "rand_cop", "rand_cop"], + ["rand_iron", "barrel_100", "rand_iron", "rand_iron", "rand_iron"], + ["rand_iron", "rand_iron", "rand_iron", "rand_iron", "rand_iron"], + ["rand_iron", "oxidized_copper_chest_inventory_front", "rand_iron", "rand_iron", "rand_iron"], + ["rand_iron", "rand_iron", "rand_iron", "rand_iron", "rand_iron"], + ["rand_gold", "rand_gold", "rand_gold", "rand_gold", "rand_gold"], + ["rand_gold", "rand_gold", "rand_gold", "rand_gold", "rand_gold"], + ["rand_gold", "rand_gold", "barrel_250", "rand_gold", "rand_gold"], + ["rand_gold", "rand_gold", "rand_gold", "rand_gold", "rand_gold"], + ["rand_gold", "rand_gold", "rand_gold", "rand_gold", "rand_gold"], + ["air", "air", "air", "air", "air"], + ["chest_250", "copper_chest_inventory_front", "chest_500", "copper_chest_inventory_front", "chest_250"], + ["bedrock", "bedrock", "bedrock", "bedrock", "bedrock"] + ] + }, + { + "id": "bonus_honey_library", + "background_color": "#FFA500", + "max_level": 0, + "random_pools": { + "rand_nest": ["bee_nest_front", "beehive_front"], + "rand_honey": ["bee_nest_front_honey", "beehive_front_honey"], + "rand_books": ["bookshelf", "chiseled_bookshelf_occupied"] + }, + "map": [ + ["rand_nest", "rand_nest", "rand_nest", "rand_nest", "rand_nest"], + ["rand_nest", "rand_nest", "tnt_side", "rand_nest", "rand_nest"], + ["rand_nest", "rand_nest", "rand_nest", "rand_nest", "rand_nest"], + ["rand_honey", "barrel_250", "rand_honey", "rand_honey", "rand_honey"], + ["rand_honey", "rand_honey", "rand_honey", "rand_honey", "rand_honey"], + ["rand_honey", "exposed_copper_chest_inventory_front", "rand_honey", "rand_honey", "rand_honey"], + ["rand_honey", "rand_honey", "rand_honey", "rand_honey", "rand_honey"], + ["rand_books", "rand_books", "rand_books", "rand_books", "rand_books"], + ["rand_books", "rand_books", "rand_books", "rand_books", "rand_books"], + ["rand_books", "rand_books", "barrel_250", "rand_books", "rand_books"], + ["rand_books", "rand_books", "rand_books", "rand_books", "rand_books"], + ["rand_books", "rand_books", "rand_books", "rand_books", "rand_books"], + ["air", "air", "air", "air", "air"], + ["chest_500", "chest_250", "chest_500", "chest_250", "chest_500"], + ["bedrock", "bedrock", "bedrock", "bedrock", "bedrock"] + ] + }, + { + "id": "bonus_admin_secret", + "background_color": "#8A2BE2", + "max_level": 0, + "random_pools": { + "rand_low": ["deepslate_emerald_ore", "ancient_debris_side"], + "rand_mid": ["ender_chest_front"], + "rand_high": ["command_block_back_mipmap"] + }, + "map": [ + ["rand_low", "rand_low", "rand_low", "rand_low", "rand_low"], + ["rand_low", "rand_low", "tnt_side", "rand_low", "rand_low"], + ["rand_low", "rand_low", "rand_low", "rand_low", "rand_low"], + ["rand_mid", "barrel_500", "rand_mid", "rand_mid", "rand_mid"], + ["rand_mid", "rand_mid", "rand_mid", "rand_mid", "rand_mid"], + ["rand_mid", "oxidized_copper_chest_inventory_front", "rand_mid", "rand_mid", "rand_mid"], + ["rand_mid", "rand_mid", "rand_mid", "rand_mid", "rand_mid"], + ["rand_high", "rand_high", "rand_high", "rand_high", "rand_high"], + ["rand_high", "rand_high", "rand_high", "rand_high", "rand_high"], + ["rand_high", "rand_high", "barrel_500", "rand_high", "rand_high"], + ["rand_high", "rand_high", "rand_high", "rand_high", "rand_high"], + ["rand_high", "rand_high", "rand_high", "rand_high", "rand_high"], + ["air", "air", "air", "air", "air"], + ["ender_chest_front", "ender_chest_front", "ender_chest_front", "ender_chest_front", "ender_chest_front"], + ["bedrock", "bedrock", "bedrock", "bedrock", "bedrock"] + ] + } + ] +} diff --git a/public/games/doge_rescue/assets/bee.png b/public/games/doge_rescue/assets/bee.png new file mode 100644 index 0000000..bcc2caa Binary files /dev/null and b/public/games/doge_rescue/assets/bee.png differ diff --git a/public/games/doge_rescue/assets/bee_nest.png b/public/games/doge_rescue/assets/bee_nest.png new file mode 100644 index 0000000..429fe06 Binary files /dev/null and b/public/games/doge_rescue/assets/bee_nest.png differ diff --git a/public/games/doge_rescue/assets/dirt.png b/public/games/doge_rescue/assets/dirt.png new file mode 100644 index 0000000..2af9958 Binary files /dev/null and b/public/games/doge_rescue/assets/dirt.png differ diff --git a/public/games/doge_rescue/assets/dog.png b/public/games/doge_rescue/assets/dog.png new file mode 100644 index 0000000..eeed12d Binary files /dev/null and b/public/games/doge_rescue/assets/dog.png differ diff --git a/public/games/doge_rescue/assets/grass.png b/public/games/doge_rescue/assets/grass.png new file mode 100644 index 0000000..30663bf Binary files /dev/null and b/public/games/doge_rescue/assets/grass.png differ diff --git a/public/games/doge_rescue/data/blocks.json b/public/games/doge_rescue/data/blocks.json new file mode 100644 index 0000000..be46fc5 --- /dev/null +++ b/public/games/doge_rescue/data/blocks.json @@ -0,0 +1,22 @@ +{ + "dirt": { + "src": "games/doge_rescue/assets/dirt.png", + "solid": true + }, + "grass": { + "src": "games/doge_rescue/assets/grass.png", + "solid": true + }, + "bee_nest": { + "src": "games/doge_rescue/assets/bee_nest.png", + "solid": true, + "spawn": "bees" + }, + "doge_spawn": { + "solid": false, + "spawn": "doge" + }, + "air": { + "solid": false + } +} diff --git a/public/games/doge_rescue/data/levels.json b/public/games/doge_rescue/data/levels.json new file mode 100644 index 0000000..8d3bf2e --- /dev/null +++ b/public/games/doge_rescue/data/levels.json @@ -0,0 +1,690 @@ +{ + "levels": [ + { + "id": "level_1", + "duration": 5, + "beesCount": 5, + "tintLimit": 1500, + "brutality": { "maxSpeed": 8, "force": 0.01 }, + "map": [ + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "bee_nest", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "doge_spawn", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["grass", "grass", "grass", "grass", "grass", "grass", "grass", "grass", "grass", "grass"], + ["dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt"] + ] + }, + { + "id": "level_2", + "duration": 8, + "beesCount": 8, + "tintLimit": 1200, + "brutality": { "maxSpeed": 10, "force": 0.01 }, + "map": [ + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "bee_nest"], + ["air", "bee_nest", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["grass", "grass", "grass", "air", "air", "air", "air", "grass", "grass", "grass"], + ["dirt", "dirt", "dirt", "air", "air", "doge_spawn", "air", "dirt", "dirt", "dirt"], + ["dirt", "dirt", "dirt", "grass", "grass", "grass", "grass", "dirt", "dirt", "dirt"], + ["dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt"], + ["dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt"], + ["dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt"] + ] + }, + { + "id": "level_3", + "duration": 10, + "beesCount": 10, + "tintLimit": 1000, + "brutality": { "maxSpeed": 12, "force": 0.012 }, + "map": [ + ["bee_nest", "air", "air", "air", "air", "air", "air", "air", "air", "bee_nest"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "doge_spawn", "air", "air", "air", "air", "air"], + ["grass", "grass", "air", "air", "grass", "grass", "air", "air", "grass", "grass"], + ["dirt", "dirt", "air", "air", "dirt", "dirt", "air", "air", "dirt", "dirt"], + ["dirt", "dirt", "air", "air", "dirt", "dirt", "air", "air", "dirt", "dirt"], + ["dirt", "dirt", "grass", "grass", "dirt", "dirt", "grass", "grass", "dirt", "dirt"] + ] + }, + { + "id": "level_4", + "duration": 10, + "beesCount": 12, + "tintLimit": 1000, + "brutality": { "maxSpeed": 12, "force": 0.012 }, + "map": [ + ["air", "air", "air", "air", "bee_nest", "bee_nest", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["grass", "air", "air", "air", "doge_spawn", "air", "air", "air", "air", "grass"], + ["dirt", "grass", "air", "grass", "grass", "grass", "grass", "air", "grass", "dirt"], + ["dirt", "dirt", "air", "dirt", "dirt", "dirt", "dirt", "air", "dirt", "dirt"], + ["dirt", "dirt", "air", "dirt", "dirt", "dirt", "dirt", "air", "dirt", "dirt"], + ["dirt", "dirt", "air", "dirt", "dirt", "dirt", "dirt", "air", "dirt", "dirt"], + ["dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt"] + ] + }, + { + "id": "level_5", + "duration": 12, + "beesCount": 15, + "tintLimit": 1000, + "brutality": { "maxSpeed": 14, "force": 0.015 }, + "map": [ + ["bee_nest", "air", "air", "air", "bee_nest", "air", "air", "air", "air", "bee_nest"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "grass", "grass", "air", "air", "grass", "grass", "air", "air"], + ["air", "air", "dirt", "dirt", "air", "air", "dirt", "dirt", "air", "air"], + ["grass", "air", "dirt", "dirt", "air", "air", "dirt", "dirt", "air", "grass"], + ["dirt", "air", "dirt", "dirt", "doge_spawn", "air", "dirt", "dirt", "air", "dirt"], + ["dirt", "grass", "dirt", "dirt", "grass", "grass", "dirt", "dirt", "grass", "dirt"], + ["dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt"] + ] + }, + { + "id": "level_6", + "duration": 12, + "beesCount": 18, + "tintLimit": 1000, + "brutality": { "maxSpeed": 14, "force": 0.015 }, + "map": [ + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "bee_nest", "air", "air", "air", "air", "air", "air", "bee_nest", "air"], + ["air", "air", "air", "air", "doge_spawn", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "grass", "grass", "air", "air", "air", "air"], + ["air", "air", "air", "air", "dirt", "dirt", "air", "air", "air", "air"], + ["air", "air", "air", "air", "dirt", "dirt", "air", "air", "air", "air"], + ["air", "air", "grass", "grass", "dirt", "dirt", "grass", "grass", "air", "air"], + ["air", "air", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "air", "air"], + ["grass", "grass", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "grass", "grass"], + ["dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt"] + ] + }, + { + "id": "level_7", + "duration": 15, + "beesCount": 20, + "tintLimit": 1000, + "brutality": { "maxSpeed": 16, "force": 0.018 }, + "map": [ + ["bee_nest", "air", "air", "air", "air", "air", "air", "air", "air", "bee_nest"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["grass", "grass", "air", "air", "air", "air", "air", "air", "grass", "grass"], + ["dirt", "dirt", "air", "air", "air", "air", "air", "air", "dirt", "dirt"], + ["dirt", "dirt", "air", "air", "air", "air", "air", "air", "dirt", "dirt"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "doge_spawn", "air", "air", "air", "air", "air"], + ["grass", "grass", "air", "grass", "grass", "grass", "grass", "air", "grass", "grass"], + ["dirt", "dirt", "air", "dirt", "dirt", "dirt", "dirt", "air", "dirt", "dirt"] + ] + }, + { + "id": "level_8", + "duration": 15, + "beesCount": 22, + "tintLimit": 1000, + "brutality": { "maxSpeed": 16, "force": 0.018 }, + "map": [ + ["grass", "grass", "grass", "grass", "grass", "grass", "grass", "grass", "grass", "grass"], + ["dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt"], + ["bee_nest", "air", "air", "air", "bee_nest", "air", "air", "air", "air", "bee_nest"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "doge_spawn", "air", "air", "air", "air", "air"], + ["grass", "grass", "grass", "grass", "grass", "grass", "grass", "grass", "grass", "grass"], + ["dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt"] + ] + }, + { + "id": "level_9", + "duration": 18, + "beesCount": 25, + "tintLimit": 1100, + "brutality": { "maxSpeed": 18, "force": 0.02 }, + "map": [ + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "bee_nest"], + ["air", "air", "air", "air", "air", "air", "air", "air", "grass", "dirt"], + ["air", "air", "air", "air", "air", "air", "air", "grass", "dirt", "dirt"], + ["air", "air", "air", "air", "air", "air", "grass", "dirt", "dirt", "dirt"], + ["bee_nest", "air", "air", "air", "air", "grass", "dirt", "dirt", "dirt", "dirt"], + ["air", "air", "air", "air", "doge_spawn", "dirt", "dirt", "dirt", "dirt", "dirt"], + ["air", "air", "air", "grass", "grass", "dirt", "dirt", "dirt", "dirt", "dirt"], + ["air", "air", "grass", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt"], + ["air", "grass", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt"], + ["grass", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt"] + ] + }, + { + "id": "level_10", + "duration": 18, + "beesCount": 28, + "tintLimit": 1100, + "brutality": { "maxSpeed": 20, "force": 0.02 }, + "map": [ + ["bee_nest", "air", "air", "air", "bee_nest", "air", "air", "air", "air", "bee_nest"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "grass", "grass", "air", "air", "air", "air", "grass", "grass", "air"], + ["air", "dirt", "dirt", "air", "air", "air", "air", "dirt", "dirt", "air"], + ["air", "dirt", "dirt", "air", "doge_spawn", "air", "air", "dirt", "dirt", "air"], + ["air", "dirt", "dirt", "air", "grass", "grass", "air", "dirt", "dirt", "air"], + ["air", "dirt", "dirt", "air", "dirt", "dirt", "air", "dirt", "dirt", "air"], + ["grass", "dirt", "dirt", "grass", "dirt", "dirt", "grass", "dirt", "dirt", "grass"], + ["dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt"] + ] + }, + { + "id": "level_11", + "duration": 20, + "beesCount": 30, + "tintLimit": 1200, + "brutality": { "maxSpeed": 22, "force": 0.022 }, + "map": [ + ["air", "bee_nest", "air", "air", "bee_nest", "air", "air", "bee_nest", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["grass", "grass", "air", "grass", "grass", "grass", "grass", "air", "grass", "grass"], + ["dirt", "dirt", "air", "dirt", "dirt", "dirt", "dirt", "air", "dirt", "dirt"], + ["dirt", "dirt", "air", "dirt", "dirt", "dirt", "dirt", "air", "dirt", "dirt"], + ["dirt", "dirt", "air", "dirt", "dirt", "dirt", "dirt", "air", "dirt", "dirt"], + ["dirt", "dirt", "air", "air", "doge_spawn", "air", "air", "air", "dirt", "dirt"], + ["dirt", "dirt", "air", "grass", "grass", "grass", "grass", "air", "dirt", "dirt"], + ["dirt", "dirt", "air", "dirt", "dirt", "dirt", "dirt", "air", "dirt", "dirt"], + ["dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt"] + ] + }, + { + "id": "level_12", + "duration": 20, + "beesCount": 35, + "tintLimit": 1200, + "brutality": { "maxSpeed": 25, "force": 0.025 }, + "map": [ + ["bee_nest", "air", "bee_nest", "air", "air", "air", "air", "bee_nest", "air", "bee_nest"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["grass", "grass", "air", "air", "air", "air", "air", "air", "grass", "grass"], + ["dirt", "dirt", "air", "air", "air", "air", "air", "air", "dirt", "dirt"], + ["dirt", "dirt", "air", "air", "doge_spawn", "air", "air", "air", "dirt", "dirt"], + ["dirt", "dirt", "air", "air", "grass", "grass", "air", "air", "dirt", "dirt"], + ["dirt", "dirt", "air", "air", "dirt", "dirt", "air", "air", "dirt", "dirt"], + ["dirt", "dirt", "grass", "grass", "dirt", "dirt", "grass", "grass", "dirt", "dirt"], + ["dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt"] + ] + }, + + { + "id": "level_1_fast", + "duration": 4, + "beesCount": 3, + "tintLimit": 2500, + "brutality": { "maxSpeed": 18, "force": 0.002 }, + "map": [ + ["air", "air", "air", "air", "bee_nest", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "doge_spawn", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["grass", "grass", "grass", "grass", "grass", "grass", "grass", "grass", "grass", "grass"], + ["dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt"] + ] + }, + { + "id": "level_2_fast", + "duration": 5, + "beesCount": 4, + "tintLimit": 2800, + "brutality": { "maxSpeed": 20, "force": 0.001 }, + "map": [ + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "bee_nest"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["grass", "air", "air", "air", "doge_spawn", "air", "air", "air", "air", "grass"], + ["dirt", "grass", "air", "air", "air", "air", "air", "air", "grass", "dirt"], + ["dirt", "dirt", "grass", "grass", "grass", "grass", "grass", "grass", "dirt", "dirt"], + ["dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt"] + ] + }, + { + "id": "level_3_fast", + "duration": 5, + "beesCount": 3, + "tintLimit": 2200, + "brutality": { "maxSpeed": 17, "force": 0.002 }, + "map": [ + ["bee_nest", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["grass", "grass", "air", "air", "air", "air", "air", "air", "grass", "grass"], + ["dirt", "dirt", "air", "air", "doge_spawn", "air", "air", "air", "dirt", "dirt"], + ["dirt", "dirt", "grass", "air", "air", "air", "air", "grass", "dirt", "dirt"], + ["dirt", "dirt", "dirt", "grass", "grass", "grass", "grass", "dirt", "dirt", "dirt"], + ["dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt"] + ] + }, + { + "id": "level_4_fast", + "duration": 6, + "beesCount": 5, + "tintLimit": 3000, + "brutality": { "maxSpeed": 19, "force": 0.003 }, + "map": [ + ["air", "air", "air", "air", "air", "air", "air", "air", "bee_nest", "air"], + ["air", "bee_nest", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "doge_spawn", "air", "air", "air", "air", "air"], + ["air", "air", "air", "grass", "grass", "grass", "grass", "air", "air", "air"], + ["air", "air", "grass", "dirt", "dirt", "dirt", "dirt", "grass", "air", "air"], + ["air", "grass", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "grass", "air"], + ["grass", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "grass"] + ] + }, + { + "id": "level_5_fast", + "duration": 4, + "beesCount": 2, + "tintLimit": 2400, + "brutality": { "maxSpeed": 16, "force": 0.001 }, + "map": [ + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "bee_nest", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "doge_spawn", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["grass", "grass", "air", "air", "air", "air", "grass", "grass", "grass", "grass"], + ["dirt", "dirt", "grass", "grass", "grass", "grass", "dirt", "dirt", "dirt", "dirt"], + ["dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt"] + ] + }, + { + "id": "level_6_fast", + "duration": 7, + "beesCount": 4, + "tintLimit": 2600, + "brutality": { "maxSpeed": 18, "force": 0.002 }, + "map": [ + ["bee_nest", "air", "air", "air", "air", "air", "air", "air", "air", "bee_nest"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "doge_spawn", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["grass", "air", "air", "grass", "grass", "grass", "grass", "air", "air", "grass"], + ["dirt", "grass", "grass", "dirt", "dirt", "dirt", "dirt", "grass", "grass", "dirt"], + ["dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt"] + ] + }, + { + "id": "level_7_slow", + "duration": 4, + "beesCount": 3, + "tintLimit": 2500, + "brutality": { "maxSpeed": 4, "force": 0.002 }, + "map": [ + ["air", "air", "air", "air", "bee_nest", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "doge_spawn", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["grass", "grass", "grass", "grass", "grass", "grass", "grass", "grass", "grass", "grass"], + ["dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt"] + ] + }, + { + "id": "level_8_slow", + "duration": 5, + "beesCount": 4, + "tintLimit": 2800, + "brutality": { "maxSpeed": 3, "force": 0.001 }, + "map": [ + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "bee_nest"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["grass", "air", "air", "air", "doge_spawn", "air", "air", "air", "air", "grass"], + ["dirt", "grass", "air", "air", "air", "air", "air", "air", "grass", "dirt"], + ["dirt", "dirt", "grass", "grass", "grass", "grass", "grass", "grass", "dirt", "dirt"], + ["dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt"] + ] + }, + { + "id": "level_9_slow", + "duration": 5, + "beesCount": 3, + "tintLimit": 2200, + "brutality": { "maxSpeed": 5, "force": 0.002 }, + "map": [ + ["bee_nest", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["grass", "grass", "air", "air", "air", "air", "air", "air", "grass", "grass"], + ["dirt", "dirt", "air", "air", "doge_spawn", "air", "air", "air", "dirt", "dirt"], + ["dirt", "dirt", "grass", "air", "air", "air", "air", "grass", "dirt", "dirt"], + ["dirt", "dirt", "dirt", "grass", "grass", "grass", "grass", "dirt", "dirt", "dirt"], + ["dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt"] + ] + }, + { + "id": "level_10_slow", + "duration": 6, + "beesCount": 5, + "tintLimit": 3000, + "brutality": { "maxSpeed": 4, "force": 0.003 }, + "map": [ + ["air", "air", "air", "air", "air", "air", "air", "air", "bee_nest", "air"], + ["air", "bee_nest", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "doge_spawn", "air", "air", "air", "air", "air"], + ["air", "air", "air", "grass", "grass", "grass", "grass", "air", "air", "air"], + ["air", "air", "grass", "dirt", "dirt", "dirt", "dirt", "grass", "air", "air"], + ["air", "grass", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "grass", "air"], + ["grass", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "grass"] + ] + }, + { + "id": "level_11_slow", + "duration": 4, + "beesCount": 2, + "tintLimit": 2400, + "brutality": { "maxSpeed": 3, "force": 0.001 }, + "map": [ + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "bee_nest", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "doge_spawn", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["grass", "grass", "air", "air", "air", "air", "grass", "grass", "grass", "grass"], + ["dirt", "dirt", "grass", "grass", "grass", "grass", "dirt", "dirt", "dirt", "dirt"], + ["dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt"] + ] + }, + { + "id": "level_12_slow", + "duration": 7, + "beesCount": 4, + "tintLimit": 2600, + "brutality": { "maxSpeed": 4, "force": 0.002 }, + "map": [ + ["bee_nest", "air", "air", "air", "air", "air", "air", "air", "air", "bee_nest"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "doge_spawn", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["grass", "air", "air", "grass", "grass", "grass", "grass", "air", "air", "grass"], + ["dirt", "grass", "grass", "dirt", "dirt", "dirt", "dirt", "grass", "grass", "dirt"], + ["dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt"] + ] + }, + + { + "id": "level_1_hard_fast", + "duration": 10, + "beesCount": 40, + "tintLimit": 800, + "brutality": { "maxSpeed": 28, "force": 0.08 }, + "map": [ + ["bee_nest", "air", "air", "bee_nest", "air", "air", "bee_nest", "air", "air", "bee_nest"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "doge_spawn", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["grass", "grass", "air", "air", "grass", "grass", "air", "air", "grass", "grass"], + ["dirt", "dirt", "air", "air", "dirt", "dirt", "air", "air", "dirt", "dirt"], + ["dirt", "dirt", "air", "air", "dirt", "dirt", "air", "air", "dirt", "dirt"] + ] + }, + { + "id": "level_2_hard_fast", + "duration": 12, + "beesCount": 45, + "tintLimit": 750, + "brutality": { "maxSpeed": 30, "force": 0.09 }, + "map": [ + ["air", "air", "air", "air", "bee_nest", "bee_nest", "air", "air", "air", "air"], + ["air", "bee_nest", "air", "air", "air", "air", "air", "air", "bee_nest", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "doge_spawn", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "grass", "grass", "air", "air", "air", "air"], + ["air", "air", "air", "air", "dirt", "dirt", "air", "air", "air", "air"], + ["air", "air", "air", "air", "dirt", "dirt", "air", "air", "air", "air"], + ["air", "air", "air", "air", "dirt", "dirt", "air", "air", "air", "air"], + ["air", "air", "air", "air", "dirt", "dirt", "air", "air", "air", "air"] + ] + }, + { + "id": "level_3_hard_fast", + "duration": 15, + "beesCount": 50, + "tintLimit": 700, + "brutality": { "maxSpeed": 30, "force": 0.1 }, + "map": [ + ["bee_nest", "bee_nest", "air", "air", "air", "air", "air", "air", "bee_nest", "bee_nest"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["grass", "grass", "grass", "air", "air", "air", "air", "grass", "grass", "grass"], + ["dirt", "dirt", "dirt", "air", "air", "air", "air", "dirt", "dirt", "dirt"], + ["dirt", "dirt", "dirt", "air", "doge_spawn", "air", "air", "dirt", "dirt", "dirt"], + ["dirt", "dirt", "dirt", "air", "air", "air", "air", "dirt", "dirt", "dirt"], + ["dirt", "dirt", "dirt", "air", "air", "air", "air", "dirt", "dirt", "dirt"], + ["dirt", "dirt", "dirt", "air", "air", "air", "air", "dirt", "dirt", "dirt"], + ["dirt", "dirt", "dirt", "air", "air", "air", "air", "dirt", "dirt", "dirt"] + ] + }, + { + "id": "level_4_hard_fast", + "duration": 10, + "beesCount": 40, + "tintLimit": 650, + "brutality": { "maxSpeed": 28, "force": 0.08 }, + "map": [ + ["air", "bee_nest", "air", "bee_nest", "air", "bee_nest", "air", "bee_nest", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["grass", "air", "air", "air", "air", "air", "air", "air", "air", "grass"], + ["dirt", "grass", "air", "air", "doge_spawn", "air", "air", "air", "grass", "dirt"], + ["dirt", "dirt", "grass", "air", "air", "air", "air", "grass", "dirt", "dirt"], + ["dirt", "dirt", "dirt", "grass", "air", "air", "grass", "dirt", "dirt", "dirt"], + ["dirt", "dirt", "dirt", "dirt", "grass", "grass", "dirt", "dirt", "dirt", "dirt"], + ["dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt"] + ] + }, + { + "id": "level_5_hard_fast", + "duration": 12, + "beesCount": 45, + "tintLimit": 600, + "brutality": { "maxSpeed": 30, "force": 0.09 }, + "map": [ + ["bee_nest", "bee_nest", "bee_nest", "air", "air", "air", "air", "bee_nest", "bee_nest", "bee_nest"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "doge_spawn", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "grass", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "dirt", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "dirt", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "dirt", "air", "air", "air", "air", "air"], + ["grass", "grass", "grass", "grass", "dirt", "grass", "grass", "grass", "grass", "grass"], + ["dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt"] + ] + }, + { + "id": "level_6_hard_fast", + "duration": 15, + "beesCount": 50, + "tintLimit": 550, + "brutality": { "maxSpeed": 30, "force": 0.1 }, + "map": [ + ["bee_nest", "air", "air", "air", "air", "air", "air", "air", "air", "bee_nest"], + ["bee_nest", "air", "air", "air", "air", "air", "air", "air", "air", "bee_nest"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "doge_spawn", "air", "air", "air", "air", "air"], + ["grass", "grass", "grass", "air", "grass", "grass", "air", "grass", "grass", "grass"], + ["dirt", "dirt", "dirt", "air", "dirt", "dirt", "air", "dirt", "dirt", "dirt"] + ] + }, + { + "id": "level_7_hard_normal", + "duration": 10, + "beesCount": 40, + "tintLimit": 800, + "brutality": { "maxSpeed": 12, "force": 0.08 }, + "map": [ + ["bee_nest", "air", "air", "bee_nest", "air", "air", "bee_nest", "air", "air", "bee_nest"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "doge_spawn", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["grass", "grass", "air", "air", "grass", "grass", "air", "air", "grass", "grass"], + ["dirt", "dirt", "air", "air", "dirt", "dirt", "air", "air", "dirt", "dirt"], + ["dirt", "dirt", "air", "air", "dirt", "dirt", "air", "air", "dirt", "dirt"] + ] + }, + { + "id": "level_8_hard_normal", + "duration": 12, + "beesCount": 45, + "tintLimit": 750, + "brutality": { "maxSpeed": 14, "force": 0.09 }, + "map": [ + ["air", "air", "air", "air", "bee_nest", "bee_nest", "air", "air", "air", "air"], + ["air", "bee_nest", "air", "air", "air", "air", "air", "air", "bee_nest", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "doge_spawn", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "grass", "grass", "air", "air", "air", "air"], + ["air", "air", "air", "air", "dirt", "dirt", "air", "air", "air", "air"], + ["air", "air", "air", "air", "dirt", "dirt", "air", "air", "air", "air"], + ["air", "air", "air", "air", "dirt", "dirt", "air", "air", "air", "air"], + ["air", "air", "air", "air", "dirt", "dirt", "air", "air", "air", "air"] + ] + }, + { + "id": "level_9_hard_normal", + "duration": 15, + "beesCount": 50, + "tintLimit": 700, + "brutality": { "maxSpeed": 15, "force": 0.1 }, + "map": [ + ["bee_nest", "bee_nest", "air", "air", "air", "air", "air", "air", "bee_nest", "bee_nest"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["grass", "grass", "grass", "air", "air", "air", "air", "grass", "grass", "grass"], + ["dirt", "dirt", "dirt", "air", "air", "air", "air", "dirt", "dirt", "dirt"], + ["dirt", "dirt", "dirt", "air", "doge_spawn", "air", "air", "dirt", "dirt", "dirt"], + ["dirt", "dirt", "dirt", "air", "air", "air", "air", "dirt", "dirt", "dirt"], + ["dirt", "dirt", "dirt", "air", "air", "air", "air", "dirt", "dirt", "dirt"], + ["dirt", "dirt", "dirt", "air", "air", "air", "air", "dirt", "dirt", "dirt"], + ["dirt", "dirt", "dirt", "air", "air", "air", "air", "dirt", "dirt", "dirt"] + ] + }, + { + "id": "level_10_hard_normal", + "duration": 10, + "beesCount": 40, + "tintLimit": 650, + "brutality": { "maxSpeed": 12, "force": 0.08 }, + "map": [ + ["air", "bee_nest", "air", "bee_nest", "air", "bee_nest", "air", "bee_nest", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["grass", "air", "air", "air", "air", "air", "air", "air", "air", "grass"], + ["dirt", "grass", "air", "air", "doge_spawn", "air", "air", "air", "grass", "dirt"], + ["dirt", "dirt", "grass", "air", "air", "air", "air", "grass", "dirt", "dirt"], + ["dirt", "dirt", "dirt", "grass", "air", "air", "grass", "dirt", "dirt", "dirt"], + ["dirt", "dirt", "dirt", "dirt", "grass", "grass", "dirt", "dirt", "dirt", "dirt"], + ["dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt"] + ] + }, + { + "id": "level_11_hard_normal", + "duration": 12, + "beesCount": 45, + "tintLimit": 600, + "brutality": { "maxSpeed": 14, "force": 0.09 }, + "map": [ + ["bee_nest", "bee_nest", "bee_nest", "air", "air", "air", "air", "bee_nest", "bee_nest", "bee_nest"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "doge_spawn", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "grass", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "dirt", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "dirt", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "dirt", "air", "air", "air", "air", "air"], + ["grass", "grass", "grass", "grass", "dirt", "grass", "grass", "grass", "grass", "grass"], + ["dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt"] + ] + }, + { + "id": "level_12_hard_normal", + "duration": 15, + "beesCount": 50, + "tintLimit": 550, + "brutality": { "maxSpeed": 15, "force": 0.1 }, + "map": [ + ["bee_nest", "air", "air", "air", "air", "air", "air", "air", "air", "bee_nest"], + ["bee_nest", "air", "air", "air", "air", "air", "air", "air", "air", "bee_nest"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "air", "air", "air", "air", "air", "air"], + ["air", "air", "air", "air", "doge_spawn", "air", "air", "air", "air", "air"], + ["grass", "grass", "grass", "air", "grass", "grass", "air", "grass", "grass", "grass"], + ["dirt", "dirt", "dirt", "air", "dirt", "dirt", "air", "dirt", "dirt", "dirt"] + ] + } + ] +} diff --git a/public/games/flappy_dunk/data/levels.json b/public/games/flappy_dunk/data/levels.json new file mode 100644 index 0000000..a849a23 --- /dev/null +++ b/public/games/flappy_dunk/data/levels.json @@ -0,0 +1,704 @@ +[ + { + "id": "level_1", + "levelSpeed": 4, + "baskestsCount": 0, + "basketSize": 110, + "basketInclinationGrades": 0, + "basketInclinationType": "aligned", + "basketSeparation": 3, + "basketColor": "rgba(156, 39, 176, 1)", + "basketNetColor": "rgba(255, 255, 255, 0.3)", + "ballSize": 18, + "ballColor": "rgba(230, 81, 0, 1)", + "ballLinesColor": "rgba(51, 51, 51, 1)", + "ballWingsColor": "rgba(255, 255, 255, 1)", + "bgColor": "rgba(135, 206, 235, 1)", + "bgLinesColor": "rgba(255, 255, 255, 0.1)", + "bgFigure": "pentagons" + }, + { + "id": "level_2_serpent", + "levelSpeed": 5, + "baskestsCount": 0, + "basketSize": 120, + "basketInclinationGrades": 20, + "basketInclinationType": "serpent", + "basketSeparation": 2.5, + "basketColor": "rgba(255, 87, 34, 1)", + "basketNetColor": "rgba(255, 255, 255, 0.4)", + "ballSize": 20, + "ballColor": "rgba(76, 175, 80, 1)", + "ballLinesColor": "rgba(255, 255, 255, 1)", + "ballWingsColor": "rgba(255, 235, 59, 1)", + "bgColor": "rgba(33, 33, 33, 1)", + "bgLinesColor": "rgba(255, 255, 255, 0.05)", + "bgFigure": "stars" + }, + { + "id": "level_3_infinite", + "levelSpeed": 6, + "baskestsCount": 0, + "basketSize": 90, + "basketInclinationGrades": 30, + "basketInclinationType": "random", + "basketSeparation": 3.5, + "basketColor": "rgba(0, 188, 212, 1)", + "basketNetColor": "rgba(255, 255, 255, 0.2)", + "ballSize": 16, + "ballColor": "rgba(255, 193, 7, 1)", + "ballLinesColor": "rgba(0, 0, 0, 1)", + "ballWingsColor": "rgba(33, 150, 243, 1)", + "bgColor": "rgba(63, 81, 181, 1)", + "bgLinesColor": "rgba(0, 0, 0, 0.1)", + "bgFigure": "triangles" + }, + { + "id": "level_4_test", + "levelSpeed": 5, + "baskestsCount": 3, + "basketSize": 300, + "basketInclinationGrades": 0, + "basketInclinationType": "aligned", + "basketSeparation": 4, + "basketColor": "rgba(0, 188, 212, 1)", + "basketNetColor": "rgba(0, 0, 0, 0.2)", + "ballSize": 16, + "ballColor": "rgba(255, 193, 7, 1)", + "ballLinesColor": "rgba(0, 0, 0, 1)", + "ballWingsColor": "rgba(33, 150, 243, 1)", + "bgColor": "rgba(63, 81, 181, 1)", + "bgLinesColor": "rgba(0, 0, 0, 0.1)", + "bgFigure": "squares" + }, + { + "id": "level_5", + "levelSpeed": 4, + "baskestsCount": 10, + "basketSize": 100, + "basketInclinationGrades": 15, + "basketInclinationType": "aligned", + "basketSeparation": 3.2, + "basketColor": "rgba(233, 30, 99, 1)", + "basketNetColor": "rgba(255, 255, 255, 0.5)", + "ballSize": 15, + "ballColor": "rgba(139, 195, 74, 1)", + "ballLinesColor": "rgba(255, 255, 255, 1)", + "ballWingsColor": "rgba(0, 188, 212, 1)", + "bgColor": "rgba(33, 33, 33, 1)", + "bgLinesColor": "rgba(255, 255, 255, 0.05)", + "bgFigure": "hexagons" + }, + { + "id": "level_6", + "levelSpeed": 5, + "baskestsCount": 15, + "basketSize": 115, + "basketInclinationGrades": 25, + "basketInclinationType": "serpent", + "basketSeparation": 2.8, + "basketColor": "rgba(255, 152, 0, 1)", + "basketNetColor": "rgba(0, 0, 0, 0.3)", + "ballSize": 18, + "ballColor": "rgba(63, 81, 181, 1)", + "ballLinesColor": "rgba(0, 0, 0, 1)", + "ballWingsColor": "rgba(255, 235, 59, 1)", + "bgColor": "rgba(244, 67, 54, 1)", + "bgLinesColor": "rgba(0, 0, 0, 0.1)", + "bgFigure": "diamonds" + }, + { + "id": "level_7", + "levelSpeed": 6, + "baskestsCount": 20, + "basketSize": 95, + "basketInclinationGrades": 35, + "basketInclinationType": "random", + "basketSeparation": 4.0, + "basketColor": "rgba(103, 58, 183, 1)", + "basketNetColor": "rgba(255, 255, 255, 0.4)", + "ballSize": 14, + "ballColor": "rgba(205, 220, 57, 1)", + "ballLinesColor": "rgba(0, 0, 0, 1)", + "ballWingsColor": "rgba(255, 87, 34, 1)", + "bgColor": "rgba(0, 150, 136, 1)", + "bgLinesColor": "rgba(255, 255, 255, 0.15)", + "bgFigure": "stars" + }, + { + "id": "level_8_infinite", + "levelSpeed": 7, + "baskestsCount": 0, + "basketSize": 85, + "basketInclinationGrades": 45, + "basketInclinationType": "serpent", + "basketSeparation": 3.5, + "basketColor": "rgba(76, 175, 80, 1)", + "basketNetColor": "rgba(0, 0, 0, 0.5)", + "ballSize": 16, + "ballColor": "rgba(244, 67, 54, 1)", + "ballLinesColor": "rgba(255, 255, 255, 1)", + "ballWingsColor": "rgba(33, 33, 33, 1)", + "bgColor": "rgba(255, 235, 59, 1)", + "bgLinesColor": "rgba(0, 0, 0, 0.2)", + "bgFigure": "triangles" + }, + { + "id": "level_9", + "levelSpeed": 4, + "baskestsCount": 12, + "basketSize": 130, + "basketInclinationGrades": 0, + "basketInclinationType": "aligned", + "basketSeparation": 4.5, + "basketColor": "rgba(0, 0, 0, 1)", + "basketNetColor": "rgba(255, 255, 255, 0.6)", + "ballSize": 22, + "ballColor": "rgba(255, 255, 255, 1)", + "ballLinesColor": "rgba(0, 0, 0, 1)", + "ballWingsColor": "rgba(158, 158, 158, 1)", + "bgColor": "rgba(96, 125, 139, 1)", + "bgLinesColor": "rgba(255, 255, 255, 0.1)", + "bgFigure": "none" + }, + { + "id": "level_10", + "levelSpeed": 8, + "baskestsCount": 30, + "basketSize": 80, + "basketInclinationGrades": 40, + "basketInclinationType": "random", + "basketSeparation": 2.5, + "basketColor": "rgba(255, 193, 7, 1)", + "basketNetColor": "rgba(255, 255, 255, 0.2)", + "ballSize": 12, + "ballColor": "rgba(156, 39, 176, 1)", + "ballLinesColor": "rgba(255, 255, 255, 1)", + "ballWingsColor": "rgba(233, 30, 99, 1)", + "bgColor": "rgba(0, 0, 0, 1)", + "bgLinesColor": "rgba(255, 255, 255, 0.05)", + "bgFigure": "squares" + }, + { + "id": "level_11", + "levelSpeed": 5, + "baskestsCount": 18, + "basketSize": 105, + "basketInclinationGrades": 10, + "basketInclinationType": "serpent", + "basketSeparation": 3.0, + "basketColor": "rgba(33, 150, 243, 1)", + "basketNetColor": "rgba(255, 255, 255, 0.4)", + "ballSize": 18, + "ballColor": "rgba(255, 87, 34, 1)", + "ballLinesColor": "rgba(0, 0, 0, 1)", + "ballWingsColor": "rgba(255, 255, 255, 1)", + "bgColor": "rgba(205, 220, 57, 1)", + "bgLinesColor": "rgba(0, 0, 0, 0.1)", + "bgFigure": "pentagons" + }, + { + "id": "level_12_infinite", + "levelSpeed": 6, + "baskestsCount": 0, + "basketSize": 110, + "basketInclinationGrades": 15, + "basketInclinationType": "aligned", + "basketSeparation": 3.8, + "basketColor": "rgba(121, 85, 72, 1)", + "basketNetColor": "rgba(255, 255, 255, 0.3)", + "ballSize": 17, + "ballColor": "rgba(0, 188, 212, 1)", + "ballLinesColor": "rgba(255, 255, 255, 1)", + "ballWingsColor": "rgba(76, 175, 80, 1)", + "bgColor": "rgba(255, 235, 59, 1)", + "bgLinesColor": "rgba(0, 0, 0, 0.15)", + "bgFigure": "hexagons" + }, + { + "id": "level_13", + "levelSpeed": 7, + "baskestsCount": 25, + "basketSize": 90, + "basketInclinationGrades": 30, + "basketInclinationType": "random", + "basketSeparation": 2.2, + "basketColor": "rgba(0, 150, 136, 1)", + "basketNetColor": "rgba(0, 0, 0, 0.4)", + "ballSize": 14, + "ballColor": "rgba(233, 30, 99, 1)", + "ballLinesColor": "rgba(255, 255, 255, 1)", + "ballWingsColor": "rgba(255, 193, 7, 1)", + "bgColor": "rgba(156, 39, 176, 1)", + "bgLinesColor": "rgba(255, 255, 255, 0.2)", + "bgFigure": "diamonds" + }, + { + "id": "level_14", + "levelSpeed": 5, + "baskestsCount": 14, + "basketSize": 125, + "basketInclinationGrades": 5, + "basketInclinationType": "serpent", + "basketSeparation": 4.2, + "basketColor": "rgba(158, 158, 158, 1)", + "basketNetColor": "rgba(0, 0, 0, 0.2)", + "ballSize": 20, + "ballColor": "rgba(33, 33, 33, 1)", + "ballLinesColor": "rgba(255, 255, 255, 1)", + "ballWingsColor": "rgba(244, 67, 54, 1)", + "bgColor": "rgba(238, 238, 238, 1)", + "bgLinesColor": "rgba(0, 0, 0, 0.05)", + "bgFigure": "none" + }, + { + "id": "level_15", + "levelSpeed": 9, + "baskestsCount": 40, + "basketSize": 75, + "basketInclinationGrades": 45, + "basketInclinationType": "random", + "basketSeparation": 3.5, + "basketColor": "rgba(244, 67, 54, 1)", + "basketNetColor": "rgba(255, 255, 255, 0.5)", + "ballSize": 13, + "ballColor": "rgba(255, 235, 59, 1)", + "ballLinesColor": "rgba(0, 0, 0, 1)", + "ballWingsColor": "rgba(33, 150, 243, 1)", + "bgColor": "rgba(103, 58, 183, 1)", + "bgLinesColor": "rgba(255, 255, 255, 0.1)", + "bgFigure": "stars" + }, + { + "id": "level_16_infinite", + "levelSpeed": 4, + "baskestsCount": 0, + "basketSize": 140, + "basketInclinationGrades": 0, + "basketInclinationType": "aligned", + "basketSeparation": 5.0, + "basketColor": "rgba(205, 220, 57, 1)", + "basketNetColor": "rgba(0, 0, 0, 0.3)", + "ballSize": 24, + "ballColor": "rgba(103, 58, 183, 1)", + "ballLinesColor": "rgba(255, 255, 255, 1)", + "ballWingsColor": "rgba(0, 188, 212, 1)", + "bgColor": "rgba(121, 85, 72, 1)", + "bgLinesColor": "rgba(255, 255, 255, 0.05)", + "bgFigure": "squares" + }, + { + "id": "level_17", + "levelSpeed": 6, + "baskestsCount": 22, + "basketSize": 95, + "basketInclinationGrades": 20, + "basketInclinationType": "serpent", + "basketSeparation": 2.8, + "basketColor": "rgba(233, 30, 99, 1)", + "basketNetColor": "rgba(255, 255, 255, 0.3)", + "ballSize": 16, + "ballColor": "rgba(0, 150, 136, 1)", + "ballLinesColor": "rgba(255, 255, 255, 1)", + "ballWingsColor": "rgba(255, 152, 0, 1)", + "bgColor": "rgba(33, 33, 33, 1)", + "bgLinesColor": "rgba(255, 255, 255, 0.1)", + "bgFigure": "triangles" + }, + { + "id": "level_18", + "levelSpeed": 7, + "baskestsCount": 28, + "basketSize": 85, + "basketInclinationGrades": 35, + "basketInclinationType": "aligned", + "basketSeparation": 3.0, + "basketColor": "rgba(255, 87, 34, 1)", + "basketNetColor": "rgba(0, 0, 0, 0.4)", + "ballSize": 15, + "ballColor": "rgba(139, 195, 74, 1)", + "ballLinesColor": "rgba(255, 255, 255, 1)", + "ballWingsColor": "rgba(33, 150, 243, 1)", + "bgColor": "rgba(255, 235, 59, 1)", + "bgLinesColor": "rgba(0, 0, 0, 0.15)", + "bgFigure": "pentagons" + }, + { + "id": "level_19", + "levelSpeed": 8, + "baskestsCount": 35, + "basketSize": 78, + "basketInclinationGrades": 42, + "basketInclinationType": "random", + "basketSeparation": 2.4, + "basketColor": "rgba(0, 188, 212, 1)", + "basketNetColor": "rgba(255, 255, 255, 0.5)", + "ballSize": 14, + "ballColor": "rgba(244, 67, 54, 1)", + "ballLinesColor": "rgba(255, 255, 255, 1)", + "ballWingsColor": "rgba(255, 193, 7, 1)", + "bgColor": "rgba(96, 125, 139, 1)", + "bgLinesColor": "rgba(255, 255, 255, 0.1)", + "bgFigure": "hexagons" + }, + { + "id": "level_20_infinite", + "levelSpeed": 5, + "baskestsCount": 0, + "basketSize": 115, + "basketInclinationGrades": 10, + "basketInclinationType": "serpent", + "basketSeparation": 3.5, + "basketColor": "rgba(103, 58, 183, 1)", + "basketNetColor": "rgba(255, 255, 255, 0.3)", + "ballSize": 18, + "ballColor": "rgba(205, 220, 57, 1)", + "ballLinesColor": "rgba(0, 0, 0, 1)", + "ballWingsColor": "rgba(0, 150, 136, 1)", + "bgColor": "rgba(233, 30, 99, 1)", + "bgLinesColor": "rgba(255, 255, 255, 0.2)", + "bgFigure": "diamonds" + }, + { + "id": "level_21", + "levelSpeed": 6, + "baskestsCount": 20, + "basketSize": 100, + "basketInclinationGrades": 25, + "basketInclinationType": "aligned", + "basketSeparation": 3.2, + "basketColor": "rgba(76, 175, 80, 1)", + "basketNetColor": "rgba(0, 0, 0, 0.3)", + "ballSize": 17, + "ballColor": "rgba(156, 39, 176, 1)", + "ballLinesColor": "rgba(255, 255, 255, 1)", + "ballWingsColor": "rgba(255, 235, 59, 1)", + "bgColor": "rgba(33, 150, 243, 1)", + "bgLinesColor": "rgba(255, 255, 255, 0.1)", + "bgFigure": "none" + }, + { + "id": "level_22", + "levelSpeed": 9, + "baskestsCount": 45, + "basketSize": 72, + "basketInclinationGrades": 45, + "basketInclinationType": "serpent", + "basketSeparation": 2.0, + "basketColor": "rgba(255, 255, 255, 1)", + "basketNetColor": "rgba(0, 0, 0, 0.6)", + "ballSize": 12, + "ballColor": "rgba(0, 0, 0, 1)", + "ballLinesColor": "rgba(255, 255, 255, 1)", + "ballWingsColor": "rgba(244, 67, 54, 1)", + "bgColor": "rgba(158, 158, 158, 1)", + "bgLinesColor": "rgba(0, 0, 0, 0.1)", + "bgFigure": "squares" + }, + { + "id": "level_23", + "levelSpeed": 4, + "baskestsCount": 10, + "basketSize": 120, + "basketInclinationGrades": 5, + "basketInclinationType": "random", + "basketSeparation": 4.5, + "basketColor": "rgba(255, 193, 7, 1)", + "basketNetColor": "rgba(0, 0, 0, 0.2)", + "ballSize": 20, + "ballColor": "rgba(33, 33, 33, 1)", + "ballLinesColor": "rgba(255, 255, 255, 1)", + "ballWingsColor": "rgba(0, 188, 212, 1)", + "bgColor": "rgba(255, 87, 34, 1)", + "bgLinesColor": "rgba(0, 0, 0, 0.15)", + "bgFigure": "stars" + }, + { + "id": "level_24_infinite", + "levelSpeed": 7, + "baskestsCount": 0, + "basketSize": 88, + "basketInclinationGrades": 38, + "basketInclinationType": "random", + "basketSeparation": 3.3, + "basketColor": "rgba(139, 195, 74, 1)", + "basketNetColor": "rgba(255, 255, 255, 0.4)", + "ballSize": 15, + "ballColor": "rgba(103, 58, 183, 1)", + "ballLinesColor": "rgba(255, 255, 255, 1)", + "ballWingsColor": "rgba(233, 30, 99, 1)", + "bgColor": "rgba(121, 85, 72, 1)", + "bgLinesColor": "rgba(255, 255, 255, 0.05)", + "bgFigure": "triangles" + }, + { + "id": "level_25_easy", + "levelSpeed": 3, + "baskestsCount": 8, + "basketSize": 150, + "basketInclinationGrades": 0, + "basketInclinationType": "aligned", + "basketSeparation": 3.0, + "basketColor": "rgba(76, 175, 80, 1)", + "basketNetColor": "rgba(255, 255, 255, 0.5)", + "ballSize": 12, + "ballColor": "rgba(255, 193, 7, 1)", + "ballLinesColor": "rgba(0, 0, 0, 1)", + "ballWingsColor": "rgba(255, 255, 255, 1)", + "bgColor": "rgba(135, 206, 235, 1)", + "bgLinesColor": "rgba(255, 255, 255, 0.1)", + "bgFigure": "none" + }, + { + "id": "level_26_easy", + "levelSpeed": 3, + "baskestsCount": 10, + "basketSize": 145, + "basketInclinationGrades": 5, + "basketInclinationType": "serpent", + "basketSeparation": 3.2, + "basketColor": "rgba(33, 150, 243, 1)", + "basketNetColor": "rgba(255, 255, 255, 0.4)", + "ballSize": 12, + "ballColor": "rgba(244, 67, 54, 1)", + "ballLinesColor": "rgba(255, 255, 255, 1)", + "ballWingsColor": "rgba(255, 235, 59, 1)", + "bgColor": "rgba(224, 247, 250, 1)", + "bgLinesColor": "rgba(0, 0, 0, 0.05)", + "bgFigure": "squares" + }, + { + "id": "level_27_easy", + "levelSpeed": 3.5, + "baskestsCount": 12, + "basketSize": 140, + "basketInclinationGrades": 10, + "basketInclinationType": "random", + "basketSeparation": 3.5, + "basketColor": "rgba(156, 39, 176, 1)", + "basketNetColor": "rgba(255, 255, 255, 0.3)", + "ballSize": 14, + "ballColor": "rgba(205, 220, 57, 1)", + "ballLinesColor": "rgba(0, 0, 0, 1)", + "ballWingsColor": "rgba(0, 188, 212, 1)", + "bgColor": "rgba(243, 229, 245, 1)", + "bgLinesColor": "rgba(0, 0, 0, 0.1)", + "bgFigure": "triangles" + }, + { + "id": "level_28_easy", + "levelSpeed": 3.5, + "baskestsCount": 15, + "basketSize": 135, + "basketInclinationGrades": 0, + "basketInclinationType": "aligned", + "basketSeparation": 3.5, + "basketColor": "rgba(255, 87, 34, 1)", + "basketNetColor": "rgba(255, 255, 255, 0.4)", + "ballSize": 14, + "ballColor": "rgba(33, 150, 243, 1)", + "ballLinesColor": "rgba(255, 255, 255, 1)", + "ballWingsColor": "rgba(255, 255, 255, 1)", + "bgColor": "rgba(255, 243, 224, 1)", + "bgLinesColor": "rgba(0, 0, 0, 0.05)", + "bgFigure": "pentagons" + }, + { + "id": "level_29_easy_infinite", + "levelSpeed": 3, + "baskestsCount": 0, + "basketSize": 150, + "basketInclinationGrades": 5, + "basketInclinationType": "serpent", + "basketSeparation": 3.0, + "basketColor": "rgba(0, 188, 212, 1)", + "basketNetColor": "rgba(0, 0, 0, 0.2)", + "ballSize": 12, + "ballColor": "rgba(233, 30, 99, 1)", + "ballLinesColor": "rgba(255, 255, 255, 1)", + "ballWingsColor": "rgba(255, 193, 7, 1)", + "bgColor": "rgba(232, 245, 233, 1)", + "bgLinesColor": "rgba(0, 0, 0, 0.1)", + "bgFigure": "stars" + }, + { + "id": "level_30_easy", + "levelSpeed": 4, + "baskestsCount": 10, + "basketSize": 135, + "basketInclinationGrades": 15, + "basketInclinationType": "random", + "basketSeparation": 3.8, + "basketColor": "rgba(139, 195, 74, 1)", + "basketNetColor": "rgba(255, 255, 255, 0.5)", + "ballSize": 14, + "ballColor": "rgba(103, 58, 183, 1)", + "ballLinesColor": "rgba(255, 255, 255, 1)", + "ballWingsColor": "rgba(33, 150, 243, 1)", + "bgColor": "rgba(255, 235, 238, 1)", + "bgLinesColor": "rgba(0, 0, 0, 0.05)", + "bgFigure": "hexagons" + }, + { + "id": "level_31_easy", + "levelSpeed": 2.5, + "baskestsCount": 8, + "basketSize": 160, + "basketInclinationGrades": 0, + "basketInclinationType": "aligned", + "basketSeparation": 3.0, + "basketColor": "rgba(255, 152, 0, 1)", + "basketNetColor": "rgba(0, 0, 0, 0.3)", + "ballSize": 10, + "ballColor": "rgba(0, 150, 136, 1)", + "ballLinesColor": "rgba(255, 255, 255, 1)", + "ballWingsColor": "rgba(255, 235, 59, 1)", + "bgColor": "rgba(238, 238, 238, 1)", + "bgLinesColor": "rgba(0, 0, 0, 0.1)", + "bgFigure": "none" + }, + { + "id": "level_32_easy", + "levelSpeed": 3, + "baskestsCount": 14, + "basketSize": 145, + "basketInclinationGrades": 10, + "basketInclinationType": "serpent", + "basketSeparation": 3.2, + "basketColor": "rgba(96, 125, 139, 1)", + "basketNetColor": "rgba(255, 255, 255, 0.6)", + "ballSize": 12, + "ballColor": "rgba(255, 87, 34, 1)", + "ballLinesColor": "rgba(0, 0, 0, 1)", + "ballWingsColor": "rgba(255, 255, 255, 1)", + "bgColor": "rgba(227, 242, 253, 1)", + "bgLinesColor": "rgba(0, 0, 0, 0.05)", + "bgFigure": "diamonds" + }, + { + "id": "level_33_easy", + "levelSpeed": 3.5, + "baskestsCount": 16, + "basketSize": 140, + "basketInclinationGrades": 5, + "basketInclinationType": "random", + "basketSeparation": 3.5, + "basketColor": "rgba(233, 30, 99, 1)", + "basketNetColor": "rgba(255, 255, 255, 0.4)", + "ballSize": 14, + "ballColor": "rgba(76, 175, 80, 1)", + "ballLinesColor": "rgba(0, 0, 0, 1)", + "ballWingsColor": "rgba(255, 193, 7, 1)", + "bgColor": "rgba(253, 236, 232, 1)", + "bgLinesColor": "rgba(0, 0, 0, 0.1)", + "bgFigure": "squares" + }, + { + "id": "level_34_easy_infinite", + "levelSpeed": 3, + "baskestsCount": 0, + "basketSize": 155, + "basketInclinationGrades": 0, + "basketInclinationType": "aligned", + "basketSeparation": 3.0, + "basketColor": "rgba(103, 58, 183, 1)", + "basketNetColor": "rgba(255, 255, 255, 0.3)", + "ballSize": 12, + "ballColor": "rgba(255, 235, 59, 1)", + "ballLinesColor": "rgba(0, 0, 0, 1)", + "ballWingsColor": "rgba(0, 188, 212, 1)", + "bgColor": "rgba(232, 234, 246, 1)", + "bgLinesColor": "rgba(0, 0, 0, 0.05)", + "bgFigure": "stars" + }, + { + "id": "level_35_easy", + "levelSpeed": 2.5, + "baskestsCount": 10, + "basketSize": 160, + "basketInclinationGrades": 10, + "basketInclinationType": "serpent", + "basketSeparation": 3.5, + "basketColor": "rgba(0, 150, 136, 1)", + "basketNetColor": "rgba(0, 0, 0, 0.2)", + "ballSize": 10, + "ballColor": "rgba(233, 30, 99, 1)", + "ballLinesColor": "rgba(255, 255, 255, 1)", + "ballWingsColor": "rgba(255, 255, 255, 1)", + "bgColor": "rgba(255, 248, 225, 1)", + "bgLinesColor": "rgba(0, 0, 0, 0.1)", + "bgFigure": "triangles" + }, + { + "id": "level_36_easy", + "levelSpeed": 4, + "baskestsCount": 18, + "basketSize": 135, + "basketInclinationGrades": 5, + "basketInclinationType": "aligned", + "basketSeparation": 3.8, + "basketColor": "rgba(121, 85, 72, 1)", + "basketNetColor": "rgba(255, 255, 255, 0.5)", + "ballSize": 14, + "ballColor": "rgba(0, 188, 212, 1)", + "ballLinesColor": "rgba(255, 255, 255, 1)", + "ballWingsColor": "rgba(139, 195, 74, 1)", + "bgColor": "rgba(239, 235, 233, 1)", + "bgLinesColor": "rgba(0, 0, 0, 0.05)", + "bgFigure": "hexagons" + }, + { + "id": "level_37_easy", + "levelSpeed": 3, + "baskestsCount": 12, + "basketSize": 150, + "basketInclinationGrades": 15, + "basketInclinationType": "random", + "basketSeparation": 3.2, + "basketColor": "rgba(244, 67, 54, 1)", + "basketNetColor": "rgba(255, 255, 255, 0.4)", + "ballSize": 12, + "ballColor": "rgba(33, 33, 33, 1)", + "ballLinesColor": "rgba(255, 255, 255, 1)", + "ballWingsColor": "rgba(255, 193, 7, 1)", + "bgColor": "rgba(241, 248, 233, 1)", + "bgLinesColor": "rgba(0, 0, 0, 0.1)", + "bgFigure": "pentagons" + }, + { + "id": "level_38_easy", + "levelSpeed": 3.5, + "baskestsCount": 14, + "basketSize": 145, + "basketInclinationGrades": 0, + "basketInclinationType": "serpent", + "basketSeparation": 3.4, + "basketColor": "rgba(205, 220, 57, 1)", + "basketNetColor": "rgba(0, 0, 0, 0.3)", + "ballSize": 14, + "ballColor": "rgba(103, 58, 183, 1)", + "ballLinesColor": "rgba(255, 255, 255, 1)", + "ballWingsColor": "rgba(233, 30, 99, 1)", + "bgColor": "rgba(250, 250, 250, 1)", + "bgLinesColor": "rgba(0, 0, 0, 0.05)", + "bgFigure": "diamonds" + }, + { + "id": "level_39_easy_infinite", + "levelSpeed": 2.5, + "baskestsCount": 0, + "basketSize": 160, + "basketInclinationGrades": 5, + "basketInclinationType": "random", + "basketSeparation": 3.0, + "basketColor": "rgba(33, 33, 33, 1)", + "basketNetColor": "rgba(255, 255, 255, 0.6)", + "ballSize": 10, + "ballColor": "rgba(255, 152, 0, 1)", + "ballLinesColor": "rgba(0, 0, 0, 1)", + "ballWingsColor": "rgba(0, 150, 136, 1)", + "bgColor": "rgba(224, 224, 224, 1)", + "bgLinesColor": "rgba(255, 255, 255, 0.5)", + "bgFigure": "squares" + } +] diff --git a/public/games/helix_jump/data/levels.json b/public/games/helix_jump/data/levels.json new file mode 100644 index 0000000..6700853 --- /dev/null +++ b/public/games/helix_jump/data/levels.json @@ -0,0 +1,257 @@ +[ + { + "id": "level_4", + "floors": 20, + "safeFloorPercentage": 65, + "holeSizePercentage": 12, + "numberOfHoles": 2, + "distanceBetweenFloors": 4.5, + "time": 50, + "holesSorting": "aligned", + "tubeColor": "rgba(70, 130, 180, 1)", + "backgroundColor": "rgba(10, 20, 40, 1)", + "floorColor": "rgba(255, 165, 0, 1)", + "floorKillerColor": "rgba(139, 0, 0, 1)", + "ballColor": "rgba(0, 255, 255, 1)" + }, + { + "id": "level_5", + "floors": 25, + "safeFloorPercentage": 60, + "holeSizePercentage": 12, + "numberOfHoles": 2, + "distanceBetweenFloors": 4.8, + "time": 60, + "holesSorting": "oposite", + "tubeColor": "rgba(85, 107, 47, 1)", + "backgroundColor": "rgba(20, 30, 20, 1)", + "floorColor": "rgba(218, 165, 32, 1)", + "floorKillerColor": "rgba(128, 0, 128, 1)", + "ballColor": "rgba(255, 255, 255, 1)" + }, + { + "id": "level_6", + "floors": 35, + "safeFloorPercentage": 55, + "holeSizePercentage": 10, + "numberOfHoles": 3, + "distanceBetweenFloors": 5.0, + "time": 75, + "holesSorting": "serpent", + "tubeColor": "rgba(148, 0, 211, 1)", + "backgroundColor": "rgba(25, 0, 50, 1)", + "floorColor": "rgba(50, 205, 50, 1)", + "floorKillerColor": "rgba(255, 69, 0, 1)", + "ballColor": "rgba(255, 215, 0, 1)" + }, + { + "id": "level_7", + "floors": 45, + "safeFloorPercentage": 50, + "holeSizePercentage": 8, + "numberOfHoles": 4, + "distanceBetweenFloors": 5.5, + "time": 90, + "holesSorting": "random", + "tubeColor": "rgba(47, 79, 79, 1)", + "backgroundColor": "rgba(0, 0, 0, 1)", + "floorColor": "rgba(0, 191, 255, 1)", + "floorKillerColor": "rgba(220, 20, 60, 1)", + "ballColor": "rgba(255, 105, 180, 1)" + }, + { + "id": "test_level_2", + "floors": 150, + "safeFloorPercentage": 80, + "holeSizePercentage": 25, + "numberOfHoles": 4, + "distanceBetweenFloors": 0.5, + "time": 0, + "holesSorting": "oposite", + "tubeColor": "rgba(200, 200, 200, 1)", + "backgroundColor": "rgba(255, 255, 255, 1)", + "floorColor": "rgba(10, 10, 10, 1)", + "floorKillerColor": "rgba(255, 0, 0, 1)", + "ballColor": "rgba(0, 0, 255, 1)" + }, + { + "id": "level_8", + "floors": 30, + "safeFloorPercentage": 60, + "holeSizePercentage": 14, + "numberOfHoles": 2, + "distanceBetweenFloors": 4.0, + "time": 60, + "holesSorting": "aligned", + "tubeColor": "rgba(40, 40, 40, 1)", + "backgroundColor": "rgba(10, 10, 10, 1)", + "floorColor": "rgba(255, 20, 147, 1)", + "floorKillerColor": "rgba(255, 255, 255, 1)", + "ballColor": "rgba(0, 250, 154, 1)" + }, + { + "id": "level_9", + "floors": 40, + "safeFloorPercentage": 55, + "holeSizePercentage": 12, + "numberOfHoles": 3, + "distanceBetweenFloors": 4.5, + "time": 75, + "holesSorting": "serpent", + "tubeColor": "rgba(139, 69, 19, 1)", + "backgroundColor": "rgba(245, 222, 179, 1)", + "floorColor": "rgba(34, 139, 34, 1)", + "floorKillerColor": "rgba(178, 34, 34, 1)", + "ballColor": "rgba(255, 215, 0, 1)" + }, + { + "id": "level_10", + "floors": 50, + "safeFloorPercentage": 50, + "holeSizePercentage": 15, + "numberOfHoles": 4, + "distanceBetweenFloors": 5.0, + "time": 90, + "holesSorting": "oposite", + "tubeColor": "rgba(72, 61, 139, 1)", + "backgroundColor": "rgba(230, 230, 250, 1)", + "floorColor": "rgba(0, 191, 255, 1)", + "floorKillerColor": "rgba(255, 69, 0, 1)", + "ballColor": "rgba(255, 255, 255, 1)" + }, + { + "id": "level_11", + "floors": 55, + "safeFloorPercentage": 45, + "holeSizePercentage": 10, + "numberOfHoles": 2, + "distanceBetweenFloors": 3.8, + "time": 80, + "holesSorting": "random", + "tubeColor": "rgba(105, 105, 105, 1)", + "backgroundColor": "rgba(0, 0, 0, 1)", + "floorColor": "rgba(173, 255, 47, 1)", + "floorKillerColor": "rgba(255, 0, 255, 1)", + "ballColor": "rgba(0, 255, 255, 1)" + }, + { + "id": "level_12", + "floors": 60, + "safeFloorPercentage": 60, + "holeSizePercentage": 18, + "numberOfHoles": 1, + "distanceBetweenFloors": 6.0, + "time": 100, + "holesSorting": "aligned", + "tubeColor": "rgba(176, 196, 222, 1)", + "backgroundColor": "rgba(25, 25, 112, 1)", + "floorColor": "rgba(255, 140, 0, 1)", + "floorKillerColor": "rgba(0, 0, 139, 1)", + "ballColor": "rgba(255, 255, 0, 1)" + }, + { + "id": "level_13", + "floors": 65, + "safeFloorPercentage": 50, + "holeSizePercentage": 11, + "numberOfHoles": 3, + "distanceBetweenFloors": 4.2, + "time": 110, + "holesSorting": "oposite", + "tubeColor": "rgba(119, 136, 153, 1)", + "backgroundColor": "rgba(240, 255, 240, 1)", + "floorColor": "rgba(46, 139, 87, 1)", + "floorKillerColor": "rgba(128, 0, 0, 1)", + "ballColor": "rgba(255, 99, 71, 1)" + }, + { + "id": "level_14", + "floors": 70, + "safeFloorPercentage": 45, + "holeSizePercentage": 10, + "numberOfHoles": 4, + "distanceBetweenFloors": 4.5, + "time": 120, + "holesSorting": "serpent", + "tubeColor": "rgba(205, 92, 92, 1)", + "backgroundColor": "rgba(255, 228, 225, 1)", + "floorColor": "rgba(75, 0, 130, 1)", + "floorKillerColor": "rgba(0, 0, 0, 1)", + "ballColor": "rgba(127, 255, 212, 1)" + }, + { + "id": "level_15", + "floors": 75, + "safeFloorPercentage": 40, + "holeSizePercentage": 9, + "numberOfHoles": 2, + "distanceBetweenFloors": 3.5, + "time": 115, + "holesSorting": "random", + "tubeColor": "rgba(188, 143, 143, 1)", + "backgroundColor": "rgba(47, 79, 79, 1)", + "floorColor": "rgba(255, 215, 0, 1)", + "floorKillerColor": "rgba(220, 20, 60, 1)", + "ballColor": "rgba(240, 248, 255, 1)" + }, + { + "id": "level_16", + "floors": 80, + "safeFloorPercentage": 65, + "holeSizePercentage": 20, + "numberOfHoles": 5, + "distanceBetweenFloors": 5.5, + "time": 140, + "holesSorting": "oposite", + "tubeColor": "rgba(218, 165, 32, 1)", + "backgroundColor": "rgba(0, 0, 0, 1)", + "floorColor": "rgba(139, 0, 139, 1)", + "floorKillerColor": "rgba(255, 255, 255, 1)", + "ballColor": "rgba(0, 250, 154, 1)" + }, + { + "id": "level_17", + "floors": 85, + "safeFloorPercentage": 45, + "holeSizePercentage": 12, + "numberOfHoles": 3, + "distanceBetweenFloors": 4.8, + "time": 135, + "holesSorting": "aligned", + "tubeColor": "rgba(0, 128, 128, 1)", + "backgroundColor": "rgba(240, 255, 255, 1)", + "floorColor": "rgba(255, 69, 0, 1)", + "floorKillerColor": "rgba(0, 0, 128, 1)", + "ballColor": "rgba(218, 112, 214, 1)" + }, + { + "id": "level_18", + "floors": 90, + "safeFloorPercentage": 40, + "holeSizePercentage": 8, + "numberOfHoles": 4, + "distanceBetweenFloors": 5.0, + "time": 150, + "holesSorting": "serpent", + "tubeColor": "rgba(112, 128, 144, 1)", + "backgroundColor": "rgba(10, 10, 10, 1)", + "floorColor": "rgba(0, 255, 127, 1)", + "floorKillerColor": "rgba(178, 34, 34, 1)", + "ballColor": "rgba(255, 250, 205, 1)" + }, + { + "id": "level_19", + "floors": 100, + "safeFloorPercentage": 35, + "holeSizePercentage": 10, + "numberOfHoles": 3, + "distanceBetweenFloors": 4.0, + "time": 180, + "holesSorting": "random", + "tubeColor": "rgba(25, 25, 112, 1)", + "backgroundColor": "rgba(255, 250, 250, 1)", + "floorColor": "rgba(220, 20, 60, 1)", + "floorKillerColor": "rgba(0, 0, 0, 1)", + "ballColor": "rgba(0, 191, 255, 1)" + } +] \ No newline at end of file diff --git a/public/games/paper_io/data/bots.json b/public/games/paper_io/data/bots.json new file mode 100644 index 0000000..c12da66 --- /dev/null +++ b/public/games/paper_io/data/bots.json @@ -0,0 +1,42 @@ +[ + { + "id": "bot_normal", + "names": ["Wanderer", "Stroller", "Drifter", "Explorer", "Traveler"], + "spawnWithAreaMin": 0.1, + "spawnWithAreaMax": 15, + "behaviour": "normal", + "speed": 1 + }, + { + "id": "bot_protective", + "names": ["Turtle", "Defender", "Guardian", "Shield", "Fortress"], + "spawnWithAreaMin": 10, + "spawnWithAreaMax": 30, + "behaviour": "protective", + "speed": 0.85 + }, + { + "id": "bot_aggresive", + "names": ["Hunter", "Predator", "Stalker", "Chaser", "Fighter"], + "spawnWithAreaMin": 0.5, + "spawnWithAreaMax": 10, + "behaviour": "aggresive", + "speed": 1.15 + }, + { + "id": "bot_killer", + "names": ["Terminator", "Assassin", "Slayer", "Executioner", "Reaper"], + "spawnWithAreaMin": 0.1, + "spawnWithAreaMax": 5, + "behaviour": "playerKiller", + "speed": 1.25 + }, + { + "id": "bot_chaotic", + "names": ["Glitch", "Random", "Chaos", "Jester", "Erratic"], + "spawnWithAreaMin": 0.1, + "spawnWithAreaMax": 70, + "behaviour": "chaotic", + "speed": 1.1 + } +] diff --git a/public/img/cheems/cubes.png b/public/img/cheems/cubes.png new file mode 100644 index 0000000..f3a6513 Binary files /dev/null and b/public/img/cheems/cubes.png differ diff --git a/public/img/locked-cheems.png b/public/img/cheems/locked-cheems.png similarity index 100% rename from public/img/locked-cheems.png rename to public/img/cheems/locked-cheems.png diff --git a/public/img/cheems/not_a_dog.png b/public/img/cheems/not_a_dog.png new file mode 100644 index 0000000..7105613 Binary files /dev/null and b/public/img/cheems/not_a_dog.png differ diff --git a/public/img/cheems/not_a_plumber.png b/public/img/cheems/not_a_plumber.png new file mode 100644 index 0000000..3332f45 Binary files /dev/null and b/public/img/cheems/not_a_plumber.png differ diff --git a/public/img/cheems/not_ai.png b/public/img/cheems/not_ai.png new file mode 100644 index 0000000..6c2a6d9 Binary files /dev/null and b/public/img/cheems/not_ai.png differ diff --git a/public/img/cheems/realistic.png b/public/img/cheems/realistic.png new file mode 100644 index 0000000..64f6f70 Binary files /dev/null and b/public/img/cheems/realistic.png differ diff --git a/public/img/hit/cubes.png b/public/img/hit/cubes.png new file mode 100644 index 0000000..1320573 Binary files /dev/null and b/public/img/hit/cubes.png differ diff --git a/public/img/hit/not_a_dog.png b/public/img/hit/not_a_dog.png new file mode 100644 index 0000000..38e168f Binary files /dev/null and b/public/img/hit/not_a_dog.png differ diff --git a/public/img/hit/not_a_plumber.png b/public/img/hit/not_a_plumber.png new file mode 100644 index 0000000..76ace2e Binary files /dev/null and b/public/img/hit/not_a_plumber.png differ diff --git a/public/img/hit/not_ai.png b/public/img/hit/not_ai.png new file mode 100644 index 0000000..f73d2eb Binary files /dev/null and b/public/img/hit/not_ai.png differ diff --git a/public/img/hit/realistic.png b/public/img/hit/realistic.png new file mode 100644 index 0000000..fb1fd33 Binary files /dev/null and b/public/img/hit/realistic.png differ diff --git a/public/img/icons/back.png b/public/img/icons/back.png deleted file mode 100644 index 8dc4965..0000000 Binary files a/public/img/icons/back.png and /dev/null differ diff --git a/public/img/icons/black-sound-svgrepo-com.svg b/public/img/icons/black-sound-svgrepo-com.svg new file mode 100644 index 0000000..91373bb --- /dev/null +++ b/public/img/icons/black-sound-svgrepo-com.svg @@ -0,0 +1,52 @@ + + + + Layer 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/img/icons/cart.png b/public/img/icons/cart.png deleted file mode 100644 index 5f3be2a..0000000 Binary files a/public/img/icons/cart.png and /dev/null differ diff --git a/public/img/icons/lock-keyhole-minimalistic-svgrepo-com.svg b/public/img/icons/lock-keyhole-minimalistic-svgrepo-com.svg index 4ac6041..639bcda 100644 --- a/public/img/icons/lock-keyhole-minimalistic-svgrepo-com.svg +++ b/public/img/icons/lock-keyhole-minimalistic-svgrepo-com.svg @@ -1,4 +1,4 @@ - + \ No newline at end of file diff --git a/public/img/music/believe_me.png b/public/img/music/believe_me.png new file mode 100644 index 0000000..b934ac0 Binary files /dev/null and b/public/img/music/believe_me.png differ diff --git a/public/img/music/bonk_the_amber.png b/public/img/music/bonk_the_amber.png new file mode 100644 index 0000000..b6091ba Binary files /dev/null and b/public/img/music/bonk_the_amber.png differ diff --git a/public/img/music/bonk_the_avatar.png b/public/img/music/bonk_the_avatar.png new file mode 100644 index 0000000..b0d10e2 Binary files /dev/null and b/public/img/music/bonk_the_avatar.png differ diff --git a/public/img/music/bonus_level_bounce.png b/public/img/music/bonus_level_bounce.png new file mode 100644 index 0000000..0ba0e4f Binary files /dev/null and b/public/img/music/bonus_level_bounce.png differ diff --git a/public/img/music/button_smash_routine.png b/public/img/music/button_smash_routine.png new file mode 100644 index 0000000..6975771 Binary files /dev/null and b/public/img/music/button_smash_routine.png differ diff --git a/public/img/music/cheems_chan_bonk.png b/public/img/music/cheems_chan_bonk.png new file mode 100644 index 0000000..438f69d Binary files /dev/null and b/public/img/music/cheems_chan_bonk.png differ diff --git a/public/img/music/city_streets.png b/public/img/music/city_streets.png new file mode 100644 index 0000000..35182ab Binary files /dev/null and b/public/img/music/city_streets.png differ diff --git a/public/img/music/click_for_a_bonk.png b/public/img/music/click_for_a_bonk.png new file mode 100644 index 0000000..faeb622 Binary files /dev/null and b/public/img/music/click_for_a_bonk.png differ diff --git a/public/img/music/electro_summer_positive_party.png b/public/img/music/electro_summer_positive_party.png new file mode 100644 index 0000000..ad19b53 Binary files /dev/null and b/public/img/music/electro_summer_positive_party.png differ diff --git a/public/img/music/hardwood_strike.png b/public/img/music/hardwood_strike.png new file mode 100644 index 0000000..58bb786 Binary files /dev/null and b/public/img/music/hardwood_strike.png differ diff --git a/public/img/music/jack_bootleg.png b/public/img/music/jack_bootleg.png new file mode 100644 index 0000000..b8efb3d Binary files /dev/null and b/public/img/music/jack_bootleg.png differ diff --git a/public/img/music/magic_night.png b/public/img/music/magic_night.png new file mode 100644 index 0000000..12ce619 Binary files /dev/null and b/public/img/music/magic_night.png differ diff --git a/public/img/music/minimalism_no10.png b/public/img/music/minimalism_no10.png new file mode 100644 index 0000000..20f10bf Binary files /dev/null and b/public/img/music/minimalism_no10.png differ diff --git a/public/img/music/minimalism_no9.png b/public/img/music/minimalism_no9.png new file mode 100644 index 0000000..2be4abc Binary files /dev/null and b/public/img/music/minimalism_no9.png differ diff --git a/public/img/music/no_image.png b/public/img/music/no_image.png new file mode 100644 index 0000000..46587cc Binary files /dev/null and b/public/img/music/no_image.png differ diff --git a/public/img/music/perfect_round.png b/public/img/music/perfect_round.png new file mode 100644 index 0000000..76655b4 Binary files /dev/null and b/public/img/music/perfect_round.png differ diff --git a/public/img/music/pocket_change_victory.png b/public/img/music/pocket_change_victory.png new file mode 100644 index 0000000..dcdb1db Binary files /dev/null and b/public/img/music/pocket_change_victory.png differ diff --git a/public/img/music/quick_loot_run.png b/public/img/music/quick_loot_run.png new file mode 100644 index 0000000..d15f520 Binary files /dev/null and b/public/img/music/quick_loot_run.png differ diff --git a/public/img/music/target_in_the_sight.png b/public/img/music/target_in_the_sight.png new file mode 100644 index 0000000..3e68617 Binary files /dev/null and b/public/img/music/target_in_the_sight.png differ diff --git a/public/img/music/tetris_bootleg.png b/public/img/music/tetris_bootleg.png new file mode 100644 index 0000000..61dcc01 Binary files /dev/null and b/public/img/music/tetris_bootleg.png differ diff --git a/public/img/music/the_hammer_falls.png b/public/img/music/the_hammer_falls.png new file mode 100644 index 0000000..cc6e629 Binary files /dev/null and b/public/img/music/the_hammer_falls.png differ diff --git a/public/img/music/the_late_commute.png b/public/img/music/the_late_commute.png new file mode 100644 index 0000000..a80c9b8 Binary files /dev/null and b/public/img/music/the_late_commute.png differ diff --git a/public/img/music/the_unwritten_page_bage.png b/public/img/music/the_unwritten_page_bage.png new file mode 100644 index 0000000..9e89810 Binary files /dev/null and b/public/img/music/the_unwritten_page_bage.png differ diff --git a/public/img/music/titanium.png b/public/img/music/titanium.png new file mode 100644 index 0000000..9416af6 Binary files /dev/null and b/public/img/music/titanium.png differ diff --git a/public/img/music/trap_future_bass.png b/public/img/music/trap_future_bass.png new file mode 100644 index 0000000..eb6b228 Binary files /dev/null and b/public/img/music/trap_future_bass.png differ diff --git a/public/img/music/when_you_smile.png b/public/img/music/when_you_smile.png new file mode 100644 index 0000000..f0e8b7e Binary files /dev/null and b/public/img/music/when_you_smile.png differ diff --git a/public/img/music/where_the_path_bends.png b/public/img/music/where_the_path_bends.png new file mode 100644 index 0000000..0fbf555 Binary files /dev/null and b/public/img/music/where_the_path_bends.png differ diff --git a/public/lang/texts.en.lang b/public/lang/texts.en.lang new file mode 100644 index 0000000..b0a4c7d --- /dev/null +++ b/public/lang/texts.en.lang @@ -0,0 +1,506 @@ +{ + "pageName": { + "closet": "Customization", + "devSettings": "Developer Settings", + "game": "Cheems Bonk Game", + "menu": "Main Menu", + "onWork": "On Development", + "p404": "Error 404", + "settings": "Settings", + "offline": "Download Resources", + "shop": "Shop", + "block_breaker": "Merge Diggers", + "attack_hole": "Attack Hole", + "doge_rescue": "Doge Rescue", + "flappy_dunk": "Flappy Dunk", + "helix_jump": "Helix Jump", + "magic_sort": "Magic Sort", + "mob_control": "Mob Control", + "paper_io": "Paper.io", + "spiral_roll": "Spiral Roll", + "stack_colors": "Stack Colors", + "minigames": "Minigames", + "licenses": "Licenses & Credits", + "gallery": "Gallery" + }, + "minigames": { + "trash": "TRASH", + "buyShovel": "Buy Shovel", + "buyPickaxe": "Buy Pickaxe", + "best": "Best: ", + "youWin": "You Win!", + "restart": "Restart", + "defeat": "Defeat!", + "convertedPointsToast": "{0} game points were converted into +{1} MG Coins!", + "flappy_dunk_inst": "Tap to make the ball fly and score through the hoops!", + "magic_sort_inst": "Pour colored liquids between bottles until each is one color!", + "spiral_roll_inst": "Tap and hold to carve wood spirals and clear obstacles!", + "spiral_roll_play_again": "PLAY AGAIN" + }, + "licensesPage": { + "aiGeneratedSong": "Gemini Lyria 3 Pro created song", + "aiGeneratedImage": "Gemini 3 Pro image generator created image" + }, + "menu": { + "minigames": "Minigames", + "settings": "Settings", + "offline": "Download Resources (Offline Mode)", + "shop": "Customization Shop", + "closet": "Closet", + "stats": "Statistics", + "licenses": "Licenses", + "devMenu": "Developer Options", + "buyDogeCoin": "Buy 1 DogeCoin", + "buyDogeCoinSub": "Today's price: ", + "buyDogeCoinSuccess": "You bought 1 DogeCoin!", + "buyDogeCoinFail": "You need more points!", + "gallery": "Gallery" + }, + "options": { + "changeLang": { + "button": "Switch Language (Cambiar idioma)" + }, + "musicVolume": "Music volume", + "effectsVolume": "Effects volume", + "appTheme": "App theme (colors):", + "themes": { + "light": "Light Mode", + "dark": "Dark Mode", + "contrast": "High Contrast Mode" + }, + "fontSize": "Font size:", + "sizes": { + "smaller": "Smallest", + "small": "Small", + "normal": "Normal", + "big": "Big", + "max": "Biggest" + }, + "saveManagement": "Save Management", + "deleteProgress": "Delete Progress", + "deleteProgressConfirm": "Are you sure you want to delete ALL progress? This cannot be undone!", + "exportSave": "Export Save", + "importSave": "Import Save", + "importSaveConfirm": "Importing a save will overwrite all current progress. Proceed?" + }, + "stats": { + "title": "Statistics", + "highScore": "Highest Combo", + "totalTouches": "Total Touches", + "lifetimePoints": "Lifetime Points Earned", + "lifetimeDogeCoins": "Lifetime DogeCoins Earned", + "lifetimeMinigameCoins": "Lifetime MG Coins Earned" + }, + "game": { + "navbar": { + "highScore": "High score", + "actScore": "Current touches", + "totalScore": "Total touches", + "booster": "Booster" + }, + "tapToBonk": "Click Cheems for a BONK!" + }, + "closet": { + "title": "Customization Shop", + "cheemsSection": "Cheems (Skins)", + "soundsSection": "Hit Sounds", + "musicSection": "Background Music", + "selected": "Selected", + "equipped": "Equipped", + "purchased": "Purchased", + "cost": "Cost:", + "free": "Free", + "buy": "Buy", + "equip": "Equip", + "needMoreCoins": "Need more DogeCoins!", + "itemBought": "Successfully purchased!", + "itemSelected": "Selected!", + "inShop": "In Shop", + "buyInShop": "Buy this item in the Shop!", + "locked": "Locked" + }, + "dev": { + "title": "Developer Options", + "resetToZero": "Reset to zero", + "unlockAll": "Unlock All", + "giveDogeCoins": "Add +100 DogeCoins", + "givePoints": "Add +1000 Points", + "success": "Done!", + "unlocked": "Developer Menu UNLOCKED!", + "locked": "Developer Menu locked." + }, + "onWork": { + "title": "Page Under Development", + "message": "This page is still under development. Check back soon!", + "backToMenu": "Back to Menu" + }, + "p404": { + "title": "Error 404", + "message": "The page you are looking for does not exist in the Cheems universe.", + "backToGame": "Back to Game" + }, + "offline": { + "title": "Download Resources (Offline Mode)", + "subtitle": "Cache game files on your device so you can play without an internet connection.", + "downloadAll": "Download All Resources", + "essentialsTitle": "Essentials", + "essentialsDesc": "Core pages, graphics, scripts, fonts, and game data (no audio).", + "sfxTitle": "Sound Effects (SFX)", + "sfxDesc": "All game and UI sound effects.", + "musicTitle": "Background Music", + "musicDesc": "Full soundtrack collection for custom background music.", + "downloaded": "Downloaded", + "download": "Download", + "downloading": "Downloading...", + "successToast": "Resources downloaded and cached successfully!", + "errorToast": "Error downloading some resources.", + "checkForUpdates": "Check for Updates", + "minigamesTitle": "Minigames", + "minigamesDesc": "Assets and data for minigames." + }, + "shop": { + "title": "Item & Booster Shop", + "subtitle": "Spend your points to buy DogeCoins or activate temporary point multipliers!", + "activeBooster": "Active Booster:", + "pointsPerClick": "Points per Click", + "remaining": "remaining", + "buyBtn": "Buy", + "todaysPrice": "Today's Price:", + "pts": "Pts", + "needMorePoints": "Not enough points!", + "boosterActivated": "Booster activated!", + "currencyToggle": "Currency:", + "buyWithPts": "Buy with Pts", + "buyWithCoins": "Buy with Coins", + "currencyPts": "Points", + "currencyCoins": "DogeCoins", + "free": "Free", + "remainingToday": "left today", + "dailyLimitReached": "Daily limit reached!", + "booster": "Booster", + "boosterOverrideWarning": "Warning! You already have an active x{current} booster. Buying a x{new} booster will override your remaining time. Do you want to continue?", + "purchased": "Purchased", + "itemBoughtGoToCloset": "Item purchased! Go to Closet to equip.", + "alreadyPurchased": "Already purchased!", + "dogecoinSection": "DogeCoins", + "boosterSection": "Boosters", + "cheemsSection": "Cheems Skins", + "sfxSection": "Sound Effects", + "musicSection": "Background Music", + "backToTop": "Back to Top ↑" + }, + "shopItemsText": { + "shop_dogecoin_special_name": "DogeCoin (Special Offer)", + "shop_dogecoin_special_desc": "Buy 1 DogeCoin for a special price!", + "shop_dogecoin_1_name": "DogeCoin x1", + "shop_dogecoin_1_desc": "You get 1 Dogecoin. The price changes everyday!", + "shop_dogecoin_2_name": "DogeCoin x2", + "shop_dogecoin_2_desc": "You get 2 Dogecoins. The price changes everyday!", + "shop_dogecoin_3_name": "DogeCoin x3", + "shop_dogecoin_3_desc": "You get 3 Dogecoins. The price changes everyday!", + "shop_dogecoin_5_name": "DogeCoin x5", + "shop_dogecoin_5_desc": "You get 5 Dogecoins. The price changes everyday!", + "shop_dogecoin_10_name": "DogeCoin x10", + "shop_dogecoin_10_desc": "You get 10 Dogecoins. The price changes everyday!", + "shop_dogecoin_20_name": "DogeCoin x20", + "shop_dogecoin_20_desc": "You get 20 Dogecoins. The price changes everyday!", + "shop_boost_2x_5m_name": "Booster x2 (5 min)", + "shop_boost_2x_5m_desc": "Double your points per click for 5 minutes.", + "shop_boost_3x_5m_name": "Booster x3 (5 min)", + "shop_boost_3x_5m_desc": "Triple your points per click for 5 minutes.", + "shop_boost_2x_10m_name": "Booster x2 (10 min)", + "shop_boost_2x_10m_desc": "Double your points per click for 10 minutes.", + "shop_boost_3x_10m_name": "Booster x3 (10 min)", + "shop_boost_3x_10m_desc": "Triple your points per click for 10 minutes.", + "shop_boost_2x_20m_name": "Booster x2 (20 min)", + "shop_boost_2x_20m_desc": "Double your points per click for 20 minutes.", + "shop_boost_3x_20m_name": "Booster x3 (20 min)", + "shop_boost_3x_20m_desc": "Triple your points per click for 20 minutes.", + "shop_boost_10x_1m_name": "Booster x10 (1 min)", + "shop_boost_10x_1m_desc": "Multiply your points by 10 for 1 minute.", + "shop_boost_10x_3m_name": "Booster x10 (3 min)", + "shop_boost_10x_3m_desc": "Multiply your points by 10 for 3 minutes.", + "shop_boost_10x_5m_name": "Booster x10 (5 min)", + "shop_boost_10x_5m_desc": "Multiply your points by 10 for 5 minutes.", + "shop_boost_10x_10m_name": "Booster x10 (10 min)", + "shop_boost_10x_10m_desc": "Multiply your points by 10 for 10 minutes.", + "shop_minigame_block_breaker_name": "Merge Diggers", + "shop_minigame_block_breaker_desc": "Unlock the digging and tool merging minigame.", + "shop_minigame_attack_hole_name": "Attack Hole", + "shop_minigame_attack_hole_desc": "Unlock the Attack Hole 3D swallowing minigame.", + "shop_minigame_doge_rescue_name": "Doge Rescue", + "shop_minigame_doge_rescue_desc": "Unlock the Draw to Save Doge physics minigame.", + "shop_minigame_flappy_dunk_name": "Flappy Dunk", + "shop_minigame_flappy_dunk_desc": "Unlock the Flappy Dunk arcade hoop minigame.", + "shop_minigame_helix_jump_name": "Helix Jump", + "shop_minigame_helix_jump_desc": "Unlock the 3D Helix Jump tower minigame.", + "shop_minigame_magic_sort_name": "Magic Sort", + "shop_minigame_magic_sort_desc": "Unlock the Magic Sort water puzzle minigame.", + "shop_minigame_mob_control_name": "Mob Control", + "shop_minigame_mob_control_desc": "Unlock the Mob Control multiplier minigame.", + "shop_minigame_paper_io_name": "Paper.io", + "shop_minigame_paper_io_desc": "Unlock the Paper.io territory capture minigame.", + "shop_minigame_spiral_roll_name": "Spiral Roll", + "shop_minigame_spiral_roll_desc": "Unlock the 3D Spiral Roll wood carving minigame.", + "shop_minigame_stack_colors_name": "Stack Colors", + "shop_minigame_stack_colors_desc": "Unlock the 3D Stack Colors runner minigame.", + "shop_curr_dgc_to_mg_name": "10 Minigame Points", + "shop_curr_dgc_to_mg_desc": "Exchange 1 DogeCoin for 10 Minigame Points.", + "shop_curr_mg_to_dgc_name": "1 DogeCoin", + "shop_curr_mg_to_dgc_desc": "Exchange 10 Minigame Points for 1 DogeCoin." + }, + "itemsText": { + "cheems_normal": "Normal Cheems", + "cheems_normal_desc": "The original Cheems.", + "cheems_little": "Little Cheems", + "cheems_little_desc": "He's cute and tiny.", + "cheems_adult": "Adult Cheems", + "cheems_adult_desc": "He's serious and maybe an actor.", + "cheems_kid": "Kid Cheems", + "cheems_kid_desc": "Little cheems, but he's a kid.", + "cheems_mamado": "Buff Cheems", + "cheems_mamado_desc": "He's a Gymbro.", + "cheems_pixelart": "Pixel Cheems", + "cheems_pixelart_desc": "Pixel art cheems, who doesn't like pixelarts?", + "cheems_elegant": "Elegant Cheems", + "cheems_elegant_desc": "He's more elegant than you.", + "cheems_3d": "3D Cheems", + "cheems_3d_desc": "Cheems printed in a 3D printer, woah.", + "cheems_black": "Black Cheems", + "cheems_black_desc": "Does it have texture or...?", + "cheems_minecraft": "Minecraft Cheems", + "cheems_minecraft_desc": "I wanna be a miner, break up the iron with pickaxe...", + "cheems_not_a_dog": "Not A Dog Cheems", + "cheems_not_a_dog_desc": "They identifies themself as a cat.", + "cheems_not_a_plumber": "Not A Plumber Cheems", + "cheems_not_a_plumber_desc": "He's not definitively based on any plumber from any franchise, but it's a funny similarity.", + "cheems_not_ai": "Not AI Cheems", + "cheems_not_ai_desc": "I didn't use AI to create this cheems, not at all, ok?", + "cheems_realistic": "Realistic Cheems", + "cheems_realistic_desc": "This is cheems, but in 4K (The game must sell, ok?).", + "sfx_1": "Hit (Bonk)", + "sfx_1_desc": "Bonk, bonk, bonk...", + "sfx_2": "Hurt Minecraft", + "sfx_2_desc": "Uh, do you remember this sound?", + "sfx_3": "Hurt Roblox", + "sfx_3_desc": "Oh no, my friend. (hope I don't get demanded).", + "sfx_4": "Level Up", + "sfx_4_desc": "You're getting stronger!", + "sfx_5": "Discord", + "sfx_5_desc": "Discord, good gamer.", + "sfx_6": "Hello", + "sfx_6_desc": "She's the only animatronic with shorts, making her beautiful for the community.", + "sfx_7": "Hit Minecraft 2", + "sfx_7_desc": "Hit gender neutral.", + "sfx_8": "No", + "sfx_8_desc": "No!!! (you got hit anyway)", + "sfx_9": "Duck (Pato)", + "sfx_9_desc": "O Pato. A duck so happily came singing, Cuack Cuak, A drake who heard her came a-winging, Cuack Cuack, And he invited her to samba.", + "sfx_10": "Plushie (Peluche)", + "sfx_10_desc": "Squeak squeak!", + "sfx_11": "Splat", + "sfx_11_desc": "Splash!", + "sfx_12": "Windows Error", + "sfx_12_desc": "Hope you don't hear it often.", + "music_0": "Mute / No Music", + "music_0_desc": "Who plays with no music?", + "music_1": "A Jazz Piano", + "music_1_desc": "A jazz piano, nice.", + "music_2": "Jack Bootleg", + "music_2_desc": "Hit with a lot of energy the cheems!", + "music_3": "Magic Night", + "music_3_desc": "Relaxing music for a relaxing game.", + "music_4": "Minimalism No9", + "music_4_desc": "Minimalistic music for a minimalistic game.", + "music_5": "Minimalism No10", + "music_5_desc": "Minimalistic music for a minimalistic game, but improved to a new release.", + "music_6": "When You Smile", + "music_6_desc": "A think cheems doesn't smile anyway...", + "music_7": "Tetris (Joey iLLah Bootleg)", + "music_7_desc": "Tetris theme but make it bounce.", + "music_8": "Separation", + "music_8_desc": "A thoughtful and quiet melody.", + "music_9": "Electro Summer", + "music_9_desc": "Positive party vibes!", + "music_10": "Titanium", + "music_10_desc": "Strong like titanium.", + "music_11": "Believe Me", + "music_11_desc": "Believe in the power of music.", + "music_12": "City Streets", + "music_12_desc": "Background music for a busy city.", + "music_13": "Coffee Shop", + "music_13_desc": "Chill coffee shop ambience.", + "music_14": "Trap Future Bass", + "music_14_desc": "Modern bass for modern bonks.", + "music_15": "Bonk The Amber", + "music_15_desc": "New music track: Bonk The Amber", + "music_16": "Bonk The Avatar", + "music_16_desc": "New music track: Bonk The Avatar", + "music_17": "Bonus Level Bounce", + "music_17_desc": "New music track: Bonus Level Bounce", + "music_18": "Button Smash Routine", + "music_18_desc": "New music track: Button Smash Routine", + "music_19": "Cheems Chan Bonk", + "music_19_desc": "New music track: Cheems Chan Bonk", + "music_20": "Click For A Bonk", + "music_20_desc": "New music track: Click For A Bonk", + "music_21": "Hardwood Strike", + "music_21_desc": "New music track: Hardwood Strike", + "music_22": "Perfect Round", + "music_22_desc": "New music track: Perfect Round", + "music_23": "Pocket Change Victory", + "music_23_desc": "New music track: Pocket Change Victory", + "music_24": "Quick Loot Run", + "music_24_desc": "New music track: Quick Loot Run", + "music_25": "Target In The Sight", + "music_25_desc": "New music track: Target In The Sight", + "music_26": "The Hammer Falls", + "music_26_desc": "New music track: The Hammer Falls", + "music_27": "The Late Commute", + "music_27_desc": "New music track: The Late Commute", + "music_28": "The Unwritten Page", + "music_28_desc": "New music track: The Unwritten Page", + "music_29": "Where The Path Bends", + "music_29_desc": "New music track: Where The Path Bends" + }, + "gallery": { + "title": "Gallery", + "skinsSection": "Skins", + "soundsSection": "Sound Effects", + "musicSection": "Music", + "normalSkin": "Normal", + "hitSkin": "Hitting", + "play": "Play", + "pause": "Pause" + }, + "flappy_dunk": { + "title": "Flappy Dunk", + "instructions_infinite": "Tap to flap.
Dunk through the hoops until you lose.
Don't miss!", + "instructions_finite": "Tap to flap.
Dunk through the hoops until you reach the end.
Don't miss!", + "tapToPlay": "TAP TO PLAY", + "gameOver": "GAME OVER", + "scoreLabel": "Score: ", + "playAgain": "PLAY AGAIN" + }, + "magic_sort": { + "title": "Magic Sort", + "instructions": "Pour colored liquids between bottles until each is one color!", + "startGame": "START GAME", + "levelCleared": "MAGIC SORTED!", + "nextLevel": "NEXT LEVEL", + "levelPrefix": "LEVEL ", + "restart": "Restart" + }, + "attack_hole": { + "attack_hole_level": "Level {0}", + "attack_hole_session_points": "Session: {0}", + "attack_hole_level_points": "Points: {0}", + "attack_hole_title": "Attack Hole", + "attack_hole_inst": "Move the hole to swallow weapons and defeat the giant boss!", + "startGame": "Start Game", + "attack_hole_attack": "Attack!", + "victory": "Victory!", + "score": "Score: ", + "playAgain": "Play Again", + "gameOver": "Game Over", + "tryAgain": "Try Again", + "title": "Attack Hole" + }, + "block_breaker": { + "title": "Merge Diggers", + "playerLevel": "Player Level: ", + "lvl": "Lvl ", + "lane1": "▼ Lane 1", + "lane2": "▼ Lane 2", + "lane3": "▼ Lane 3", + "lane4": "▼ Lane 4", + "lane5": "▼ Lane 5", + "dropTools": "DROP TOOLS!", + "digging": "DIGGING...", + "levelCleared": "Level Cleared!", + "levelClearedDesc": "You successfully broke through to the bedrock.", + "nextLevel": "Next Level", + "levelFailed": "Level Failed", + "levelFailedDesc": "Your tools broke before reaching the bottom.", + "tryAgain": "Try Again", + "sell": "SELL" + }, + "doge_rescue": { + "level": "Level ", + "doge_rescue_title": "Doge Rescue", + "doge_rescue_inst": "Draw a line to protect Doge from the bees!", + "startGame": "Start Game", + "victory": "Victory!", + "score": "Score: ", + "nextLevel": "Next Level", + "gameOver": "Game Over", + "tryAgain": "Try Again", + "title": "Doge Rescue" + }, + "helix_jump": { + "score": "Score: ", + "level": "Level ", + "time": "Time: ", + "helix_jump_title": "Helix Jump", + "helix_jump_inst": "Rotate the tower to drop the bouncing ball to the bottom!", + "startGame": "Start Game", + "levelCleared": "Level Cleared!", + "nextLevel": "Next Level", + "gameOver": "Game Over", + "tryAgain": "Try Again", + "title": "Helix Jump" + }, + "mob_control": { + "level": "Level ", + "mob_control_title": "Mob Control", + "mob_control_inst": "Shoot and multiply your mob to overwhelm the enemy!", + "startGame": "Start Game", + "victory": "Victory!", + "score": "Score: ", + "nextLevel": "Next Level", + "gameOver": "Game Over", + "tryAgain": "Try Again", + "title": "Mob Control" + }, + "paper_io": { + "score": "Score: ", + "paper_io_title": "Paper.io", + "paper_io_inst": "Conquer territory by enclosing loops and defeat opponents!", + "startGame": "Start Game", + "gameOver": "Game Over", + "playAgain": "Play Again", + "title": "Paper.io" + }, + "spiral_roll": { + "spiral_roll_session": "Session: ", + "spiral_roll_score": "Score: ", + "spiral_roll_level_lbl": "Level: ", + "spiral_roll_title": "Spiral Roll", + "spiral_roll_inst_orig": "Hold to carve a spiral.\nRelease to launch it!\nBigger rolls = More points.", + "startGame": "Start Game", + "spiral_roll_cleared": "LEVEL CLEARED!", + "spiral_roll_final_score": "Final Score: ", + "spiral_roll_next_level": "NEXT LEVEL", + "spiral_roll_crashed": "CRASHED!", + "spiral_roll_try_again": "TRY AGAIN", + "spiral_roll_bonus": "BONUS!", + "title": "Spiral Roll" + }, + "stack_colors": { + "stack_colors_session": "Session: ", + "stack_colors_score": "Score: ", + "stack_colors_level_lbl": "Level: ", + "stack_colors_stack": "Stack: ", + "stack_colors_tap_kick": "TAP TO KICK!", + "stack_colors_kick_btn": "KICK!", + "stack_colors_title": "Stack Colors", + "stack_colors_inst": "Move left and right to collect matching colored blocks!", + "stack_colors_start_run": "START RUN", + "stack_colors_level_complete": "LEVEL COMPLETE", + "stack_colors_final_score": "Final Score: ", + "stack_colors_play_again": "PLAY AGAIN", + "stack_colors_game_over": "GAME OVER", + "stack_colors_bonus": "BONUS!", + "title": "Stack Colors" + } +} \ No newline at end of file diff --git a/public/lang/texts.es.lang b/public/lang/texts.es.lang new file mode 100644 index 0000000..453a6b9 --- /dev/null +++ b/public/lang/texts.es.lang @@ -0,0 +1,506 @@ +{ + "pageName": { + "closet": "Personalización", + "devSettings": "Opciones de desarrollador", + "game": "Juego de Cheems Bonk", + "menu": "Menú principal", + "onWork": "En desarrollo", + "p404": "Error 404", + "settings": "Ajustes", + "offline": "Descarga de recursos", + "shop": "Tienda", + "block_breaker": "Merge Diggers", + "attack_hole": "Attack Hole", + "doge_rescue": "Doge Rescue", + "flappy_dunk": "Flappy Dunk", + "helix_jump": "Helix Jump", + "magic_sort": "Magic Sort", + "mob_control": "Mob Control", + "paper_io": "Paper.io", + "spiral_roll": "Spiral Roll", + "stack_colors": "Stack Colors", + "minigames": "Minijuegos", + "licenses": "Licencias y Créditos", + "gallery": "Galería" + }, + "minigames": { + "trash": "BASURA", + "buyShovel": "Comprar pala", + "buyPickaxe": "Comprar pico", + "best": "Mejor: ", + "youWin": "¡Ganaste!", + "restart": "Reiniciar", + "defeat": "¡Derrota!", + "convertedPointsToast": "¡Se convirtieron {0} puntos del juego en +{1} MG Coins!", + "flappy_dunk_inst": "¡Toca para hacer volar la pelota y encestar en los aros!", + "magic_sort_inst": "¡Vierte líquidos de color entre botellas hasta ordenar los colores!", + "spiral_roll_inst": "¡Mantén presionado para tallar espirales de madera y saltar obstáculos!", + "spiral_roll_play_again": "JUGAR DE NUEVO" + }, + "licensesPage": { + "aiGeneratedSong": "Canción generada por Gemini Lyria 3 Pro", + "aiGeneratedImage": "Imagen generada por el generador de imágenes de Gemini 3 Pro" + }, + "menu": { + "minigames": "Minijuegos", + "settings": "Ajustes", + "offline": "Descarga de recursos (Modo offline)", + "shop": "Tienda de personalización", + "closet": "Personalización", + "stats": "Estadísticas", + "licenses": "Licencias", + "devMenu": "Opciones de desarrollo", + "buyDogeCoin": "Comprar 1 DogeCoin", + "buyDogeCoinSub": "Costo de hoy: ", + "buyDogeCoinSuccess": "¡Compraste 1 DogeCoin!", + "buyDogeCoinFail": "¡Necesitas más puntos!", + "gallery": "Galería" + }, + "options": { + "changeLang": { + "button": "Cambiar idioma (Switch Language)" + }, + "musicVolume": "Volumen de la música", + "effectsVolume": "Volumen de los efectos", + "appTheme": "Tema de la app (colores):", + "themes": { + "light": "Modo claro", + "dark": "Modo oscuro", + "contrast": "Modo alto contraste" + }, + "fontSize": "Tamaño de la fuente:", + "sizes": { + "smaller": "Muy pequeña", + "small": "Pequeña", + "normal": "Normal", + "big": "Grande", + "max": "Muy grande" + }, + "saveManagement": "Gestión de Datos", + "deleteProgress": "Borrar Progreso", + "deleteProgressConfirm": "¿Estás seguro de que deseas borrar TODO el progreso? ¡Esto no se puede deshacer!", + "exportSave": "Exportar Partida", + "importSave": "Importar Partida", + "importSaveConfirm": "Importar una partida sobrescribirá todo tu progreso actual. ¿Continuar?" + }, + "stats": { + "title": "Estadísticas", + "highScore": "Combo Máximo", + "totalTouches": "Toques Totales", + "lifetimePoints": "Puntos Obtenidos (Total)", + "lifetimeDogeCoins": "DogeCoins Obtenidos (Total)", + "lifetimeMinigameCoins": "Monedas MG Obtenidas (Total)" + }, + "game": { + "navbar": { + "highScore": "Mayor puntaje", + "actScore": "Toques actuales", + "totalScore": "Toques totales", + "booster": "Potenciador" + }, + "tapToBonk": "¡Haz clic en Cheems para un BONK!" + }, + "closet": { + "title": "Personalización", + "cheemsSection": "Cheems (Skins)", + "soundsSection": "Sonidos de golpe", + "musicSection": "Música de fondo", + "selected": "Seleccionado", + "equipped": "Equipado", + "purchased": "Comprado", + "cost": "Costo:", + "free": "Gratis", + "buy": "Comprar", + "equip": "Equipar", + "needMoreCoins": "¡Necesitas más DogeCoins!", + "itemBought": "¡Comprado con éxito!", + "itemSelected": "¡Seleccionado!", + "inShop": "En Tienda", + "buyInShop": "¡Compra este artículo en la Tienda!", + "locked": "Bloqueado" + }, + "dev": { + "title": "Opciones de desarrollo", + "resetToZero": "Restablecer a cero (Reset)", + "unlockAll": "Desbloquear todo", + "giveDogeCoins": "Añadir +100 DogeCoins", + "givePoints": "Añadir +1000 Puntos", + "success": "¡Completado!", + "unlocked": "¡Menú de desarrollo DESBLOQUEADO!", + "locked": "Menú de desarrollo bloqueado." + }, + "onWork": { + "title": "Página en desarrollo", + "message": "Esta página está en desarrollo aún. ¡Vuelve pronto!", + "backToMenu": "Volver al menú" + }, + "p404": { + "title": "Error 404", + "message": "La página que buscas no existe en el universo Cheems.", + "backToGame": "Volver al Juego" + }, + "offline": { + "title": "Descargar recursos (Modo Offline)", + "subtitle": "Guarda los archivos del juego en tu dispositivo para jugar sin conexión a Internet.", + "downloadAll": "Descargar todos los recursos", + "essentialsTitle": "Esenciales", + "essentialsDesc": "Páginas del juego, gráficos, scripts, fuentes y datos principales (sin audio).", + "sfxTitle": "Efectos de sonido (SFX)", + "sfxDesc": "Todos los efectos de sonido del juego y menú.", + "musicTitle": "Música de fondo", + "musicDesc": "Colección completa de pistas de música de fondo.", + "downloaded": "Descargado", + "download": "Descargar", + "downloading": "Descargando...", + "successToast": "¡Recursos descargados y guardados con éxito!", + "errorToast": "Error al descargar algunos recursos.", + "checkForUpdates": "Buscar Actualizaciones", + "minigamesTitle": "Minijuegos", + "minigamesDesc": "Activos y datos para los minijuegos." + }, + "shop": { + "title": "Tienda de Objetos y Potenciadores", + "subtitle": "¡Gasta tus puntos en DogeCoins o activa multiplicadores de puntos por tiempo limitado!", + "activeBooster": "Potenciador Activo:", + "pointsPerClick": "Puntos por Clic", + "remaining": "restantes", + "buyBtn": "Comprar", + "todaysPrice": "Precio de Hoy:", + "pts": "Pts", + "needMorePoints": "¡Puntos insuficientes!", + "boosterActivated": "¡Potenciador activado!", + "currencyToggle": "Moneda:", + "buyWithPts": "Comprar con Pts", + "buyWithCoins": "Comprar con Coins", + "currencyPts": "Puntos", + "currencyCoins": "DogeCoins", + "free": "Gratis", + "remainingToday": "disponibles hoy", + "dailyLimitReached": "¡Límite diario alcanzado!", + "booster": "Potenciador", + "boosterOverrideWarning": "¡Advertencia! Ya tienes un potenciador x{current} activo. Si compras un x{new}, se sobreescribirá tu tiempo restante. ¿Deseas continuar?", + "purchased": "Comprado", + "itemBoughtGoToCloset": "¡Artículo comprado! Ve a Personalización para equipar.", + "alreadyPurchased": "¡Ya comprado!", + "dogecoinSection": "DogeCoins", + "boosterSection": "Potenciadores", + "cheemsSection": "Aspectos Cheems", + "sfxSection": "Efectos de Sonido", + "musicSection": "Música de Fondo", + "backToTop": "Volver Arriba ↑" + }, + "shopItemsText": { + "shop_dogecoin_special_name": "DogeCoin (Oferta Especial)", + "shop_dogecoin_special_desc": "¡Compra 1 DogeCoin a precio especial!", + "shop_dogecoin_1_name": "DogeCoin x1", + "shop_dogecoin_1_desc": "Obtienes 1 Dogecoin. ¡El precio cambia cada día!", + "shop_dogecoin_2_name": "DogeCoin x2", + "shop_dogecoin_2_desc": "Obtienes 2 Dogecoin. ¡El precio cambia cada día!", + "shop_dogecoin_3_name": "DogeCoin x3", + "shop_dogecoin_3_desc": "Obtienes 3 Dogecoin. ¡El precio cambia cada día!", + "shop_dogecoin_5_name": "DogeCoin x5", + "shop_dogecoin_5_desc": "Obtienes 5 Dogecoin. ¡El precio cambia cada día!", + "shop_dogecoin_10_name": "DogeCoin x10", + "shop_dogecoin_10_desc": "Obtienes 10 Dogecoin. ¡El precio cambia cada día!", + "shop_dogecoin_20_name": "DogeCoin x20", + "shop_dogecoin_20_desc": "Obtienes 20 Dogecoin. ¡El precio cambia cada día!", + "shop_boost_2x_5m_name": "Potenciador x2 (5 min)", + "shop_boost_2x_5m_desc": "Duplica tus puntos por clic durante 5 minutos.", + "shop_boost_3x_5m_name": "Potenciador x3 (5 min)", + "shop_boost_3x_5m_desc": "Triplica tus puntos por clic durante 5 minutos.", + "shop_boost_2x_10m_name": "Potenciador x2 (10 min)", + "shop_boost_2x_10m_desc": "Duplica tus puntos por clic durante 10 minutos.", + "shop_boost_3x_10m_name": "Potenciador x3 (10 min)", + "shop_boost_3x_10m_desc": "Triplica tus puntos por clic durante 10 minutos.", + "shop_boost_2x_20m_name": "Potenciador x2 (20 min)", + "shop_boost_2x_20m_desc": "Duplica tus puntos por clic durante 20 minutos.", + "shop_boost_3x_20m_name": "Potenciador x3 (20 min)", + "shop_boost_3x_20m_desc": "Triplica tus puntos por clic durante 20 minutos.", + "shop_boost_10x_1m_name": "Potenciador x10 (1 min)", + "shop_boost_10x_1m_desc": "Multiplica tus puntos por 10 durante 1 minuto.", + "shop_boost_10x_3m_name": "Potenciador x10 (3 min)", + "shop_boost_10x_3m_desc": "Multiplica tus puntos por 10 durante 3 minutos.", + "shop_boost_10x_5m_name": "Potenciador x10 (5 min)", + "shop_boost_10x_5m_desc": "Multiplica tus puntos por 10 durante 5 minutos.", + "shop_boost_10x_10m_name": "Potenciador x10 (10 min)", + "shop_boost_10x_10m_desc": "Multiplica tus puntos por 10 durante 10 minutos.", + "shop_minigame_block_breaker_name": "Merge Diggers", + "shop_minigame_block_breaker_desc": "Desbloquea el minijuego de cavar y combinar herramientas.", + "shop_minigame_attack_hole_name": "Attack Hole", + "shop_minigame_attack_hole_desc": "Desbloquea el minijuego 3D de absorber armas.", + "shop_minigame_doge_rescue_name": "Doge Rescue", + "shop_minigame_doge_rescue_desc": "Desbloquea el minijuego de física de salvar a Doge.", + "shop_minigame_flappy_dunk_name": "Flappy Dunk", + "shop_minigame_flappy_dunk_desc": "Desbloquea el minijuego arcade de encestar en aros.", + "shop_minigame_helix_jump_name": "Helix Jump", + "shop_minigame_helix_jump_desc": "Desbloquea el minijuego 3D de torre con pelota rebotando.", + "shop_minigame_magic_sort_name": "Magic Sort", + "shop_minigame_magic_sort_desc": "Desbloquea el minijuego de puzle de ordenar colores.", + "shop_minigame_mob_control_name": "Mob Control", + "shop_minigame_mob_control_desc": "Desbloquea el minijuego de multiplicar multitudes.", + "shop_minigame_paper_io_name": "Paper.io", + "shop_minigame_paper_io_desc": "Desbloquea el minijuego de capturar territorios.", + "shop_minigame_spiral_roll_name": "Spiral Roll", + "shop_minigame_spiral_roll_desc": "Desbloquea el minijuego 3D de tallar madera en espiral.", + "shop_minigame_stack_colors_name": "Stack Colors", + "shop_minigame_stack_colors_desc": "Desbloquea el minijuego 3D de apilar bloques por color.", + "shop_curr_dgc_to_mg_name": "10 Puntos de Minijuegos", + "shop_curr_dgc_to_mg_desc": "Intercambia 1 DogeCoin por 10 Puntos de Minijuegos.", + "shop_curr_mg_to_dgc_name": "1 DogeCoin", + "shop_curr_mg_to_dgc_desc": "Intercambia 10 Puntos de Minijuegos por 1 DogeCoin." + }, + "itemsText": { + "cheems_normal": "Cheems Normal", + "cheems_normal_desc": "El cheems original.", + "cheems_little": "Cheems Chiquito", + "cheems_little_desc": "Es pequeño y lindo.", + "cheems_adult": "Cheems Adulto", + "cheems_adult_desc": "Él es serio, y posiblemente un actor.", + "cheems_kid": "Cheems Niño", + "cheems_kid_desc": "Cheems chiquito, pero es un niño.", + "cheems_mamado": "Cheems Mamado", + "cheems_mamado_desc": "Él es un Gymbro.", + "cheems_pixelart": "Cheems Pixel", + "cheems_pixelart_desc": "Cheems en pixel art, ¿A quien no le gustan los pixel arts?", + "cheems_elegant": "Cheems Elegante", + "cheems_elegant_desc": "Él es más elegante que tú.", + "cheems_3d": "Cheems 3D", + "cheems_3d_desc": "Cheems impreso en una impresora 3D, Wow.", + "cheems_black": "Cheems Negro", + "cheems_black_desc": "¿Tiene textura o...?", + "cheems_minecraft": "Cheems Minecraft", + "cheems_minecraft_desc": "Yo quiero ser minero, romper el pico en el hierro...", + "cheems_not_a_dog": "Cheems No Es Un Perro", + "cheems_not_a_dog_desc": "Elle se identifica como un gato.", + "cheems_not_a_plumber": "Cheems No Fontanero", + "cheems_not_a_plumber_desc": "No está definitivamente basado en ningún fontanero de ninguna franquicia, pero es una similitud curiosa.", + "cheems_not_ai": "Cheems No IA", + "cheems_not_ai_desc": "No usé IA para crear este cheems, para nada, ¿ok?", + "cheems_realistic": "Cheems Realista", + "cheems_realistic_desc": "Este es cheems, pero en 4K (El juego debía de vender, ¿ok?).", + "sfx_1": "Golpe (Bonk)", + "sfx_1_desc": "Bonk, bonk, bonk...", + "sfx_2": "Daño Minecraft", + "sfx_2_desc": "Uh, ¿Recuerdas este sonido?", + "sfx_3": "Daño Roblox", + "sfx_3_desc": "Oh no, amigo. (Espero no ser demandado)", + "sfx_4": "Subir de nivel", + "sfx_4_desc": "¡Te estás haciendo más fuerte!", + "sfx_5": "Discord", + "sfx_5_desc": "Discord, buen gamer.", + "sfx_6": "Hola (Hello)", + "sfx_6_desc": "Ella es la única animatronica que usa shorts, lo que la hace hermosa para la comunidad", + "sfx_7": "Golpe Minecraft", + "sfx_7_desc": "Golpe género-neutral.", + "sfx_8": "No", + "sfx_8_desc": "¡¡¡No!!! (Fuiste golpeado de todas formas)", + "sfx_9": "Pato", + "sfx_9_desc": "Un pato que va cantando alegremente Cuá, cuá, Cuando se encuentra a un lindo gato Miau, miau, para cantar bossa nova.", + "sfx_10": "Peluche", + "sfx_10_desc": "Squeak squeak!", + "sfx_11": "Splat", + "sfx_11_desc": "Splash!", + "sfx_12": "Error Windows", + "sfx_12_desc": "Espero no lo escuches seguido.", + "music_0": "Mute / Sin música", + "music_0_desc": "¿Quién juega sin música?", + "music_1": "A Jazz Piano", + "music_1_desc": "Una canción de piano Jazz, nice.", + "music_2": "Jack Bootleg", + "music_2_desc": "¡Golpea con mucha energía a cheems!", + "music_3": "Magic Night", + "music_3_desc": "Música relajante para un juego relajante.", + "music_4": "Minimalism No9", + "music_4_desc": "Música minimalista para un juego minimalista.", + "music_5": "Minimalism No10", + "music_5_desc": "Música minimalista para un juego minimalista, pero mejorada a una nueva actualización.", + "music_6": "When You Smile", + "music_6_desc": "Creo que cheems no sonrie de todas maneras...", + "music_7": "Tetris (Joey iLLah Bootleg)", + "music_7_desc": "La canción de Tetris, pero mejorada.", + "music_8": "Separation", + "music_8_desc": "Una melodía pensativa y tranquila.", + "music_9": "Electro Summer", + "music_9_desc": "¡Vibras de fiesta positiva!", + "music_10": "Titanium", + "music_10_desc": "Fuerte como el titanio.", + "music_11": "Believe Me", + "music_11_desc": "Cree en el poder de la música.", + "music_12": "City Streets", + "music_12_desc": "Música de fondo para una ciudad ajetreada.", + "music_13": "Coffee Shop", + "music_13_desc": "Ambiente relajado de cafetería.", + "music_14": "Trap Future Bass", + "music_14_desc": "Música moderna para golpes modernos.", + "music_15": "Bonk The Amber", + "music_15_desc": "Nueva pista de música: Bonk The Amber", + "music_16": "Bonk The Avatar", + "music_16_desc": "Nueva pista de música: Bonk The Avatar", + "music_17": "Bonus Level Bounce", + "music_17_desc": "Nueva pista de música: Bonus Level Bounce", + "music_18": "Button Smash Routine", + "music_18_desc": "Nueva pista de música: Button Smash Routine", + "music_19": "Cheems Chan Bonk", + "music_19_desc": "Nueva pista de música: Cheems Chan Bonk", + "music_20": "Click For A Bonk", + "music_20_desc": "Nueva pista de música: Click For A Bonk", + "music_21": "Hardwood Strike", + "music_21_desc": "Nueva pista de música: Hardwood Strike", + "music_22": "Perfect Round", + "music_22_desc": "Nueva pista de música: Perfect Round", + "music_23": "Pocket Change Victory", + "music_23_desc": "Nueva pista de música: Pocket Change Victory", + "music_24": "Quick Loot Run", + "music_24_desc": "Nueva pista de música: Quick Loot Run", + "music_25": "Target In The Sight", + "music_25_desc": "Nueva pista de música: Target In The Sight", + "music_26": "The Hammer Falls", + "music_26_desc": "Nueva pista de música: The Hammer Falls", + "music_27": "The Late Commute", + "music_27_desc": "Nueva pista de música: The Late Commute", + "music_28": "The Unwritten Page", + "music_28_desc": "Nueva pista de música: The Unwritten Page", + "music_29": "Where The Path Bends", + "music_29_desc": "Nueva pista de música: Where The Path Bends" + }, + "gallery": { + "title": "Galería", + "skinsSection": "Skins", + "soundsSection": "Efectos de Sonido", + "musicSection": "Música", + "normalSkin": "Normal", + "hitSkin": "Golpeando", + "play": "Reproducir", + "pause": "Pausar" + }, + "flappy_dunk": { + "title": "Flappy Dunk", + "instructions_infinite": "Toca para aletear.
Encesta en los aros hasta que pierdas.
¡No falles!", + "instructions_finite": "Toca para aletear.
Encesta en los aros hasta que llegues al final.
¡No falles!", + "tapToPlay": "TOCA PARA JUGAR", + "gameOver": "FIN DEL JUEGO", + "scoreLabel": "Puntos: ", + "playAgain": "JUGAR DE NUEVO" + }, + "magic_sort": { + "title": "Magic Sort", + "instructions": "¡Vierte líquidos de colores entre las botellas hasta que cada una sea de un solo color!", + "startGame": "INICIAR JUEGO", + "levelCleared": "¡MAGIA ORDENADA!", + "nextLevel": "SIGUIENTE NIVEL", + "levelPrefix": "NIVEL ", + "restart": "Reiniciar" + }, + "attack_hole": { + "attack_hole_level": "Nivel {0}", + "attack_hole_session_points": "Sesión: {0}", + "attack_hole_level_points": "Puntos: {0}", + "attack_hole_title": "Attack Hole", + "attack_hole_inst": "¡Mueve el agujero para tragar armas y derrotar al jefe gigante!", + "startGame": "Iniciar Juego", + "attack_hole_attack": "¡Atacar!", + "victory": "¡Victoria!", + "score": "Puntuación: ", + "playAgain": "Jugar de nuevo", + "gameOver": "Fin del Juego", + "tryAgain": "Intentar de nuevo", + "title": "Attack Hole" + }, + "block_breaker": { + "title": "Merge Diggers", + "playerLevel": "Nivel de Jugador: ", + "lvl": "Nivel ", + "lane1": "▼ Carril 1", + "lane2": "▼ Carril 2", + "lane3": "▼ Carril 3", + "lane4": "▼ Carril 4", + "lane5": "▼ Carril 5", + "dropTools": "¡SOLTAR HERRAMIENTAS!", + "digging": "EXCAVANDO...", + "levelCleared": "¡Nivel Completado!", + "levelClearedDesc": "Has logrado atravesar hasta la roca base.", + "nextLevel": "Siguiente Nivel", + "levelFailed": "Nivel Fallido", + "levelFailedDesc": "Tus herramientas se rompieron antes de llegar al fondo.", + "tryAgain": "Intentar de nuevo", + "sell": "VENDER" + }, + "doge_rescue": { + "level": "Nivel ", + "doge_rescue_title": "Doge Rescue", + "doge_rescue_inst": "¡Dibuja una línea para proteger a Doge de las abejas!", + "startGame": "Iniciar Juego", + "victory": "¡Victoria!", + "score": "Puntuación: ", + "nextLevel": "Siguiente Nivel", + "gameOver": "Fin del Juego", + "tryAgain": "Intentar de nuevo", + "title": "Doge Rescue" + }, + "helix_jump": { + "score": "Puntuación: ", + "level": "Nivel ", + "time": "Tiempo: ", + "helix_jump_title": "Helix Jump", + "helix_jump_inst": "¡Gira la torre para hacer caer la pelota hasta el fondo!", + "startGame": "Iniciar Juego", + "levelCleared": "¡Nivel Completado!", + "nextLevel": "Siguiente Nivel", + "gameOver": "Fin del Juego", + "tryAgain": "Intentar de nuevo", + "title": "Helix Jump" + }, + "mob_control": { + "level": "Nivel ", + "mob_control_title": "Mob Control", + "mob_control_inst": "¡Dispara y multiplica tu multitud para aplastar al enemigo!", + "startGame": "Iniciar Juego", + "victory": "¡Victoria!", + "score": "Puntuación: ", + "nextLevel": "Siguiente Nivel", + "gameOver": "Fin del Juego", + "tryAgain": "Intentar de nuevo", + "title": "Mob Control" + }, + "paper_io": { + "score": "Puntuación: ", + "paper_io_title": "Paper.io", + "paper_io_inst": "¡Conquista territorio cerrando circuitos y derrota a tus rivales!", + "startGame": "Iniciar Juego", + "gameOver": "Fin del Juego", + "playAgain": "Jugar de nuevo", + "title": "Paper.io" + }, + "spiral_roll": { + "spiral_roll_session": "Sesión: ", + "spiral_roll_score": "Puntos: ", + "spiral_roll_level_lbl": "Nivel: ", + "spiral_roll_title": "Spiral Roll", + "spiral_roll_inst_orig": "Mantén presionado para tallar.\n¡Suelta para lanzar!\nEspirales más grandes = Más puntos.", + "startGame": "Iniciar Juego", + "spiral_roll_cleared": "¡NIVEL COMPLETADO!", + "spiral_roll_final_score": "Puntuación Final: ", + "spiral_roll_next_level": "SIGUIENTE NIVEL", + "spiral_roll_crashed": "¡CHOCASTE!", + "spiral_roll_try_again": "REINTENTAR", + "spiral_roll_bonus": "¡BONUS!", + "title": "Spiral Roll" + }, + "stack_colors": { + "stack_colors_session": "Sesión: ", + "stack_colors_score": "Puntos: ", + "stack_colors_level_lbl": "Nivel: ", + "stack_colors_stack": "Apilados: ", + "stack_colors_tap_kick": "¡TOCA PARA PATEAR!", + "stack_colors_kick_btn": "¡PATEAR!", + "stack_colors_title": "Stack Colors", + "stack_colors_inst": "¡Muévete de izquierda a derecha para recolectar bloques de color coincidente!", + "stack_colors_start_run": "INICIAR CARRERA", + "stack_colors_level_complete": "¡NIVEL COMPLETADO!", + "stack_colors_final_score": "Puntuación Final: ", + "stack_colors_play_again": "JUGAR DE NUEVO", + "stack_colors_game_over": "¡FIN DEL JUEGO!", + "stack_colors_bonus": "¡BONUS!", + "title": "Stack Colors" + } +} \ No newline at end of file diff --git a/public/licences/electro-electro-summer-positive-party-141081-license.txt b/public/licences/electro-electro-summer-positive-party-141081-license.txt deleted file mode 100644 index d45314b..0000000 --- a/public/licences/electro-electro-summer-positive-party-141081-license.txt +++ /dev/null @@ -1,34 +0,0 @@ -PIXABAY LICENSE CERTIFICATE -============================================== - -This document confirms the download of an audio file pursuant to the Content License as defined in the Pixabay Terms of Service available at https://pixabay.com/service/terms/ - -Licensor's Username: -https://pixabay.com/es/users/alex_kizenkov-33612407/ - -Licensee: -u_5469lku7m5 - -Audio File Title: -Electro Summer Positive Party - -Audio File URL: -https://pixabay.com/es/music/electro-electro-summer-positive-party-141081/ - -Audio File ID: -141081 - -Date of download: -2024-03-11 02:42:03 UTC - -Pixabay, a Canva Germany GmbH brand -Pappelallee 78/79 -10437 Berlin -Germany - -Pixabay is a user-contributed stock content website. The above-named Licensor is responsible for this audio file. Pixabay monitors uploaded audio files only to a reasonable extent. Pixabay cannot be held responsible for the acts or omissions of its users and does not represent or warrant that any required third-party consents or licenses have been obtained. - -For any queries related to this document please contact Pixabay via info@pixabay.com. - - -==== THIS IS NOT A TAX RECEIPT OR INVOICE ==== \ No newline at end of file diff --git a/public/licences/futuro-bajo-titanium-170190-license.txt b/public/licences/futuro-bajo-titanium-170190-license.txt deleted file mode 100644 index 07cfbba..0000000 --- a/public/licences/futuro-bajo-titanium-170190-license.txt +++ /dev/null @@ -1,34 +0,0 @@ -PIXABAY LICENSE CERTIFICATE -============================================== - -This document confirms the download of an audio file pursuant to the Content License as defined in the Pixabay Terms of Service available at https://pixabay.com/service/terms/ - -Licensor's Username: -https://pixabay.com/es/users/alisiabeats-39461785/ - -Licensee: -u_5469lku7m5 - -Audio File Title: -Titanium - -Audio File URL: -https://pixabay.com/es/music/futuro-bajo-titanium-170190/ - -Audio File ID: -170190 - -Date of download: -2024-03-05 06:11:27 UTC - -Pixabay, a Canva Germany GmbH brand -Pappelallee 78/79 -10437 Berlin -Germany - -Pixabay is a user-contributed stock content website. The above-named Licensor is responsible for this audio file. Pixabay monitors uploaded audio files only to a reasonable extent. Pixabay cannot be held responsible for the acts or omissions of its users and does not represent or warrant that any required third-party consents or licenses have been obtained. - -For any queries related to this document please contact Pixabay via info@pixabay.com. - - -==== THIS IS NOT A TAX RECEIPT OR INVOICE ==== \ No newline at end of file diff --git a/public/licences/futuro-bajo-trap-future-bass-royalty-free-music-167020-license.txt b/public/licences/futuro-bajo-trap-future-bass-royalty-free-music-167020-license.txt deleted file mode 100644 index 8a2658f..0000000 --- a/public/licences/futuro-bajo-trap-future-bass-royalty-free-music-167020-license.txt +++ /dev/null @@ -1,34 +0,0 @@ -PIXABAY LICENSE CERTIFICATE -============================================== - -This document confirms the download of an audio file pursuant to the Content License as defined in the Pixabay Terms of Service available at https://pixabay.com/service/terms/ - -Licensor's Username: -https://pixabay.com/es/users/royaltyfreemusic-29393722/ - -Licensee: -u_5469lku7m5 - -Audio File Title: -Trap Future Bass (Royalty Free Music) - -Audio File URL: -https://pixabay.com/es/music/futuro-bajo-trap-future-bass-royalty-free-music-167020/ - -Audio File ID: -167020 - -Date of download: -2024-03-11 02:40:44 UTC - -Pixabay, a Canva Germany GmbH brand -Pappelallee 78/79 -10437 Berlin -Germany - -Pixabay is a user-contributed stock content website. The above-named Licensor is responsible for this audio file. Pixabay monitors uploaded audio files only to a reasonable extent. Pixabay cannot be held responsible for the acts or omissions of its users and does not represent or warrant that any required third-party consents or licenses have been obtained. - -For any queries related to this document please contact Pixabay via info@pixabay.com. - - -==== THIS IS NOT A TAX RECEIPT OR INVOICE ==== \ No newline at end of file diff --git a/public/licences/guitarra-solista-separation-185196-license.txt b/public/licences/guitarra-solista-separation-185196-license.txt deleted file mode 100644 index 401ca37..0000000 --- a/public/licences/guitarra-solista-separation-185196-license.txt +++ /dev/null @@ -1,34 +0,0 @@ -PIXABAY LICENSE CERTIFICATE -============================================== - -This document confirms the download of an audio file pursuant to the Content License as defined in the Pixabay Terms of Service available at https://pixabay.com/service/terms/ - -Licensor's Username: -https://pixabay.com/es/users/william_king-33448498/ - -Licensee: -u_5469lku7m5 - -Audio File Title: -Separation - -Audio File URL: -https://pixabay.com/es/music/guitarra-solista-separation-185196/ - -Audio File ID: -185196 - -Date of download: -2024-03-05 06:09:10 UTC - -Pixabay, a Canva Germany GmbH brand -Pappelallee 78/79 -10437 Berlin -Germany - -Pixabay is a user-contributed stock content website. The above-named Licensor is responsible for this audio file. Pixabay monitors uploaded audio files only to a reasonable extent. Pixabay cannot be held responsible for the acts or omissions of its users and does not represent or warrant that any required third-party consents or licenses have been obtained. - -For any queries related to this document please contact Pixabay via info@pixabay.com. - - -==== THIS IS NOT A TAX RECEIPT OR INVOICE ==== \ No newline at end of file diff --git a/public/licences/needed.txt b/public/licences/needed.txt deleted file mode 100644 index dd999d7..0000000 --- a/public/licences/needed.txt +++ /dev/null @@ -1,56 +0,0 @@ -*** -Obfuscator.io: -Options preset: High -Seed: 76819637732 -*** - -SVG -> -CC0 -> -License: https://www.svgrepo.com/page/licensing/#CC0 -Page: https://www.svgrepo.com/ -Solar bold icons: https://www.svgrepo.com/collection/solar-bold-icons/ -Isometric 3d interface icons collection: https://www.svgrepo.com/collection/isometric-3d-interface-icons/ - -music -> -Minimalism N. 9, Notre envol - Raphaël Novarina [Piano] -https://soundcloud.com/relaxing-music-production/sugar6borg-dust-ft-raphael-novarina?si=dcf18380d94e4f029906b5ab13f212c9&utm_source=clipboard&utm_medium=text&utm_campaign=social_sharing - -Jack Bootleg -https://soundcloud.com/dj-noah-6/jack-bootleg-free-download?si=0ea8c3007d314b6aba92cb5a5dc9fc73&utm_source=clipboard&utm_medium=text&utm_campaign=social_sharing - -Minimalism N. 10, Notre envol II - Raphaël Novarina [Piano] -https://soundcloud.com/relaxing-music-production/chillout-piano-lounge-calming-music?si=698f869d606546518e751a83447600a3&utm_source=clipboard&utm_medium=text&utm_campaign=social_sharing - -A Jazz Piano -Music by Oleg Kyrylkovv from Pixabay - -When you smile -Music by Aleksey Chistilin from Pixabay - -Magic Night -Music by Keyframe Audio from Pixabay - -Separation -Music by William_King from Pixabay - -Titanium -Music by Alisia from Pixabay - -Coffe Shop -Music by Barnabas from Pixabay - -Believe me -Music by Oleksii Holubiev from Pixabay - -City Streets (Background version) -Music by Nathaniel from Pixabay - -Trap Future bass (Royalty free music) -Music by Nver Avetyan from Pixabay - -Electro summer positive party -Music by Alex_Kizenkov from Pixabay - -TETRIS (Joey iLLah Bootleg) FREE DOWNLOAD -https://soundcloud.com/joeyillah/tetris-joey-illah-bootleg-1?si=d58f385c9db242479b066090d6536864&utm_source=clipboard&utm_medium=text&utm_campaign=social_sharing - diff --git a/public/manifest.webmanifest b/public/manifest.webmanifest index 324a1b9..ff2a2e2 100644 --- a/public/manifest.webmanifest +++ b/public/manifest.webmanifest @@ -7,28 +7,46 @@ "start_url": "./", "icons": [ { - "src": "img/icons/pwa/icon-72x72.png", + "src": "../icons/icon-48.webp", + "type": "image/png", + "sizes": "48x48", + "purpose": "any maskable" + }, + { + "src": "../icons/icon-72.webp", + "type": "image/png", "sizes": "72x72", + "purpose": "any maskable" + }, + { + "src": "../icons/icon-96.webp", "type": "image/png", - "purpose": "maskable any" + "sizes": "96x96", + "purpose": "any maskable" }, { - "src": "img/icons/pwa/icon-144x144.png", - "sizes": "144x144", + "src": "../icons/icon-128.webp", "type": "image/png", - "purpose": "maskable any" + "sizes": "128x128", + "purpose": "any maskable" }, { - "src": "img/icons/pwa/icon-192x192.png", + "src": "../icons/icon-192.webp", + "type": "image/png", "sizes": "192x192", + "purpose": "any maskable" + }, + { + "src": "../icons/icon-256.webp", "type": "image/png", - "purpose": "maskable any" + "sizes": "256x256", + "purpose": "any maskable" }, { - "src": "img/icons/pwa/icon-512x512.png", - "sizes": "512x512", + "src": "../icons/icon-512.webp", "type": "image/png", - "purpose": "maskable any" + "sizes": "512x512", + "purpose": "any maskable" } ] } diff --git a/public/sound/menu/Desaparecer.ogg b/public/sound/menu/Desaparecer.ogg deleted file mode 100644 index 05822e5..0000000 Binary files a/public/sound/menu/Desaparecer.ogg and /dev/null differ diff --git a/public/sound/menu/deslis.ogg b/public/sound/menu/deslis.ogg deleted file mode 100644 index 63bea03..0000000 Binary files a/public/sound/menu/deslis.ogg and /dev/null differ diff --git a/public/sound/menu/teclas.ogg b/public/sound/menu/teclas.ogg deleted file mode 100644 index f558443..0000000 Binary files a/public/sound/menu/teclas.ogg and /dev/null differ diff --git a/public/sound/music/bonk_the_amber.mp3 b/public/sound/music/bonk_the_amber.mp3 new file mode 100644 index 0000000..426aa64 Binary files /dev/null and b/public/sound/music/bonk_the_amber.mp3 differ diff --git a/public/sound/music/bonk_the_avatar.mp3 b/public/sound/music/bonk_the_avatar.mp3 new file mode 100644 index 0000000..15bf632 Binary files /dev/null and b/public/sound/music/bonk_the_avatar.mp3 differ diff --git a/public/sound/music/bonus_level_bounce.mp3 b/public/sound/music/bonus_level_bounce.mp3 new file mode 100644 index 0000000..76c5fe4 Binary files /dev/null and b/public/sound/music/bonus_level_bounce.mp3 differ diff --git a/public/sound/music/button_smash_routine.mp3 b/public/sound/music/button_smash_routine.mp3 new file mode 100644 index 0000000..5544f21 Binary files /dev/null and b/public/sound/music/button_smash_routine.mp3 differ diff --git a/public/sound/music/cheems-chan_bonk.mp3 b/public/sound/music/cheems-chan_bonk.mp3 new file mode 100644 index 0000000..6345af6 Binary files /dev/null and b/public/sound/music/cheems-chan_bonk.mp3 differ diff --git a/public/sound/music/click_for_a_bonk.mp3 b/public/sound/music/click_for_a_bonk.mp3 new file mode 100644 index 0000000..291819b Binary files /dev/null and b/public/sound/music/click_for_a_bonk.mp3 differ diff --git a/public/sound/music/hardwood_strike.mp3 b/public/sound/music/hardwood_strike.mp3 new file mode 100644 index 0000000..f402d4e Binary files /dev/null and b/public/sound/music/hardwood_strike.mp3 differ diff --git a/public/sound/music/perfect_round.mp3 b/public/sound/music/perfect_round.mp3 new file mode 100644 index 0000000..b03236c Binary files /dev/null and b/public/sound/music/perfect_round.mp3 differ diff --git a/public/sound/music/pocket_change_victory.mp3 b/public/sound/music/pocket_change_victory.mp3 new file mode 100644 index 0000000..c52f63a Binary files /dev/null and b/public/sound/music/pocket_change_victory.mp3 differ diff --git a/public/sound/music/quick_loot_run.mp3 b/public/sound/music/quick_loot_run.mp3 new file mode 100644 index 0000000..5bd991f Binary files /dev/null and b/public/sound/music/quick_loot_run.mp3 differ diff --git a/public/sound/music/target_in_the_sight.mp3 b/public/sound/music/target_in_the_sight.mp3 new file mode 100644 index 0000000..e690e1b Binary files /dev/null and b/public/sound/music/target_in_the_sight.mp3 differ diff --git a/public/sound/music/the_hammer_falls.mp3 b/public/sound/music/the_hammer_falls.mp3 new file mode 100644 index 0000000..32fb10a Binary files /dev/null and b/public/sound/music/the_hammer_falls.mp3 differ diff --git a/public/sound/music/the_late_commute.mp3 b/public/sound/music/the_late_commute.mp3 new file mode 100644 index 0000000..4afe09c Binary files /dev/null and b/public/sound/music/the_late_commute.mp3 differ diff --git a/public/sound/music/the_unwritten_page.mp3 b/public/sound/music/the_unwritten_page.mp3 new file mode 100644 index 0000000..e849add Binary files /dev/null and b/public/sound/music/the_unwritten_page.mp3 differ diff --git a/public/sound/music/where_the_path_bends.mp3 b/public/sound/music/where_the_path_bends.mp3 new file mode 100644 index 0000000..58f89ad Binary files /dev/null and b/public/sound/music/where_the_path_bends.mp3 differ diff --git a/public/sound/discord-connect.ogg b/public/sound/sfx/discord-connect.ogg similarity index 100% rename from public/sound/discord-connect.ogg rename to public/sound/sfx/discord-connect.ogg diff --git a/public/sound/discord-disconnect.ogg b/public/sound/sfx/discord-disconnect.ogg similarity index 100% rename from public/sound/discord-disconnect.ogg rename to public/sound/sfx/discord-disconnect.ogg diff --git a/public/sound/discord-msg.ogg b/public/sound/sfx/discord-msg.ogg similarity index 100% rename from public/sound/discord-msg.ogg rename to public/sound/sfx/discord-msg.ogg diff --git a/public/sound/hello.ogg b/public/sound/sfx/hello.ogg similarity index 100% rename from public/sound/hello.ogg rename to public/sound/sfx/hello.ogg diff --git a/public/sound/hit-minecraft.ogg b/public/sound/sfx/hit-minecraft.ogg similarity index 100% rename from public/sound/hit-minecraft.ogg rename to public/sound/sfx/hit-minecraft.ogg diff --git a/public/sound/hit.ogg b/public/sound/sfx/hit.ogg similarity index 100% rename from public/sound/hit.ogg rename to public/sound/sfx/hit.ogg diff --git a/public/sound/hurt-minecraft.ogg b/public/sound/sfx/hurt-minecraft.ogg similarity index 100% rename from public/sound/hurt-minecraft.ogg rename to public/sound/sfx/hurt-minecraft.ogg diff --git a/public/sound/hurt-roblox.ogg b/public/sound/sfx/hurt-roblox.ogg similarity index 100% rename from public/sound/hurt-roblox.ogg rename to public/sound/sfx/hurt-roblox.ogg diff --git a/public/sound/levelup1.ogg b/public/sound/sfx/levelup1.ogg similarity index 100% rename from public/sound/levelup1.ogg rename to public/sound/sfx/levelup1.ogg diff --git a/public/sound/levelup2.ogg b/public/sound/sfx/levelup2.ogg similarity index 100% rename from public/sound/levelup2.ogg rename to public/sound/sfx/levelup2.ogg diff --git a/public/sound/no.ogg b/public/sound/sfx/no.ogg similarity index 100% rename from public/sound/no.ogg rename to public/sound/sfx/no.ogg diff --git a/public/sound/pato.ogg b/public/sound/sfx/pato.ogg similarity index 100% rename from public/sound/pato.ogg rename to public/sound/sfx/pato.ogg diff --git a/public/sound/peluche.ogg b/public/sound/sfx/peluche.ogg similarity index 100% rename from public/sound/peluche.ogg rename to public/sound/sfx/peluche.ogg diff --git a/public/sound/splat.ogg b/public/sound/sfx/splat.ogg similarity index 100% rename from public/sound/splat.ogg rename to public/sound/sfx/splat.ogg diff --git a/public/sound/windows-error.ogg b/public/sound/sfx/windows-error.ogg similarity index 100% rename from public/sound/windows-error.ogg rename to public/sound/sfx/windows-error.ogg diff --git a/src/app/app.component.html b/src/app/app.component.html index ba6429e..f929b7d 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -1,2 +1,7 @@ - \ No newline at end of file + +@if (tools.toastMessage) { +
+ {{tools.toastMessage}} +
+} \ No newline at end of file diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 7c8711a..671c362 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -18,20 +18,29 @@ export class AppComponent implements OnInit { //!document.oncontextmenu = function(){return false}; document.ondragstart = function(){return false}; document.onselectstart = function(){return false}; - document.onmousedown = function() {return false}; - document.addEventListener('keydown', this.onKeyDown.bind(this)); - document.addEventListener('touchstart', this.onTouchStart.bind(this)); + window.onkeydown = this.onKeyDown.bind(this); + document.addEventListener('touchstart', this.onTouchStart.bind(this), { passive: false }); + + window.addEventListener('beforeunload', (event: BeforeUnloadEvent) => { + event.preventDefault(); + event.returnValue = 'Changes may not be saved'; + return 'Changes may not be saved'; + }); this.tools.loadApp(); } - onKeyDown(event: KeyboardEvent): void { - event.preventDefault(); + onKeyDown(event: KeyboardEvent) { + if (event.key === ' ' || event.code === 'Space' || ['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight', 'PageUp', 'PageDown', 'Home', 'End'].includes(event.key)) { + if (event.cancelable) { + event.preventDefault(); + } + } } onTouchStart(event: TouchEvent): void { - if (event.touches.length >= 2) { + if (event.touches.length >= 2 && event.cancelable) { event.preventDefault(); } } diff --git a/src/app/app.config.ts b/src/app/app.config.ts index eb929b3..191f50d 100644 --- a/src/app/app.config.ts +++ b/src/app/app.config.ts @@ -1,12 +1,16 @@ import { ApplicationConfig, provideZoneChangeDetection, isDevMode } from '@angular/core'; -import { provideRouter } from '@angular/router'; +import { provideRouter, withHashLocation } from '@angular/router'; import { routes } from './app.routes'; import { provideServiceWorker } from '@angular/service-worker'; export const appConfig: ApplicationConfig = { - providers: [provideZoneChangeDetection({ eventCoalescing: true }), provideRouter(routes), provideServiceWorker('ngsw-worker.js', { - enabled: !isDevMode(), - registrationStrategy: 'registerWhenStable:30000' - })] + providers: [ + provideZoneChangeDetection({ eventCoalescing: true }), + provideRouter(routes, withHashLocation()), + provideServiceWorker('ngsw-worker.js', { + enabled: !isDevMode() || (typeof window !== 'undefined' && window.location.hostname !== 'localhost'), + registrationStrategy: 'registerWhenStable:30000' + }) + ] }; diff --git a/src/app/app.routes.ts b/src/app/app.routes.ts index fa90180..f90edc6 100644 --- a/src/app/app.routes.ts +++ b/src/app/app.routes.ts @@ -5,8 +5,23 @@ import { SettingsComponent } from './pages/settings/settings.component'; import { DevSettingsComponent } from './pages/dev-settings/dev-settings.component'; import { ClosetComponent } from './pages/closet/closet.component'; import { OnworkPageComponent } from './pages/onwork-page/onwork-page.component'; +import { LicensesComponent } from './pages/licenses/licenses.component'; import { P404Component } from './pages/p404/p404.component'; -import { developmentGuard, testingGuard } from './guards/guard.guard'; +import { ShopComponent } from './pages/shop/shop.component'; +import { BlockBreakerComponent } from './games/block_breaker/block_breaker.component'; +import { AttackHoleComponent } from './games/attack_hole/attack_hole.component'; +import { DogeRescueComponent } from './games/doge_rescue/doge_rescue.component'; +import { FlappyDunkComponent } from './games/flappy_dunk/flappy_dunk.component'; +import { HelixJumpComponent } from './games/helix_jump/helix_jump.component'; +import { MagicSortComponent } from './games/magic_sort/magic_sort.component'; +import { MobControlComponent } from './games/mob_control/mob_control.component'; +import { PaperIoComponent } from './games/paper_io/paper_io.component'; +import { SpiralRollComponent } from './games/spiral_roll/spiral_roll.component'; +import { StackColorsComponent } from './games/stack_colors/stack_colors.component'; +import { MinigamesComponent } from './pages/minigames/minigames.component'; +import { StatsComponent } from './pages/stats/stats.component'; +import { GalleryComponent } from './pages/gallery/gallery.component'; +import { developmentGuard, devGuard, testingGuard, appGuard } from './guards/guard.guard'; export const routes: Routes = [ {path: "game", component: GameComponent, pathMatch: "full"}, @@ -14,10 +29,33 @@ export const routes: Routes = [ {path: "settings", component: SettingsComponent, pathMatch: "full"}, {path: "devSettings", component: DevSettingsComponent, pathMatch: "full"}, {path: "closet", component: ClosetComponent, pathMatch: "full"}, + {path: "gallery", component: GalleryComponent, pathMatch: "full"}, {path: "onWork", component: OnworkPageComponent, pathMatch: "full"}, + {path: "licenses", component: LicensesComponent, pathMatch: "full"}, + {path: "shop", component: ShopComponent, pathMatch: "full"}, + {path: "stats", component: StatsComponent, pathMatch: "full"}, + {path: "minigames", component: MinigamesComponent, pathMatch: "full"}, + {path: "minigames/block-breaker", component: BlockBreakerComponent, pathMatch: "full"}, + {path: "minigames/block_breaker", component: BlockBreakerComponent, pathMatch: "full"}, + {path: "minigames/attack_hole", component: AttackHoleComponent, pathMatch: "full"}, + {path: "minigames/doge_rescue", component: DogeRescueComponent, pathMatch: "full"}, + {path: "minigames/flappy_dunk", component: FlappyDunkComponent, pathMatch: "full"}, + {path: "minigames/helix_jump", component: HelixJumpComponent, pathMatch: "full"}, + {path: "minigames/magic_sort", component: MagicSortComponent, pathMatch: "full"}, + {path: "minigames/mob_control", component: MobControlComponent, pathMatch: "full"}, + {path: "minigames/paper_io", component: PaperIoComponent, pathMatch: "full"}, + {path: "minigames/spiral_roll", component: SpiralRollComponent, pathMatch: "full"}, + {path: "minigames/stack_colors", component: StackColorsComponent, pathMatch: "full"}, {path: "p404", component: P404Component, pathMatch: "full"}, {path: "", redirectTo: "game", pathMatch: "full"}, + {path: "dev", component: GameComponent, canActivate: [devGuard]}, + {path: "dev/**", component: GameComponent, canActivate: [devGuard]}, {path: "development", component: GameComponent, canActivate: [developmentGuard]}, + {path: "development/**", component: GameComponent, canActivate: [developmentGuard]}, {path: "test", component: GameComponent, canActivate: [testingGuard]}, + {path: "test/**", component: GameComponent, canActivate: [testingGuard]}, + {path: "app", component: GameComponent, canActivate: [appGuard]}, + {path: "app/**", component: GameComponent, canActivate: [appGuard]}, {path: "**", redirectTo: "p404"} ]; + diff --git a/src/app/components/navbar/navbar.component.css b/src/app/components/navbar/navbar.component.css index 8888aa6..2ae4660 100644 --- a/src/app/components/navbar/navbar.component.css +++ b/src/app/components/navbar/navbar.component.css @@ -1,52 +1,195 @@ +nav { + width: 100%; + min-height: 70px; + padding: 0.5rem 1.5rem; + display: flex; + flex-direction: row; + align-items: center; + justify-content: space-between; + font-weight: 900; + box-shadow: 0 4px 15px rgba(0, 0, 0, 0.35); + z-index: 10000; + position: sticky; + top: 0; + left: 0; + backdrop-filter: blur(15px); + -webkit-backdrop-filter: blur(15px); + transition: background-color 0.3s ease, border-color 0.3s ease; + gap: 0.5rem; +} + +.counters-group { + display: flex; + align-items: center; + gap: 0.65rem; + flex-wrap: wrap; + z-index: 10; +} + .text { display: flex; align-items: center; + gap: 0.4rem; } -.preventive { - max-width: 60vw; - max-height: 10vh; + +.count-badge { + background: rgba(0, 0, 0, 0.35); + padding: 0.35rem 0.85rem; + border-radius: 50px; + border: 1px solid rgba(255, 255, 255, 0.15); } -nav { - width: 100%; - height: 8vh; + +.logo-coin { + height: 36px; + width: 36px; + cursor: pointer; + object-fit: contain; +} + +.pts-icon { + filter: drop-shadow(0 0 5px rgba(255, 209, 102, 0.6)); + cursor: default; +} + +.badge-number { + font-weight: 900; +} + +.preventive { + position: absolute; + left: 50%; + transform: translateX(-50%); + max-width: 45vw; text-align: center; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + pointer-events: none; + z-index: 5; +} + +.title-text { font-weight: 900; - display: flex; - flex-direction: row; - justify-content: space-between; + letter-spacing: 0.5px; +} + +.nav-action { + cursor: pointer; + padding: 0.4rem; + border-radius: 50%; + background: rgba(0, 0, 0, 0.15); + transition: background-color 0.2s ease, transform 0.2s ease; + flex-shrink: 0; + z-index: 10; } + +.nav-action:hover { + background: rgba(0, 0, 0, 0.35); + transform: scale(1.1); +} + +.nav-icon { + height: 34px; + width: 34px; +} + .upper-container { width: 100%; - height: auto; - text-align: center; + padding: 0.75rem 2rem; + display: flex; + justify-content: space-around; + align-items: center; font-weight: 900; + border-bottom: 2px solid rgba(0, 0, 0, 0.2); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); + transition: background-color 0.3s ease; +} + +.score-box { display: flex; - justify-content: space-between; + flex-direction: column; + align-items: center; + justify-content: center; + gap: 0.2rem; } -/*Themes*/ -nav.theme-contrast { - background-color: rgb(255, 115, 0); - border: solid rgb(255, 0, 255); +.score-label { + font-size: 0.8em; + opacity: 0.85; + text-transform: uppercase; + letter-spacing: 1px; } + +.score-value { + font-size: 1.3em; + font-weight: 900; +} + +/* Theme Colors */ nav.theme-dark { - background-color: rgb(63, 35, 12); - border: solid black; + background: linear-gradient(180deg, rgb(55, 45, 35) 0%, rgb(35, 28, 22) 100%); + border-bottom: 2px solid rgb(25, 20, 15); } + nav.theme-light { - background-color: rgb(167, 93, 33); - border: solid black; + background: linear-gradient(180deg, rgb(240, 220, 185) 0%, rgb(220, 195, 150) 100%); + border-bottom: 2px solid rgb(180, 150, 110); } -.upper-container.theme-contrast { - border: solid rgb(255, 0, 255); - background-color: rgba(255, 230, 0, 0.801); +nav.theme-contrast { + background-color: #000000; + border-bottom: 2px solid #ffffff; } + .upper-container.theme-dark { - border: solid black; - background-color: rgba(90, 86, 49, 0.568); + background: rgba(45, 38, 30, 0.9); + color: #ffd166; } + .upper-container.theme-light { - border: solid black; - background-color: rgba(223, 213, 118, 0.568); + background: rgba(235, 215, 175, 0.9); + color: #9c5c14; +} + +.upper-container.theme-contrast { + background: #000000; + color: #ffff00; + border-bottom: 2px solid #ffffff; +} + +.booster-nav-label { + color: #f59e0b; + font-weight: 900; + text-shadow: 0 0 8px rgba(245, 158, 11, 0.4); +} + +.booster-nav-value { + color: #fbbf24; + font-weight: 900; + text-shadow: 0 0 10px rgba(245, 158, 11, 0.5); +} + +@media (max-width: 600px) { + nav { + padding: 0.5rem 0.75rem; + } + .counters-group { + gap: 0.35rem; + } + .count-badge { + padding: 0.25rem 0.6rem; + } + .logo-coin { + height: 28px; + width: 28px; + } + .upper-container { + padding: 0.5rem 0.5rem; + } + .score-label { + font-size: 0.7em; + } + .score-value { + font-size: 1.1em; + } } \ No newline at end of file diff --git a/src/app/components/navbar/navbar.component.html b/src/app/components/navbar/navbar.component.html index 3bc2d99..46a2460 100644 --- a/src/app/components/navbar/navbar.component.html +++ b/src/app/components/navbar/navbar.component.html @@ -1,25 +1,51 @@ + @if (tools.actPage === "game") {
- {{tools.game[tools.lang].navbar.highScore}}:
{{tools.highScore}}
- {{tools.game[tools.lang].navbar.totalScore}}:
{{tools.totalScore}}
- {{tools.game[tools.lang].navbar.actScore}}:
{{tools.actScore}}
+
+ {{tools.game[tools.lang].navbar.highScore}} + {{tools.highScore}} +
+
+ @if (tools.boosterEndTime !== 0 && tools.getBoosterRemainingSeconds() > 0) { + ⚡ x{{tools.boosterMultiplier}} {{tools.game[tools.lang]?.navbar?.booster || 'Booster'}} + {{tools.getBoosterFormattedTime()}} + } +
+
+ {{tools.game[tools.lang].navbar.actScore}} + {{tools.actScore}} +
} \ No newline at end of file diff --git a/src/app/components/navbar/navbar.component.ts b/src/app/components/navbar/navbar.component.ts index 3297b1a..d75d8c5 100644 --- a/src/app/components/navbar/navbar.component.ts +++ b/src/app/components/navbar/navbar.component.ts @@ -1,20 +1,29 @@ -import { Component, inject, OnInit } from '@angular/core'; +import { Component, inject, OnInit, OnDestroy } from '@angular/core'; import { ToolsService } from '../../services/tools.service'; @Component({ - selector: 'app-navbar', - imports: [], - templateUrl: './navbar.component.html', - styleUrl: './navbar.component.css' + selector: 'app-navbar', + imports: [], + templateUrl: './navbar.component.html', + styleUrl: './navbar.component.css' }) -export class NavbarComponent { +export class NavbarComponent implements OnInit, OnDestroy { tools: ToolsService = inject(ToolsService); + private timerInterval: any = null; + ngOnInit(): void { + this.timerInterval = setInterval(() => { + // Trigger change detection for live booster countdown in navbar + }, 1000); + } - enableDevOption(): void { - if (this.tools.actPage === "menu") { - console.log("Devb") + ngOnDestroy(): void { + if (this.timerInterval) { + clearInterval(this.timerInterval); } } + onDogeCoinClick(): void { + this.tools.registerDevClick(); + } } diff --git a/src/app/games/attack_hole/attack_hole.component.css b/src/app/games/attack_hole/attack_hole.component.css new file mode 100644 index 0000000..d5f6b1e --- /dev/null +++ b/src/app/games/attack_hole/attack_hole.component.css @@ -0,0 +1,202 @@ +.attack-hole-wrapper { + position: relative; + width: 100vw; + height: 100vh; + overflow: hidden; + background-color: #222; + user-select: none; + touch-action: none; +} + +#game-container { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; +} + +.ui-layer { + position: absolute; + top: 60px; + left: 0; + width: 100%; + height: calc(100% - 60px); + pointer-events: none; + display: flex; + flex-direction: column; + justify-content: space-between; + z-index: 10; +} + +.hud { + padding: 15px 25px; + display: flex; + justify-content: space-between; + align-items: flex-start; + font-size: 1.5em; + font-weight: bold; + color: #fff; + text-shadow: 2px 2px 4px rgba(0,0,0,0.8); +} + +.hud-right { + position: absolute; + top: 15px; + right: 25px; + display: flex; + flex-direction: column; + gap: 5px; + font-size: 1.2em; + font-weight: bold; + color: #fff; + text-shadow: 2px 2px 4px rgba(0,0,0,0.8); + align-items: flex-end; +} + +.ammo-item { + display: flex; + align-items: center; + gap: 8px; +} + +.stats-top { + display: flex; + flex-direction: column; + gap: 5px; +} + +.attack-ready-screen { + background: transparent !important; + backdrop-filter: none !important; +} + +.attack-text { + font-size: 4em !important; + color: #FF1744 !important; + text-shadow: 0 0 20px #FF1744, 0 0 30px #D50000 !important; + pointer-events: none; +} + +@keyframes flash { + 0%, 100% { opacity: 1; transform: scale(1); } + 50% { opacity: 0.5; transform: scale(1.1); } +} + +.flashing { + animation: flash 1s infinite; +} + +.boss-health-container { + position: absolute; + top: 70px; + left: 50%; + transform: translateX(-50%); + width: 60%; + display: flex; + flex-direction: column; + align-items: center; + z-index: 15; +} + +.boss-health-bar-bg { + width: 100%; + height: 25px; + background: rgba(0, 0, 0, 0.5); + border: 2px solid #fff; + border-radius: 15px; + overflow: hidden; + box-shadow: 0 0 10px rgba(255, 0, 0, 0.5); +} + +.boss-health-bar-fill { + height: 100%; + background: linear-gradient(90deg, #ff1744, #d50000); + transition: width 0.2s ease-out; +} + +.boss-health-text { + font-size: 1.5em; + font-weight: bold; + color: #fff; + text-shadow: 1px 1px 3px rgba(0,0,0,0.8); + margin-top: 5px; +} + +.timer-container { + position: absolute; + top: 15px; + left: 50%; + transform: translateX(-50%); + display: flex; + flex-direction: column; + align-items: center; + z-index: 10; + font-size: 1.5em; + font-weight: bold; + color: #fff; + text-shadow: 2px 2px 4px rgba(0,0,0,0.8); +} + +.timer-ui { + font-size: 1.3em; + color: #FFEB3B; +} + +.screen { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(0,0,0,0.7); + backdrop-filter: blur(5px); + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + pointer-events: auto; + z-index: 20; +} + +.screen h1 { + font-size: 3em; + color: #fff; + margin-bottom: 10px; + text-shadow: 0 0 10px rgba(255,255,255,0.5); + text-align: center; +} + +.screen p { + font-size: 1.2em; + color: #ddd; + margin-bottom: 30px; + max-width: 80%; + text-align: center; +} + +.btn { + padding: 15px 40px; + font-size: 1.5em; + font-weight: bold; + color: #fff; + background: linear-gradient(135deg, #4CAF50, #2E7D32); + border: none; + border-radius: 50px; + cursor: pointer; + box-shadow: 0 5px 15px rgba(0,0,0,0.3); + transition: transform 0.1s, box-shadow 0.1s; +} + +.btn:hover { + transform: scale(1.05); + background: linear-gradient(135deg, #66BB6A, #388E3C); +} + +.btn:active { + transform: scale(0.95); +} + +.hidden { + display: none !important; +} diff --git a/src/app/games/attack_hole/attack_hole.component.html b/src/app/games/attack_hole/attack_hole.component.html new file mode 100644 index 0000000..b2fd439 --- /dev/null +++ b/src/app/games/attack_hole/attack_hole.component.html @@ -0,0 +1,63 @@ +
+
+ +
+
+
+
{{ (tools.attack_hole[tools.lang]?.attack_hole_level || 'Level {0}').replace('{0}', level.toString()) }}
+
{{ (tools.attack_hole[tools.lang]?.attack_hole_session_points || 'Session: {0}').replace('{0}', sessionPoints.toString()) }}
+
{{ (tools.attack_hole[tools.lang]?.attack_hole_level_points || 'Points: {0}').replace('{0}', levelPoints.toString()) }}
+
+
+ +
+ ⏱️ + {{timeLeftFormatted}} +
+ +
+ @for (item of itemsConfig; track item.id) { +
{{item.emojiCounter}} {{collectedItems[item.id] || 0}}
+ } +
+
+ + @if (gameState === 'START') { +
+

{{tools.attack_hole[tools.lang]?.attack_hole_title || 'Attack Hole'}}

+

{{tools.attack_hole[tools.lang]?.attack_hole_inst || 'Move the hole to swallow weapons and defeat the giant boss!'}}

+ +
+ } + + @if (gameState === 'ATTACK_READY' || gameState === 'ATTACKING' || gameState === 'ATTACK_END_DELAY') { +
+
+
+
+
{{wallCurrentHealth | number:'1.0-0'}} / {{wallMaxHealthValue | number:'1.0-0'}}
+
+ } + + @if (gameState === 'ATTACK_READY') { +
+

{{tools.attack_hole[tools.lang]?.attack_hole_attack || 'Attack!'}}

+
+ } + + @if (gameState === 'WIN') { +
+

{{tools.attack_hole[tools.lang]?.victory || 'Victory!'}}

+

{{tools.attack_hole[tools.lang]?.score || 'Score: '}} {{gamePoints}}

+ +
+ } + + @if (gameState === 'LOSE') { +
+

{{tools.attack_hole[tools.lang]?.gameOver || 'Game Over'}}

+

{{tools.attack_hole[tools.lang]?.score || 'Score: '}} {{gamePoints}}

+ +
+ } +
diff --git a/src/app/games/attack_hole/attack_hole.component.ts b/src/app/games/attack_hole/attack_hole.component.ts new file mode 100644 index 0000000..6a61a9d --- /dev/null +++ b/src/app/games/attack_hole/attack_hole.component.ts @@ -0,0 +1,879 @@ +import { Component, OnInit, OnDestroy, AfterViewInit, ViewChild, ElementRef, inject, NgZone } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import * as THREE from 'three'; +import { ToolsService } from '../../services/tools.service'; + +@Component({ + selector: 'app-attack-hole', + standalone: true, + imports: [CommonModule], + templateUrl: './attack_hole.component.html', + styleUrl: './attack_hole.component.css' +}) +export class AttackHoleComponent implements OnInit, AfterViewInit, OnDestroy { + tools: ToolsService = inject(ToolsService); + private ngZone: NgZone = inject(NgZone); + + @ViewChild('gameContainer') gameContainer!: ElementRef; + + gameState: 'START' | 'PLAYING' | 'ATTACK_READY' | 'ATTACKING' | 'ATTACK_END_DELAY' | 'WIN' | 'LOSE' = 'START'; + gamePoints = 0; // Keeping this for backward compatibility with leaveMinigame + levelPoints = 0; + sessionPoints = 0; + level = 0; + + levelsConfig: any[] = []; + currentLevelConfig: any = null; + + collectedItems: Record = {}; + + timeLeft = 30; + timeLeftFormatted = "00:30"; + + private scene!: THREE.Scene; + private camera!: THREE.PerspectiveCamera; + private renderer!: THREE.WebGLRenderer; + private hole!: THREE.Mesh; + private ring!: THREE.Mesh; + private items: THREE.Object3D[] = []; + private holeRadius = 1.8; + private targetPosition = new THREE.Vector3(0, 0, 0); + private animationFrameId: number | null = null; + private timerInterval: any = null; + + private onResizeBound = this.onWindowResize.bind(this); + private onPointerDownBound = this.onPointerDown.bind(this); + private onPointerMoveBound = this.onPointerMove.bind(this); + private onPointerUpBound = this.onPointerUp.bind(this); + + private mouseNDC = new THREE.Vector2(0, 0); + private isPointerDown = false; + + private ground!: THREE.Mesh; + private wall!: THREE.Mesh; + wallCurrentHealth = 1000; // make public for HTML binding + get wallMaxHealthValue(): number { return this.currentLevelConfig ? this.currentLevelConfig.wallLife : (1000 + (this.level * 500)); } + private attackProjectiles: { mesh: THREE.Object3D, target: THREE.Vector3, damage: number, type: string, delay: number }[] = []; + private activeExplosions: { particles: THREE.Points, velocities: THREE.Vector3[] }[] = []; + itemsConfig: any[] = []; + private modelCache: Record = {}; + + ngOnInit(): void { + this.tools.setTitle("attack_hole" as any); + this.tools.actPage = "attack_hole" as any; + this.loadModels(); + } + + ngAfterViewInit(): void { + this.init3D(); + } + + ngOnDestroy(): void { + this.stopGameLoop(); + if (this.timerInterval) { + clearInterval(this.timerInterval); + } + window.removeEventListener('resize', this.onResizeBound); + const container = this.gameContainer?.nativeElement; + if (container) { + container.removeEventListener('pointerdown', this.onPointerDownBound); + window.removeEventListener('pointermove', this.onPointerMoveBound); + window.removeEventListener('pointerup', this.onPointerUpBound); + window.removeEventListener('pointercancel', this.onPointerUpBound); + } + + if (this.renderer) { + this.renderer.dispose(); + const dom = this.gameContainer?.nativeElement; + if (dom && dom.contains(this.renderer.domElement)) { + dom.removeChild(this.renderer.domElement); + } + } + const totalPoints = this.sessionPoints + (['WIN', 'LOSE', 'START'].includes(this.gameState) ? 0 : this.levelPoints); + this.tools.leaveMinigame('attack_hole', totalPoints, this.level); + } + + startGame(): void { + if (this.levelsConfig && this.levelsConfig.length > 1) { + let nextLevel; + do { + nextLevel = this.levelsConfig[Math.floor(Math.random() * this.levelsConfig.length)]; + } while (this.currentLevelConfig && nextLevel.id === this.currentLevelConfig.id); + this.currentLevelConfig = nextLevel; + } else if (this.levelsConfig && this.levelsConfig.length > 0) { + this.currentLevelConfig = this.levelsConfig[0]; + } + + this.levelPoints = 0; + this.gamePoints = 0; // backward compat + + // reset ammo counters + this.itemsConfig.forEach(item => { + this.collectedItems[item.id] = 0; + }); + + this.timeLeft = this.currentLevelConfig ? (this.currentLevelConfig.time || 30) : 30; + + if (this.currentLevelConfig && this.ground) { + const floorSize = this.currentLevelConfig.floorSize || 100; + const scale = floorSize / 100; + this.ground.scale.set(scale, scale, 1); + + if (this.currentLevelConfig.floorPattern) { + const tex = this.generatePatternTexture( + this.currentLevelConfig.floorPattern, + this.currentLevelConfig.floorPrimaryColor, + this.currentLevelConfig.floorSecondaryColor + ); + (this.ground.material as THREE.MeshLambertMaterial).map = tex; + (this.ground.material as THREE.MeshLambertMaterial).color.setHex(0xffffff); + (this.ground.material as THREE.MeshLambertMaterial).needsUpdate = true; + } + } + + // Clear attack phase items + if (this.wall && this.scene) { + this.scene.remove(this.wall); + } + this.attackProjectiles.forEach(p => this.scene.remove(p.mesh)); + this.attackProjectiles = []; + this.activeExplosions.forEach(expl => this.scene.remove(expl.particles)); + this.activeExplosions = []; + + // Reset hole scale instantly + if (this.hole && this.ring) { + this.hole.scale.set(1, 1, 1); + this.ring.scale.set(1, 1, 1); + this.hole.visible = true; + this.ring.visible = true; + this.holeRadius = 1.8; + if (this.camera) { + this.camera.position.set(0, 5, 6); + } + } + + this.updateTimeFormatted(); + this.gameState = 'PLAYING'; + this.resetScene(); + + if (this.timerInterval) clearInterval(this.timerInterval); + this.timerInterval = setInterval(() => { + if (this.tools.isWindowBlurred) return; + if (this.gameState === 'PLAYING') { + this.timeLeft--; + this.updateTimeFormatted(); + if (this.timeLeft <= 0) { + this.ngZone.run(() => this.triggerAttackReady()); + } + } + }, 1000); + } + + private updateTimeFormatted(): void { + const m = Math.floor(this.timeLeft / 60); + const s = this.timeLeft % 60; + this.timeLeftFormatted = `${String(m).padStart(2, '0')}:${String(s).padStart(2, '0')}`; + } + + private init3D(): void { + const container = this.gameContainer.nativeElement; + const width = container.clientWidth || window.innerWidth; + const height = container.clientHeight || window.innerHeight; + + this.scene = new THREE.Scene(); + this.scene.background = new THREE.Color(0x222222); + + this.camera = new THREE.PerspectiveCamera(60, width / height, 0.1, 1000); + this.camera.position.set(0, 5, 6); + this.camera.lookAt(0, 0, 0); + + this.renderer = new THREE.WebGLRenderer({ antialias: true }); + this.renderer.setSize(width, height); + this.renderer.shadowMap.enabled = true; + container.appendChild(this.renderer.domElement); + + const ambientLight = new THREE.AmbientLight(0xffffff, 0.7); + this.scene.add(ambientLight); + + const dirLight = new THREE.DirectionalLight(0xffffff, 0.8); + dirLight.position.set(10, 20, 10); + dirLight.castShadow = true; + this.scene.add(dirLight); + + const groundGeo = new THREE.PlaneGeometry(60, 80); + const groundMat = new THREE.MeshLambertMaterial({ color: 0xE0E0E0 }); + this.ground = new THREE.Mesh(groundGeo, groundMat); + this.ground.rotation.x = -Math.PI / 2; + this.ground.receiveShadow = true; + this.scene.add(this.ground); + + const holeGeo = new THREE.CircleGeometry(this.holeRadius, 32); + const holeMat = new THREE.MeshBasicMaterial({ color: 0x050505 }); + this.hole = new THREE.Mesh(holeGeo, holeMat); + this.hole.rotation.x = -Math.PI / 2; + this.hole.position.y = 0.01; + this.scene.add(this.hole); + + const ringGeo = new THREE.RingGeometry(this.holeRadius, this.holeRadius + 0.15, 32); + const ringMat = new THREE.MeshBasicMaterial({ color: 0x00E5FF, side: THREE.DoubleSide }); + this.ring = new THREE.Mesh(ringGeo, ringMat); + this.ring.rotation.x = -Math.PI / 2; + this.ring.position.y = 0.02; + this.scene.add(this.ring); + + window.addEventListener('resize', this.onResizeBound); + container.addEventListener('pointerdown', this.onPointerDownBound); + window.addEventListener('pointermove', this.onPointerMoveBound); + window.addEventListener('pointerup', this.onPointerUpBound); + window.addEventListener('pointercancel', this.onPointerUpBound); + + this.ngZone.runOutsideAngular(() => { + this.animate(); + }); + } + + private async loadModels(): Promise { + try { + const levelsResponse = await fetch('games/attack_hole/data/levels.json'); + this.levelsConfig = await levelsResponse.json(); + + const response = await fetch('games/attack_hole/data/items.json'); + this.itemsConfig = await response.json(); + this.itemsConfig.forEach(item => { + this.collectedItems[item.id] = 0; + }); + + const texLoader = new THREE.TextureLoader(); + + for (const item of this.itemsConfig) { + const texture = await texLoader.loadAsync(item.texture); + texture.magFilter = THREE.NearestFilter; + texture.minFilter = THREE.NearestFilter; + + const geoResponse = await fetch(item.model); + const geoJson = await geoResponse.json(); + const geoData = geoJson['minecraft:geometry'][0]; + const texW = geoData.description.texture_width; + const texH = geoData.description.texture_height; + + const group = new THREE.Group(); + texture.wrapS = THREE.RepeatWrapping; + texture.wrapT = THREE.RepeatWrapping; + + const mat = new THREE.MeshStandardMaterial({ + map: texture, + transparent: true, + alphaTest: 0.1, + side: THREE.DoubleSide, + emissive: new THREE.Color(0x222222) + }); + + geoData.bones.forEach((bone: any) => { + bone.cubes.forEach((cube: any) => { + const [cx, cy, cz] = cube.size; + const [ox, oy, oz] = cube.origin; + + const scale = 0.1; + const geo = new THREE.BoxGeometry(cx * scale, cy * scale, cz * scale); + + if (cube.uv) { + const uvs = geo.attributes['uv'].array as Float32Array; + const faceMap: Record = { + 0: 'east', 1: 'west', 2: 'up', 3: 'down', 4: 'south', 5: 'north' + }; + for (let i = 0; i < 6; i++) { + const faceName = faceMap[i]; + const uvData = cube.uv[faceName]; + if (uvData) { + const uvStart = uvData.uv; + const uvSize = uvData.uv_size; + const idx = i * 8; + + const u0 = uvStart[0]; + const v0 = uvStart[1]; + const u1 = u0 + uvSize[0]; + const v1 = v0 + uvSize[1]; + + const webgl_u0 = u0 / texW; + const webgl_u1 = u1 / texW; + const webgl_v0 = 1.0 - (v0 / texH); + const webgl_v1 = 1.0 - (v1 / texH); + + uvs[idx + 0] = webgl_u0; uvs[idx + 1] = webgl_v0; + uvs[idx + 2] = webgl_u1; uvs[idx + 3] = webgl_v0; + uvs[idx + 4] = webgl_u0; uvs[idx + 5] = webgl_v1; + uvs[idx + 6] = webgl_u1; uvs[idx + 7] = webgl_v1; + } + } + } + const mesh = new THREE.Mesh(geo, mat); + mesh.castShadow = true; + mesh.position.set((ox + cx/2) * scale, (oy + cy/2) * scale, (oz + cz/2) * scale); + group.add(mesh); + }); + }); + + this.modelCache[item.id] = group; + } + } catch(e) { + console.error('Failed to load models', e); + } + } + + private createItem(type: string): { group: THREE.Group, points: number, category: string } { + let itemGroup = new THREE.Group(); + let category = 'ammo'; + let points = 10; + + const config = this.itemsConfig.find(i => i.id === type); + if (config) { + category = config.category; + points = config.points; + } + + if (this.modelCache[type]) { + itemGroup.add(this.modelCache[type].clone()); + } else { + const box = new THREE.Mesh(new THREE.BoxGeometry(0.5, 0.5, 0.5), new THREE.MeshStandardMaterial({color: 0xff0000})); + itemGroup.add(box); + } + + return { group: itemGroup, points, category }; + } + + private generatePatternTexture(pattern: string, primaryColor: string, secondaryColor: string): THREE.Texture { + const canvas = document.createElement('canvas'); + canvas.width = 512; + canvas.height = 512; + const ctx = canvas.getContext('2d'); + if (!ctx) return new THREE.Texture(); + + ctx.fillStyle = primaryColor || '#ffffff'; + ctx.fillRect(0, 0, 512, 512); + + ctx.fillStyle = secondaryColor || '#000000'; + + if (pattern === 'squares') { + for (let y = 0; y < 512; y += 64) { + for (let x = 0; x < 512; x += 64) { + if ((x / 64 + y / 64) % 2 === 0) ctx.fillRect(x, y, 64, 64); + } + } + } else if (pattern === 'triangles') { + for (let y = 0; y < 512; y += 64) { + for (let x = 0; x < 512; x += 64) { + ctx.beginPath(); + ctx.moveTo(x + 32, y); + ctx.lineTo(x + 64, y + 64); + ctx.lineTo(x, y + 64); + ctx.fill(); + } + } + } else if (pattern === 'pentagons') { + for (let y = 0; y < 512; y += 64) { + for (let x = 0; x < 512; x += 64) { + ctx.beginPath(); + ctx.moveTo(x + 32, y + 10); + ctx.lineTo(x + 60, y + 30); + ctx.lineTo(x + 50, y + 60); + ctx.lineTo(x + 14, y + 60); + ctx.lineTo(x + 4, y + 30); + ctx.fill(); + } + } + } else if (pattern === 'hexagons') { + for (let y = 0; y < 512; y += 64) { + for (let x = 0; x < 512; x += 64) { + ctx.beginPath(); + ctx.moveTo(x + 32, y + 5); + ctx.lineTo(x + 60, y + 20); + ctx.lineTo(x + 60, y + 45); + ctx.lineTo(x + 32, y + 60); + ctx.lineTo(x + 4, y + 45); + ctx.lineTo(x + 4, y + 20); + ctx.fill(); + } + } + } else if (pattern === 'stars') { + for (let y = 0; y < 512; y += 64) { + for (let x = 0; x < 512; x += 64) { + const cx = x + 32; + const cy = y + 32; + ctx.beginPath(); + let rot = Math.PI / 2 * 3; + let xx = cx; let yy = cy; + const step = Math.PI / 5; + ctx.moveTo(cx, cy - 30); + for (let i = 0; i < 5; i++) { + xx = cx + Math.cos(rot) * 30; + yy = cy + Math.sin(rot) * 30; + ctx.lineTo(xx, yy); + rot += step; + xx = cx + Math.cos(rot) * 15; + yy = cy + Math.sin(rot) * 15; + ctx.lineTo(xx, yy); + rot += step; + } + ctx.lineTo(cx, cy - 30); + ctx.fill(); + } + } + } + + const texture = new THREE.CanvasTexture(canvas); + texture.wrapS = THREE.RepeatWrapping; + texture.wrapT = THREE.RepeatWrapping; + texture.repeat.set(4, 4); + return texture; + } + + private spawnItem(type: string, x: number, z: number): void { + const { group: itemGroup, points, category } = this.createItem(type); + if (category === 'ammo') { + itemGroup.rotation.x = Math.PI / 2; + itemGroup.rotation.z = Math.random() * Math.PI * 2; + itemGroup.position.y = 0.3; + } else { + itemGroup.position.y = 0.6; + } + + itemGroup.userData = { category, type, points, isFalling: false }; + itemGroup.position.x = x; + itemGroup.position.z = z; + this.scene.add(itemGroup); + this.items.push(itemGroup); + } + + private resetScene(): void { + this.items.forEach(item => this.scene.remove(item)); + this.items = []; + + if (this.itemsConfig.length === 0) return; + + const floorSize = this.currentLevelConfig ? (this.currentLevelConfig.floorSize || 100) : 100; + const scale = floorSize / 100; + const boundsX = 50 * scale; + const boundsZ = 70 * scale; + const grouping = this.currentLevelConfig ? (this.currentLevelConfig.ammoGrouping || 'random') : 'random'; + + const itemsToSpawn: string[] = []; + + if (this.currentLevelConfig && this.currentLevelConfig.ammo) { + const ammoConfig = this.currentLevelConfig.ammo; + Object.keys(ammoConfig).forEach(type => { + const [min, max] = ammoConfig[type]; + const count = Math.floor(Math.random() * (max - min + 1)) + min; + for (let i = 0; i < count; i++) { + itemsToSpawn.push(type); + } + }); + } else { + const ammoItems = this.itemsConfig.filter(i => i.category === 'ammo'); + const bombItems = this.itemsConfig.filter(i => i.category === 'bomb'); + for (let i = 0; i < 100; i++) { + let type = ''; + const rand = Math.random(); + if (rand < 0.25 && bombItems.length > 0) { + type = bombItems[Math.floor(Math.random() * bombItems.length)].id; + } else if (ammoItems.length > 0) { + type = ammoItems[Math.floor(Math.random() * ammoItems.length)].id; + } else { + type = this.itemsConfig[0].id; + } + itemsToSpawn.push(type); + } + } + + if (grouping === 'grouped') { + const typeCenters: Record = {}; + itemsToSpawn.forEach(type => { + if (!typeCenters[type]) { + typeCenters[type] = { + x: (Math.random() - 0.5) * boundsX, + z: (Math.random() - 0.5) * boundsZ - 2 + }; + } + const center = typeCenters[type]; + const angle = Math.random() * Math.PI * 2; + const radius = Math.random() * 5 * scale; + const spawnX = Math.max(-boundsX/2, Math.min(boundsX/2, center.x + Math.cos(angle) * radius)); + const spawnZ = Math.max(-boundsZ/2 - 2, Math.min(boundsZ/2 - 2, center.z + Math.sin(angle) * radius)); + this.spawnItem(type, spawnX, spawnZ); + }); + } else if (grouping === 'near') { + // shuffle randomly + for (let i = itemsToSpawn.length - 1; i > 0; i--) { + const j = Math.floor(Math.random() * (i + 1)); + [itemsToSpawn[i], itemsToSpawn[j]] = [itemsToSpawn[j], itemsToSpawn[i]]; + } + + let angle = 0; + let radius = 2; + itemsToSpawn.forEach((type, index) => { + const spawnX = Math.max(-boundsX/2, Math.min(boundsX/2, Math.cos(angle) * radius)); + const spawnZ = Math.max(-boundsZ/2 - 2, Math.min(boundsZ/2 - 2, -2 + Math.sin(angle) * radius)); + this.spawnItem(type, spawnX, spawnZ); + + angle += 1.5; // step angle + if (index % 5 === 0) { + radius += 1.2; // increase radius periodically to form a spiral/circle + } + }); + } else { + // random + itemsToSpawn.forEach(type => { + const spawnX = (Math.random() - 0.5) * boundsX; + const spawnZ = (Math.random() - 0.5) * boundsZ - 2; + this.spawnItem(type, spawnX, spawnZ); + }); + } + } + + private onWindowResize(): void { + if (!this.camera || !this.renderer) return; + const container = this.gameContainer.nativeElement; + const width = container.clientWidth || window.innerWidth; + const height = container.clientHeight || window.innerHeight; + this.camera.aspect = width / height; + this.camera.updateProjectionMatrix(); + this.renderer.setSize(width, height); + } + + private updateMouseNDC(event: PointerEvent): void { + const container = this.gameContainer.nativeElement; + const rect = container.getBoundingClientRect(); + this.mouseNDC.x = ((event.clientX - rect.left) / rect.width) * 2 - 1; + this.mouseNDC.y = -((event.clientY - rect.top) / rect.height) * 2 + 1; + } + + private onPointerDown(event: PointerEvent): void { + if (this.gameState === 'ATTACK_READY') { + this.triggerAttack(); + return; + } + if (this.gameState !== 'PLAYING') return; + this.isPointerDown = true; + this.updateMouseNDC(event); + } + + private onPointerMove(event: PointerEvent): void { + if (!this.isPointerDown || this.gameState !== 'PLAYING') return; + this.updateMouseNDC(event); + } + + private onPointerUp(event: PointerEvent): void { + this.isPointerDown = false; + } + + private animate(): void { + this.animationFrameId = requestAnimationFrame(() => this.animate()); + if (this.tools.isWindowBlurred) return; + + if (this.gameState === 'PLAYING') { + if (this.isPointerDown && this.camera) { + const vector = new THREE.Vector3(this.mouseNDC.x, this.mouseNDC.y, 0.5); + vector.unproject(this.camera); + const dir = vector.sub(this.camera.position).normalize(); + const distance = -this.camera.position.y / dir.y; + const pos = this.camera.position.clone().add(dir.multiplyScalar(distance)); + + const floorSize = this.currentLevelConfig ? (this.currentLevelConfig.floorSize || 100) : 100; + const scale = floorSize / 100; + this.targetPosition.x = Math.max(-28 * scale, Math.min(28 * scale, pos.x)); + this.targetPosition.z = Math.max(-38 * scale, Math.min(38 * scale, pos.z)); + } + + this.hole.position.x += (this.targetPosition.x - this.hole.position.x) * 0.15; + this.hole.position.z += (this.targetPosition.z - this.hole.position.z) * 0.15; + this.ring.position.x = this.hole.position.x; + this.ring.position.z = this.hole.position.z; + + const currentFloorScale = this.currentLevelConfig ? (this.currentLevelConfig.floorSize || 100) / 100 : 1; + + const growthFactor = this.currentLevelConfig ? ((this.currentLevelConfig.HoleSizeIncreasePercentage || 100) / 100) : 1.0; + + // Calculate growth relative to the map size so it stays proportional across all levels + let targetScale = 1 + ((this.gamePoints / 800) * (growthFactor / currentFloorScale)); + + // Prevent the hole from growing larger than the map boundaries just in case + const maxHoleRadius = 24 * currentFloorScale; + const maxTargetScale = maxHoleRadius / 1.8; + + if (targetScale > maxTargetScale) { + targetScale = maxTargetScale; + } + const currentScale = this.hole.scale.x; + const newScale = currentScale + (targetScale - currentScale) * 0.1; + + this.hole.scale.set(newScale, newScale, 1); + this.ring.scale.set(newScale, newScale, 1); + this.holeRadius = 1.8 * newScale; + this.hole.position.y = 0.02 * newScale; + this.ring.position.y = 0.03 * newScale; + + const targetCamY = 5 * newScale; + const targetCamZOffset = 6 * newScale; + + this.camera.position.y += (targetCamY - this.camera.position.y) * 0.1; + this.camera.position.x += (this.hole.position.x - this.camera.position.x) * 0.1; + this.camera.position.z += ((this.hole.position.z + targetCamZOffset) - this.camera.position.z) * 0.1; + this.camera.lookAt(this.hole.position); + + for (let i = this.items.length - 1; i >= 0; i--) { + const item = this.items[i]; + if (!item.userData['isFalling']) { + const dx = item.position.x - this.hole.position.x; + const dz = item.position.z - this.hole.position.z; + const distSq = dx * dx + dz * dz; + if (distSq < (this.holeRadius - 0.5) * (this.holeRadius - 0.5)) { + item.userData['isFalling'] = true; + // Disable shadows when falling + item.children.forEach(c => c.castShadow = false); + } + } else { + item.position.y -= 0.15; + item.scale.multiplyScalar(0.85); + item.position.x += (this.hole.position.x - item.position.x) * 0.2; + item.position.z += (this.hole.position.z - item.position.z) * 0.2; + + if (item.scale.x < 0.1) { + const itemType = item.userData['type'] as string; + this.collectedItems[itemType] = (this.collectedItems[itemType] || 0) + 1; + this.levelPoints += item.userData['points']; + this.gamePoints = this.levelPoints; // compat + + this.scene.remove(item); + this.items.splice(i, 1); + if (this.items.length === 0) { + this.ngZone.run(() => this.triggerAttackReady()); + } + } + } + } + this.ring.rotation.z -= 0.02; + } else if (this.gameState === 'ATTACKING') { + // Animate projectiles toward the wall + let allHit = true; + let damageThisFrame = 0; + for (let i = this.attackProjectiles.length - 1; i >= 0; i--) { + const proj = this.attackProjectiles[i]; + if (proj.delay > 0) { + proj.delay--; + if (proj.delay <= 0) { + proj.mesh.visible = true; + this.ngZone.run(() => { + if (this.collectedItems[proj.type] > 0) { + this.collectedItems[proj.type]--; + } + }); + } + allHit = false; + } else if (proj.mesh.position.z > proj.target.z) { + proj.mesh.position.z -= 0.5; // speed + proj.mesh.rotation.x += 0.2; + proj.mesh.rotation.y += 0.2; + allHit = false; + } else if (proj.damage > 0) { + // Hit the wall + damageThisFrame += proj.damage; + proj.damage = 0; // prevent multiple damage instances + proj.mesh.visible = false; + } + } + + if (damageThisFrame > 0) { + this.ngZone.run(() => { + this.wallCurrentHealth = Math.max(0, this.wallCurrentHealth - damageThisFrame); + }); + + // Update wall color + const healthRatio = this.wallCurrentHealth / this.wallMaxHealthValue; + const r = 1.0; + const g = healthRatio; + const b = healthRatio; + (this.wall.material as THREE.MeshLambertMaterial).color.setRGB(r, g, b); + + if (this.wallCurrentHealth <= 0) { + this.ngZone.run(() => { + this.triggerWallBreak(); + this.gameState = 'ATTACK_END_DELAY'; + setTimeout(() => this.ngZone.run(() => this.endLevel(true)), 2500); + }); + return; + } + } + + if (allHit && this.wallCurrentHealth > 0) { + this.ngZone.run(() => { + this.gameState = 'ATTACK_END_DELAY'; + setTimeout(() => this.ngZone.run(() => this.endLevel(false)), 2500); + }); + } + } + + // Animate explosions + for (const expl of this.activeExplosions) { + const positions = expl.particles.geometry.attributes['position'].array as Float32Array; + for (let i = 0; i < expl.velocities.length; i++) { + positions[i * 3] += expl.velocities[i].x; + positions[i * 3 + 1] += expl.velocities[i].y; + positions[i * 3 + 2] += expl.velocities[i].z; + expl.velocities[i].y -= 0.01; // gravity + } + expl.particles.geometry.attributes['position'].needsUpdate = true; + } + + if (this.renderer && this.scene && this.camera) { + this.renderer.render(this.scene, this.camera); + } + } + + private triggerAttackReady(): void { + if (this.gameState === 'PLAYING') { + if (this.timerInterval) clearInterval(this.timerInterval); + this.gameState = 'ATTACK_READY'; + this.setupAttackPhase(); + } + } + + private setupAttackPhase(): void { + // Hide hole and items on the floor + this.hole.visible = false; + this.ring.visible = false; + this.items.forEach(item => item.visible = false); + + // Setup Camera for attack + this.camera.position.set(0, 5, 20); + this.camera.lookAt(0, 5, 0); + + // Setup Boss Wall + this.wallCurrentHealth = this.wallMaxHealthValue; + + const wallGeo = new THREE.BoxGeometry(20, 20, 2); + const wallMat = new THREE.MeshLambertMaterial({ color: 0xFFFFFF }); + + if (this.currentLevelConfig && this.currentLevelConfig.wallPattern) { + const tex = this.generatePatternTexture( + this.currentLevelConfig.wallPattern, + this.currentLevelConfig.wallPrimaryColor, + this.currentLevelConfig.wallSecondaryColor + ); + wallMat.map = tex; + } + + this.wall = new THREE.Mesh(wallGeo, wallMat); + this.wall.position.set(0, 5, -10); + this.scene.add(this.wall); + } + + triggerAttack(): void { + this.gameState = 'ATTACKING'; + + // Instantiate a barrage of projectiles based on collectedItems + this.attackProjectiles = []; + + let currentDelay = 0; + + const itemsList: {type: string, category: string, points: number}[] = []; + Object.keys(this.collectedItems).forEach(type => { + const count = this.collectedItems[type]; + const config = this.itemsConfig.find(i => i.id === type); + const points = config ? config.points : 10; + const category = config ? config.category : (type.includes('bomb') ? 'bomb' : 'ammo'); + + for (let i = 0; i < count; i++) { + itemsList.push({type, category, points}); + } + }); + + itemsList.sort((a, b) => { + if (a.category !== b.category) { + return a.category === 'ammo' ? -1 : 1; + } + return a.points - b.points; + }); + + itemsList.forEach((item) => { + const { group, points, category } = this.createItem(item.type); + group.position.set((Math.random() - 0.5) * 10, 5 + (Math.random() - 0.5) * 10, 15 + Math.random() * 5); + + currentDelay += category === 'bomb' ? 15 : 5; + const delay = currentDelay; + group.visible = false; + + this.scene.add(group); + const target = new THREE.Vector3((Math.random() - 0.5) * 10, 5 + (Math.random() - 0.5) * 10, -9); + this.attackProjectiles.push({ mesh: group, target, damage: points, type: item.type, delay }); + }); + + if (this.attackProjectiles.length === 0) { + // Player collected nothing + this.endLevel(false); + } + } + + private triggerWallBreak(): void { + this.wall.visible = false; + + // Boss explosion + this.spawnExplosion(this.wall.position.clone(), 100, 10, 0xFF0000); + this.tools.playSound('sfx_7'); // hit-minecraft.ogg for explosion + + // Blow up any mid-air projectiles so the screen is clear + for (const proj of this.attackProjectiles) { + if (proj.mesh.visible && proj.damage > 0) { + proj.mesh.visible = false; + proj.damage = 0; + this.spawnExplosion(proj.mesh.position.clone(), 20, 2, 0xFFFF00); + } + } + } + + private spawnExplosion(position: THREE.Vector3, count: number, spread: number, color: number): void { + const particleGeo = new THREE.BufferGeometry(); + const positions = new Float32Array(count * 3); + const velocities: THREE.Vector3[] = []; + + for (let i = 0; i < count; i++) { + positions[i * 3] = position.x + (Math.random() - 0.5) * spread; + positions[i * 3 + 1] = position.y + (Math.random() - 0.5) * spread; + positions[i * 3 + 2] = position.z + (Math.random() - 0.5) * (spread * 0.2); + + velocities.push(new THREE.Vector3( + (Math.random() - 0.5) * 0.5, + Math.random() * 0.5, + (Math.random() - 0.5) * 0.5 + )); + } + + particleGeo.setAttribute('position', new THREE.BufferAttribute(positions, 3)); + const particleMat = new THREE.PointsMaterial({ color, size: 0.5 }); + const particles = new THREE.Points(particleGeo, particleMat); + this.scene.add(particles); + this.activeExplosions.push({ particles, velocities }); + } + + private endLevel(won: boolean): void { + this.gameState = won ? 'WIN' : 'LOSE'; + if (won) { + this.level++; + this.sessionPoints += this.levelPoints; + } else { + this.sessionPoints += this.levelPoints; + } + this.tools.playSound(won ? 'sfx_4' : 'sfx_2'); + } + + private endGame(won: boolean = false): void { + this.gameState = won ? 'WIN' : 'LOSE'; + if (this.timerInterval) clearInterval(this.timerInterval); + this.tools.playSound(won ? 'sfx_4' : 'sfx_2'); + } + + private stopGameLoop(): void { + if (this.animationFrameId !== null) { + cancelAnimationFrame(this.animationFrameId); + this.animationFrameId = null; + } + } +} diff --git a/src/app/games/block_breaker/block_breaker.component.css b/src/app/games/block_breaker/block_breaker.component.css new file mode 100644 index 0000000..4dfd715 --- /dev/null +++ b/src/app/games/block_breaker/block_breaker.component.css @@ -0,0 +1,310 @@ +:root { + --bg-color: #121212; + --panel-bg: #1e1e1e; + --grid-bg: #2d2d2d; + --accent: #4CAF50; + --text: #ffffff; + --col-width: 80px; +} + +.block-breaker-wrapper { + background-color: var(--bg-color); + color: var(--text); + font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; + display: flex; + flex-direction: column; + align-items: center; + margin: 0; + padding: 20px; + user-select: none; + min-height: 100vh; + box-sizing: border-box; +} + +h1 { margin: 0 0 5px 0; color: var(--accent); text-align: center; } +.level-title { margin: 0 0 15px 0; color: #aaa; font-size: 1.2em; } + +#game-container { + background: var(--panel-bg); + padding: 20px; + border-radius: 12px; + box-shadow: 0 8px 32px rgba(0,0,0,0.8); + display: flex; + flex-direction: column; + align-items: center; + gap: 15px; + width: 500px; + max-width: 100%; + position: relative; + box-sizing: border-box; +} + +.ui-header { + display: flex; + justify-content: space-between; + width: 100%; + align-items: center; + gap: 10px; + flex-wrap: wrap; +} + +.stats-display { + display: flex; + flex-direction: column; + gap: 5px; +} + +.stat-box { + font-size: 1.2em; + font-weight: bold; + background: #333; + padding: 8px 15px; + border-radius: 8px; + border: 2px solid #555; + white-space: nowrap; +} + +.coins { color: #FFD700; } +.lvl { color: #00FFFF; } + +.buy-controls { + display: flex; + flex-direction: column; + gap: 5px; +} + +button { + background: var(--accent); + color: white; + border: none; + padding: 8px 16px; + border-radius: 8px; + font-size: 1em; + font-weight: bold; + cursor: pointer; + transition: transform 0.1s, background 0.2s; +} + +button:hover { background: #45a049; } +button:active { transform: scale(0.95); } +button:disabled { background: #555; color: #888; cursor: not-allowed; transform: none; } +.buy-btn { background: #2196F3; } +.buy-btn:hover { background: #1976D2; } + +.trash-slot { + width: 80px; + height: 80px; + background: #4a1919; + border-radius: 8px; + border: 2px dashed #ff4444; + display: flex; + justify-content: center; + align-items: center; + font-weight: bold; + color: #ffaaaa; + text-align: center; + transition: background 0.2s; +} + +.trash-slot.drag-over { + background: #8b2222; + border-color: #ff8888; +} + +.trash-slot.highlight { + border-color: #FFD700; + background: #6e4010; + cursor: pointer; + box-shadow: 0 0 12px rgba(255, 215, 0, 0.6); +} + +#merge-grid { + display: grid; + grid-template-columns: repeat(5, 80px); + grid-template-rows: repeat(2, 80px); + gap: 6px; + background: #2d2d2d; + padding: 8px; + border-radius: 8px; + width: 430px; + max-width: 100%; + box-sizing: border-box; + justify-content: center; + margin: 10px auto; +} + +.lane-markers { + display: flex; + width: 430px; + max-width: 100%; + justify-content: space-around; + color: #888; + font-size: 0.85em; + margin-bottom: 2px; +} + +.grid-slot { + width: 80px; + height: 80px; + background: #3d3d3d; + border-radius: 6px; + border: 2px dashed #555; + display: flex; + justify-content: center; + align-items: center; + position: relative; + box-sizing: border-box; + cursor: pointer; + transition: border-color 0.2s, background 0.2s; +} + +.grid-slot.selected { + border: 2px solid #FFD700; + background: #4a4a30; + box-shadow: 0 0 10px rgba(255, 215, 0, 0.6); +} + +.grid-slot.drag-over { + background: #4d4d4d; + border-color: #fff; +} + +.tool { + width: 85%; + height: 85%; + border-radius: 8px; + display: flex; + flex-direction: column; + justify-content: flex-end; + align-items: center; + font-weight: bold; + cursor: grab; + text-shadow: -1px -1px 0 #000, 1px -1px 0 #000, -1px 1px 0 #000, 1px 1px 0 #000; + font-size: 0.85em; + text-align: center; + padding-bottom: 5px; + box-sizing: border-box; + background-size: contain; + background-repeat: no-repeat; + background-position: center; +} + +.tool:active { cursor: grabbing; } + +#dig-canvas { + background-color: #87CEEB; + border-radius: 8px; + border: 4px solid #333; + width: 420px; + height: auto; + min-height: 480px; + max-width: 100%; + display: block; +} + +/* End Game Overlay */ +.overlay { + position: absolute; + top: 0; left: 0; right: 0; bottom: 0; + background: rgba(0, 0, 0, 0.9); + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + border-radius: 12px; + z-index: 100; + backdrop-filter: blur(4px); + text-align: center; + padding: 20px; +} + +.overlay.hidden { display: none !important; } +.overlay h2 { font-size: 3em; margin: 0 0 10px 0; text-transform: uppercase; } +.overlay p { font-size: 1.2em; color: #ddd; margin-bottom: 30px; } + +.overlay.success h2 { color: #4CAF50; text-shadow: 0 0 20px rgba(76, 175, 80, 0.5); } +.overlay.danger h2 { color: #f44336; text-shadow: 0 0 20px rgba(244, 67, 54, 0.5); } + +.overlay button { + font-size: 1.5em; + padding: 15px 40px; + border-radius: 30px; + background: #2196F3; +} +.overlay button:hover { background: #1976D2; } + +.lvl-up-btn { + background: linear-gradient(135deg, #ff9800, #f57c00); + color: #fff; + border: none; + border-radius: 20px; + padding: 6px 14px; + font-weight: bold; + cursor: pointer; + box-shadow: 0 4px 10px rgba(255, 152, 0, 0.4); + transition: transform 0.2s, box-shadow 0.2s; + margin-left: 10px; +} +.lvl-up-btn:hover { + transform: scale(1.05); + box-shadow: 0 6px 14px rgba(255, 152, 0, 0.6); +} + +.modal-overlay { + position: absolute; + top: 0; left: 0; right: 0; bottom: 0; + background: rgba(0, 0, 0, 0.85); + display: flex; + justify-content: center; + align-items: center; + z-index: 200; + backdrop-filter: blur(5px); +} +.confirm-modal { + background: #222; + border: 2px solid #ff9800; + border-radius: 16px; + padding: 24px; + text-align: center; + max-width: 320px; + box-shadow: 0 10px 30px rgba(0, 0, 0, 0.8); +} +.confirm-modal h3 { + margin-top: 0; + color: #ff9800; + font-size: 1.5em; +} +.confirm-modal p { + color: #ccc; + margin-bottom: 24px; + line-height: 1.4; +} +.modal-buttons { + display: flex; + gap: 12px; + justify-content: center; +} +.confirm-btn { + padding: 10px 20px; + border-radius: 10px; + border: none; + font-weight: bold; + cursor: pointer; + transition: transform 0.2s; +} +.yes-btn { + background: #4CAF50; + color: #fff; +} +.yes-btn:hover { + background: #43a047; + transform: scale(1.05); +} +.no-btn { + background: #f44336; + color: #fff; +} +.no-btn:hover { + background: #e53935; + transform: scale(1.05); +} diff --git a/src/app/games/block_breaker/block_breaker.component.html b/src/app/games/block_breaker/block_breaker.component.html new file mode 100644 index 0000000..5f4db04 --- /dev/null +++ b/src/app/games/block_breaker/block_breaker.component.html @@ -0,0 +1,94 @@ +
+

{{tools.block_breaker[tools.lang]?.title || 'Merge Diggers'}}

+
{{tools.block_breaker[tools.lang]?.playerLevel || 'Player Level: '}}{{ playerLevel }}
+ +
+ +
+

{{overlayTitleText}}

+

{{overlayDescText}}

+ +
+ +
+
+
🪙 {{ getFloorCoins() }}
+
⭐ {{tools.block_breaker[tools.lang]?.lvl || 'Lvl '}}{{ playerLevel }}
+
+ +
+ @for (toolKey of getToolKeys(); track toolKey) { + + } +
+ + +
+ 🗑️
{{tools.block_breaker[tools.lang]?.sell || 'SELL'}} +
+
+ +
+ {{tools.block_breaker[tools.lang]?.lane1 || '▼ Lane 1'}}{{tools.block_breaker[tools.lang]?.lane2 || '▼ Lane 2'}}{{tools.block_breaker[tools.lang]?.lane3 || '▼ Lane 3'}}{{tools.block_breaker[tools.lang]?.lane4 || '▼ Lane 4'}}{{tools.block_breaker[tools.lang]?.lane5 || '▼ Lane 5'}} +
+ +
+ @for (item of grid; track $index) { +
+ @if (item) { +
+ Lv{{item.level}}
{{getToolDamage(item)}} DMG +
+ } +
+ } +
+ + + + + + @if (showLevelUpModal) { + + } +
+
diff --git a/src/app/games/block_breaker/block_breaker.component.ts b/src/app/games/block_breaker/block_breaker.component.ts new file mode 100644 index 0000000..03b3521 --- /dev/null +++ b/src/app/games/block_breaker/block_breaker.component.ts @@ -0,0 +1,872 @@ +import { Component, inject, OnInit, OnDestroy, AfterViewInit, NgZone, ChangeDetectorRef } from '@angular/core'; +import { ToolsService } from '../../services/tools.service'; + +interface ToolItem { + type: string; + level: number; +} + +interface ActiveTool { + col: number; + type: string; + x: number; + y: number; + vx: number; + vy: number; + radius: number; + level: number; + img?: HTMLImageElement; + damage: number; + hitsRemaining: number; + maxHits: number; + rotation: number; +} + +interface DigBlock { + col: number; + x: number; + y: number; + w: number; + h: number; + hp: number; + maxHp: number; + img?: HTMLImageElement; + prize: number; + unbreakable: boolean; + desired_tools: string[]; +} + +interface Particle { + x: number; + y: number; + vx: number; + vy: number; + life: number; + color: string; +} + +@Component({ + selector: 'app-block-breaker', + imports: [], + templateUrl: './block_breaker.component.html', + styleUrl: './block_breaker.component.css' +}) +export class BlockBreakerComponent implements OnInit, OnDestroy, AfterViewInit { + tools: ToolsService = inject(ToolsService); + private ngZone: NgZone = inject(NgZone); + private cdr: ChangeDetectorRef = inject(ChangeDetectorRef); + + readonly cols = 5; + readonly rows = 2; + laneWidth = 84; + assetPath = 'games/block_breaker/assets/'; + + toolTypes: Record> = { + 'shovel': [ + { level: 1, name: "Wood", src: "items/wood_shovel.png", damage: 1, maxHits: 5, price: 5 }, + { level: 2, name: "Stone", src: "items/stone_shovel.png", damage: 4, maxHits: 12, price: 12 }, + { level: 3, name: "Iron", src: "items/iron_shovel.png", damage: 15, maxHits: 25, price: 28 }, + { level: 4, name: "Gold", src: "items/gold_shovel.png", damage: 60, maxHits: 6, price: 65 }, + { level: 5, name: "Diamond", src: "items/diamond_shovel.png", damage: 150, maxHits: 75, price: 150 }, + { level: 6, name: "Netherite", src: "items/netherite_shovel.png", damage: 500, maxHits: 150, price: 350 } + ], + 'pickaxe': [ + { level: 1, name: "Wood", src: "items/wood_pickaxe.png", damage: 1, maxHits: 5, price: 5 }, + { level: 2, name: "Stone", src: "items/stone_pickaxe.png", damage: 4, maxHits: 12, price: 12 }, + { level: 3, name: "Iron", src: "items/iron_pickaxe.png", damage: 15, maxHits: 25, price: 28 }, + { level: 4, name: "Gold", src: "items/gold_pickaxe.png", damage: 60, maxHits: 6, price: 65 }, + { level: 5, name: "Diamond", src: "items/diamond_pickaxe.png", damage: 150, maxHits: 75, price: 150 }, + { level: 6, name: "Netherite", src: "items/netherite_pickaxe.png", damage: 500, maxHits: 150, price: 350 } + ] + }; + + blockRegistry: Record = { + "air": { hp: 0, solid: false, src: null, desired_tools: [] }, + "dirt": { hp: 5, solid: true, src: "blocks/dirt.png", desired_tools: ['shovel'] }, + "grass": { hp: 6, solid: true, src: "blocks/grass_side_carried.png", desired_tools: ['shovel'] }, + "gravel": { hp: 12, solid: true, src: "blocks/gravel.png", desired_tools: ['shovel'] }, + + "stone": { hp: 25, solid: true, src: "blocks/stone.png", desired_tools: ['pickaxe'] }, + "diorite": { hp: 30, solid: true, src: "blocks/stone_diorite.png", desired_tools: ['pickaxe'] }, + "granite": { hp: 30, solid: true, src: "blocks/stone_granite.png", desired_tools: ['pickaxe'] }, + "andesite": { hp: 30, solid: true, src: "blocks/stone_andesite.png", desired_tools: ['pickaxe'] }, + "cobblestone": { hp: 40, solid: true, src: "blocks/cobblestone.png", desired_tools: ['pickaxe'] }, + "deepslate": { hp: 100, solid: true, src: "blocks/deepslate.png", desired_tools: ['pickaxe'] }, + "cobbled_deepslate": { hp: 120, solid: true, src: "blocks/cobbled_deepslate.png", desired_tools: ['pickaxe'] }, + + "bedrock": { hp: Infinity, solid: true, unbreakable: true, src: "blocks/bedrock.png", desired_tools: [] }, + "chest_50": { hp: 1, solid: true, src: "blocks/chest_front.png", prize: 50, desired_tools: [] }, + "chest_100": { hp: 1, solid: true, src: "blocks/chest_front.png", prize: 100, desired_tools: [] }, + "chest_250": { hp: 1, solid: true, src: "blocks/chest_front.png", prize: 250, desired_tools: [] }, + "chest_500": { hp: 1, solid: true, src: "blocks/chest_front.png", prize: 500, desired_tools: [] }, + "chest_1000": { hp: 1, solid: true, src: "blocks/chest_front.png", prize: 1000, desired_tools: [] } + }; + + gameState: 'MERGE' | 'DIG' = 'MERGE'; + playerLevel = 0; + selectedSlotIndex: number | null = null; + gamePoints: number = 50; + get coins(): number { + return this.gamePoints; + } + set coins(val: number) { + this.gamePoints = Math.floor(val); + } + currentCost: Record = { 'shovel': 10, 'pickaxe': 10 }; + grid: Array = new Array(this.cols * this.rows).fill(null); + isDragOver: boolean[] = new Array(this.cols * this.rows).fill(false); + isTrashDragOver = false; + + allLevelDefs: any[] = []; + currentLevelData: any = null; + digBlocks: DigBlock[] = []; + activeTools: ActiveTool[] = []; + particles: Particle[] = []; + bedrockHit = false; + + overlayHidden = true; + overlaySuccess = false; + overlayDanger = false; + overlayTitleText = this.tools.block_breaker[this.tools.lang]?.title || "Title"; + overlayDescText = "Description goes here"; + overlayBtnText = "Continue"; + actionBtnText = this.tools.block_breaker[this.tools.lang]?.dropTools || "DROP TOOLS!"; + showLevelUpModal = false; + + private canvas!: HTMLCanvasElement; + private ctx!: CanvasRenderingContext2D; + private animationFrameId: number | null = null; + + ngOnInit(): void { + this.tools.setTitle("block_breaker" as any); + this.tools.actPage = "block_breaker" as any; + localStorage.removeItem("CheemsAppLiMinigame_PlayerLevel"); + localStorage.removeItem("CheemsAppLiMinigame_Grid"); + localStorage.removeItem("CheemsAppLiMinigame_Costs"); + this.loadLevel(); + this.loadGrid(); + this.loadCosts(); + } + + async loadDefinitions(): Promise { + try { + let resItems = await fetch('games/block_breaker/data/items.json'); + if (!resItems.ok) resItems = await fetch('/games/block_breaker/data/items.json'); + + if (resItems.ok) { + this.toolTypes = await resItems.json(); + Object.keys(this.toolTypes).forEach(key => { + if (!this.currentCost[key]) { + this.currentCost[key] = 10; + } + }); + } + } catch (e) { + console.warn('Could not load items.json', e); + } + + try { + let resBlocks = await fetch('games/block_breaker/data/blocks.json'); + if (!resBlocks.ok) resBlocks = await fetch('/games/block_breaker/data/blocks.json'); + + if (resBlocks.ok) { + const rawBlocks = await resBlocks.json(); + this.blockRegistry = {}; + Object.keys(rawBlocks).forEach(k => { + this.blockRegistry[k] = { + ...rawBlocks[k], + hp: rawBlocks[k].hp === null ? Infinity : rawBlocks[k].hp + }; + }); + } + } catch (e) { + console.warn('Could not load blocks.json', e); + } + + this.preloadImages(); + } + + ngAfterViewInit(): void { + this.canvas = document.getElementById('dig-canvas') as HTMLCanvasElement; + if (this.canvas) { + this.ctx = this.canvas.getContext('2d')!; + this.laneWidth = this.canvas.width / this.cols; + } + this.initGame(); + } + + ngOnDestroy(): void { + if (this.animationFrameId !== null) { + cancelAnimationFrame(this.animationFrameId); + this.animationFrameId = null; + } + this.tools.leaveMinigame('block_breaker', this.coins); + } + + preloadImages(): void { + Object.keys(this.toolTypes).forEach(type => { + this.toolTypes[type].forEach(t => { + t.img = new Image(); + t.img.src = this.assetPath + t.src; + t.img.onload = () => { + if (this.gameState === 'MERGE') { + this.drawCanvasStatic(); + } + }; + }); + }); + + Object.values(this.blockRegistry).forEach(b => { + if (b.src) { + b.img = new Image(); + b.img.src = this.assetPath + b.src; + b.img.onload = () => { + if (this.gameState === 'MERGE') { + this.drawCanvasStatic(); + } + }; + } + }); + } + + async fetchLevels(): Promise { + try { + let response = await fetch('games/block_breaker/data/level.json'); + if (!response.ok) { + response = await fetch('/games/block_breaker/data/level.json'); + } + if (response.ok) { + const data = await response.json(); + if (data && Array.isArray(data.levels)) { + return data.levels; + } + } + throw new Error('Failed to load level.json'); + } catch (e) { + console.warn("Could not fetch level.json, using fallback level system:", e); + return [ + { + "id": "starter_level", + "background_color": "#87CEEB", + "min_level": 1, + "max_level": 2, + "random_pools": { + "rand_surface": ["dirt", "grass", "air"], + "rand_mid": ["stone", "coal_ore", "copper_ore", "iron_ore"], + "rand_deep": ["deepslate", "deepslate_iron_ore", "deepslate_diamond_ore"], + "rand_treasure": ["chest_100", "chest_250", "chest_500"] + }, + "map": [ + ["rand_surface", "air", "rand_surface", "air", "rand_surface"], + ["dirt", "dirt", "stone", "dirt", "dirt"], + ["stone", "stone", "stone", "stone", "stone"], + ["rand_mid", "rand_mid", "air", "rand_mid", "rand_mid"], + ["stone", "stone", "stone", "stone", "stone"], + ["rand_mid", "rand_mid", "rand_mid", "rand_mid", "rand_mid"], + ["stone", "stone", "barrel_50", "stone", "stone"], + ["rand_mid", "rand_mid", "rand_mid", "rand_mid", "rand_mid"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["rand_deep", "copper_chest_inventory_front", "rand_deep", "rand_deep", "rand_deep"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["rand_deep", "rand_deep", "rand_deep", "rand_deep", "rand_deep"], + ["air", "air", "air", "air", "air"], + ["rand_treasure", "chest_250", "rand_treasure", "chest_250", "rand_treasure"], + ["bedrock", "bedrock", "bedrock", "bedrock", "bedrock"] + ] + } + ]; + } + } + + pickEligibleLevel(): void { + if (!this.allLevelDefs || this.allLevelDefs.length === 0) return; + let eligible = this.allLevelDefs.filter(l => { + if (l.max_level === undefined || l.max_level === null || l.max_level === 0) { + return true; + } + return this.playerLevel <= l.max_level; + }); + if (eligible.length === 0) eligible = this.allLevelDefs; + this.currentLevelData = eligible[Math.floor(Math.random() * eligible.length)]; + } + + async initGame(): Promise { + await this.loadDefinitions(); + this.allLevelDefs = await this.fetchLevels(); + this.pickEligibleLevel(); + this.buildLevel(); + setTimeout(() => { + this.drawCanvasStatic(); + this.cdr.detectChanges(); + }, 200); + } + + buildLevel(): void { + this.digBlocks = []; + if (!this.currentLevelData || !this.currentLevelData.map) return; + const blockHeight = 40; + const startY = 100; + + const requiredHeight = Math.max(480, startY + this.currentLevelData.map.length * blockHeight + 20); + if (this.canvas && this.canvas.height !== requiredHeight) { + this.canvas.height = requiredHeight; + } + const bgColor = this.currentLevelData?.background_color || this.currentLevelData?.backgroundColor || "#87CEEB"; + if (this.canvas) { + this.canvas.style.backgroundColor = bgColor; + } + + for (let r = 0; r < this.currentLevelData.map.length; r++) { + const row = this.currentLevelData.map[r]; + for (let c = 0; c < row.length; c++) { + let blockId = row[c]; + + if (this.currentLevelData.random_pools && this.currentLevelData.random_pools[blockId]) { + const pool = this.currentLevelData.random_pools[blockId]; + blockId = pool[Math.floor(Math.random() * pool.length)]; + } + + const def = this.blockRegistry[blockId]; + + if (def && def.solid) { + this.digBlocks.push({ + col: c, + x: c * this.laneWidth, + y: startY + r * blockHeight, + w: this.laneWidth, + h: blockHeight, + hp: def.hp, + maxHp: def.hp, + img: def.img, + prize: def.prize || 0, + unbreakable: def.unbreakable || false, + desired_tools: def.desired_tools || [] + }); + } + } + } + } + + getFloorCoins(): number { + return Math.floor(this.coins); + } + + getToolKeys(): string[] { + return Object.keys(this.toolTypes); + } + + isBuyToolDisabled(toolKey: string): boolean { + const cost = this.currentCost[toolKey] || 10; + return this.coins < cost || !this.grid.includes(null) || this.gameState !== 'MERGE'; + } + + getToolBuyLabel(toolKey: string): string { + const langObj = this.tools.minigames[this.tools.lang]; + if (toolKey === 'shovel' && langObj?.buyShovel) return langObj.buyShovel; + if (toolKey === 'pickaxe' && langObj?.buyPickaxe) return langObj.buyPickaxe; + const buyWord = langObj?.buy || 'Buy'; + return `${buyWord} ${toolKey.charAt(0).toUpperCase() + toolKey.slice(1)}`; + } + + isActionDisabled(): boolean { + return this.gameState !== 'MERGE' || !this.grid.some(t => t !== null); + } + + getToolImage(item: ToolItem): string { + const toolData = this.toolTypes[item.type][item.level - 1]; + return this.assetPath + toolData.src; + } + + getToolDamage(item: ToolItem): number { + const toolData = this.toolTypes[item.type][item.level - 1]; + return toolData.damage; + } + + buyTool(type: string): void { + const cost = this.currentCost[type] || 10; + if (this.coins >= cost && this.gameState === 'MERGE') { + const emptyIndex = this.grid.indexOf(null); + if (emptyIndex !== -1) { + this.coins -= cost; + this.currentCost[type] = Math.floor(cost * 1.15); + this.grid[emptyIndex] = { type, level: 1 }; + this.tools.playSound('sfx_1'); + this.saveGrid(); + this.saveCosts(); + } else { + this.tools.showToast("Grid is full!"); + this.tools.playSound('sfx_8'); + } + } else { + this.tools.showToast(this.tools.block_breaker[this.tools.lang]?.notEnoughMinigameCoins || "Not enough Minigame Points!"); + this.tools.playSound('sfx_8'); + } + } + + clickSlot(index: number): void { + if (this.gameState !== 'MERGE') return; + const clickedObj = this.grid[index]; + + if (this.selectedSlotIndex === null) { + if (clickedObj !== null) { + this.selectedSlotIndex = index; + this.tools.playSound('sfx_1'); + } + return; + } + + const fromIndex = this.selectedSlotIndex; + if (fromIndex === index) { + this.selectedSlotIndex = null; + return; + } + + const fromObj = this.grid[fromIndex]; + const toObj = this.grid[index]; + if (!fromObj) { + this.selectedSlotIndex = null; + return; + } + + if (toObj === null) { + this.grid[index] = fromObj; + this.grid[fromIndex] = null; + this.tools.playSound('sfx_1'); + } else if (fromObj.type === toObj.type && fromObj.level === toObj.level && fromObj.level < (this.toolTypes[fromObj.type]?.length || 0)) { + this.grid[index] = { type: fromObj.type, level: fromObj.level + 1 }; + this.grid[fromIndex] = null; + this.tools.playSound('sfx_4'); + } else { + this.grid[index] = fromObj; + this.grid[fromIndex] = toObj; + this.tools.playSound('sfx_1'); + } + this.selectedSlotIndex = null; + this.saveGrid(); + } + + getToolPrice(item: ToolItem): number { + const toolData = this.toolTypes[item.type]?.[item.level - 1]; + return toolData?.price || (item.level * 5); + } + + sellSelectedTool(): void { + if (this.selectedSlotIndex !== null && this.gameState === 'MERGE') { + this.sellToolAtIndex(this.selectedSlotIndex); + this.selectedSlotIndex = null; + } + } + + sellToolAtIndex(index: number): void { + const item = this.grid[index]; + if (item) { + const price = this.getToolPrice(item); + this.grid[index] = null; + this.coins += price; + this.tools.playSound('sfx_4'); + this.tools.showToast(`Sold ${item.type} Lv${item.level} for +${price} 🎮`); + this.saveGrid(); + } + } + + onDragOver(e: DragEvent, index: number): void { + e.preventDefault(); + if (this.gameState === 'MERGE') { + this.isDragOver[index] = true; + } + } + + onDragLeave(e: DragEvent, index: number): void { + this.isDragOver[index] = false; + } + + onDragStart(e: DragEvent, index: number): void { + if (e.dataTransfer) { + e.dataTransfer.setData('text/plain', String(index)); + } + } + + onDragEnd(e: DragEvent, index: number): void { + this.isDragOver[index] = false; + } + + onDrop(e: DragEvent, index: number): void { + e.preventDefault(); + this.isDragOver[index] = false; + if (this.gameState !== 'MERGE') return; + + const fromIndexStr = e.dataTransfer?.getData('text/plain'); + if (!fromIndexStr) return; + const fromIndex = parseInt(fromIndexStr, 10); + const toIndex = index; + if (fromIndex === toIndex || isNaN(fromIndex) || fromIndex < 0 || fromIndex >= this.grid.length) return; + + const fromObj = this.grid[fromIndex]; + const toObj = this.grid[toIndex]; + if (!fromObj) return; + + if (toObj === null) { + this.grid[toIndex] = fromObj; + this.grid[fromIndex] = null; + } else if (fromObj.type === toObj.type && fromObj.level === toObj.level && fromObj.level < (this.toolTypes[fromObj.type]?.length || 0)) { + this.grid[toIndex] = { type: fromObj.type, level: fromObj.level + 1 }; + this.grid[fromIndex] = null; + this.tools.playSound('sfx_4'); + } else { + this.grid[toIndex] = fromObj; + this.grid[fromIndex] = toObj; + } + this.tools.playSound('sfx_1'); + this.saveGrid(); + } + + allowDrop(e: DragEvent): void { + e.preventDefault(); + if (this.gameState === 'MERGE') { + this.isTrashDragOver = true; + } + } + + leaveTrash(e: DragEvent): void { + this.isTrashDragOver = false; + } + + dropTrash(e: DragEvent): void { + e.preventDefault(); + this.isTrashDragOver = false; + if (this.gameState !== 'MERGE') return; + const fromIndexStr = e.dataTransfer?.getData('text/plain'); + if (!fromIndexStr) return; + const fromIndex = parseInt(fromIndexStr, 10); + if (!isNaN(fromIndex) && fromIndex >= 0 && fromIndex < this.grid.length) { + this.sellToolAtIndex(fromIndex); + } + } + + spawnParticles(x: number, y: number, color = "#ffffff"): void { + for (let i = 0; i < 8; i++) { + this.particles.push({ + x, + y, + vx: (Math.random() - 0.5) * 8, + vy: (Math.random() - 0.5) * 8, + life: 1.0, + color + }); + } + } + + startDigging(): void { + if (this.gameState !== 'MERGE' || !this.grid.some(t => t !== null)) return; + + this.gameState = 'DIG'; + this.bedrockHit = false; + this.actionBtnText = this.tools.block_breaker[this.tools.lang]?.digging || "DIGGING..."; + this.activeTools = []; + + for (let i = 0; i < this.grid.length; i++) { + if (this.grid[i] !== null) { + const col = i % this.cols; + const toolObj = this.grid[i]!; + const typeData = this.toolTypes[toolObj.type][toolObj.level - 1]; + + let toolImg = typeData.img; + if (!toolImg) { + toolImg = new Image(); + toolImg.src = this.assetPath + typeData.src; + typeData.img = toolImg; + } + + this.activeTools.push({ + col, + type: toolObj.type, + x: col * this.laneWidth + (this.laneWidth / 2), + y: (Math.floor(i / this.cols) * -50) - 20, + vx: 0, + vy: 0, + radius: 14, + level: toolObj.level, + img: toolImg, + damage: typeData.damage, + hitsRemaining: typeData.maxHits, + maxHits: typeData.maxHits, + rotation: 0 + }); + } + } + + if (this.animationFrameId !== null) { + cancelAnimationFrame(this.animationFrameId); + } + this.ngZone.runOutsideAngular(() => { + this.animationFrameId = requestAnimationFrame(() => this.digLoop()); + }); + } + + digLoop(): void { + if (this.gameState !== 'DIG' || !this.ctx || !this.canvas) return; + if (this.tools.isWindowBlurred) { + this.animationFrameId = requestAnimationFrame(() => this.digLoop()); + return; + } + const bgColor = this.currentLevelData?.background_color || this.currentLevelData?.backgroundColor || "#87CEEB"; + this.ctx.fillStyle = bgColor; + this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height); + + for (const b of this.digBlocks) { + if (b.img && b.img.complete && b.img.naturalWidth !== 0) { + this.ctx.drawImage(b.img, b.x, b.y, b.w, b.h); + } else { + this.ctx.fillStyle = b.unbreakable ? "#222" : "#555"; + this.ctx.fillRect(b.x, b.y, b.w, b.h); + } + this.ctx.strokeStyle = "rgba(0,0,0,0.5)"; + this.ctx.lineWidth = 1; + this.ctx.strokeRect(b.x, b.y, b.w, b.h); + + if (!b.unbreakable) { + this.ctx.font = "bold 16px Arial"; + this.ctx.textAlign = "center"; + this.ctx.textBaseline = "middle"; + this.ctx.lineWidth = 4; + this.ctx.strokeStyle = "#000"; + this.ctx.strokeText(String(Math.ceil(b.hp)), b.x + b.w / 2, b.y + b.h / 2); + this.ctx.fillStyle = "#fff"; + this.ctx.fillText(String(Math.ceil(b.hp)), b.x + b.w / 2, b.y + b.h / 2); + } + } + + let toolsActive = false; + + for (let i = this.activeTools.length - 1; i >= 0; i--) { + const t = this.activeTools[i]; + t.x += t.vx; + t.y += t.vy; + t.vy += 0.25; + + t.rotation += 0.1; + + if (t.x - t.radius < 0) { + t.x = t.radius; + t.vx *= -0.7; + } else if (t.x + t.radius > this.canvas.width) { + t.x = this.canvas.width - t.radius; + t.vx *= -0.7; + } + + let hitBlock = false; + for (const targetBlock of this.digBlocks) { + if ( + t.x + t.radius > targetBlock.x && + t.x - t.radius < targetBlock.x + targetBlock.w && + t.y + t.radius > targetBlock.y && + t.y - t.radius < targetBlock.y + targetBlock.h + ) { + hitBlock = true; + this.tools.playSound('sfx_1'); + + const overlapLeft = (t.x + t.radius) - targetBlock.x; + const overlapRight = (targetBlock.x + targetBlock.w) - (t.x - t.radius); + const overlapTop = (t.y + t.radius) - targetBlock.y; + const overlapBottom = (targetBlock.y + targetBlock.h) - (t.y - t.radius); + + const minOverlap = Math.min(overlapLeft, overlapRight, overlapTop, overlapBottom); + + if (minOverlap === overlapLeft || minOverlap === overlapRight) { + t.vx *= -0.8; + } else { + t.vy *= -0.8; + } + + if (!targetBlock.unbreakable) { + targetBlock.hp -= t.damage; + const hasPreferred = targetBlock.desired_tools && targetBlock.desired_tools.length > 0; + const isPreferredTool = hasPreferred ? targetBlock.desired_tools.includes(t.type) : true; + t.hitsRemaining -= isPreferredTool ? 1 : 2; + + this.spawnParticles(t.x, t.y, "#8B4513"); + + if (targetBlock.hp <= 0) { + if (targetBlock.prize > 0) { + this.coins += targetBlock.prize; + } else { + this.coins += targetBlock.maxHp * 0.5; + } + this.digBlocks = this.digBlocks.filter(b => b !== targetBlock); + } + } else { + this.spawnParticles(t.x, t.y, "#333333"); + t.hitsRemaining = 0; + + if (targetBlock.hp === Infinity) { + this.bedrockHit = true; + } + } + + if (t.hitsRemaining <= 0) { + this.spawnParticles(t.x, t.y, "#ff0000"); + this.activeTools.splice(i, 1); + continue; + } + } + } + + const renderSize = 40; + this.ctx.save(); + this.ctx.translate(t.x, t.y); + this.ctx.rotate(t.rotation); + if (t.img && t.img.complete && t.img.naturalWidth !== 0) { + this.ctx.drawImage(t.img, -renderSize / 2, -renderSize / 2, renderSize, renderSize); + } else { + this.ctx.fillStyle = t.type === 'shovel' ? '#8B4513' : '#708090'; + this.ctx.beginPath(); + this.ctx.arc(0, 0, renderSize / 2, 0, Math.PI * 2); + this.ctx.fill(); + this.ctx.fillStyle = '#ffffff'; + this.ctx.font = 'bold 12px Arial'; + this.ctx.textAlign = 'center'; + this.ctx.textBaseline = 'middle'; + this.ctx.fillText(`L${t.level}`, 0, 0); + } + this.ctx.restore(); + + this.ctx.beginPath(); + this.ctx.arc(t.x, t.y, renderSize / 2 + 2, -Math.PI / 2, (-Math.PI / 2) + (Math.PI * 2 * (t.hitsRemaining / t.maxHits))); + this.ctx.strokeStyle = "#0f0"; + this.ctx.lineWidth = 3; + this.ctx.stroke(); + toolsActive = true; + } + + for (let i = this.particles.length - 1; i >= 0; i--) { + const p = this.particles[i]; + p.x += p.vx; + p.y += p.vy; + p.life -= 0.05; + if (p.life <= 0) { + this.particles.splice(i, 1); + continue; + } + this.ctx.globalAlpha = p.life; + this.ctx.fillStyle = p.color; + this.ctx.fillRect(p.x, p.y, 4, 4); + this.ctx.globalAlpha = 1.0; + } + + if (toolsActive || this.particles.length > 0) { + this.animationFrameId = requestAnimationFrame(() => this.digLoop()); + } else { + this.ngZone.run(() => { + this.endDigging(); + this.cdr.detectChanges(); + }); + } + } + + endDigging(): void { + this.overlayHidden = false; + + if (this.bedrockHit) { + this.overlayTitleText = this.tools.block_breaker[this.tools.lang]?.levelCleared || "Level Cleared!"; + this.overlayDescText = this.tools.block_breaker[this.tools.lang]?.levelClearedDesc || "You successfully broke through to the bedrock."; + this.overlayBtnText = this.tools.block_breaker[this.tools.lang]?.nextLevel || "Next Level"; + this.overlaySuccess = true; + this.overlayDanger = false; + this.playerLevel++; + this.saveLevel(); + } else { + this.overlayTitleText = this.tools.block_breaker[this.tools.lang]?.levelFailed || "Level Failed"; + this.overlayDescText = this.tools.block_breaker[this.tools.lang]?.levelFailedDesc || "Your tools broke before reaching the bottom."; + this.overlayBtnText = this.tools.block_breaker[this.tools.lang]?.tryAgain || "Try Again"; + this.overlaySuccess = false; + this.overlayDanger = true; + } + } + + closeOverlay(): void { + this.overlayHidden = true; + + this.pickEligibleLevel(); + this.buildLevel(); + this.drawCanvasStatic(); + + this.gameState = 'MERGE'; + this.actionBtnText = this.tools.block_breaker[this.tools.lang]?.dropTools || "DROP TOOLS!"; + } + + drawCanvasStatic(): void { + if (!this.ctx || !this.canvas) return; + const bgColor = this.currentLevelData?.background_color || this.currentLevelData?.backgroundColor || "#87CEEB"; + this.ctx.fillStyle = bgColor; + this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height); + for (const b of this.digBlocks) { + if (b.img && b.img.complete) { + this.ctx.drawImage(b.img, b.x, b.y, b.w, b.h); + } else { + this.ctx.fillStyle = b.unbreakable ? "#222" : "#555"; + this.ctx.fillRect(b.x, b.y, b.w, b.h); + } + this.ctx.strokeStyle = "rgba(0,0,0,0.5)"; + this.ctx.lineWidth = 1; + this.ctx.strokeRect(b.x, b.y, b.w, b.h); + if (!b.unbreakable) { + this.ctx.font = "bold 16px Arial"; + this.ctx.textAlign = "center"; + this.ctx.textBaseline = "middle"; + this.ctx.lineWidth = 4; + this.ctx.strokeStyle = "#000"; + this.ctx.strokeText(String(Math.ceil(b.hp)), b.x + b.w / 2, b.y + b.h / 2); + this.ctx.fillStyle = "#fff"; + this.ctx.fillText(String(Math.ceil(b.hp)), b.x + b.w / 2, b.y + b.h / 2); + } + } + } + + loadLevel(): void { + this.playerLevel = 0; + } + + saveLevel(): void { + } + + loadGrid(): void { + this.grid = new Array(this.cols * this.rows).fill(null); + } + + saveGrid(): void { + } + + loadCosts(): void { + } + + saveCosts(): void { + } + + openSellLevelConfirm(): void { + if (this.playerLevel <= 1) { + this.tools.showToast("You need to be at least Level 2 to sell your level!"); + this.tools.playSound('sfx_8'); + return; + } + this.showLevelUpModal = true; + } + + closeSellLevelConfirm(): void { + this.showLevelUpModal = false; + } + + confirmSellLevel(): void { + if (this.playerLevel > 1) { + const reward = this.playerLevel * 20; + this.coins += reward; + this.playerLevel = 0; + this.saveLevel(); + this.pickEligibleLevel(); + this.buildLevel(); + this.drawCanvasStatic(); + this.tools.showToast(`Sold level for +${reward} points!`); + this.tools.playSound('sfx_4'); + this.showLevelUpModal = false; + } + } +} diff --git a/src/app/games/doge_rescue/doge_rescue.component.css b/src/app/games/doge_rescue/doge_rescue.component.css new file mode 100644 index 0000000..d07154e --- /dev/null +++ b/src/app/games/doge_rescue/doge_rescue.component.css @@ -0,0 +1,110 @@ +.doge-rescue-wrapper { + position: relative; + width: 100vw; + height: 100vh; + display: flex; + justify-content: center; + align-items: center; + background-color: #333; + user-select: none; + touch-action: none; + overflow: hidden; +} + +#game-container { + position: relative; + width: 100%; + max-width: 600px; + aspect-ratio: 3 / 4; + background: linear-gradient(180deg, #e0f7fa 0%, #b2ebf2 100%); + box-shadow: 0 10px 30px rgba(0,0,0,0.5); + overflow: hidden; +} + +canvas { + display: block; + width: 100%; + height: 100%; + cursor: crosshair; +} + +.ui-layer { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + pointer-events: none; + display: flex; + flex-direction: column; + justify-content: space-between; + z-index: 10; +} + +.hud { + padding: 15px 25px; + display: flex; + justify-content: space-between; + align-items: center; + font-size: 1.5em; + font-weight: bold; + color: #333; +} + +.timer-box { + font-size: 1.5em; + color: #d32f2f; + font-weight: 800; +} + +.screen { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(0,0,0,0.75); + backdrop-filter: blur(4px); + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + pointer-events: auto; + z-index: 20; +} + +.screen h1 { + font-size: 2.5em; + color: #fff; + margin-bottom: 15px; + text-align: center; +} + +.screen p { + font-size: 1.2em; + color: #eee; + margin-bottom: 25px; + text-align: center; + max-width: 80%; +} + +.btn { + padding: 12px 35px; + font-size: 1.3em; + font-weight: bold; + color: #fff; + background: linear-gradient(135deg, #FF9800, #F57C00); + border: none; + border-radius: 40px; + cursor: pointer; + box-shadow: 0 4px 12px rgba(0,0,0,0.3); + transition: transform 0.1s; +} + +.btn:hover { + transform: scale(1.05); +} + +.btn:active { + transform: scale(0.95); +} diff --git a/src/app/games/doge_rescue/doge_rescue.component.html b/src/app/games/doge_rescue/doge_rescue.component.html new file mode 100644 index 0000000..3b8304d --- /dev/null +++ b/src/app/games/doge_rescue/doge_rescue.component.html @@ -0,0 +1,39 @@ +
+
+ + +
+
+
{{tools.doge_rescue[tools.lang]?.level || 'Level '}} {{level}}
+
+ ⏳ {{timerDisplay}} +
+
🪙 {{gamePoints}}
+
+
+ + @if (gameState === 'START') { +
+

{{tools.doge_rescue[tools.lang]?.doge_rescue_title || 'Doge Rescue'}}

+

{{tools.doge_rescue[tools.lang]?.doge_rescue_inst || 'Draw a line to protect Doge from the bees!'}}

+ +
+ } + + @if (gameState === 'WIN') { +
+

{{tools.doge_rescue[tools.lang]?.victory || 'Victory!'}}

+

{{tools.doge_rescue[tools.lang]?.score || 'Score: '}} {{gamePoints}}

+ +
+ } + + @if (gameState === 'LOSE') { +
+

{{tools.doge_rescue[tools.lang]?.gameOver || 'Game Over'}}

+

{{tools.doge_rescue[tools.lang]?.score || 'Score: '}} {{gamePoints}}

+ +
+ } +
+
diff --git a/src/app/games/doge_rescue/doge_rescue.component.ts b/src/app/games/doge_rescue/doge_rescue.component.ts new file mode 100644 index 0000000..12bbde6 --- /dev/null +++ b/src/app/games/doge_rescue/doge_rescue.component.ts @@ -0,0 +1,552 @@ +import { Component, OnInit, OnDestroy, AfterViewInit, ViewChild, ElementRef, inject, NgZone } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import * as Matter from 'matter-js'; +import { ToolsService } from '../../services/tools.service'; + +interface BlockDef { + src?: string; + solid?: boolean; + spawn?: 'doge' | 'bees'; +} + +interface LevelDef { + id: string; + duration: number; + beesCount: number; + tintLimit: number; + brutality: { maxSpeed: number; force: number }; + map: string[][]; +} + +@Component({ + selector: 'app-doge-rescue', + standalone: true, + imports: [CommonModule], + templateUrl: './doge_rescue.component.html', + styleUrl: './doge_rescue.component.css' +}) +export class DogeRescueComponent implements OnInit, AfterViewInit, OnDestroy { + tools: ToolsService = inject(ToolsService); + private ngZone: NgZone = inject(NgZone); + + @ViewChild('gameContainer') gameContainer!: ElementRef; + @ViewChild('canvas') canvasRef!: ElementRef; + + gameState: 'LOADING' | 'START' | 'DRAWING' | 'ATTACK' | 'WIN' | 'LOSE' = 'LOADING'; + gamePoints = 0; + level = 0; + timerDisplay = 5; + + private engine!: Matter.Engine; + private dogeBody: Matter.Body | null = null; + private drawnLineBody: Matter.Body | null = null; + private bees: Array<{ body: Matter.Body; position: { x: number; y: number }; velocity: { x: number; y: number }; circleRadius: number }> = []; + + private blocksDef: Record = {}; + private levelsDef: LevelDef[] = []; + private textures: Record = {}; + private mapGrid: { id: string; body: Matter.Body | null; rect: {x:number, y:number, w:number, h:number} }[][] = []; + private beeNests: { x: number; y: number }[] = []; + private currentLevelDef!: LevelDef; + + private currentDrawing: { x: number; y: number }[] = []; + private isDrawing = false; + private lineLength = 0; + private maxLineLength = 2000; + private animationFrameId: number | null = null; + private attackTimer: any = null; + private beeSpawnTimer: any = null; + + private onPointerDownBound = this.onPointerDown.bind(this); + private onPointerMoveBound = this.onPointerMove.bind(this); + private onPointerUpBound = this.onPointerUp.bind(this); + private onResizeBound = this.onResize.bind(this); + + ngOnInit(): void { + this.tools.setTitle("doge_rescue" as any); + this.tools.actPage = "doge_rescue" as any; + } + + ngAfterViewInit(): void { + this.initPhysics(); + this.loadData(); + } + + ngOnDestroy(): void { + this.stopLoop(); + if (this.attackTimer) clearInterval(this.attackTimer); + if (this.beeSpawnTimer) clearInterval(this.beeSpawnTimer); + window.removeEventListener('resize', this.onResizeBound); + + const canvas = this.canvasRef?.nativeElement; + if (canvas) { + canvas.removeEventListener('pointerdown', this.onPointerDownBound); + canvas.removeEventListener('pointermove', this.onPointerMoveBound); + canvas.removeEventListener('pointerup', this.onPointerUpBound); + } + this.tools.leaveMinigame('doge_rescue', this.gamePoints, this.level); + } + + async loadData(): Promise { + try { + let resBlocks = await fetch('games/doge_rescue/data/blocks.json'); + if (!resBlocks.ok) resBlocks = await fetch('/games/doge_rescue/data/blocks.json'); + this.blocksDef = await resBlocks.json(); + + let resLevels = await fetch('games/doge_rescue/data/levels.json'); + if (!resLevels.ok) resLevels = await fetch('/games/doge_rescue/data/levels.json'); + const levelsData = await resLevels.json(); + this.levelsDef = levelsData.levels; + + // Preload images + const imagesToLoad: { key: string, url: string }[] = [ + { key: 'doge', url: 'games/doge_rescue/assets/dog.png' }, + { key: 'bee', url: 'games/doge_rescue/assets/bee.png' } + ]; + + for (const blockId in this.blocksDef) { + if (this.blocksDef[blockId].src) { + imagesToLoad.push({ key: blockId, url: this.blocksDef[blockId].src! }); + } + } + + await Promise.all(imagesToLoad.map(img => new Promise((resolve) => { + const image = new Image(); + image.src = img.url; + image.onload = () => { + this.textures[img.key] = image; + resolve(); + }; + image.onerror = () => resolve(); + }))); + + this.startLevel(); + } catch (err) { + console.error("Error loading Doge Rescue data", err); + } + } + + startLevel(): void { + this.gameState = 'DRAWING'; + + // Choose level randomly + const randomIdx = Math.floor(Math.random() * this.levelsDef.length); + this.currentLevelDef = this.levelsDef[randomIdx]; + this.timerDisplay = this.currentLevelDef.duration; + this.maxLineLength = this.currentLevelDef.tintLimit || 2000; + + this.resetPhysics(); + } + + nextLevel(): void { + this.level++; + this.startLevel(); + } + + private initPhysics(): void { + this.engine = Matter.Engine.create(); + this.engine.gravity.y = 1; + + const canvas = this.canvasRef.nativeElement; + const container = this.gameContainer.nativeElement; + canvas.width = container.clientWidth; + canvas.height = container.clientHeight; + + canvas.addEventListener('pointerdown', this.onPointerDownBound); + canvas.addEventListener('pointermove', this.onPointerMoveBound); + canvas.addEventListener('pointerup', this.onPointerUpBound); + window.addEventListener('resize', this.onResizeBound); + + // Collision listener + Matter.Events.on(this.engine, 'collisionStart', (event) => { + if (this.gameState !== 'ATTACK') return; + const pairs = event.pairs; + for (let i = 0; i < pairs.length; i++) { + const { bodyA, bodyB } = pairs[i]; + if ((bodyA.label === 'doge' && bodyB.label === 'bee') || (bodyA.label === 'bee' && bodyB.label === 'doge')) { + this.ngZone.run(() => { + this.gameState = 'LOSE'; + if (this.attackTimer) clearInterval(this.attackTimer); + if (this.beeSpawnTimer) clearInterval(this.beeSpawnTimer); + this.tools.playSound('sfx_8'); + }); + return; + } + } + }); + + this.ngZone.runOutsideAngular(() => { + this.loop(); + }); + } + + private resetPhysics(): void { + Matter.World.clear(this.engine.world, false); + this.bees = []; + this.currentDrawing = []; + this.isDrawing = false; + this.lineLength = 0; + this.drawnLineBody = null; + this.mapGrid = []; + this.beeNests = []; + this.dogeBody = null; + + if (this.attackTimer) clearInterval(this.attackTimer); + if (this.beeSpawnTimer) clearInterval(this.beeSpawnTimer); + + const canvas = this.canvasRef.nativeElement; + const w = canvas.width; + const h = canvas.height; + + // Boundaries + const wallOpts = { isStatic: true, render: { visible: false } }; + const ground = Matter.Bodies.rectangle(w / 2, h + 100, w * 2, 200, wallOpts); + const leftWall = Matter.Bodies.rectangle(-50, h / 2, 100, h * 2, wallOpts); + const rightWall = Matter.Bodies.rectangle(w + 50, h / 2, 100, h * 2, wallOpts); + const ceiling = Matter.Bodies.rectangle(w / 2, -100, w * 2, 200, wallOpts); + Matter.World.add(this.engine.world, [ground, leftWall, rightWall, ceiling]); + + // Build map + if (this.currentLevelDef && this.currentLevelDef.map.length > 0) { + const rows = this.currentLevelDef.map.length; + const cols = this.currentLevelDef.map[0].length; + const blockW = w / cols; + const blockH = h / rows; + + for (let r = 0; r < rows; r++) { + const rowArr = []; + for (let c = 0; c < cols; c++) { + const blockId = this.currentLevelDef.map[r][c]; + const blockDef = this.blocksDef[blockId]; + const rect = { x: c * blockW, y: r * blockH, w: blockW, h: blockH }; + + let body = null; + if (blockDef) { + const centerX = rect.x + blockW / 2; + const centerY = rect.y + blockH / 2; + + if (blockDef.solid) { + body = Matter.Bodies.rectangle(centerX, centerY, blockW + 1, blockH + 1, { + isStatic: true, + friction: 1, + restitution: 0.1 + }); + Matter.World.add(this.engine.world, body); + } + + if (blockDef.spawn === 'doge') { + this.dogeBody = Matter.Bodies.circle(centerX, centerY, blockW * 0.4, { + restitution: 0.3, + friction: 0.8, + density: 0.05, + label: 'doge' + }); + Matter.World.add(this.engine.world, this.dogeBody); + } else if (blockDef.spawn === 'bees') { + this.beeNests.push({ x: centerX, y: centerY }); + } + } + rowArr.push({ id: blockId, body, rect }); + } + this.mapGrid.push(rowArr); + } + } + } + + private onPointerDown(e: PointerEvent): void { + if (this.gameState !== 'DRAWING') return; + const rect = this.canvasRef.nativeElement.getBoundingClientRect(); + const x = e.clientX - rect.left; + const y = e.clientY - rect.top; + this.isDrawing = true; + this.currentDrawing = [{ x, y }]; + this.lineLength = 0; + } + + private onPointerMove(e: PointerEvent): void { + if (!this.isDrawing || this.gameState !== 'DRAWING') return; + const rect = this.canvasRef.nativeElement.getBoundingClientRect(); + const x = e.clientX - rect.left; + const y = e.clientY - rect.top; + + const last = this.currentDrawing[this.currentDrawing.length - 1]; + const dist = Math.hypot(x - last.x, y - last.y); + if (dist > 15) { + if (this.lineLength + dist <= this.maxLineLength) { + this.currentDrawing.push({ x, y }); + this.lineLength += dist; + } else { + this.onPointerUp(); + } + } + } + + private onPointerUp(): void { + if (!this.isDrawing || this.gameState !== 'DRAWING') return; + this.isDrawing = false; + if (this.currentDrawing.length > 2) { + this.createPhysicalLine(this.currentDrawing); + this.currentDrawing = []; + this.startAttack(); + } else { + this.currentDrawing = []; + } + } + + private createPhysicalLine(points: { x: number; y: number }[]): void { + const parts: Matter.Body[] = []; + const thickness = 14; + for (let i = 0; i < points.length - 1; i++) { + const p1 = points[i]; + const p2 = points[i + 1]; + const dx = p2.x - p1.x; + const dy = p2.y - p1.y; + const length = Math.hypot(dx, dy); + const angle = Math.atan2(dy, dx); + const cx = (p1.x + p2.x) / 2; + const cy = (p1.y + p2.y) / 2; + + const seg = Matter.Bodies.rectangle(cx, cy, length + 5, thickness, { + angle: angle, + chamfer: { radius: thickness / 2 } + }); + parts.push(seg); + } + + this.drawnLineBody = Matter.Body.create({ + parts: parts, + friction: 0.8, + restitution: 0.2, + density: 0.1 + }); + Matter.World.add(this.engine.world, this.drawnLineBody); + } + + private startAttack(): void { + this.gameState = 'ATTACK'; + this.timerDisplay = this.currentLevelDef.duration; + + // Bee Spawning logic + let beesSpawnedPerNest = 0; + const spawnBees = () => { + if (this.gameState !== 'ATTACK') return; + if (beesSpawnedPerNest >= this.currentLevelDef.beesCount) return; + + this.beeNests.forEach(nest => { + const beeBody = Matter.Bodies.circle(nest.x + (Math.random() - 0.5) * 20, nest.y + 20, 10, { + restitution: 0.8, + frictionAir: 0.05, + density: 0.01, + label: 'bee' + }); + Matter.Body.setVelocity(beeBody, { x: (Math.random() - 0.5) * 4, y: Math.random() * 2 }); + Matter.World.add(this.engine.world, beeBody); + this.bees.push({ + body: beeBody, + position: beeBody.position, + velocity: beeBody.velocity, + circleRadius: 10 + }); + }); + beesSpawnedPerNest++; + }; + + // Spawn first burst + for(let i=0; i<3 && i { + if (this.tools.isWindowBlurred) return; + spawnBees(); + }, 500); + + if (this.attackTimer) clearInterval(this.attackTimer); + this.attackTimer = setInterval(() => { + if (this.tools.isWindowBlurred) return; + if (this.gameState === 'ATTACK') { + this.timerDisplay--; + if (this.timerDisplay <= 0) { + clearInterval(this.attackTimer); + clearInterval(this.beeSpawnTimer); + this.ngZone.run(() => { + this.gamePoints += 10; + this.gameState = 'WIN'; + this.tools.playSound('sfx_4'); + }); + } + } + }, 1000); + } + + private loop(): void { + this.animationFrameId = requestAnimationFrame(() => this.loop()); + if (this.tools.isWindowBlurred) return; + + if (this.gameState === 'ATTACK') { + Matter.Engine.update(this.engine, 1000 / 60); + + // Bee AI + if (this.dogeBody) { + this.bees.forEach(bee => { + const dx = this.dogeBody!.position.x - bee.body.position.x; + const dy = this.dogeBody!.position.y - bee.body.position.y; + const dist = Math.hypot(dx, dy); + + if (dist > 0) { + Matter.Body.applyForce(bee.body, bee.body.position, { + x: (dx / dist) * this.currentLevelDef.brutality.force, + y: (dy / dist) * this.currentLevelDef.brutality.force + }); + } + + if (bee.body.speed > this.currentLevelDef.brutality.maxSpeed) { + Matter.Body.setVelocity(bee.body, { + x: (bee.body.velocity.x / bee.body.speed) * this.currentLevelDef.brutality.maxSpeed, + y: (bee.body.velocity.y / bee.body.speed) * this.currentLevelDef.brutality.maxSpeed + }); + } + }); + } + + // Check Doge out of bounds + if (this.dogeBody) { + const canvas = this.canvasRef.nativeElement; + if (this.dogeBody.position.y > canvas.height + 50 || this.dogeBody.position.x < -50 || this.dogeBody.position.x > canvas.width + 50) { + this.ngZone.run(() => { + this.gameState = 'LOSE'; + if (this.attackTimer) clearInterval(this.attackTimer); + if (this.beeSpawnTimer) clearInterval(this.beeSpawnTimer); + this.tools.playSound('sfx_8'); + }); + } + } + } + + this.draw(); + } + + private draw(): void { + const canvas = this.canvasRef?.nativeElement; + if (!canvas) return; + const ctx = canvas.getContext('2d'); + if (!ctx) return; + + ctx.clearRect(0, 0, canvas.width, canvas.height); + + // Draw Map Blocks + for (let r = 0; r < this.mapGrid.length; r++) { + for (let c = 0; c < this.mapGrid[r].length; c++) { + const cell = this.mapGrid[r][c]; + const blockDef = this.blocksDef[cell.id]; + if (blockDef && blockDef.src && this.textures[cell.id]) { + ctx.drawImage(this.textures[cell.id], cell.rect.x, cell.rect.y, cell.rect.w, cell.rect.h); + } + } + } + + // Draw Doge + if (this.dogeBody && this.textures['doge']) { + ctx.save(); + ctx.translate(this.dogeBody.position.x, this.dogeBody.position.y); + ctx.rotate(this.dogeBody.angle); + const rad = this.dogeBody.circleRadius || 20; + ctx.drawImage(this.textures['doge'], -rad, -rad, rad * 2, rad * 2); + ctx.restore(); + } + + // Draw Pre-physics Line + if (this.isDrawing && this.currentDrawing.length > 1) { + ctx.strokeStyle = '#222'; + ctx.lineWidth = 14; + ctx.lineCap = 'round'; + ctx.lineJoin = 'round'; + ctx.beginPath(); + this.currentDrawing.forEach((p, i) => { + i === 0 ? ctx.moveTo(p.x, p.y) : ctx.lineTo(p.x, p.y); + }); + ctx.stroke(); + } + + // Draw Physical Line + if (this.drawnLineBody) { + ctx.fillStyle = '#222'; + ctx.beginPath(); + for (let i = 1; i < this.drawnLineBody.parts.length; i++) { + const part = this.drawnLineBody.parts[i]; + ctx.moveTo(part.vertices[0].x, part.vertices[0].y); + for (let j = 1; j < part.vertices.length; j++) { + ctx.lineTo(part.vertices[j].x, part.vertices[j].y); + } + ctx.lineTo(part.vertices[0].x, part.vertices[0].y); + } + ctx.fill(); + } + + // Draw Bees + if (this.textures['bee']) { + this.bees.forEach(bee => { + ctx.save(); + ctx.translate(bee.body.position.x, bee.body.position.y); + let angle = Math.atan2(bee.body.velocity.y, bee.body.velocity.x); + // If speed is very low, stay upright or last angle, but simple rotation here is fine + ctx.rotate(angle); + const rad = bee.circleRadius * 1.5; // Visual size vs physics size + ctx.drawImage(this.textures['bee'], -rad, -rad, rad * 2, rad * 2); + ctx.restore(); + }); + } + + // Draw Ink Bar UI + if (this.gameState === 'DRAWING' || this.gameState === 'ATTACK') { + const barWidth = canvas.width * 0.8; + const barHeight = 15; + const x = (canvas.width - barWidth) / 2; + const y = 80; + + ctx.fillStyle = 'rgba(0,0,0,0.5)'; + ctx.beginPath(); + if (ctx.roundRect) ctx.roundRect(x, y, barWidth, barHeight, 8); + else ctx.rect(x, y, barWidth, barHeight); + ctx.fill(); + + const remainingRatio = Math.max(0, 1 - (this.lineLength / this.maxLineLength)); + if (remainingRatio > 0) { + ctx.fillStyle = remainingRatio > 0.25 ? '#4CAF50' : '#F44336'; + ctx.beginPath(); + if (ctx.roundRect) ctx.roundRect(x, y, barWidth * remainingRatio, barHeight, 8); + else ctx.rect(x, y, barWidth * remainingRatio, barHeight); + ctx.fill(); + } + + ctx.strokeStyle = '#fff'; + ctx.lineWidth = 2; + ctx.beginPath(); + if (ctx.roundRect) ctx.roundRect(x, y, barWidth, barHeight, 8); + else ctx.rect(x, y, barWidth, barHeight); + ctx.stroke(); + } + } + + private onResize(): void { + const canvas = this.canvasRef?.nativeElement; + const container = this.gameContainer?.nativeElement; + if (canvas && container) { + canvas.width = container.clientWidth; + canvas.height = container.clientHeight; + // We don't dynamically reconstruct map bounds on resize during active play, + // but restarting level corrects it. + if (this.gameState === 'START' || this.gameState === 'DRAWING') { + this.resetPhysics(); + } + } + } + + private stopLoop(): void { + if (this.animationFrameId !== null) { + cancelAnimationFrame(this.animationFrameId); + this.animationFrameId = null; + } + } +} diff --git a/src/app/games/flappy_dunk/flappy_dunk.component.css b/src/app/games/flappy_dunk/flappy_dunk.component.css new file mode 100644 index 0000000..f547d85 --- /dev/null +++ b/src/app/games/flappy_dunk/flappy_dunk.component.css @@ -0,0 +1,131 @@ +:host { + position: relative; + display: block; + width: 100vw; + height: calc(100vh - 70px); + --bg-color: #f5e4c3; + background-color: var(--bg-color); + overflow: hidden; + touch-action: none; + user-select: none; +} + +#game-container { + position: absolute; + top: 0; left: 0; width: 100%; height: 100%; + display: flex; + justify-content: center; + align-items: center; +} + +canvas { + display: block; + background-color: var(--bg-color); +} + +#ui-layer { + position: absolute; + top: 0; left: 0; width: 100%; height: 100%; + pointer-events: none; + display: flex; + flex-direction: column; + justify-content: space-between; + z-index: 30; +} + +.hud { + position: absolute; + top: 20%; + left: 50%; + transform: translateX(-50%); + font-size: 4em; + font-weight: bold; + color: #fff; + text-shadow: 0px 4px 0px #ccc, 0px 6px 10px rgba(0,0,0,0.2); + transition: transform 0.1s; +} + +.screen { + position: absolute; + top: 0; left: 0; width: 100%; height: 100%; + background: rgba(245, 228, 195, 0.85); + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + pointer-events: auto; + backdrop-filter: blur(4px); + z-index: 20; +} + +.hidden { display: none !important; } + +h1 { + font-size: 3.5em; + color: #fff; + margin: 0 0 10px 0; + text-transform: uppercase; + text-shadow: 0 4px 0 #ff4081, 0 8px 15px rgba(0,0,0,0.3); + text-align: center; +} + +p { + font-size: 1.5em; + color: #555; + margin-bottom: 30px; + text-align: center; + font-weight: bold; +} + +.btn { + background: #e91e63; + color: white; + border: none; + padding: 15px 50px; + border-radius: 30px; + font-size: 1.5em; + font-weight: bold; + cursor: pointer; + box-shadow: 0 6px 0 #880e4f, 0 10px 15px rgba(0,0,0,0.3); + transition: transform 0.1s, box-shadow 0.1s; +} +.btn:active { + transform: translateY(6px); + box-shadow: 0 0 0 #880e4f, 0 4px 5px rgba(0,0,0,0.3); +} + +::ng-deep .swish-text { + position: absolute; + color: #FFEB3B; + font-size: 2em; + font-weight: bold; + text-shadow: 0 2px 5px rgba(0,0,0,0.5); + pointer-events: none; + animation: floatUp 1s ease-out forwards; + z-index: 15; +} + +@keyframes floatUp { + 0% { opacity: 1; transform: translateY(0) scale(1); } + 100% { opacity: 0; transform: translateY(-50px) scale(1.5); } +} + +.top-hud { + position: absolute; + top: 20px; + left: 20px; + right: 20px; + display: flex; + justify-content: space-between; + z-index: 30; + pointer-events: none; +} +.hud-item { + font-size: 1.5em; + font-weight: bold; + color: #fff; + background: rgba(0,0,0,0.3); + padding: 5px 15px; + border-radius: 20px; + text-shadow: 1px 1px 2px rgba(0,0,0,0.8); +} diff --git a/src/app/games/flappy_dunk/flappy_dunk.component.html b/src/app/games/flappy_dunk/flappy_dunk.component.html new file mode 100644 index 0000000..c7367a9 --- /dev/null +++ b/src/app/games/flappy_dunk/flappy_dunk.component.html @@ -0,0 +1,37 @@ +
+ +
+ +
+ +
+
Level: {{currentLevelIndex + 1}}
+
Score: {{gamePoints}}
+
Session: {{sessionPoints}}
+
+ + +
+ {{gamePoints}} +
+
+ + +
+

{{tools.flappy_dunk[tools.lang]?.title || 'Flappy Dunk'}}

+

+ +
+ +
+

+ {{gameState === 'LEVEL_CLEAR' ? 'LEVEL CLEARED!' : (tools.flappy_dunk[tools.lang]?.gameOver || 'GAME OVER')}} +

+

+ {{tools.flappy_dunk[tools.lang]?.scoreLabel || 'Score: '}} + {{gamePoints}} +

+ +
diff --git a/src/app/games/flappy_dunk/flappy_dunk.component.ts b/src/app/games/flappy_dunk/flappy_dunk.component.ts new file mode 100644 index 0000000..ae0a56d --- /dev/null +++ b/src/app/games/flappy_dunk/flappy_dunk.component.ts @@ -0,0 +1,629 @@ +import { Component, OnInit, OnDestroy, AfterViewInit, ViewChild, ElementRef, inject, NgZone, Renderer2 } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { ToolsService } from '../../services/tools.service'; + +export interface LevelConfig { + id: string; + levelSpeed: number; + baskestsCount: number; + basketSize: number; + basketInclinationGrades: number; + basketInclinationType: string; + basketSeparation: number; + basketColor: string; + basketNetColor: string; + ballSize: number; + ballColor: string; + ballLinesColor: string; + ballWingsColor: string; + bgColor: string; + bgLinesColor: string; + bgFigure: string; +} + +interface Hoop { + x: number; + y: number; + passed: boolean; + swish: boolean; + scored: boolean; + color: string; + rotation: number; +} + +interface Particle { + x: number; + y: number; + vx: number; + vy: number; + life: number; + color: string; + size: number; +} + +interface FinishLine { + x: number; + passed: boolean; +} + +@Component({ + selector: 'app-flappy-dunk', + standalone: true, + imports: [CommonModule], + templateUrl: './flappy_dunk.component.html', + styleUrl: './flappy_dunk.component.css' +}) +export class FlappyDunkComponent implements OnInit, AfterViewInit, OnDestroy { + tools: ToolsService = inject(ToolsService); + private ngZone: NgZone = inject(NgZone); + private renderer: Renderer2 = inject(Renderer2); + + @ViewChild('gameContainer') gameContainer!: ElementRef; + @ViewChild('canvas') canvasRef!: ElementRef; + + gameState: 'START' | 'PLAYING' | 'GAMEOVER' | 'LEVEL_CLEAR' = 'START'; + + levels: LevelConfig[] = []; + currentLevelIndex = 0; + currentLevelConfig: LevelConfig | null = null; + + gamePoints = 0; + sessionPoints = 0; + + private combo = 1; + private frames = 0; + private bgOffset = 0; + private bgFigureOffset = 0; + + private ball = { + x: 0, + y: 0, + vy: 0, + radius: 18, + gravity: 0.35, + jump: -7.5, + rotation: 0, + wingAngle: 0, + prevX: 0, + prevY: 0 + }; + + private hoops: Hoop[] = []; + private particles: Particle[] = []; + private finishLine: FinishLine | null = null; + private basketsSpawned = 0; + private basketsPassed = 0; + + private rimRadius = 6; + private animationFrameId: number | null = null; + private ctx!: CanvasRenderingContext2D; + + private onPointerDownBound = this.onTap.bind(this); + private onKeyDownBound = this.onKeyDown.bind(this); + private onResizeBound = this.onResize.bind(this); + + ngOnInit(): void { + this.tools.setTitle("flappy_dunk" as any); + this.tools.actPage = "flappy_dunk" as any; + this.sessionPoints = 0; + this.currentLevelIndex = 0; + + fetch('games/flappy_dunk/data/levels.json') + .then(res => res.json()) + .then((data: LevelConfig[]) => { + this.levels = data; + this.loadLevel(this.currentLevelIndex); + }) + .catch(err => console.error("Could not load levels.json", err)); + } + + ngAfterViewInit(): void { + const canvas = this.canvasRef.nativeElement; + this.ctx = canvas.getContext('2d')!; + + this.onResize(); + window.addEventListener('resize', this.onResizeBound); + + document.addEventListener('mousedown', this.onPointerDownBound); + document.addEventListener('touchstart', this.onPointerDownBound, { passive: false }); + window.addEventListener('keydown', this.onKeyDownBound); + + this.ngZone.runOutsideAngular(() => { + this.loop(); + }); + } + + ngOnDestroy(): void { + if (this.animationFrameId !== null) { + cancelAnimationFrame(this.animationFrameId); + } + window.removeEventListener('resize', this.onResizeBound); + window.removeEventListener('keydown', this.onKeyDownBound); + document.removeEventListener('mousedown', this.onPointerDownBound); + document.removeEventListener('touchstart', this.onPointerDownBound); + + this.tools.leaveMinigame('flappy_dunk', this.sessionPoints); + } + + private onResize(): void { + if (!this.canvasRef) return; + const canvas = this.canvasRef.nativeElement; + canvas.width = window.innerWidth; + canvas.height = window.innerHeight; + } + + loadLevel(index: number) { + if (this.levels.length === 0) return; + this.currentLevelIndex = index; + const randomIndex = Math.floor(Math.random() * this.levels.length); + this.currentLevelConfig = this.levels[randomIndex]; + this.initGameState(); + } + + initGameState(): void { + if (!this.canvasRef || !this.currentLevelConfig) return; + const canvas = this.canvasRef.nativeElement; + + this.ball.x = canvas.width * 0.3; + this.ball.y = canvas.height / 2; + this.ball.vy = 0; + this.ball.rotation = 0; + this.ball.radius = this.currentLevelConfig.ballSize; + + this.hoops = []; + this.particles = []; + this.finishLine = null; + this.basketsSpawned = 0; + this.basketsPassed = 0; + + this.gamePoints = 0; + this.combo = 1; + this.frames = 0; + + this.gameState = 'START'; + this.spawnHoop(canvas.width + 200); + } + + startGame(): void { + this.gameState = 'PLAYING'; + this.flap(); + } + + private winLevel(): void { + this.ngZone.run(() => { + this.gameState = 'LEVEL_CLEAR'; + this.currentLevelIndex++; + this.createExplosion(this.ball.x, this.ball.y, '#4CAF50'); + this.tools.playSound('sfx_4'); + }); + } + + private endGame(): void { + this.ngZone.run(() => { + if (this.currentLevelConfig?.baskestsCount === 0 && this.basketsPassed >= 1) { + this.winLevel(); + } else { + this.gameState = 'GAMEOVER'; + this.createExplosion(this.ball.x, this.ball.y, '#e65100'); + this.tools.playSound('sfx_3'); + } + }); + } + + private onTap(e?: Event): void { + if (e && e.type === 'touchstart') e.preventDefault(); + this.ngZone.run(() => { + if (this.gameState === 'START') { + this.startGame(); + } else if (this.gameState === 'PLAYING') { + this.flap(); + } else if (this.gameState === 'LEVEL_CLEAR' || this.gameState === 'GAMEOVER') { + // If clicking during game over, reset or next level + if (this.gameState === 'LEVEL_CLEAR') { + this.loadLevel(this.currentLevelIndex); + } else { + this.loadLevel(this.currentLevelIndex); // Retry same level + } + } + }); + } + + private onKeyDown(e: KeyboardEvent): void { + if (e.code === 'Space' || e.key === ' ') { + if (e.cancelable) { + e.preventDefault(); + } + this.onTap(); + } + } + + private flap(): void { + if (this.gameState === 'PLAYING') { + this.ball.vy = this.ball.jump; + for (let i = 0; i < 3; i++) { + this.particles.push({ + x: this.ball.x - 15, y: this.ball.y, + vx: (Math.random() - 0.5) * 2 - 2, + vy: (Math.random() - 0.5) * 2, + life: 1, color: '#fff', size: Math.random() * 3 + 2 + }); + } + this.tools.playSound('sfx_1'); + } + } + + private spawnHoop(xPos: number): void { + if (!this.currentLevelConfig) return; + const config = this.currentLevelConfig; + + if (config.baskestsCount > 0 && this.basketsSpawned >= config.baskestsCount) { + if (!this.finishLine) { + this.finishLine = { x: xPos, passed: false }; + } + return; + } + + const canvas = this.canvasRef.nativeElement; + const minY = 200; + const maxY = canvas.height - 200; + const yPos = Math.random() * (maxY - minY) + minY; + + let rotation = 0; + if (config.basketInclinationGrades > 0) { + const maxRad = config.basketInclinationGrades * (Math.PI / 180); + if (config.basketInclinationType === 'aligned') { + rotation = maxRad; + } else if (config.basketInclinationType === 'serpent') { + rotation = (this.basketsSpawned % 2 === 0) ? maxRad : -maxRad; + } else if (config.basketInclinationType === 'random') { + rotation = (Math.random() * 2 * maxRad) - maxRad; + } + } + + this.hoops.push({ + x: xPos, + y: yPos, + passed: false, + swish: true, + scored: false, + color: config.basketColor, + rotation: rotation + }); + this.basketsSpawned++; + } + + private createExplosion(x: number, y: number, color: string): void { + for (let i = 0; i < 20; i++) { + this.particles.push({ + x: x, y: y, + vx: (Math.random() - 0.5) * 10, + vy: (Math.random() - 0.5) * 10, + life: 1, color: color, size: Math.random() * 6 + 2 + }); + } + } + + private showPopup(text: string, x: number, y: number, isSwish: boolean): void { + const el = this.renderer.createElement('div'); + this.renderer.addClass(el, 'swish-text'); + this.renderer.setProperty(el, 'innerText', text); + this.renderer.setStyle(el, 'left', `${x}px`); + this.renderer.setStyle(el, 'top', `${y}px`); + + if (isSwish) { + this.renderer.setStyle(el, 'color', '#FFEB3B'); + this.renderer.setStyle(el, 'textShadow', '0 2px 10px #FF9800'); + } else { + this.renderer.setStyle(el, 'color', '#fff'); + } + + const uiLayer = document.getElementById('ui-layer'); + if (uiLayer) { + this.renderer.appendChild(uiLayer, el); + setTimeout(() => { + if (el.parentNode) { + this.renderer.removeChild(el.parentNode, el); + } + }, 1000); + } + } + + private loop(): void { + if (this.tools.isWindowBlurred) { + this.animationFrameId = requestAnimationFrame(() => this.loop()); + return; + } + this.update(); + this.draw(); + this.animationFrameId = requestAnimationFrame(() => this.loop()); + } + + private update(): void { + if (!this.canvasRef || !this.currentLevelConfig) return; + const canvas = this.canvasRef.nativeElement; + const config = this.currentLevelConfig; + + if (this.gameState === 'PLAYING') { + this.frames++; + this.bgOffset -= config.levelSpeed * 0.1; // Slower grid scrolling as requested + + + this.ball.prevX = this.ball.x; + this.ball.prevY = this.ball.y; + + this.ball.vy += this.ball.gravity; + this.ball.y += this.ball.vy; + this.ball.rotation += this.ball.vy * 0.05; + this.ball.wingAngle = Math.max(-0.5, Math.min(0.5, this.ball.vy * 0.1)); + + if (this.ball.y - this.ball.radius < 0 || this.ball.y + this.ball.radius > canvas.height) { + this.endGame(); + } + + if (this.finishLine) { + this.finishLine.x -= config.levelSpeed; + if (this.ball.x > this.finishLine.x && !this.finishLine.passed) { + this.finishLine.passed = true; + this.winLevel(); + } + } else { + if (this.hoops.length > 0) { + let lastHoop = this.hoops[this.hoops.length - 1]; + let sep = config.basketSize * config.basketSeparation; + if (canvas.width - lastHoop.x >= sep) { + this.spawnHoop(canvas.width + 100); + } + } + } + + for (let i = 0; i < this.hoops.length; i++) { + let h = this.hoops[i]; + h.x -= config.levelSpeed; + + let rotLeftX = h.x + (-config.basketSize/2 * Math.cos(h.rotation)); + let rotLeftY = h.y + (-config.basketSize/2 * Math.sin(h.rotation)); + let rotRightX = h.x + (config.basketSize/2 * Math.cos(h.rotation)); + let rotRightY = h.y + (config.basketSize/2 * Math.sin(h.rotation)); + + let distL = Math.hypot(this.ball.x - rotLeftX, this.ball.y - rotLeftY); + let distR = Math.hypot(this.ball.x - rotRightX, this.ball.y - rotRightY); + + if (distL < this.ball.radius + this.rimRadius || distR < this.ball.radius + this.rimRadius) { + this.ball.vy = -Math.abs(this.ball.vy) * 0.7 - 2; + h.swish = false; + this.createExplosion(distL < distR ? rotLeftX : rotRightX, distL < distR ? rotLeftY : rotRightY, '#fff'); + this.tools.playSound('sfx_1'); + } + + let dxPrev = this.ball.prevX - h.x; + let dyPrev = this.ball.prevY - h.y; + let localPrevY = h.y + (dxPrev * Math.sin(-h.rotation) + dyPrev * Math.cos(-h.rotation)); + + let dxCurr = this.ball.x - h.x; + let dyCurr = this.ball.y - h.y; + let localCurrX = h.x + (dxCurr * Math.cos(-h.rotation) - dyCurr * Math.sin(-h.rotation)); + let localCurrY = h.y + (dxCurr * Math.sin(-h.rotation) + dyCurr * Math.cos(-h.rotation)); + + if (!h.scored && localPrevY <= h.y && localCurrY > h.y) { + if (localCurrX > h.x - config.basketSize / 2 && localCurrX < h.x + config.basketSize / 2) { + h.scored = true; + this.basketsPassed++; + + let pts = 1; + if (h.swish) { + this.combo++; + pts = this.combo; + this.ngZone.run(() => { + this.showPopup("SWISH! +" + pts, this.ball.x, this.ball.y - 40, true); + }); + } else { + this.combo = 1; + this.ngZone.run(() => { + this.showPopup("+" + pts, this.ball.x, this.ball.y - 40, false); + }); + } + + this.ngZone.run(() => { + this.gamePoints += pts; + this.sessionPoints += pts; + this.tools.playSound('sfx_1'); + }); + + const scoreUI = document.getElementById('scoreUI'); + if (scoreUI) { + scoreUI.style.transform = 'scale(1.3)'; + setTimeout(() => { scoreUI.style.transform = 'scale(1)'; }, 100); + } + this.createExplosion(this.ball.x, h.y, h.swish ? '#FFEB3B' : '#4CAF50'); + } + } + + if (!h.scored && h.x < this.ball.x - config.basketSize && !h.passed) { + h.passed = true; + this.endGame(); + } + } + + if (this.hoops.length > 0 && this.hoops[0].x < -300) { + this.hoops.shift(); + } + } else if (this.gameState === 'START') { + this.ball.y = canvas.height / 2 + Math.sin(Date.now() / 200) * 10; + this.ball.wingAngle = Math.sin(Date.now() / 150) * 0.5; + } + + for (let i = this.particles.length - 1; i >= 0; i--) { + let p = this.particles[i]; + p.x += p.vx; + p.y += p.vy; + p.vy += 0.2; + p.life -= 0.02; + if (p.life <= 0) this.particles.splice(i, 1); + } + } + + private drawBgFigures(ctx: CanvasRenderingContext2D, canvas: HTMLCanvasElement, config: LevelConfig) { + if (!config.bgFigure || config.bgFigure === 'none') return; + + ctx.save(); + ctx.fillStyle = 'rgba(255,255,255,0.02)'; + ctx.strokeStyle = 'rgba(255,255,255,0.05)'; + ctx.lineWidth = 2; + + // Draw figures across the background that scroll slower than the main grid + const parallaxOffset = this.bgOffset * 0.5; + const spacing = 100; // Align with the big grid spacing + + for (let x = (parallaxOffset % spacing) - spacing; x < canvas.width + spacing; x += spacing) { + for (let y = 0; y < canvas.height; y += spacing) { + ctx.save(); + ctx.translate(x + spacing/2, y + spacing/2); + + ctx.beginPath(); + let size = 40; + + if (config.bgFigure === 'squares') { + ctx.rect(-size/2, -size/2, size, size); + } else if (config.bgFigure === 'triangles') { + ctx.moveTo(0, -size/2); ctx.lineTo(size/2, size/2); ctx.lineTo(-size/2, size/2); ctx.closePath(); + } else if (config.bgFigure === 'diamonds') { + ctx.moveTo(0, -size/2); ctx.lineTo(size/2, 0); ctx.lineTo(0, size/2); ctx.lineTo(-size/2, 0); ctx.closePath(); + } else if (config.bgFigure === 'pentagons') { + for(let j=0; j<5; j++) { + ctx.lineTo(size/2 * Math.cos(j * 2 * Math.PI / 5 - Math.PI/2), size/2 * Math.sin(j * 2 * Math.PI / 5 - Math.PI/2)); + } + ctx.closePath(); + } else if (config.bgFigure === 'hexagons') { + for(let j=0; j<6; j++) { + ctx.lineTo(size/2 * Math.cos(j * 2 * Math.PI / 6), size/2 * Math.sin(j * 2 * Math.PI / 6)); + } + ctx.closePath(); + } else if (config.bgFigure === 'stars') { + for(let j=0; j<10; j++) { + let r = j%2===0 ? size/2 : size/4; + ctx.lineTo(r * Math.cos(j * Math.PI / 5 - Math.PI/2), r * Math.sin(j * Math.PI / 5 - Math.PI/2)); + } + ctx.closePath(); + } + + ctx.fill(); + ctx.stroke(); + ctx.restore(); + } + } + ctx.restore(); + } + + private draw(): void { + if (!this.canvasRef || !this.currentLevelConfig) return; + const canvas = this.canvasRef.nativeElement; + const ctx = this.ctx; + const config = this.currentLevelConfig; + + ctx.fillStyle = config.bgColor; + ctx.fillRect(0, 0, canvas.width, canvas.height); + + this.drawBgFigures(ctx, canvas, config); + + // Big Grid (only big squares) + ctx.save(); + ctx.beginPath(); + for (let x = this.bgOffset % 100; x < canvas.width; x += 100) { ctx.moveTo(x, 0); ctx.lineTo(x, canvas.height); } + for (let y = 0; y < canvas.height; y += 100) { ctx.moveTo(0, y); ctx.lineTo(canvas.width, y); } + ctx.strokeStyle = config.bgLinesColor; + ctx.lineWidth = 2; + ctx.stroke(); + ctx.restore(); + + if (this.finishLine) { + ctx.save(); + ctx.translate(this.finishLine.x, 0); + ctx.fillStyle = 'rgba(255, 255, 255, 0.2)'; + ctx.fillRect(-20, 0, 40, canvas.height); + for(let yy=0; yy { + ctx.save(); + ctx.translate(h.x, h.y); + ctx.rotate(h.rotation); + + ctx.beginPath(); + ctx.moveTo(-config.basketSize / 2, 0); + ctx.lineTo(-config.basketSize / 2 + 15, 70); + ctx.lineTo(config.basketSize / 2 - 15, 70); + ctx.lineTo(config.basketSize / 2, 0); + ctx.fillStyle = config.basketNetColor; + ctx.fill(); + ctx.lineWidth = 2; + ctx.strokeStyle = config.basketNetColor; + ctx.stroke(); + + ctx.beginPath(); + ctx.ellipse(0, 0, config.basketSize / 2, 10, 0, Math.PI, 0); + ctx.strokeStyle = config.basketColor; + ctx.lineWidth = 4; + ctx.stroke(); + + ctx.beginPath(); + ctx.ellipse(0, 0, config.basketSize / 2, 10, 0, 0, Math.PI); + ctx.strokeStyle = config.basketColor; + ctx.lineWidth = 6; + ctx.stroke(); + + ctx.fillStyle = config.basketColor; + ctx.beginPath(); ctx.arc(-config.basketSize / 2, 0, this.rimRadius, 0, Math.PI * 2); ctx.fill(); + ctx.beginPath(); ctx.arc(config.basketSize / 2, 0, this.rimRadius, 0, Math.PI * 2); ctx.fill(); + ctx.restore(); + }); + + this.particles.forEach(p => { + ctx.globalAlpha = p.life; + ctx.fillStyle = p.color; + ctx.beginPath(); + ctx.arc(p.x, p.y, p.size, 0, Math.PI * 2); + ctx.fill(); + }); + ctx.globalAlpha = 1.0; + + if (this.gameState !== 'GAMEOVER' || this.particles.length > 0) { + ctx.save(); + ctx.translate(this.ball.x, this.ball.y); + + ctx.fillStyle = config.ballWingsColor; + ctx.save(); + ctx.translate(-this.ball.radius, -5); + ctx.rotate(this.ball.wingAngle); + ctx.beginPath(); ctx.ellipse(-10, 0, 15, 6, 0, 0, Math.PI * 2); ctx.fill(); + ctx.restore(); + + ctx.save(); + ctx.translate(this.ball.radius, -5); + ctx.rotate(-this.ball.wingAngle); + ctx.beginPath(); ctx.ellipse(10, 0, 15, 6, 0, 0, Math.PI * 2); ctx.fill(); + ctx.restore(); + + ctx.rotate(this.ball.rotation); + ctx.beginPath(); + ctx.arc(0, 0, this.ball.radius, 0, Math.PI * 2); + ctx.fillStyle = config.ballColor; + ctx.fill(); + ctx.lineWidth = 2; + ctx.strokeStyle = config.ballLinesColor; + ctx.stroke(); + + ctx.beginPath(); ctx.moveTo(0, -this.ball.radius); ctx.lineTo(0, this.ball.radius); ctx.stroke(); + ctx.beginPath(); ctx.moveTo(-this.ball.radius, 0); ctx.lineTo(this.ball.radius, 0); ctx.stroke(); + ctx.beginPath(); ctx.arc(-this.ball.radius, 0, this.ball.radius * 0.7, -Math.PI / 2, Math.PI / 2); ctx.stroke(); + ctx.beginPath(); ctx.arc(this.ball.radius, 0, this.ball.radius * 0.7, Math.PI / 2, Math.PI * 1.5); ctx.stroke(); + + ctx.restore(); + } + } +} diff --git a/src/app/games/helix_jump/helix_jump.component.css b/src/app/games/helix_jump/helix_jump.component.css new file mode 100644 index 0000000..5c15235 --- /dev/null +++ b/src/app/games/helix_jump/helix_jump.component.css @@ -0,0 +1,90 @@ +.helix-jump-wrapper { + position: relative; + width: 100vw; + height: 100vh; + overflow: hidden; + background-color: #ECECEC; + user-select: none; + touch-action: none; +} + +#game-container { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: 1; +} + +.ui-layer { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + pointer-events: none; + display: flex; + flex-direction: column; + justify-content: space-between; + z-index: 10; +} + +.hud { + display: flex; + justify-content: space-between; + padding: 20px 30px; + font-size: 1.8em; + font-weight: 800; + color: #333; +} + +.screen { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(255,255,255,0.75); + backdrop-filter: blur(5px); + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + pointer-events: auto; + z-index: 20; +} + +.screen h1 { + font-size: 3em; + color: #222; + margin-bottom: 15px; +} + +.screen p { + font-size: 1.3em; + color: #555; + margin-bottom: 25px; + text-align: center; +} + +.btn { + padding: 14px 40px; + font-size: 1.4em; + font-weight: bold; + color: #fff; + background: linear-gradient(135deg, #E91E63, #C2185B); + border: none; + border-radius: 50px; + cursor: pointer; + box-shadow: 0 4px 15px rgba(0,0,0,0.2); + transition: transform 0.1s; +} + +.btn:hover { + transform: scale(1.05); +} + +.btn:active { + transform: scale(0.95); +} diff --git a/src/app/games/helix_jump/helix_jump.component.html b/src/app/games/helix_jump/helix_jump.component.html new file mode 100644 index 0000000..2a02b48 --- /dev/null +++ b/src/app/games/helix_jump/helix_jump.component.html @@ -0,0 +1,37 @@ +
+
+ +
+
+
{{tools.helix_jump[tools.lang]?.score || 'Score: '}} {{gamePoints}}
+
{{tools.helix_jump[tools.lang]?.level || 'Level '}} {{level}}
+ @if (timeLeft > 0) { +
{{tools.helix_jump[tools.lang]?.time || 'Time: '}} {{timeLeft}}
+ } +
+
+ + @if (gameState === 'START') { +
+

{{tools.helix_jump[tools.lang]?.helix_jump_title || 'Helix Jump'}}

+

{{tools.helix_jump[tools.lang]?.helix_jump_inst || 'Rotate the tower to drop the bouncing ball to the bottom!'}}

+ +
+ } + + @if (gameState === 'WIN') { +
+

{{tools.helix_jump[tools.lang]?.levelCleared || 'Level Cleared!'}}

+

{{tools.helix_jump[tools.lang]?.score || 'Score: '}} {{levelPoints}}

+ +
+ } + + @if (gameState === 'LOSE') { +
+

{{tools.helix_jump[tools.lang]?.gameOver || 'Game Over'}}

+

{{tools.helix_jump[tools.lang]?.score || 'Score: '}} {{levelPoints}}

+ +
+ } +
diff --git a/src/app/games/helix_jump/helix_jump.component.ts b/src/app/games/helix_jump/helix_jump.component.ts new file mode 100644 index 0000000..175712a --- /dev/null +++ b/src/app/games/helix_jump/helix_jump.component.ts @@ -0,0 +1,616 @@ +import { Component, OnInit, OnDestroy, AfterViewInit, ViewChild, ElementRef, inject, NgZone } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import * as THREE from 'three'; +import { ToolsService } from '../../services/tools.service'; + +@Component({ + selector: 'app-helix-jump', + standalone: true, + imports: [CommonModule], + templateUrl: './helix_jump.component.html', + styleUrl: './helix_jump.component.css' +}) +export class HelixJumpComponent implements OnInit, AfterViewInit, OnDestroy { + tools: ToolsService = inject(ToolsService); + private ngZone: NgZone = inject(NgZone); + + @ViewChild('gameContainer') gameContainer!: ElementRef; + + gameState: 'START' | 'PLAYING' | 'DYING' | 'WIN' | 'LOSE' = 'START'; + gamePoints = 0; + levelPoints = 0; + level = 0; + + levelsConfig: any[] = []; + currentLevelConfig: any = null; + timeLeft: number = 0; + private timerInterval: any = null; + + private scene!: THREE.Scene; + private camera!: THREE.PerspectiveCamera; + private renderer!: THREE.WebGLRenderer; + private towerGroup!: THREE.Group; + private ball!: THREE.Mesh; + private pillar!: THREE.Mesh; + + private explosionParticles: THREE.Points | null = null; + private explosionVelocities: THREE.Vector3[] = []; + + private ballVy = 0; + private gravity = -0.015; + private bounceVelocity = 0.28; + private ballRadius = 0.45; + private platformThickness = 0.4; + private currentPlatformIndex = 0; + private platformsData: Array<{ y: number; group: THREE.Group; broken?: boolean }> = []; + + private consecutiveHoles = 0; + private chargeTrail: THREE.Mesh[] = []; + private breakingWedges: Array<{ mesh: THREE.Mesh, vx: number, vy: number, vz: number }> = []; + + private isDragging = false; + private previousMouseX = 0; + private animationFrameId: number | null = null; + private raycaster = new THREE.Raycaster(); + private downVector = new THREE.Vector3(0, -1, 0); + + private onPointerDownBound = this.onPointerDown.bind(this); + private onPointerMoveBound = this.onPointerMove.bind(this); + private onPointerUpBound = this.onPointerUp.bind(this); + private onResizeBound = this.onResize.bind(this); + + ngOnInit(): void { + this.tools.setTitle("helix_jump" as any); + this.tools.actPage = "helix_jump" as any; + this.fetchLevels(); + } + + + async fetchLevels(): Promise { + try { + const response = await fetch('/games/helix_jump/data/levels.json'); + if (response.ok) { + this.levelsConfig = await response.json(); + } + } catch (e) { + console.error("Failed to load levels.json", e); + } + } + + ngAfterViewInit(): void { + this.init3D(); + } + + ngOnDestroy(): void { + this.stopLoop(); + this.stopTimer(); + window.removeEventListener('resize', this.onResizeBound); + window.removeEventListener('pointerup', this.onPointerUpBound); + if (this.renderer) { + this.renderer.dispose(); + const dom = this.gameContainer?.nativeElement; + if (dom && dom.contains(this.renderer.domElement)) { + dom.removeChild(this.renderer.domElement); + } + } + this.tools.leaveMinigame('helix_jump', this.gamePoints, this.level); + } + + startGame(): void { + this.gameState = 'PLAYING'; + this.levelPoints = 0; + this.resetLevel(); + } + + nextLevel(): void { + this.level++; + this.levelPoints = 0; + this.gameState = 'PLAYING'; + this.resetLevel(); + } + + private startTimer(): void { + this.stopTimer(); + if (this.currentLevelConfig && this.currentLevelConfig.time > 0) { + this.ngZone.run(() => { + this.timeLeft = this.currentLevelConfig.time; + }); + this.timerInterval = setInterval(() => { + if (this.tools.isWindowBlurred) return; + this.ngZone.run(() => { + this.timeLeft--; + if (this.timeLeft <= 0) { + this.stopTimer(); + this.triggerExplosion(); + } + }); + }, 1000); + } else { + this.timeLeft = 0; + } + } + + private stopTimer(): void { + if (this.timerInterval) { + clearInterval(this.timerInterval); + this.timerInterval = null; + } + } + + private init3D(): void { + const container = this.gameContainer.nativeElement; + const width = container.clientWidth || window.innerWidth; + const height = container.clientHeight || window.innerHeight; + + this.scene = new THREE.Scene(); + this.scene.background = new THREE.Color(0xECECEC); + + this.camera = new THREE.PerspectiveCamera(60, width / height, 0.1, 1000); + this.camera.position.set(0, 8, 11); + this.camera.lookAt(0, 4, 0); + + this.renderer = new THREE.WebGLRenderer({ antialias: true }); + this.renderer.setSize(width, height); + this.renderer.shadowMap.enabled = true; + container.appendChild(this.renderer.domElement); + + const ambientLight = new THREE.AmbientLight(0xffffff, 0.65); + this.scene.add(ambientLight); + + const dirLight = new THREE.DirectionalLight(0xffffff, 0.8); + dirLight.position.set(10, 20, 10); + dirLight.castShadow = true; + this.scene.add(dirLight); + + this.towerGroup = new THREE.Group(); + this.scene.add(this.towerGroup); + + const pillarGeo = new THREE.CylinderGeometry(1.2, 1.2, 150, 32); + const pillarMat = new THREE.MeshLambertMaterial({ color: 0xD0D0D0 }); + this.pillar = new THREE.Mesh(pillarGeo, pillarMat); + this.pillar.position.y = -50; + this.towerGroup.add(this.pillar); + + const ballGeo = new THREE.SphereGeometry(this.ballRadius, 32, 32); + const ballMat = new THREE.MeshLambertMaterial({ color: 0xFF4081 }); + this.ball = new THREE.Mesh(ballGeo, ballMat); + this.ball.castShadow = true; + this.scene.add(this.ball); + + container.addEventListener('pointerdown', this.onPointerDownBound); + window.addEventListener('pointermove', this.onPointerMoveBound); + window.addEventListener('pointerup', this.onPointerUpBound); + window.addEventListener('resize', this.onResizeBound); + + this.ngZone.runOutsideAngular(() => { + this.animate(); + }); + } + + private resetLevel(): void { + if (this.explosionParticles) { + this.scene.remove(this.explosionParticles); + this.explosionParticles.geometry.dispose(); + (this.explosionParticles.material as THREE.Material).dispose(); + this.explosionParticles = null; + } + + this.consecutiveHoles = 0; + this.chargeTrail.forEach(p => { + this.scene.remove(p); + p.geometry.dispose(); + (p.material as THREE.Material).dispose(); + }); + this.chargeTrail = []; + + this.breakingWedges.forEach(w => { + this.scene.remove(w.mesh); + w.mesh.geometry.dispose(); + (w.mesh.material as THREE.Material).dispose(); + }); + this.breakingWedges = []; + + if (this.levelsConfig && this.levelsConfig.length > 0) { + this.currentLevelConfig = this.levelsConfig[Math.floor(Math.random() * this.levelsConfig.length)]; + } else { + this.currentLevelConfig = { + floors: 6 + this.level * 2, + safeFloorPercentage: 60, + holeSizePercentage: 15, + numberOfHoles: 1, + holesSorting: "random", + distanceBetweenFloors: 3.5, + time: 30, + tubeColor: "rgba(208, 208, 208, 1)", + backgroundColor: "rgba(236, 236, 236, 1)", + floorColor: "rgba(0, 230, 118, 1)", + floorKillerColor: "rgba(211, 47, 47, 1)", + ballColor: "rgba(255, 64, 129, 1)" + }; + } + + this.scene.background = new THREE.Color(this.currentLevelConfig.backgroundColor); + (this.pillar.material as THREE.MeshLambertMaterial).color = new THREE.Color(this.currentLevelConfig.tubeColor); + (this.ball.material as THREE.MeshLambertMaterial).color = new THREE.Color(this.currentLevelConfig.ballColor); + + this.platformsData.forEach(p => this.towerGroup.remove(p.group)); + this.platformsData = []; + + this.currentPlatformIndex = 0; + this.ball.visible = true; + this.ball.position.set(0, 8, 2.5); + this.ballVy = 0; + this.towerGroup.rotation.y = 0; + + const numPlatforms = this.currentLevelConfig.floors; + const gapY = this.currentLevelConfig.distanceBetweenFloors || 3.5; + this.platformThickness = Math.min(0.4, gapY * 0.8); + + const tubeHeight = Math.max(150, numPlatforms * gapY + 50); + this.pillar.scale.set(1, tubeHeight / 150, 1); + this.pillar.position.y = 30 - (tubeHeight / 2); + + let previousRotationOffset = Math.random() * Math.PI * 2; + let holesSorting = this.currentLevelConfig.holesSorting || "random"; + let alignDrift = Math.random() < 0.33 ? 0 : (Math.random() < 0.5 ? -1 : 1); + + for (let i = 0; i < numPlatforms; i++) { + const y = 6 - i * gapY; + const group = new THREE.Group(); + group.position.y = y; + + const isLast = i === numPlatforms - 1; + const numSlices = 36; + + let safePercent = this.currentLevelConfig.safeFloorPercentage || 60; + let holePercent = this.currentLevelConfig.holeSizePercentage || 15; + + if (isLast) { + safePercent = 100; + holePercent = 0; + } + + const holeSlicesTotal = Math.floor(numSlices * (holePercent / 100)); + + const minHoleSize = 3; + let holes = isLast ? 0 : this.currentLevelConfig.numberOfHoles; + let holeSize = holes > 0 ? Math.max(1, Math.floor(holeSlicesTotal / holes)) : 0; + + let rotationOffset = 0; + if (holesSorting !== "random") { + if (i === 0) { + rotationOffset = previousRotationOffset; + } else if (holesSorting === "oposite") { + rotationOffset = previousRotationOffset + Math.PI; + } else if (holesSorting === "aligned") { + rotationOffset = previousRotationOffset + (alignDrift * 0.08); + } else if (holesSorting === "serpent") { + let serpentDrift = Math.random() < 0.5 ? -0.08 : 0.08; + rotationOffset = previousRotationOffset + serpentDrift; + } + group.rotation.y = rotationOffset; + previousRotationOffset = rotationOffset; + } + + const holeStartIndices: number[] = []; + if (holes > 0) { + const interval = Math.floor(numSlices / holes); + for (let h = 0; h < holes; h++) { + if (holesSorting === "random") { + let start = h * interval + Math.floor(Math.random() * (interval - holeSize + 1)); + holeStartIndices.push(start); + } else { + let start = h * interval; + holeStartIndices.push(start); + } + } + } + + const sliceAngle = (Math.PI * 2) / numSlices; + let startAngle = 0; + + const dangerPercent = Math.max(0, 100 - safePercent - holePercent); + let dangerSlices = Math.floor(numSlices * (dangerPercent / 100)); + if (isLast || i === 0) dangerSlices = 0; + + let nonHoleCount = numSlices - (holes * holeSize); + let dangerArray = new Array(nonHoleCount).fill(false); + for(let d = 0; d < dangerSlices; d++) { + if (d < dangerArray.length) dangerArray[d] = true; + } + for (let j = dangerArray.length - 1; j > 0; j--) { + const k = Math.floor(Math.random() * (j + 1)); + [dangerArray[j], dangerArray[k]] = [dangerArray[k], dangerArray[j]]; + } + + for (let s = 0; s < numSlices; s++) { + let isHole = false; + for (let startIdx of holeStartIndices) { + if (s >= startIdx && s < startIdx + holeSize) { + isHole = true; + break; + } + } + + if (isHole) { + startAngle += sliceAngle; + continue; + } + + const wedgeGeo = new THREE.CylinderGeometry(3.2, 3.2, this.platformThickness, 4, 1, false, startAngle, sliceAngle); + let colorStr = this.currentLevelConfig.floorColor; + let isDanger = false; + let isWin = false; + + if (isLast) { + colorStr = "rgba(255, 213, 79, 1)"; + isWin = true; + } else { + isDanger = dangerArray.pop() || false; + if (isDanger) { + colorStr = this.currentLevelConfig.floorKillerColor; + } + } + + const mat = new THREE.MeshLambertMaterial({ color: new THREE.Color(colorStr) }); + const wedge = new THREE.Mesh(wedgeGeo, mat); + wedge.receiveShadow = true; + wedge.userData = { isDanger, isWin }; + group.add(wedge); + + startAngle += sliceAngle; + } + + this.towerGroup.add(group); + this.platformsData.push({ y, group }); + } + + this.startTimer(); + } + + private breakFloor(pData: { y: number; group: THREE.Group; broken?: boolean }, isSmashed: boolean = false): void { + if (pData.broken) return; + pData.broken = true; + + const worldPos = new THREE.Vector3(); + const worldQuat = new THREE.Quaternion(); + const wedgesToBreak = [...pData.group.children]; + const speedMultiplier = isSmashed ? 1.5 : 0.8; + + wedgesToBreak.forEach((child) => { + const wedge = child as THREE.Mesh; + wedge.getWorldPosition(worldPos); + wedge.getWorldQuaternion(worldQuat); + this.scene.add(wedge); + wedge.position.copy(worldPos); + wedge.quaternion.copy(worldQuat); + const r = Math.random() * Math.PI * 2; + this.breakingWedges.push({ + mesh: wedge, + vx: Math.cos(r) * 0.4 * speedMultiplier, + vy: (Math.random() * 0.3 + 0.2) * speedMultiplier, + vz: Math.sin(r) * 0.4 * speedMultiplier + }); + }); + this.towerGroup.remove(pData.group); + } + + + + private onPointerDown(e: PointerEvent): void { + if (this.gameState !== 'PLAYING') return; + this.isDragging = true; + this.previousMouseX = e.clientX; + } + + private onPointerMove(e: PointerEvent): void { + if (!this.isDragging || this.gameState !== 'PLAYING') return; + const deltaX = e.clientX - this.previousMouseX; + this.towerGroup.rotation.y += deltaX * 0.01; + this.previousMouseX = e.clientX; + } + + private onPointerUp(): void { + this.isDragging = false; + } + + private triggerExplosion(): void { + if (this.explosionParticles) return; + + this.ball.visible = false; + this.gameState = 'LOSE'; + this.stopTimer(); + + const particleCount = 60; + const geometry = new THREE.BufferGeometry(); + const positions = new Float32Array(particleCount * 3); + this.explosionVelocities = []; + + const ballColor = new THREE.Color(this.currentLevelConfig?.ballColor || 0xFF4081); + + for (let i = 0; i < particleCount; i++) { + positions[i * 3] = this.ball.position.x + (Math.random() - 0.5) * 0.5; + positions[i * 3 + 1] = this.ball.position.y + (Math.random() - 0.5) * 0.5; + positions[i * 3 + 2] = this.ball.position.z + (Math.random() - 0.5) * 0.5; + + this.explosionVelocities.push(new THREE.Vector3( + (Math.random() - 0.5) * 0.3, + (Math.random() - 0.5) * 0.3 + 0.2, + (Math.random() - 0.5) * 0.3 + )); + } + + geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3)); + + const material = new THREE.PointsMaterial({ + color: ballColor, + size: 0.3, + }); + + this.explosionParticles = new THREE.Points(geometry, material); + this.scene.add(this.explosionParticles); + + this.tools.playSound('sfx_8'); + } + + private animate = () => { + this.animationFrameId = requestAnimationFrame(this.animate); + if (this.tools.isWindowBlurred) return; + + if (this.gameState === 'PLAYING') { + this.ballVy += this.gravity; + this.ball.position.y += this.ballVy; + + this.ball.scale.x += (1 - this.ball.scale.x) * 0.1; + this.ball.scale.y += (1 - this.ball.scale.y) * 0.1; + this.ball.scale.z += (1 - this.ball.scale.z) * 0.1; + + // Pass-through fix + const lastPlatform = this.platformsData[this.platformsData.length - 1]; + if (lastPlatform && this.ball.position.y < lastPlatform.y - this.platformThickness) { + this.ngZone.run(() => { + this.gamePoints += 50; + this.gameState = 'WIN'; + this.stopTimer(); + this.tools.playSound('sfx_4'); + }); + return; + } + + const pData = this.platformsData[this.currentPlatformIndex]; + if (pData) { + let didHit = false; + const platformTopY = pData.y + this.platformThickness / 2; + + if (!pData.broken && this.ballVy < 0 && this.ball.position.y - this.ballRadius <= platformTopY) { + const rayPos = new THREE.Vector3(this.ball.position.x, platformTopY + 1.0, this.ball.position.z); + this.raycaster.set(rayPos, this.downVector); + const intersects = this.raycaster.intersectObjects(pData.group.children); + + if (intersects.length > 0) { + didHit = true; + const hit = intersects[0].object; + + if (this.consecutiveHoles >= 3) { + this.consecutiveHoles = 0; + this.ngZone.run(() => { + this.gamePoints += 20; + this.levelPoints += 20; + this.tools.playSound('sfx_1'); + }); + + this.breakFloor(pData, true); + } else { + this.consecutiveHoles = 0; + if (hit.userData['isDanger']) { + this.ngZone.run(() => { + this.triggerExplosion(); + }); + } else if (hit.userData['isWin']) { + this.ngZone.run(() => { + this.gamePoints += 50; + this.levelPoints += 50; + this.gameState = 'WIN'; + this.stopTimer(); + this.tools.playSound('sfx_4'); + }); + } else { + this.ball.position.y = platformTopY + this.ballRadius; + this.ballVy = this.bounceVelocity; + this.ball.scale.set(1.3, 0.7, 1.3); + this.tools.playSound('sfx_1'); + } + } + } + } + + if (!didHit && this.ball.position.y < pData.y - this.platformThickness) { + this.currentPlatformIndex++; + if (!pData.broken) { + this.consecutiveHoles++; + this.breakFloor(pData, false); + } + this.ngZone.run(() => { + this.gamePoints += 10; + this.levelPoints += 10; + }); + } + } + + if (this.consecutiveHoles >= 3) { + const pGeo = new THREE.SphereGeometry(this.ballRadius * 0.6, 8, 8); + const pMat = new THREE.MeshBasicMaterial({ color: 0xFFFFFF, transparent: true, opacity: 0.7 }); + const p = new THREE.Mesh(pGeo, pMat); + p.position.copy(this.ball.position); + p.position.x += (Math.random() - 0.5) * 0.6; + p.position.z += (Math.random() - 0.5) * 0.6; + this.scene.add(p); + this.chargeTrail.push(p); + } + + for(let i = this.chargeTrail.length - 1; i >= 0; i--) { + const p = this.chargeTrail[i]; + p.scale.multiplyScalar(0.85); + p.position.y += 0.1; + (p.material as THREE.MeshBasicMaterial).opacity -= 0.05; + if (p.scale.x < 0.1 || (p.material as THREE.MeshBasicMaterial).opacity <= 0) { + this.scene.remove(p); + p.geometry.dispose(); + (p.material as THREE.Material).dispose(); + this.chargeTrail.splice(i, 1); + } + } + + for(let i = this.breakingWedges.length - 1; i >= 0; i--) { + const bw = this.breakingWedges[i]; + bw.vy += this.gravity; + bw.mesh.position.x += bw.vx; + bw.mesh.position.y += bw.vy; + bw.mesh.position.z += bw.vz; + bw.mesh.rotation.x += 0.1; + bw.mesh.rotation.z += 0.1; + if (bw.mesh.position.y < this.camera.position.y - 20) { + this.scene.remove(bw.mesh); + bw.mesh.geometry.dispose(); + (bw.mesh.material as THREE.Material).dispose(); + this.breakingWedges.splice(i, 1); + } + } + + this.camera.position.y += (this.ball.position.y + 3 - this.camera.position.y) * 0.1; + this.camera.lookAt(0, this.ball.position.y - 1, 0); + } + + if (this.explosionParticles) { + const positions = this.explosionParticles.geometry.attributes['position'].array as Float32Array; + for (let i = 0; i < this.explosionVelocities.length; i++) { + this.explosionVelocities[i].y += this.gravity; + positions[i * 3] += this.explosionVelocities[i].x; + positions[i * 3 + 1] += this.explosionVelocities[i].y; + positions[i * 3 + 2] += this.explosionVelocities[i].z; + } + this.explosionParticles.geometry.attributes['position'].needsUpdate = true; + } + + if (this.renderer && this.scene && this.camera) { + this.renderer.render(this.scene, this.camera); + } + } + + private onResize(): void { + if (!this.camera || !this.renderer) return; + const container = this.gameContainer.nativeElement; + const width = container.clientWidth || window.innerWidth; + const height = container.clientHeight || window.innerHeight; + this.camera.aspect = width / height; + this.camera.updateProjectionMatrix(); + this.renderer.setSize(width, height); + } + + private stopLoop(): void { + if (this.animationFrameId !== null) { + cancelAnimationFrame(this.animationFrameId); + this.animationFrameId = null; + } + } +} diff --git a/src/app/games/magic_sort/magic_sort.component.css b/src/app/games/magic_sort/magic_sort.component.css new file mode 100644 index 0000000..3e7a514 --- /dev/null +++ b/src/app/games/magic_sort/magic_sort.component.css @@ -0,0 +1,189 @@ +:host { + display: block; + width: 100vw; + height: calc(100vh - 70px); + --bg-top: #1a0b2e; + --bg-bottom: #3b1763; + --tube-bg: rgba(255, 255, 255, 0.1); + --tube-border: rgba(255, 255, 255, 0.5); + background: radial-gradient(circle at top, var(--bg-top), var(--bg-bottom)); + color: white; + user-select: none; + touch-action: manipulation; + overflow: hidden; +} + +.magic-sort-wrapper { + width: 100%; + height: 100%; + display: flex; + flex-direction: column; + align-items: center; + position: relative; + z-index: 10; +} + +.hud { + width: 100%; + max-width: 500px; + display: flex; + justify-content: space-between; + align-items: center; + padding: 20px; + box-sizing: border-box; + z-index: 10; + gap: 15px; + flex-wrap: wrap; +} + +h1 { + margin: 0; + font-size: 2em; + text-transform: uppercase; + letter-spacing: 2px; + text-shadow: 0 0 10px rgba(255,255,255,0.5); + text-align: center; +} + +.level-text { + font-size: 1.5em; + font-weight: bold; + color: #FFEB3B; + text-shadow: 0 0 10px rgba(255, 235, 59, 0.5); +} + +.controls { + display: flex; + gap: 10px; +} + +.btn { + background: #9C27B0; + color: white; + border: 2px solid #E1BEE7; + padding: 10px 20px; + border-radius: 20px; + font-size: 1.1em; + font-weight: bold; + cursor: pointer; + box-shadow: 0 4px 10px rgba(156, 39, 176, 0.5); + transition: transform 0.1s, background 0.2s; +} +.btn:active { transform: scale(0.95); } +.btn:hover { background: #7B1FA2; } + +.big-btn { + font-size: 1.5em; + padding: 15px 40px; +} + +/* Game Area */ +#game-board { + flex: 1; + width: 100%; + max-width: 500px; + display: flex; + flex-wrap: wrap; + justify-content: center; + align-items: center; + align-content: center; + gap: 15px; + padding: 20px; + box-sizing: border-box; +} + +/* Tubes */ +.tube-wrapper { + position: relative; + width: 60px; + height: 200px; + cursor: pointer; + transition: transform 0.2s ease-in-out; +} + +.tube-wrapper.selected { + transform: translateY(-20px); +} + +.tube { + width: 100%; + height: 100%; + background: var(--tube-bg); + border: 3px solid var(--tube-border); + border-top: none; + border-bottom-left-radius: 30px; + border-bottom-right-radius: 30px; + display: flex; + flex-direction: column-reverse; /* Stack from bottom to top */ + overflow: hidden; + box-sizing: border-box; + box-shadow: inset 0 0 15px rgba(255,255,255,0.2), 0 10px 20px rgba(0,0,0,0.4); +} + +/* The lip of the tube */ +.tube::before { + content: ''; + position: absolute; + top: -5px; + left: -5px; + right: -5px; + height: 10px; + border: 3px solid var(--tube-border); + border-radius: 10px; + background: rgba(255,255,255,0.1); +} + +/* Liquid Segments */ +.segment { + width: 100%; + height: 25%; /* 4 segments max per tube */ + transition: height 0.3s ease-in-out; + box-shadow: inset 0 2px 5px rgba(255,255,255,0.3); +} + +/* Screens */ +.screen { + position: absolute; + top: 0; left: 0; width: 100%; height: 100%; + background: rgba(26, 11, 46, 0.9); + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + z-index: 100; + backdrop-filter: blur(5px); +} + +.hidden { display: none !important; } + +.screen h2 { + font-size: 3em; + color: #FFEB3B; + margin-bottom: 20px; + text-shadow: 0 0 20px rgba(255, 235, 59, 0.8); + text-align: center; +} + +.screen p { + font-size: 1.5em; + color: #ddd; + margin-bottom: 30px; + text-align: center; + font-weight: bold; + padding: 0 20px; +} + +/* Particles Background */ +::ng-deep .star { + position: absolute; + background: white; + border-radius: 50%; + animation: twinkle infinite ease-in-out; + z-index: 1; /* behind wrapper */ + pointer-events: none; +} + +@keyframes twinkle { + 0%, 100% { opacity: 0.2; transform: scale(0.8); } + 50% { opacity: 1; transform: scale(1.2); } +} diff --git a/src/app/games/magic_sort/magic_sort.component.html b/src/app/games/magic_sort/magic_sort.component.html new file mode 100644 index 0000000..1038b75 --- /dev/null +++ b/src/app/games/magic_sort/magic_sort.component.html @@ -0,0 +1,38 @@ + +
+
+
{{tools.magic_sort[tools.lang]?.levelPrefix || 'LEVEL '}} {{level}}
+
+ +
+
+ +
+ @for (tube of tubes; track $index) { +
+
+ @for (color of tube; track $index) { +
+ } +
+
+ } +
+ + @if (gameState === 'START') { +
+

{{tools.magic_sort[tools.lang]?.title || 'Magic Sort'}}

+

{{tools.magic_sort[tools.lang]?.instructions || 'Pour colored liquids between bottles until each is one color!'}}

+ +
+ } + + +
+

{{tools.magic_sort[tools.lang]?.levelCleared || 'MAGIC SORTED!'}}

+ +
+
diff --git a/src/app/games/magic_sort/magic_sort.component.ts b/src/app/games/magic_sort/magic_sort.component.ts new file mode 100644 index 0000000..0946092 --- /dev/null +++ b/src/app/games/magic_sort/magic_sort.component.ts @@ -0,0 +1,205 @@ +import { Component, OnInit, OnDestroy, AfterViewInit, inject, Renderer2, ElementRef } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { ToolsService } from '../../services/tools.service'; + +@Component({ + selector: 'app-magic-sort', + standalone: true, + imports: [CommonModule], + templateUrl: './magic_sort.component.html', + styleUrl: './magic_sort.component.css' +}) +export class MagicSortComponent implements OnInit, AfterViewInit, OnDestroy { + tools: ToolsService = inject(ToolsService); + private renderer: Renderer2 = inject(Renderer2); + private elRef: ElementRef = inject(ElementRef); + + gameState: 'START' | 'PLAYING' | 'WIN' = 'START'; + level = 0; + + tubes: string[][] = []; + selectedTubeIndex: number | null = null; + private initialTubesState: string[][] = []; + private TUBE_CAPACITY = 4; + private COLORS = [ + '#F44336', // Red + '#2196F3', // Blue + '#4CAF50', // Green + '#FFEB3B', // Yellow + '#9C27B0', // Purple + '#FF9800', // Orange + '#00BCD4', // Cyan + '#E91E63' // Pink + ]; + + private stars: any[] = []; + + ngOnInit(): void { + this.tools.setTitle("magic_sort" as any); + this.tools.actPage = "magic_sort" as any; + } + + ngAfterViewInit(): void { + this.createStars(); + this.startLevel(); // Set initial UI states + this.gameState = 'START'; + } + + ngOnDestroy(): void { + // Remove stars from body/host + this.stars.forEach(star => { + if (star.parentNode) { + this.renderer.removeChild(star.parentNode, star); + } + }); + this.tools.leaveMinigame('magic_sort', this.tools.sessionPoints); + } + + private createStars(): void { + for (let i = 0; i < 50; i++) { + let star = this.renderer.createElement('div'); + this.renderer.addClass(star, 'star'); + const size = Math.random() * 4 + 1; + this.renderer.setStyle(star, 'width', `${size}px`); + this.renderer.setStyle(star, 'height', `${size}px`); + this.renderer.setStyle(star, 'left', `${Math.random() * 100}vw`); + this.renderer.setStyle(star, 'top', `${Math.random() * 100}vh`); + this.renderer.setStyle(star, 'animationDuration', `${Math.random() * 2 + 1}s`); + this.renderer.setStyle(star, 'animationDelay', `${Math.random() * 2}s`); + this.renderer.appendChild(this.elRef.nativeElement, star); + this.stars.push(star); + } + } + + startLevel(): void { + this.gameState = 'PLAYING'; + this.generateLevel(this.level); + } + + nextLevel(): void { + this.level++; + this.tools.sessionPoints += 10; // Award points for completing the level + this.tools.playSound('sfx_3'); // Win sound + this.startLevel(); + } + + restartLevel(): void { + this.tubes = JSON.parse(JSON.stringify(this.initialTubesState)); + this.selectedTubeIndex = null; + this.gameState = 'PLAYING'; + } + + onTubeClick(index: number): void { + if (this.gameState !== 'PLAYING') return; + + if (this.selectedTubeIndex === null) { + if (this.tubes[index].length > 0 && !this.isTubeComplete(index)) { + this.selectedTubeIndex = index; + this.tools.playSound('sfx_1'); + } + } else if (this.selectedTubeIndex === index) { + this.selectedTubeIndex = null; + } else { + if (this.canPour(this.selectedTubeIndex, index)) { + this.pour(this.selectedTubeIndex, index); + this.selectedTubeIndex = null; + this.tools.playSound('sfx_1'); // Pouring sound + this.checkWinCondition(); + } else { + if (this.tubes[index].length > 0 && !this.isTubeComplete(index)) { + this.selectedTubeIndex = index; + this.tools.playSound('sfx_1'); + } else { + this.selectedTubeIndex = null; + this.tools.playSound('sfx_8'); // Error sound + } + } + } + } + + private generateLevel(lvl: number): void { + const numColors = Math.min(3 + Math.floor(lvl / 3), this.COLORS.length); + const numEmpty = 2; + const totalTubes = numColors + numEmpty; + + let colorPool: string[] = []; + for (let i = 0; i < numColors; i++) { + for (let j = 0; j < this.TUBE_CAPACITY; j++) { + colorPool.push(this.COLORS[i]); + } + } + + for (let i = colorPool.length - 1; i > 0; i--) { + const j = Math.floor(Math.random() * (i + 1)); + [colorPool[i], colorPool[j]] = [colorPool[j], colorPool[i]]; + } + + this.tubes = []; + let poolIndex = 0; + + for (let i = 0; i < numColors; i++) { + let tube: string[] = []; + for (let j = 0; j < this.TUBE_CAPACITY; j++) { + tube.push(colorPool[poolIndex++]); + } + this.tubes.push(tube); + } + + for (let i = 0; i < numEmpty; i++) { + this.tubes.push([]); + } + + this.initialTubesState = JSON.parse(JSON.stringify(this.tubes)); + this.selectedTubeIndex = null; + } + + private isTubeComplete(index: number): boolean { + const tube = this.tubes[index]; + if (tube.length !== this.TUBE_CAPACITY) return false; + const firstColor = tube[0]; + return tube.every(color => color === firstColor); + } + + private canPour(srcIdx: number, tgtIdx: number): boolean { + const srcTube = this.tubes[srcIdx]; + const tgtTube = this.tubes[tgtIdx]; + + if (srcTube.length === 0 || tgtTube.length === this.TUBE_CAPACITY) return false; + if (tgtTube.length === 0) return true; + + const srcTopColor = srcTube[srcTube.length - 1]; + const tgtTopColor = tgtTube[tgtTube.length - 1]; + + return srcTopColor === tgtTopColor; + } + + private pour(srcIdx: number, tgtIdx: number): void { + const srcTube = this.tubes[srcIdx]; + const tgtTube = this.tubes[tgtIdx]; + const colorToMove = srcTube[srcTube.length - 1]; + + let blocksToMove = 0; + for (let i = srcTube.length - 1; i >= 0; i--) { + if (srcTube[i] === colorToMove) blocksToMove++; + else break; + } + + const availableSpace = this.TUBE_CAPACITY - tgtTube.length; + const actualMoves = Math.min(blocksToMove, availableSpace); + + for (let i = 0; i < actualMoves; i++) { + const popped = srcTube.pop(); + if (popped) tgtTube.push(popped); + } + } + + private checkWinCondition(): void { + const isWon = this.tubes.every((t, i) => t.length === 0 || this.isTubeComplete(i)); + + if (isWon) { + setTimeout(() => { + this.gameState = 'WIN'; + }, 300); + } + } +} diff --git a/src/app/games/mob_control/mob_control.component.css b/src/app/games/mob_control/mob_control.component.css new file mode 100644 index 0000000..d265768 --- /dev/null +++ b/src/app/games/mob_control/mob_control.component.css @@ -0,0 +1,109 @@ +.mob-control-wrapper { + position: relative; + width: 100vw; + height: 100vh; + background-color: #2b2b2b; + color: #ffffff; + font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + user-select: none; + overflow: hidden; + touch-action: none; +} + +#game-container { + position: relative; + width: 100%; + max-width: 500px; + aspect-ratio: 2 / 3; + background: #444; + border-radius: 12px; + box-shadow: 0 10px 30px rgba(0,0,0,0.8); + overflow: hidden; +} + +canvas { + display: block; + width: 100%; + height: 100%; + background-color: #1e1e1e; + cursor: ew-resize; +} + +.ui-layer { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + pointer-events: none; + display: flex; + flex-direction: column; + justify-content: space-between; + z-index: 10; +} + +.hud { + display: flex; + justify-content: space-between; + padding: 15px 20px; + font-size: 1.5em; + font-weight: bold; + color: #fff; + background: linear-gradient(180deg, rgba(0,0,0,0.6) 0%, transparent 100%); +} + +.screen { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(0,0,0,0.75); + backdrop-filter: blur(5px); + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + pointer-events: auto; + z-index: 20; +} + +.screen h1 { + font-size: 2.8em; + color: #4CAF50; + margin-bottom: 15px; + text-align: center; +} + +.screen p { + font-size: 1.2em; + color: #ddd; + margin-bottom: 25px; + text-align: center; + max-width: 80%; +} + +.btn { + padding: 12px 35px; + font-size: 1.3em; + font-weight: bold; + color: #fff; + background: linear-gradient(135deg, #4CAF50, #2E7D32); + border: none; + border-radius: 50px; + cursor: pointer; + box-shadow: 0 4px 15px rgba(0,0,0,0.3); + transition: transform 0.1s; +} + +.btn:hover { + transform: scale(1.05); +} + +.btn:active { + transform: scale(0.95); +} diff --git a/src/app/games/mob_control/mob_control.component.html b/src/app/games/mob_control/mob_control.component.html new file mode 100644 index 0000000..3a3804c --- /dev/null +++ b/src/app/games/mob_control/mob_control.component.html @@ -0,0 +1,36 @@ +
+
+ + +
+
+
{{tools.mob_control[tools.lang]?.level || 'Level '}} {{level}}
+
🪙 {{gamePoints}}
+
+
+ + @if (gameState === 'START') { +
+

{{tools.mob_control[tools.lang]?.mob_control_title || 'Mob Control'}}

+

{{tools.mob_control[tools.lang]?.mob_control_inst || 'Shoot and multiply your mob to overwhelm the enemy!'}}

+ +
+ } + + @if (gameState === 'WIN') { +
+

{{tools.mob_control[tools.lang]?.victory || 'Victory!'}}

+

{{tools.mob_control[tools.lang]?.score || 'Score: '}} {{gamePoints}}

+ +
+ } + + @if (gameState === 'LOSE') { +
+

{{tools.mob_control[tools.lang]?.gameOver || 'Game Over'}}

+

{{tools.mob_control[tools.lang]?.score || 'Score: '}} {{gamePoints}}

+ +
+ } +
+
diff --git a/src/app/games/mob_control/mob_control.component.ts b/src/app/games/mob_control/mob_control.component.ts new file mode 100644 index 0000000..be0af86 --- /dev/null +++ b/src/app/games/mob_control/mob_control.component.ts @@ -0,0 +1,328 @@ +import { Component, OnInit, OnDestroy, AfterViewInit, ViewChild, ElementRef, inject, NgZone } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { ToolsService } from '../../services/tools.service'; + +interface Unit { + x: number; + y: number; + vx: number; + vy: number; + radius: number; + color: string; + isEnemy: boolean; + multiplied?: boolean; +} + +interface Gate { + x: number; + y: number; + width: number; + height: number; + multiplier: number; + color: string; +} + +@Component({ + selector: 'app-mob-control', + standalone: true, + imports: [CommonModule], + templateUrl: './mob_control.component.html', + styleUrl: './mob_control.component.css' +}) +export class MobControlComponent implements OnInit, AfterViewInit, OnDestroy { + tools: ToolsService = inject(ToolsService); + private ngZone: NgZone = inject(NgZone); + + @ViewChild('gameContainer') gameContainer!: ElementRef; + @ViewChild('canvas') canvasRef!: ElementRef; + + gameState: 'START' | 'PLAYING' | 'WIN' | 'LOSE' = 'START'; + gamePoints = 0; + level = 0; + + private cannonX = 200; + private units: Unit[] = []; + private gates: Gate[] = []; + private enemyBaseHp = 100; + private maxEnemyBaseHp = 100; + private spawnCooldown = 0; + private enemySpawnCooldown = 0; + private animationFrameId: number | null = null; + private isPointerDown = false; + private pointerX = 200; + + private onPointerDownBound = this.onPointerDown.bind(this); + private onPointerMoveBound = this.onPointerMove.bind(this); + private onPointerUpBound = this.onPointerUp.bind(this); + private onResizeBound = this.onResize.bind(this); + + ngOnInit(): void { + this.tools.setTitle("mob_control" as any); + this.tools.actPage = "mob_control" as any; + } + + ngAfterViewInit(): void { + this.initGame(); + } + + ngOnDestroy(): void { + this.stopLoop(); + window.removeEventListener('resize', this.onResizeBound); + window.removeEventListener('pointerup', this.onPointerUpBound); + const canvas = this.canvasRef?.nativeElement; + if (canvas) { + canvas.removeEventListener('pointerdown', this.onPointerDownBound); + canvas.removeEventListener('pointermove', this.onPointerMoveBound); + } + this.tools.leaveMinigame('mob_control', this.gamePoints, this.level); + } + + startLevel(): void { + this.gamePoints = 0; + this.gameState = 'PLAYING'; + this.resetLevel(); + } + + nextLevel(): void { + this.level++; + this.gameState = 'PLAYING'; + this.resetLevel(); + } + + private initGame(): void { + const canvas = this.canvasRef.nativeElement; + const container = this.gameContainer.nativeElement; + canvas.width = container.clientWidth || 400; + canvas.height = container.clientHeight || 600; + + canvas.addEventListener('pointerdown', this.onPointerDownBound); + canvas.addEventListener('pointermove', this.onPointerMoveBound); + window.addEventListener('pointerup', this.onPointerUpBound); + window.addEventListener('resize', this.onResizeBound); + + this.ngZone.runOutsideAngular(() => { + this.loop(); + }); + } + + private resetLevel(): void { + const canvas = this.canvasRef.nativeElement; + this.units = []; + this.gates = []; + this.cannonX = canvas.width / 2; + this.maxEnemyBaseHp = 80 + this.level * 30; + this.enemyBaseHp = this.maxEnemyBaseHp; + + const mult1 = Math.floor(Math.random() * 2) + 2; + const mult2 = Math.floor(Math.random() * 3) + 2; + this.gates.push({ + x: canvas.width * 0.25, + y: canvas.height * 0.5, + width: canvas.width * 0.4, + height: 25, + multiplier: mult1, + color: '#2196F3' + }); + this.gates.push({ + x: canvas.width * 0.75, + y: canvas.height * 0.5, + width: canvas.width * 0.4, + height: 25, + multiplier: mult2, + color: '#4CAF50' + }); + } + + private onPointerDown(e: PointerEvent): void { + if (this.gameState !== 'PLAYING') return; + this.isPointerDown = true; + const rect = this.canvasRef.nativeElement.getBoundingClientRect(); + this.pointerX = e.clientX - rect.left; + } + + private onPointerMove(e: PointerEvent): void { + if (this.gameState !== 'PLAYING') return; + const rect = this.canvasRef.nativeElement.getBoundingClientRect(); + this.pointerX = e.clientX - rect.left; + } + + private onPointerUp(): void { + this.isPointerDown = false; + } + + private loop(): void { + this.animationFrameId = requestAnimationFrame(() => this.loop()); + if (this.tools.isWindowBlurred) return; + + if (this.gameState === 'PLAYING') { + const canvas = this.canvasRef.nativeElement; + + this.cannonX += (this.pointerX - this.cannonX) * 0.2; + this.cannonX = Math.max(30, Math.min(canvas.width - 30, this.cannonX)); + + if (this.isPointerDown) { + this.spawnCooldown--; + if (this.spawnCooldown <= 0) { + this.units.push({ + x: this.cannonX, + y: canvas.height - 50, + vx: (Math.random() - 0.5) * 1.5, + vy: -5, + radius: 8, + color: '#00E5FF', + isEnemy: false + }); + this.spawnCooldown = 8; + this.tools.playSound('sfx_1'); + } + } + + this.enemySpawnCooldown--; + if (this.enemySpawnCooldown <= 0) { + this.units.push({ + x: 40 + Math.random() * (canvas.width - 80), + y: 70, + vx: (Math.random() - 0.5) * 1, + vy: 2.2 + this.level * 0.2, + radius: 10, + color: '#FF5252', + isEnemy: true + }); + this.enemySpawnCooldown = 35 - Math.min(20, this.level * 2); + } + + for (let i = this.units.length - 1; i >= 0; i--) { + const u = this.units[i]; + u.x += u.vx; + u.y += u.vy; + + if (u.x - u.radius < 0 || u.x + u.radius > canvas.width) { + u.vx *= -1; + } + + if (!u.isEnemy) { + this.gates.forEach(g => { + if (u.y - u.radius <= g.y + g.height / 2 && u.y + u.radius >= g.y - g.height / 2 && + u.x >= g.x - g.width / 2 && u.x <= g.x + g.width / 2 && !u.multiplied) { + u.multiplied = true; + for (let m = 1; m < g.multiplier; m++) { + this.units.push({ + x: u.x + (Math.random() - 0.5) * 20, + y: u.y + (Math.random() - 0.5) * 10, + vx: u.vx + (Math.random() - 0.5) * 2, + vy: u.vy, + radius: 8, + color: '#00E5FF', + isEnemy: false, + multiplied: true + }); + } + } + }); + + if (u.y < 45) { + this.enemyBaseHp -= 2; + this.ngZone.run(() => { + this.gamePoints += 2; + }); + this.units.splice(i, 1); + if (this.enemyBaseHp <= 0) { + this.ngZone.run(() => { + this.gamePoints += 50; + this.gameState = 'WIN'; + this.tools.playSound('sfx_4'); + }); + } + continue; + } + } else { + if (u.y > canvas.height - 30) { + this.ngZone.run(() => { + this.gameState = 'LOSE'; + this.tools.playSound('sfx_8'); + }); + break; + } + } + + for (let j = i - 1; j >= 0; j--) { + const u2 = this.units[j]; + if (u.isEnemy !== u2.isEnemy) { + const dist = Math.hypot(u.x - u2.x, u.y - u2.y); + if (dist < u.radius + u2.radius) { + this.units.splice(i, 1); + this.units.splice(j, 1); + if (!u.isEnemy || !u2.isEnemy) { + this.ngZone.run(() => { + this.gamePoints += 5; + }); + } + break; + } + } + } + } + } + + this.draw(); + } + + private draw(): void { + const canvas = this.canvasRef?.nativeElement; + if (!canvas) return; + const ctx = canvas.getContext('2d'); + if (!ctx) return; + + ctx.clearRect(0, 0, canvas.width, canvas.height); + + ctx.fillStyle = '#D32F2F'; + ctx.fillRect(20, 10, canvas.width - 40, 30); + ctx.fillStyle = '#4CAF50'; + const hpWidth = Math.max(0, ((canvas.width - 40) * this.enemyBaseHp) / this.maxEnemyBaseHp); + ctx.fillRect(20, 10, hpWidth, 30); + ctx.strokeStyle = '#fff'; + ctx.lineWidth = 2; + ctx.strokeRect(20, 10, canvas.width - 40, 30); + + this.gates.forEach(g => { + ctx.fillStyle = g.color; + ctx.fillRect(g.x - g.width / 2, g.y - g.height / 2, g.width, g.height); + ctx.fillStyle = '#fff'; + ctx.font = 'bold 16px sans-serif'; + ctx.textAlign = 'center'; + ctx.textBaseline = 'middle'; + ctx.fillText(`x${g.multiplier}`, g.x, g.y); + }); + + ctx.fillStyle = '#607D8B'; + ctx.fillRect(this.cannonX - 20, canvas.height - 35, 40, 25); + ctx.fillStyle = '#CFD8DC'; + ctx.fillRect(this.cannonX - 8, canvas.height - 45, 16, 15); + + this.units.forEach(u => { + ctx.fillStyle = u.color; + ctx.beginPath(); + ctx.arc(u.x, u.y, u.radius, 0, Math.PI * 2); + ctx.fill(); + ctx.lineWidth = 1.5; + ctx.strokeStyle = '#fff'; + ctx.stroke(); + }); + } + + private onResize(): void { + const canvas = this.canvasRef?.nativeElement; + const container = this.gameContainer?.nativeElement; + if (canvas && container) { + canvas.width = container.clientWidth || 400; + canvas.height = container.clientHeight || 600; + } + } + + private stopLoop(): void { + if (this.animationFrameId !== null) { + cancelAnimationFrame(this.animationFrameId); + this.animationFrameId = null; + } + } +} diff --git a/src/app/games/paper_io/paper_io.component.css b/src/app/games/paper_io/paper_io.component.css new file mode 100644 index 0000000..09bd99d --- /dev/null +++ b/src/app/games/paper_io/paper_io.component.css @@ -0,0 +1,121 @@ +.paper-io-wrapper { + position: relative; + width: 100vw; + height: 100vh; + background-color: #f0f4f8; + overflow: hidden; + font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; + user-select: none; + touch-action: none; +} + +#game-container { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; +} + +canvas { + display: block; + width: 100%; + height: 100%; +} + +.ui-layer { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + pointer-events: none; + display: flex; + flex-direction: column; + justify-content: space-between; + z-index: 10; +} + +.hud { + display: flex; + justify-content: space-between; + padding: 15px 25px; + font-size: 1.5em; + font-weight: bold; + color: #2c3e50; + background: linear-gradient(180deg, rgba(255,255,255,0.7) 0%, transparent 100%); +} + +.leaderboard { + position: absolute; + top: 70px; + right: 20px; + background: rgba(255, 255, 255, 0.9); + padding: 10px 15px; + border-radius: 8px; + box-shadow: 0 4px 10px rgba(0,0,0,0.15); + pointer-events: auto; + min-width: 160px; + max-height: 40vh; + overflow-y: auto; + font-weight: bold; + color: #2c3e50; +} + +.lb-entry { + display: flex; + justify-content: space-between; + margin-bottom: 5px; + font-size: 0.95em; +} + +.screen { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(0,0,0,0.75); + backdrop-filter: blur(5px); + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + pointer-events: auto; + z-index: 20; +} + +.screen h1 { + font-size: 3em; + color: #fff; + margin-bottom: 15px; + text-shadow: 0 0 10px rgba(255,255,255,0.3); +} + +.screen p { + font-size: 1.3em; + color: #ddd; + margin-bottom: 25px; + text-align: center; +} + +.btn { + padding: 14px 40px; + font-size: 1.4em; + font-weight: bold; + color: #fff; + background: linear-gradient(135deg, #2196F3, #1976D2); + border: none; + border-radius: 50px; + cursor: pointer; + box-shadow: 0 4px 15px rgba(0,0,0,0.3); + transition: transform 0.1s; +} + +.btn:hover { + transform: scale(1.05); +} + +.btn:active { + transform: scale(0.95); +} diff --git a/src/app/games/paper_io/paper_io.component.html b/src/app/games/paper_io/paper_io.component.html new file mode 100644 index 0000000..2e2e60f --- /dev/null +++ b/src/app/games/paper_io/paper_io.component.html @@ -0,0 +1,38 @@ +
+
+ +
+ +
+
+
{{tools.paper_io[tools.lang]?.score || 'Score: '}} {{gamePoints}}
+
+ + @if (gameState === 'PLAYING') { +
+ @for (entry of leaderboard; track $index) { +
+ {{entry.name}} + {{entry.pct}} +
+ } +
+ } +
+ + @if (gameState === 'START') { +
+

{{tools.paper_io[tools.lang]?.paper_io_title || 'Paper.io'}}

+

{{tools.paper_io[tools.lang]?.paper_io_inst || 'Conquer territory by enclosing loops and defeat opponents!'}}

+ +
+ } + + @if (gameState === 'GAMEOVER') { +
+

{{tools.paper_io[tools.lang]?.gameOver || 'Game Over'}}

+

{{tools.paper_io[tools.lang]?.score || 'Score: '}} {{gamePoints}}

+ +
+ } +
diff --git a/src/app/games/paper_io/paper_io.component.ts b/src/app/games/paper_io/paper_io.component.ts new file mode 100644 index 0000000..410ea41 --- /dev/null +++ b/src/app/games/paper_io/paper_io.component.ts @@ -0,0 +1,942 @@ +import { Component, OnInit, OnDestroy, AfterViewInit, ViewChild, ElementRef, inject, NgZone } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { ToolsService } from '../../services/tools.service'; + +interface BotTemplate { + id: string; + names: string[]; + spawnWithAreaMin: number; + spawnWithAreaMax: number; + behaviour: 'normal' | 'protective' | 'aggresive' | 'playerKiller' | 'chaotic'; + speed: number; +} + +interface Player { + id: number; + name: string; + color: string; + trailColor: string; + x: number; + y: number; + px: number; + py: number; + dir: number; + nextDir: number; + state: 'IDLE' | 'DRAWING'; + trail: { x: number; y: number }[]; + isDead: boolean; + scoreCount: number; + + speed: number; + tickAccumulator: number; + behaviour: 'player' | 'normal' | 'protective' | 'aggresive' | 'playerKiller' | 'chaotic'; + template?: BotTemplate; +} + +@Component({ + selector: 'app-paper-io', + standalone: true, + imports: [CommonModule], + templateUrl: './paper_io.component.html', + styleUrl: './paper_io.component.css' +}) +export class PaperIoComponent implements OnInit, AfterViewInit, OnDestroy { + tools: ToolsService = inject(ToolsService); + private ngZone: NgZone = inject(NgZone); + + @ViewChild('gameContainer') gameContainer!: ElementRef; + @ViewChild('canvas') canvasRef!: ElementRef; + + gameState: 'START' | 'PLAYING' | 'GAMEOVER' = 'START'; + gamePoints = 0; + leaderboard: Array<{ name: string; pct: string; color: string }> = []; + + private GRID_SIZE = 120; + private TILE_SIZE = 25; + private TICK_RATE = 70; + + private DIRS = [ + { x: 0, y: -1 }, // 0: UP + { x: 1, y: 0 }, // 1: RIGHT + { x: 0, y: 1 }, // 2: DOWN + { x: -1, y: 0 } // 3: LEFT + ]; + + private grid: number[][] = []; + private trailGrid: number[][] = []; + private players: Player[] = []; + private botTemplates: BotTemplate[] = []; + + private animationFrameId: number | null = null; + private lastTime = 0; + private accumulator = 0; + private botCounter = 0; + + private touchStartX = 0; + private touchStartY = 0; + + private onKeyDownBound = this.onKeyDown.bind(this); + private onResizeBound = this.onResize.bind(this); + private onTouchStartBound = this.onTouchStart.bind(this); + private onTouchMoveBound = this.onTouchMove.bind(this); + private onTouchEndBound = this.onTouchEnd.bind(this); + + ngOnInit(): void { + this.tools.setTitle("paper_io" as any); + this.tools.actPage = "paper_io" as any; + } + + async ngAfterViewInit(): Promise { + const canvas = this.canvasRef.nativeElement; + const container = this.gameContainer.nativeElement; + canvas.width = container.clientWidth || window.innerWidth; + canvas.height = container.clientHeight || window.innerHeight; + + window.addEventListener('keydown', this.onKeyDownBound, { passive: false }); + window.addEventListener('resize', this.onResizeBound); + canvas.addEventListener('touchstart', this.onTouchStartBound, { passive: true }); + canvas.addEventListener('touchmove', this.onTouchMoveBound, { passive: false }); + canvas.addEventListener('touchend', this.onTouchEndBound, { passive: true }); + + await this.loadData(); + } + + ngOnDestroy(): void { + this.stopLoop(); + window.removeEventListener('keydown', this.onKeyDownBound); + window.removeEventListener('resize', this.onResizeBound); + const canvas = this.canvasRef?.nativeElement; + if (canvas) { + canvas.removeEventListener('touchstart', this.onTouchStartBound); + canvas.removeEventListener('touchmove', this.onTouchMoveBound); + canvas.removeEventListener('touchend', this.onTouchEndBound); + } + this.tools.leaveMinigame('paper_io', this.tools.sessionPoints); + } + + async loadData(): Promise { + try { + let res = await fetch('games/paper_io/data/bots.json'); + if (!res.ok) res = await fetch('/games/paper_io/data/bots.json'); + this.botTemplates = await res.json(); + } catch (err) { + console.error("Error loading bots.json, using defaults", err); + this.botTemplates = [ + { id: 'default', names: ['Bot'], spawnWithAreaMin: 0.1, spawnWithAreaMax: 70, behaviour: 'normal', speed: 1 } + ]; + } + } + + startGame(): void { + this.gamePoints = 0; + this.gameState = 'PLAYING'; + + this.grid = new Array(this.GRID_SIZE).fill(0).map(() => new Array(this.GRID_SIZE).fill(-1)); + this.trailGrid = new Array(this.GRID_SIZE).fill(0).map(() => new Array(this.GRID_SIZE).fill(-1)); + this.players = []; + this.botCounter = 0; + + let sx = Math.floor(Math.random() * (this.GRID_SIZE - 40)) + 20; + let sy = Math.floor(Math.random() * (this.GRID_SIZE - 40)) + 20; + + this.players.push({ + id: 0, + name: 'You', + color: '#FF4081', + trailColor: 'rgba(255, 64, 129, 0.4)', + x: sx, y: sy, + px: sx, py: sy, + dir: 1, nextDir: 1, + state: 'IDLE', + trail: [], + isDead: false, + scoreCount: 9, + speed: 1, + tickAccumulator: 0, + behaviour: 'player' + }); + + for(let dx = -1; dx <= 1; dx++) { + for(let dy = -1; dy <= 1; dy++) { + this.grid[sx+dx][sy+dy] = 0; + } + } + + for (let i = 1; i <= 14; i++) { + let bot = { id: i, isDead: true, scoreCount: 0 } as any; + this.players.push(bot); + this.reviveBot(bot); + } + + this.lastTime = performance.now(); + this.accumulator = 0; + + this.ngZone.runOutsideAngular(() => { + this.loop(performance.now()); + }); + } + + private reviveBot(bot: Player): void { + if (this.botTemplates.length === 0) return; + + let template = this.botTemplates[Math.floor(Math.random() * this.botTemplates.length)]; + let sx = 0, sy = 0, radius = 0; + let attempts = 0; + let found = false; + let human = this.players[0]; + + while(attempts < 100) { + let pct = Math.random() * (template.spawnWithAreaMax - template.spawnWithAreaMin) + template.spawnWithAreaMin; + let targetArea = (this.GRID_SIZE * this.GRID_SIZE) * (pct / 100); + radius = Math.floor(Math.sqrt(targetArea) / 2); + + let maxBound = Math.max(0, this.GRID_SIZE - radius * 2); + sx = Math.floor(Math.random() * maxBound) + radius; + sy = Math.floor(Math.random() * maxBound) + radius; + + let safe = true; + + if (!human.isDead) { + let distToHuman = Math.hypot(sx - human.x, sy - human.y); + if (distToHuman < radius + 40) { + safe = false; + } + } + + if (safe) { + for (let i = 0; i < this.players.length; i++) { + let p = this.players[i]; + if (!p.isDead && p.x >= sx - radius && p.x <= sx + radius && p.y >= sy - radius && p.y <= sy + radius) { + safe = false; + break; + } + } + } + + if (safe) { + for(let dx = -radius; dx <= radius; dx++) { + for(let dy = -radius; dy <= radius; dy++) { + let nx = sx + dx, ny = sy + dy; + if(nx >= 0 && nx < this.GRID_SIZE && ny >= 0 && ny < this.GRID_SIZE) { + if(this.trailGrid[nx][ny] !== -1) { + safe = false; + break; + } + } + } + if(!safe) break; + } + } + + if (safe) { + found = true; + break; + } + attempts++; + } + + if (!found) return; + + this.botCounter++; + let hue = Math.floor(Math.random() * 360); + + let randomName = template.names[Math.floor(Math.random() * template.names.length)] || "Bot"; + bot.name = `${randomName} ${this.botCounter}`; + bot.color = `hsl(${hue}, 70%, 50%)`; + bot.trailColor = `hsla(${hue}, 70%, 50%, 0.4)`; + bot.x = sx; bot.y = sy; + bot.px = sx; bot.py = sy; + bot.dir = Math.floor(Math.random() * 4); + bot.nextDir = bot.dir; + bot.state = 'IDLE'; + bot.trail = []; + bot.isDead = false; + bot.scoreCount = 0; + bot.speed = template.speed; + bot.behaviour = template.behaviour; + bot.template = template; + bot.tickAccumulator = 0; + + for(let dx = -radius; dx <= radius; dx++) { + for(let dy = -radius; dy <= radius; dy++) { + let nx = sx + dx, ny = sy + dy; + if(nx >= 0 && nx < this.GRID_SIZE && ny >= 0 && ny < this.GRID_SIZE) { + this.grid[nx][ny] = bot.id; + bot.scoreCount++; + } + } + } + + this.players.forEach(p => { + if(p.id !== bot.id && !p.isDead) { + let count = 0; + for (let x = 0; x < this.GRID_SIZE; x++) { + for (let y = 0; y < this.GRID_SIZE; y++) { + if (this.grid[x][y] === p.id) count++; + } + } + p.scoreCount = count; + } + }); + } + + private logicTickForPlayer(p: Player): void { + if(p.isDead) return; + + p.px = p.x; + p.py = p.y; + + if (Math.abs(p.dir - p.nextDir) !== 2) { + p.dir = p.nextDir; + } + + let nextX = p.x + this.DIRS[p.dir].x; + let nextY = p.y + this.DIRS[p.dir].y; + + if (nextX < 0 || nextX >= this.GRID_SIZE || nextY < 0 || nextY >= this.GRID_SIZE) { + let validTurns = [0, 1, 2, 3].filter(d => { + if (Math.abs(d - p.dir) === 2) return false; + let checkX = p.x + this.DIRS[d].x; + let checkY = p.y + this.DIRS[d].y; + return (checkX >= 0 && checkX < this.GRID_SIZE && checkY >= 0 && checkY < this.GRID_SIZE); + }); + + let safeTurns = validTurns.filter(d => { + let checkX = p.x + this.DIRS[d].x; + let checkY = p.y + this.DIRS[d].y; + return this.trailGrid[checkX][checkY] !== p.id; + }); + + let chosenTurns = safeTurns.length > 0 ? safeTurns : validTurns; + + if (chosenTurns.length > 0) { + p.dir = chosenTurns[Math.floor(Math.random() * chosenTurns.length)]; + p.nextDir = p.dir; + nextX = p.x + this.DIRS[p.dir].x; + nextY = p.y + this.DIRS[p.dir].y; + } else { + this.killPlayer(p.id); + return; + } + } + + p.x = nextX; + p.y = nextY; + + let hitTrailId = this.trailGrid[p.x][p.y]; + if (hitTrailId !== -1) { + this.killPlayer(hitTrailId, p.id); + if (hitTrailId === p.id) { + return; + } + } + + let currentTerritoryId = this.grid[p.x][p.y]; + + if (currentTerritoryId === p.id) { + if (p.state === 'DRAWING') { + this.closeLoop(p); + } + } else { + p.state = 'DRAWING'; + p.trail.push({x: p.x, y: p.y}); + this.trailGrid[p.x][p.y] = p.id; + } + + if (p.id !== 0 && !p.isDead) { + this.updateBotAI(p); + } + } + + private killPlayer(id: number, killerId?: number): void { + let p = this.players.find(p => p.id === id); + if(!p || p.isDead) return; + p.isDead = true; + + let validKiller = killerId !== undefined && killerId !== id; + let isTouching = false; + + if (validKiller) { + for (let x = 0; x < this.GRID_SIZE; x++) { + for (let y = 0; y < this.GRID_SIZE; y++) { + if (this.grid[x][y] === id) { + for (let d of this.DIRS) { + let nx = x + d.x, ny = y + d.y; + if (nx >= 0 && nx < this.GRID_SIZE && ny >= 0 && ny < this.GRID_SIZE) { + if (this.grid[nx][ny] === killerId) { + isTouching = true; + break; + } + } + } + } + if (isTouching) break; + } + if (isTouching) break; + } + } + + let shouldTransfer = validKiller && isTouching; + + for(let x=0; x kp.id === killerId); + if (killer && !killer.isDead) { + let count = 0; + for (let x = 0; x < this.GRID_SIZE; x++) { + for (let y = 0; y < this.GRID_SIZE; y++) { + if (this.grid[x][y] === killerId) count++; + } + } + killer.scoreCount = count; + + if (killer.id === 0) { + this.ngZone.run(() => { + this.gamePoints = killer!.scoreCount * 2; + }); + } + } + } + + if (id === 0) { + this.ngZone.run(() => { + this.tools.sessionPoints += this.gamePoints; + this.gameState = 'GAMEOVER'; + this.tools.playSound('sfx_8'); + }); + } else if (killerId === 0) { + this.ngZone.run(() => { + this.gamePoints += 100; + }); + } + } + + private closeLoop(player: Player): void { + player.trail.forEach(t => { + this.grid[t.x][t.y] = player.id; + this.trailGrid[t.x][t.y] = -1; + }); + player.trail = []; + player.state = 'IDLE'; + + let visited = new Array(this.GRID_SIZE + 2).fill(0).map(() => new Array(this.GRID_SIZE + 2).fill(false)); + let queue = [[-1, -1]]; + visited[0][0] = true; + let head = 0; + + while (head < queue.length) { + let [cx, cy] = queue[head++]; + + for (let d of this.DIRS) { + let nx = cx + d.x; + let ny = cy + d.y; + + if (nx >= -1 && nx <= this.GRID_SIZE && ny >= -1 && ny <= this.GRID_SIZE) { + if (!visited[nx + 1][ny + 1]) { + let isWall = false; + if (nx >= 0 && nx < this.GRID_SIZE && ny >= 0 && ny < this.GRID_SIZE) { + if (this.grid[nx][ny] === player.id) { + isWall = true; + } + } + + if (!isWall) { + visited[nx + 1][ny + 1] = true; + queue.push([nx, ny]); + } + } + } + } + } + + player.scoreCount = 0; + for (let x = 0; x < this.GRID_SIZE; x++) { + for (let y = 0; y < this.GRID_SIZE; y++) { + if (!visited[x + 1][y + 1]) { + this.grid[x][y] = player.id; + } + if (this.grid[x][y] === player.id) { + player.scoreCount++; + } + } + } + + this.players.forEach(p => { + if(p.id !== player.id && !p.isDead) { + let count = 0; + for (let x = 0; x < this.GRID_SIZE; x++) { + for (let y = 0; y < this.GRID_SIZE; y++) { + if (this.grid[x][y] === p.id) count++; + } + } + p.scoreCount = count; + + // 2. Lost all territory + if (p.scoreCount === 0) { + this.killPlayer(p.id, player.id); + } + // 3. Connection is cut (trail no longer connects to their territory) + else if (p.state === 'DRAWING' && p.trail.length > 0) { + let start = p.trail[0]; + let isConnected = false; + for (let d of this.DIRS) { + let nx = start.x + d.x; + let ny = start.y + d.y; + if (nx >= 0 && nx < this.GRID_SIZE && ny >= 0 && ny < this.GRID_SIZE) { + if (this.grid[nx][ny] === p.id) { + isConnected = true; + break; + } + } + } + if (!isConnected) { + this.killPlayer(p.id, player.id); + } + } + } + }); + + if (player.id === 0) { + this.ngZone.run(() => { + this.gamePoints = player.scoreCount * 2; + }); + } + } + + private updateBotAI(bot: Player): void { + let possibleDirs = [0, 1, 2, 3].filter(d => Math.abs(d - bot.dir) !== 2); + + let safeDirs = possibleDirs.filter(d => { + let nx = bot.x + this.DIRS[d].x; + let ny = bot.y + this.DIRS[d].y; + + if (nx < 0 || nx >= this.GRID_SIZE || ny < 0 || ny >= this.GRID_SIZE) return false; + if (this.trailGrid[nx][ny] === bot.id) return false; + + let openSpaces = 0; + for (let nextD of [0, 1, 2, 3]) { + if (Math.abs(nextD - d) === 2) continue; + let nnx = nx + this.DIRS[nextD].x; + let nny = ny + this.DIRS[nextD].y; + if (nnx >= 0 && nnx < this.GRID_SIZE && nny >= 0 && nny < this.GRID_SIZE && this.trailGrid[nnx][nny] !== bot.id) { + openSpaces++; + } + } + + if (openSpaces === 0 && bot.state === 'DRAWING') return false; + return true; + }); + + if (safeDirs.length === 0) safeDirs = possibleDirs; + + let chosenDir = bot.nextDir; + let immediateDanger = !safeDirs.includes(bot.dir); + + if (immediateDanger) { + chosenDir = safeDirs[Math.floor(Math.random() * safeDirs.length)]; + } else { + // --- Behaviors --- + let p0 = this.players[0]; + + if (bot.behaviour === 'normal') { + let turnChance = bot.state === 'IDLE' ? 0.05 : 0.1; + if (bot.state === 'DRAWING' && bot.trail.length > 8) turnChance = 0.4; + + if (Math.random() < turnChance) { + chosenDir = safeDirs[Math.floor(Math.random() * safeDirs.length)]; + } + } + else if (bot.behaviour === 'chaotic') { + let turnChance = 0.4; + if (Math.random() < turnChance) { + chosenDir = safeDirs[Math.floor(Math.random() * safeDirs.length)]; + } + } + else if (bot.behaviour === 'protective') { + let turnChance = bot.state === 'IDLE' ? 0.02 : 0.2; + if (bot.state === 'DRAWING' && bot.trail.length > 5) turnChance = 0.7; + + if (Math.random() < turnChance) { + let bestDir = safeDirs[Math.floor(Math.random() * safeDirs.length)]; + let minDistance = 9999; + for (let d of safeDirs) { + let checkX = bot.x + this.DIRS[d].x; + let checkY = bot.y + this.DIRS[d].y; + let dist = this.findNearestGrid(checkX, checkY, bot.id, 10); + if (dist < minDistance) { + minDistance = dist; + bestDir = d; + } + } + chosenDir = bestDir; + } + } + else if (bot.behaviour === 'aggresive') { + let turnChance = bot.state === 'IDLE' ? 0.05 : 0.2; + if (bot.state === 'DRAWING' && bot.trail.length > 10) turnChance = 0.5; + + if (Math.random() < turnChance) { + chosenDir = safeDirs[Math.floor(Math.random() * safeDirs.length)]; + } + + let targetInfo = this.findNearestEnemy(bot, 15, -1); + if (targetInfo) { + let dx = targetInfo.x - bot.x; + let dy = targetInfo.y - bot.y; + let prefDirs = this.getPreferredDirs(dx, dy); + let validPref = prefDirs.filter(d => safeDirs.includes(d)); + if (validPref.length > 0) chosenDir = validPref[0]; + } + } + else if (bot.behaviour === 'playerKiller') { + let turnChance = bot.state === 'IDLE' ? 0.05 : 0.2; + if (bot.state === 'DRAWING' && bot.trail.length > 10) turnChance = 0.5; + + if (Math.random() < turnChance) { + chosenDir = safeDirs[Math.floor(Math.random() * safeDirs.length)]; + } + + if (!p0.isDead) { + let targetInfo = this.findNearestEnemy(bot, 30, 0); + if (targetInfo) { + let dx = targetInfo.x - bot.x; + let dy = targetInfo.y - bot.y; + let prefDirs = this.getPreferredDirs(dx, dy); + let validPref = prefDirs.filter(d => safeDirs.includes(d)); + if (validPref.length > 0) chosenDir = validPref[0]; + } + } + } + } + + // --- Safety Overrides --- + let foundOverride = false; + for (let d of safeDirs) { + let checkX = bot.x + this.DIRS[d].x; + let checkY = bot.y + this.DIRS[d].y; + if (checkX >= 0 && checkX < this.GRID_SIZE && checkY >= 0 && checkY < this.GRID_SIZE) { + let tId = this.trailGrid[checkX][checkY]; + if (tId !== -1 && tId !== bot.id) { + chosenDir = d; + foundOverride = true; + break; + } + } + } + + if (!foundOverride && bot.state === 'DRAWING' && bot.trail.length > 5) { + for (let d of safeDirs) { + let checkX = bot.x + this.DIRS[d].x; + let checkY = bot.y + this.DIRS[d].y; + if (checkX >= 0 && checkX < this.GRID_SIZE && checkY >= 0 && checkY < this.GRID_SIZE) { + if (this.grid[checkX][checkY] === bot.id) { + chosenDir = d; + break; + } + } + } + } + + bot.nextDir = chosenDir; + } + + private findNearestGrid(x: number, y: number, id: number, radius: number): number { + let minDist = 9999; + for(let dx = -radius; dx <= radius; dx++) { + for(let dy = -radius; dy <= radius; dy++) { + let nx = x + dx, ny = y + dy; + if (nx >= 0 && nx < this.GRID_SIZE && ny >= 0 && ny < this.GRID_SIZE) { + if (this.grid[nx][ny] === id) { + let dist = Math.hypot(dx, dy); + if (dist < minDist) minDist = dist; + } + } + } + } + return minDist; + } + + private findNearestEnemy(bot: Player, radius: number, targetId: number): {x: number, y: number} | null { + let minDist = 9999; + let target = null; + this.players.forEach(p => { + if (p.isDead || p.id === bot.id) return; + if (targetId !== -1 && p.id !== targetId) return; + + let dist = Math.hypot(p.x - bot.x, p.y - bot.y); + if (dist < radius && dist < minDist) { + minDist = dist; + target = {x: p.x, y: p.y}; + } + + p.trail.forEach(t => { + let d2 = Math.hypot(t.x - bot.x, t.y - bot.y); + if (d2 < radius && d2 < minDist) { + minDist = d2; + target = {x: t.x, y: t.y}; + } + }); + }); + return target; + } + + private getPreferredDirs(dx: number, dy: number): number[] { + let dirs = []; + if (Math.abs(dx) > Math.abs(dy)) { + dirs.push(dx > 0 ? 3 : 1); + dirs.push(dy > 0 ? 0 : 2); + dirs.push(dy > 0 ? 2 : 0); + dirs.push(dx > 0 ? 1 : 3); + } else { + dirs.push(dy > 0 ? 0 : 2); + dirs.push(dx > 0 ? 3 : 1); + dirs.push(dx > 0 ? 1 : 3); + dirs.push(dy > 0 ? 2 : 0); + } + return dirs; + } + + private updateLeaderboard(): void { + let sorted = [...this.players].sort((a,b) => b.scoreCount - a.scoreCount); + let list: any[] = []; + + let top7 = sorted.slice(0, 7); + top7.forEach((p, index) => { + if(!p.isDead) { + let pct = ((p.scoreCount / (this.GRID_SIZE * this.GRID_SIZE)) * 100).toFixed(1); + let displayName = p.id === 0 ? p.name : `${index+1}. ${p.name}`; + list.push({ + name: displayName, + pct: `${pct}%`, + color: p.color + }); + } + }); + + this.ngZone.run(() => { + this.leaderboard = list; + }); + } + + private loop(timestamp: number): void { + if (this.tools.isWindowBlurred || this.gameState !== 'PLAYING') { + this.animationFrameId = requestAnimationFrame((ts) => this.loop(ts)); + return; + } + + let deltaTime = timestamp - this.lastTime; + if (deltaTime > 200) { + deltaTime = this.TICK_RATE; + } + this.lastTime = timestamp; + + this.players.forEach(p => { + if (p.isDead) return; + p.tickAccumulator += deltaTime; + let pTickRate = this.TICK_RATE / (p.speed || 1); + + while (p.tickAccumulator >= pTickRate) { + this.logicTickForPlayer(p); + p.tickAccumulator -= pTickRate; + } + }); + + let aliveBots = this.players.filter(p => p.id !== 0 && !p.isDead).length; + if (aliveBots < 14 && Math.random() < 0.05) { + let deadBot = this.players.find(p => p.id !== 0 && p.isDead); + if (deadBot) this.reviveBot(deadBot); + } + + this.updateLeaderboard(); + + let p0 = this.players[0]; + let lerp = p0 && !p0.isDead ? p0.tickAccumulator / (this.TICK_RATE / (p0.speed || 1)) : 0; + this.draw(lerp); + + this.animationFrameId = requestAnimationFrame((ts) => this.loop(ts)); + } + + private draw(lerp: number): void { + const canvas = this.canvasRef?.nativeElement; + if (!canvas) return; + const ctx = canvas.getContext('2d'); + if (!ctx) return; + + ctx.fillStyle = '#f0f4f8'; + ctx.fillRect(0, 0, canvas.width, canvas.height); + + let mainPlayer = this.players[0]; + if (!mainPlayer) return; + + let cx = (mainPlayer.px + (mainPlayer.x - mainPlayer.px) * lerp) * this.TILE_SIZE; + let cy = (mainPlayer.py + (mainPlayer.y - mainPlayer.py) * lerp) * this.TILE_SIZE; + + ctx.save(); + ctx.translate(canvas.width / 2 - cx, canvas.height / 2 - cy); + + ctx.strokeStyle = '#e1e8ed'; + ctx.lineWidth = 1; + + let startX = Math.max(0, Math.floor((cx - canvas.width / 2) / this.TILE_SIZE)); + let endX = Math.min(this.GRID_SIZE, Math.ceil((cx + canvas.width / 2) / this.TILE_SIZE)); + let startY = Math.max(0, Math.floor((cy - canvas.height / 2) / this.TILE_SIZE)); + let endY = Math.min(this.GRID_SIZE, Math.ceil((cy + canvas.height / 2) / this.TILE_SIZE)); + + for(let x = startX; x <= endX; x++) { + ctx.beginPath(); + ctx.moveTo(x * this.TILE_SIZE, startY * this.TILE_SIZE); + ctx.lineTo(x * this.TILE_SIZE, endY * this.TILE_SIZE); + ctx.stroke(); + } + for(let y = startY; y <= endY; y++) { + ctx.beginPath(); + ctx.moveTo(startX * this.TILE_SIZE, y * this.TILE_SIZE); + ctx.lineTo(endX * this.TILE_SIZE, y * this.TILE_SIZE); + ctx.stroke(); + } + + for(let x = startX; x < endX; x++) { + for(let y = startY; y < endY; y++) { + let pId = this.grid[x][y]; + if(pId !== -1) { + let colorObj = this.players.find(c => c.id === pId); + if(colorObj) { + ctx.fillStyle = colorObj.color; + ctx.fillRect(x * this.TILE_SIZE, y * this.TILE_SIZE, this.TILE_SIZE, this.TILE_SIZE); + } + } + } + } + + for(let x = startX; x < endX; x++) { + for(let y = startY; y < endY; y++) { + let pId = this.trailGrid[x][y]; + if(pId !== -1) { + let colorObj = this.players.find(c => c.id === pId); + if(colorObj) { + ctx.fillStyle = colorObj.trailColor; + ctx.fillRect(x * this.TILE_SIZE, y * this.TILE_SIZE, this.TILE_SIZE, this.TILE_SIZE); + } + } + } + } + + this.players.forEach(p => { + if(p.isDead) return; + + let playerLerp = p.tickAccumulator / (this.TICK_RATE / (p.speed || 1)); + if (playerLerp > 1) playerLerp = 1; + + let drawX = p.px + (p.x - p.px) * playerLerp; + let drawY = p.py + (p.y - p.py) * playerLerp; + + if (p.state === 'DRAWING') { + ctx.fillStyle = p.trailColor; + if (p.dir === 0) ctx.fillRect(p.x * this.TILE_SIZE, drawY * this.TILE_SIZE, this.TILE_SIZE, (p.py - drawY + 1) * this.TILE_SIZE); + if (p.dir === 1) ctx.fillRect(p.px * this.TILE_SIZE, p.y * this.TILE_SIZE, (drawX - p.px + 1) * this.TILE_SIZE, this.TILE_SIZE); + if (p.dir === 2) ctx.fillRect(p.x * this.TILE_SIZE, p.py * this.TILE_SIZE, this.TILE_SIZE, (drawY - p.py + 1) * this.TILE_SIZE); + if (p.dir === 3) ctx.fillRect(drawX * this.TILE_SIZE, p.y * this.TILE_SIZE, (p.px - drawX + 1) * this.TILE_SIZE, this.TILE_SIZE); + } + + let pad = 2; + ctx.fillStyle = p.color; + ctx.shadowColor = 'rgba(0,0,0,0.3)'; + ctx.shadowBlur = 5; + ctx.shadowOffsetY = 3; + ctx.fillRect(drawX * this.TILE_SIZE - pad, drawY * this.TILE_SIZE - pad, this.TILE_SIZE + pad*2, this.TILE_SIZE + pad*2); + ctx.shadowColor = 'transparent'; + + ctx.fillStyle = '#2c3e50'; + ctx.font = 'bold 14px "Comic Sans MS", "Chalkboard SE", sans-serif'; // Doge/Cheems themed font + ctx.textAlign = 'center'; + ctx.fillText(p.name, drawX * this.TILE_SIZE + (this.TILE_SIZE / 2), drawY * this.TILE_SIZE - 10); + }); + + ctx.strokeStyle = '#2c3e50'; + ctx.lineWidth = 5; + ctx.strokeRect(0, 0, this.GRID_SIZE * this.TILE_SIZE, this.GRID_SIZE * this.TILE_SIZE); + + ctx.restore(); + } + + private onKeyDown(e: KeyboardEvent): void { + if (this.gameState !== 'PLAYING') return; + let p = this.players[0]; + if(!p || p.isDead) return; + + if (['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight', 'w', 'a', 's', 'd', 'W', 'A', 'S', 'D'].includes(e.key)) { + if (e.cancelable) e.preventDefault(); + } + + if (e.key === 'ArrowUp' || e.key === 'w' || e.key === 'W') { if (p.dir !== 2) p.nextDir = 0; } + if (e.key === 'ArrowRight' || e.key === 'd' || e.key === 'D') { if (p.dir !== 3) p.nextDir = 1; } + if (e.key === 'ArrowDown' || e.key === 's' || e.key === 'S') { if (p.dir !== 0) p.nextDir = 2; } + if (e.key === 'ArrowLeft' || e.key === 'a' || e.key === 'A') { if (p.dir !== 1) p.nextDir = 3; } + } + + private onTouchStart(e: TouchEvent): void { + if (this.gameState !== 'PLAYING') return; + if (e.touches.length > 0) { + this.touchStartX = e.touches[0].clientX; + this.touchStartY = e.touches[0].clientY; + } + } + + private onTouchMove(e: TouchEvent): void { + if (this.gameState === 'PLAYING') { + if (e.cancelable) e.preventDefault(); + } + } + + private onTouchEnd(e: TouchEvent): void { + if (this.gameState !== 'PLAYING') return; + let p = this.players[0]; + if (!p || p.isDead) return; + + if (e.changedTouches.length > 0) { + let touchEndX = e.changedTouches[0].clientX; + let touchEndY = e.changedTouches[0].clientY; + + let dx = touchEndX - this.touchStartX; + let dy = touchEndY - this.touchStartY; + + if (Math.abs(dx) > 30 || Math.abs(dy) > 30) { + if (Math.abs(dx) > Math.abs(dy)) { + if (dx > 0) { if (p.dir !== 3) p.nextDir = 1; } + else { if (p.dir !== 1) p.nextDir = 3; } + } else { + if (dy > 0) { if (p.dir !== 0) p.nextDir = 2; } + else { if (p.dir !== 2) p.nextDir = 0; } + } + } + } + } + + private onResize(): void { + const canvas = this.canvasRef?.nativeElement; + const container = this.gameContainer?.nativeElement; + if (canvas && container) { + canvas.width = container.clientWidth || window.innerWidth; + canvas.height = container.clientHeight || window.innerHeight; + } + } + + private stopLoop(): void { + if (this.animationFrameId !== null) { + cancelAnimationFrame(this.animationFrameId); + this.animationFrameId = null; + } + } +} diff --git a/src/app/games/spiral_roll/spiral_roll.component.css b/src/app/games/spiral_roll/spiral_roll.component.css new file mode 100644 index 0000000..0c2cbb5 --- /dev/null +++ b/src/app/games/spiral_roll/spiral_roll.component.css @@ -0,0 +1,83 @@ +.spiral-roll-wrapper { + position: relative; + width: 100vw; + height: 100vh; + overflow: hidden; + background-color: #4facfe; + font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; + user-select: none; + touch-action: none; +} + +#game-container { + position: absolute; + top: 0; left: 0; width: 100%; height: 100%; + z-index: 1; +} + +.ui-layer { + position: absolute; + top: 0; left: 0; width: 100%; height: 100%; + pointer-events: none; + display: flex; + flex-direction: column; + justify-content: space-between; + z-index: 10; +} + +.hud { + padding: 20px; + display: flex; + justify-content: space-between; + font-size: 2em; + font-weight: bold; + color: #fff; + text-shadow: 2px 2px 4px rgba(0,0,0,0.5); +} + +/* Screens */ +.screen { + position: absolute; + top: 0; left: 0; width: 100%; height: 100%; + background: rgba(0, 0, 0, 0.6); + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + pointer-events: auto; + backdrop-filter: blur(4px); + z-index: 20; +} + +h1 { + font-size: 4em; + color: #fff; + margin: 0 0 10px 0; + text-transform: uppercase; + letter-spacing: 2px; + text-shadow: 0 4px 10px rgba(0,0,0,0.5); + text-align: center; +} + +p { + font-size: 1.5em; + color: #ddd; + margin-bottom: 30px; + text-align: center; +} + +.btn { + background: #FF9800; + color: white; + border: none; + padding: 15px 50px; + border-radius: 30px; + font-size: 1.5em; + font-weight: bold; + cursor: pointer; + box-shadow: 0 6px 15px rgba(255, 152, 0, 0.4); + transition: transform 0.1s; + pointer-events: auto; +} +.btn:active { transform: scale(0.95); } +.btn:hover { transform: scale(1.05); } diff --git a/src/app/games/spiral_roll/spiral_roll.component.html b/src/app/games/spiral_roll/spiral_roll.component.html new file mode 100644 index 0000000..d776ca2 --- /dev/null +++ b/src/app/games/spiral_roll/spiral_roll.component.html @@ -0,0 +1,35 @@ +
+
+ +
+
+
{{tools.spiral_roll[tools.lang]?.spiral_roll_session || 'Session: '}} {{sessionPoints}}
+
{{tools.spiral_roll[tools.lang]?.spiral_roll_score || 'Score: '}} {{levelPoints}}
+
{{tools.spiral_roll[tools.lang]?.spiral_roll_level_lbl || 'Level: '}} {{level}}
+
+
+ + @if (gameState === 'START') { +
+

{{tools.spiral_roll[tools.lang]?.spiral_roll_title || 'Spiral Roll'}}

+

{{tools.spiral_roll[tools.lang]?.spiral_roll_inst_orig || 'Hold to carve a spiral.\nRelease to launch it!\nBigger rolls = More points.'}}

+ +
+ } + + @if (gameState === 'WIN') { +
+

{{tools.spiral_roll[tools.lang]?.spiral_roll_cleared || 'LEVEL CLEARED!'}}

+

{{tools.spiral_roll[tools.lang]?.spiral_roll_final_score || 'Final Score: '}} {{levelPoints}}

+ +
+ } + + @if (gameState === 'LOSE') { +
+

{{tools.spiral_roll[tools.lang]?.spiral_roll_crashed || 'CRASHED!'}}

+

{{tools.spiral_roll[tools.lang]?.spiral_roll_final_score || 'Final Score: '}} {{levelPoints}}

+ +
+ } +
diff --git a/src/app/games/spiral_roll/spiral_roll.component.ts b/src/app/games/spiral_roll/spiral_roll.component.ts new file mode 100644 index 0000000..b6a8004 --- /dev/null +++ b/src/app/games/spiral_roll/spiral_roll.component.ts @@ -0,0 +1,710 @@ +import { Component, OnInit, OnDestroy, AfterViewInit, ViewChild, ElementRef, inject, NgZone } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import * as THREE from 'three'; +import { ToolsService } from '../../services/tools.service'; + +@Component({ + selector: 'app-spiral-roll', + standalone: true, + imports: [CommonModule], + templateUrl: './spiral_roll.component.html', + styleUrl: './spiral_roll.component.css' +}) +export class SpiralRollComponent implements OnInit, AfterViewInit, OnDestroy { + tools: ToolsService = inject(ToolsService); + private ngZone: NgZone = inject(NgZone); + + @ViewChild('gameContainer') gameContainer!: ElementRef; + + gameState: 'START' | 'PLAYING' | 'WIN' | 'LOSE' = 'START'; + sessionPoints = 0; + levelPoints = 0; + level = 0; + + private scene!: THREE.Scene; + private camera!: THREE.PerspectiveCamera; + private renderer!: THREE.WebGLRenderer; + private playerGroup!: THREE.Group; + private blade!: THREE.Mesh; + private handle!: THREE.Mesh; + private activeRoll: THREE.Mesh | null = null; + private rollRadius = 0; + private maxRollRadius = 3.0; + private launchedRolls: Array<{ mesh: THREE.Mesh; radius: number; speed: number; combo: number }> = []; + + // Game Objects + private obstacles: Array<{ mesh: THREE.Mesh; active: boolean; type: string }> = []; + private coins: Array<{ mesh: THREE.Mesh; active: boolean; color: string }> = []; + private particles: Array<{ mesh: THREE.Mesh; vx: number; vy: number; vz: number; life: number }> = []; + private floatingTexts: Array<{ sprite: THREE.Sprite; life: number }> = []; + private multiplierStairs: THREE.Group | null = null; + + private finishLineZ = -300; + private finishLine!: THREE.Mesh; + private trackLength = 300; + private isHolding = false; + private animationFrameId: number | null = null; + private speed = 0.3; + private baseSpeed = 0.3; + private speedMultiplier = 1; + + private onPointerDownBound = this.onPointerDown.bind(this); + private onPointerUpBound = this.onPointerUp.bind(this); + private onResizeBound = this.onResize.bind(this); + + // Materials + private woodMat!: THREE.MeshLambertMaterial; + private spiralMat!: THREE.MeshLambertMaterial; + private metalMat!: THREE.MeshLambertMaterial; + private handleMat!: THREE.MeshLambertMaterial; + private waterMat!: THREE.MeshLambertMaterial; + private obstacleMat!: THREE.MeshLambertMaterial; + private stoneMat!: THREE.MeshLambertMaterial; + private enemyMat!: THREE.MeshLambertMaterial; + private coinTex!: THREE.Texture; + + private onKeyDownBound = this.onKeyDown.bind(this); + private onKeyUpBound = this.onKeyUp.bind(this); + + ngOnInit(): void { + this.tools.setTitle("spiral_roll" as any); + this.tools.actPage = "spiral_roll" as any; + } + + ngAfterViewInit(): void { + this.init3D(); + window.addEventListener('keydown', this.onKeyDownBound); + window.addEventListener('keyup', this.onKeyUpBound); + } + + ngOnDestroy(): void { + this.stopLoop(); + window.removeEventListener('resize', this.onResizeBound); + window.removeEventListener('pointerup', this.onPointerUpBound); + window.removeEventListener('keydown', this.onKeyDownBound); + window.removeEventListener('keyup', this.onKeyUpBound); + if (this.renderer) { + this.renderer.dispose(); + const dom = this.gameContainer?.nativeElement; + if (dom && dom.contains(this.renderer.domElement)) { + dom.removeChild(this.renderer.domElement); + } + } + // Only sessionPoints are converted to MG Coins when exiting + this.tools.leaveMinigame('spiral_roll', this.sessionPoints, this.level); + } + + startGame(): void { + if (this.gameState === 'START' || this.gameState === 'LOSE') { + this.levelPoints = 0; + } + this.gameState = 'PLAYING'; + this.resetLevel(); + } + + nextLevel(): void { + this.level++; + this.gameState = 'PLAYING'; + this.resetLevel(); + } + + private init3D(): void { + const container = this.gameContainer.nativeElement; + const width = container.clientWidth || window.innerWidth; + const height = container.clientHeight || window.innerHeight; + + this.scene = new THREE.Scene(); + this.scene.background = new THREE.Color(0x87CEEB); // Sky blue + this.scene.fog = new THREE.Fog(0x87CEEB, 20, 100); + + this.camera = new THREE.PerspectiveCamera(60, width / height, 0.1, 150); + this.camera.position.set(4, 5, 8); + this.camera.lookAt(0, 0, -5); + + this.renderer = new THREE.WebGLRenderer({ antialias: true }); + this.renderer.setSize(width, height); + this.renderer.shadowMap.enabled = true; + container.appendChild(this.renderer.domElement); + + const ambientLight = new THREE.AmbientLight(0xffffff, 0.6); + this.scene.add(ambientLight); + + const dirLight = new THREE.DirectionalLight(0xffffff, 0.6); + dirLight.position.set(-10, 20, -10); + dirLight.castShadow = true; + dirLight.shadow.camera.left = -20; + dirLight.shadow.camera.right = 20; + dirLight.shadow.camera.top = 40; + dirLight.shadow.camera.bottom = -40; + this.scene.add(dirLight); + + // Textures & Materials + const texCanvas = document.createElement('canvas'); + texCanvas.width = 256; texCanvas.height = 256; + const tCtx = texCanvas.getContext('2d')!; + tCtx.fillStyle = '#f4a261'; + tCtx.fillRect(0, 0, 256, 256); + tCtx.fillStyle = '#e76f51'; + tCtx.save(); + tCtx.translate(128, 128); + tCtx.rotate(Math.PI / 4); + for(let i = -300; i < 300; i += 32) { + tCtx.fillRect(i, -300, 16, 600); + } + tCtx.restore(); + + const spiralTex = new THREE.CanvasTexture(texCanvas); + spiralTex.wrapS = THREE.RepeatWrapping; + spiralTex.wrapT = THREE.RepeatWrapping; + + const textureLoader = new THREE.TextureLoader(); + this.coinTex = textureLoader.load('img/dogecoin-min.png'); + + this.woodMat = new THREE.MeshLambertMaterial({ color: 0xe6b981 }); + this.spiralMat = new THREE.MeshLambertMaterial({ map: spiralTex }); + this.metalMat = new THREE.MeshLambertMaterial({ color: 0xbdc3c7 }); + this.handleMat = new THREE.MeshLambertMaterial({ color: 0x8b5a2b }); + this.waterMat = new THREE.MeshLambertMaterial({ color: 0x4facfe, transparent: true, opacity: 0.8 }); + this.obstacleMat = new THREE.MeshLambertMaterial({ color: 0xc0392b }); // red block + this.stoneMat = new THREE.MeshLambertMaterial({ color: 0x7f8c8d }); // gray stone + this.enemyMat = new THREE.MeshLambertMaterial({ color: 0x8e44ad }); // purple enemy + + this.playerGroup = new THREE.Group(); + this.playerGroup.position.set(0, 0, 0); + this.scene.add(this.playerGroup); + + const bladeGeo = new THREE.BoxGeometry(1.5, 0.2, 1); + this.blade = new THREE.Mesh(bladeGeo, this.metalMat); + this.blade.position.set(0, 0.5, 0); + this.blade.castShadow = true; + this.playerGroup.add(this.blade); + + const handleGeo = new THREE.CylinderGeometry(0.3, 0.3, 2, 16); + this.handle = new THREE.Mesh(handleGeo, this.handleMat); + this.handle.rotation.x = Math.PI / 2; + this.handle.position.set(0, 0.7, 1.5); + this.handle.castShadow = true; + this.playerGroup.add(this.handle); + + container.addEventListener('pointerdown', this.onPointerDownBound); + window.addEventListener('pointerup', this.onPointerUpBound); + window.addEventListener('resize', this.onResizeBound); + + this.ngZone.runOutsideAngular(() => { + this.animate(); + }); + } + + private createRollMesh(radius: number) { + const geo = new THREE.CylinderGeometry(radius, radius, 1.4, 32); + const mesh = new THREE.Mesh(geo, this.spiralMat); + mesh.rotation.z = Math.PI / 2; + mesh.castShadow = true; + return mesh; + } + + private createFloatingText(text: string, position: THREE.Vector3, color: string = "white") { + const canvas = document.createElement('canvas'); + canvas.width = 512; + canvas.height = 256; + const context = canvas.getContext('2d')!; + context.font = "Bold 80px Arial"; + context.fillStyle = color; + context.strokeStyle = "black"; + context.lineWidth = 6; + context.textAlign = "center"; + context.strokeText(text, 256, 128); + context.fillText(text, 256, 128); + + const texture = new THREE.CanvasTexture(canvas); + const spriteMaterial = new THREE.SpriteMaterial({ map: texture, transparent: true }); + const sprite = new THREE.Sprite(spriteMaterial); + sprite.position.copy(position); + sprite.position.y += 2; + sprite.scale.set(6, 3, 1); + this.scene.add(sprite); + + this.floatingTexts.push({ sprite, life: 1.0 }); + } + + private generateObjects(): void { + // Generate Obstacles and Coins + let zPos = -30; + while (zPos > -this.trackLength + 30) { + // Density increases with level (smaller gaps) + const maxGap = Math.max(10, 30 - (this.level * 2)); + const minGap = Math.max(5, 15 - (this.level * 1)); + zPos -= Math.random() * maxGap + minGap; + + const rand = Math.random(); + if (rand < 0.2) { + // Coin + const coinGeo = new THREE.CylinderGeometry(0.6, 0.6, 0.15, 16); + const colors = [0xf1c40f, 0xbdc3c7, 0xcd7f32, 0xff9ff3]; + const color = colors[Math.floor(Math.random() * colors.length)]; + const coinMat = new THREE.MeshLambertMaterial({ map: this.coinTex, color: color }); + const coin = new THREE.Mesh(coinGeo, coinMat); + coin.rotation.x = Math.PI / 2; + coin.position.set(0, 1.5, zPos); + coin.castShadow = true; + this.scene.add(coin); + this.coins.push({ mesh: coin, active: true, color: color.toString() }); + } else if (rand < 0.4) { + // Stone + const stoneGeo = new THREE.DodecahedronGeometry(1.2); + const stone = new THREE.Mesh(stoneGeo, this.stoneMat); + stone.position.set(0, 1.2, zPos); + stone.castShadow = true; + this.scene.add(stone); + this.obstacles.push({ mesh: stone, active: true, type: 'stone' }); + } else if (rand < 0.6) { + // Wall + const wallGeo = new THREE.BoxGeometry(3, 2, 0.5); + const wall = new THREE.Mesh(wallGeo, this.woodMat); + wall.position.set(0, 1, zPos); + wall.castShadow = true; + this.scene.add(wall); + this.obstacles.push({ mesh: wall, active: true, type: 'wall' }); + } else if (rand < 0.8) { + // Enemy + const enemyGeo = new THREE.SphereGeometry(1.0, 16, 16); + const enemy = new THREE.Mesh(enemyGeo, this.enemyMat); + enemy.position.set(0, 1.0, zPos); + enemy.castShadow = true; + this.scene.add(enemy); + this.obstacles.push({ mesh: enemy, active: true, type: 'enemy' }); + } else { + // Standard Red Block + const height = Math.random() * 2 + 1; + const obsGeo = new THREE.BoxGeometry(1.8, height, 1); + const obs = new THREE.Mesh(obsGeo, this.obstacleMat); + obs.position.set(0, height / 2 + 0.5, zPos); + obs.castShadow = true; + this.scene.add(obs); + this.obstacles.push({ mesh: obs, active: true, type: 'red' }); + } + } + } + + private resetLevel(): void { + this.levelPoints = 0; + this.speedMultiplier = 1; + this.obstacles.forEach(o => this.scene.remove(o.mesh)); + this.obstacles = []; + this.coins.forEach(c => this.scene.remove(c.mesh)); + this.coins = []; + this.launchedRolls.forEach(r => this.scene.remove(r.mesh)); + this.launchedRolls = []; + this.particles.forEach(p => { + this.scene.remove(p.mesh); + p.mesh.geometry.dispose(); + (p.mesh.material as THREE.Material).dispose(); + }); + this.particles = []; + this.floatingTexts.forEach(f => { + this.scene.remove(f.sprite); + (f.sprite.material as THREE.Material).dispose(); + }); + this.floatingTexts = []; + + if (this.multiplierStairs) { + this.scene.remove(this.multiplierStairs); + this.multiplierStairs = null; + } + + if (this.activeRoll) { + this.scene.remove(this.activeRoll); + this.activeRoll = null; + } + if (this.finishLine) this.scene.remove(this.finishLine); + + this.playerGroup.position.set(0, 0, 0); + this.rollRadius = 0; + this.isHolding = false; + + // Track gets longer every level + this.trackLength = 300 + (this.level * 100); + this.baseSpeed = 0.3 + Math.min(0.3, this.level * 0.02); + this.speed = this.baseSpeed; + this.finishLineZ = -this.trackLength; + + if (!this.scene.getObjectByName("water")) { + const waterGeo = new THREE.PlaneGeometry(200, 2000); + const water = new THREE.Mesh(waterGeo, this.waterMat); + water.rotation.x = -Math.PI / 2; + water.position.set(0, -1, -1000); + water.name = "water"; + this.scene.add(water); + } + + if (this.scene.getObjectByName("track")) { + const oldTrack = this.scene.getObjectByName("track") as THREE.Mesh; + this.scene.remove(oldTrack); + oldTrack.geometry.dispose(); + } + const trackGeo = new THREE.BoxGeometry(2, 1, this.trackLength + 100); + const track = new THREE.Mesh(trackGeo, this.woodMat); + track.position.set(0, 0, -this.trackLength / 2 + 30); + track.receiveShadow = true; + track.name = "track"; + this.scene.add(track); + + this.generateObjects(); + + // Finish line + const finGeo = new THREE.BoxGeometry(4, 0.5, 4); + const finMat = new THREE.MeshLambertMaterial({ color: 0x4CAF50 }); + this.finishLine = new THREE.Mesh(finGeo, finMat); + this.finishLine.position.set(0, 0.75, this.finishLineZ); + this.scene.add(this.finishLine); + + // Multiplier Stairs + this.multiplierStairs = new THREE.Group(); + this.multiplierStairs.position.set(0, 0, this.finishLineZ - 5); + const colors = [0x2ecc71, 0x3498db, 0x9b59b6, 0xf1c40f, 0xe74c3c]; + for(let i=1; i<=5; i++) { + const stepGeo = new THREE.BoxGeometry(4, i * 1.5, 4); + const stepMat = new THREE.MeshLambertMaterial({ color: colors[i-1] }); + const step = new THREE.Mesh(stepGeo, stepMat); + step.position.set(0, (i*1.5)/2, -i * 4); + step.receiveShadow = true; + step.castShadow = true; + // Text for step + const canvas = document.createElement('canvas'); + canvas.width = 128; canvas.height = 128; + const ctx = canvas.getContext('2d')!; + ctx.font = "Bold 60px Arial"; ctx.fillStyle = "white"; ctx.textAlign = "center"; + ctx.fillText(`x${i}`, 64, 80); + const tex = new THREE.CanvasTexture(canvas); + const spriteMat = new THREE.SpriteMaterial({map: tex}); + const sprite = new THREE.Sprite(spriteMat); + sprite.position.set(0, (i*1.5)/2 + 1, -i * 4 + 2); + this.multiplierStairs.add(step); + this.multiplierStairs.add(sprite); + } + this.scene.add(this.multiplierStairs); + } + + private onPointerDown(): void { + if (this.gameState === 'PLAYING') { + this.isHolding = true; + } + } + + private onPointerUp(): void { + if (this.gameState === 'PLAYING' && this.isHolding) { + this.isHolding = false; + this.launchRoll(); + } + } + + private onKeyDown(e: KeyboardEvent): void { + if (e.code === 'Space' && !e.repeat) { + if (this.gameState === 'PLAYING') { + this.onPointerDown(); + } else if (this.gameState === 'START' || this.gameState === 'LOSE') { + this.ngZone.run(() => { + this.startGame(); + }); + } else if (this.gameState === 'WIN') { + this.ngZone.run(() => { + this.nextLevel(); + }); + } + } + } + + private onKeyUp(e: KeyboardEvent): void { + if (e.code === 'Space') { + this.onPointerUp(); + } + } + + private spawnParticles(x: number, y: number, z: number, color: number, count: number) { + const particleGeo = new THREE.BoxGeometry(0.3, 0.3, 0.3); + for(let i=0; i 0.3) { + let pointsGained = Math.floor(this.rollRadius * 100); + this.ngZone.run(() => { + this.levelPoints += pointsGained; + }); + + this.launchedRolls.push({ + mesh: this.activeRoll!, + radius: this.rollRadius, + speed: this.speed * 2.5, + combo: 1 + }); + this.activeRoll = null; + this.tools.playSound('sfx_1'); + } else if (this.activeRoll) { + this.scene.remove(this.activeRoll); + this.activeRoll = null; + } + this.rollRadius = 0; + } + + private updateCarving() { + if (this.isHolding) { + this.blade.position.y = 0.3; + this.handle.position.y = 0.5; + + if (this.rollRadius < this.maxRollRadius) { + this.rollRadius += 0.04; + } + + if (!this.activeRoll) { + this.activeRoll = this.createRollMesh(this.rollRadius); + this.scene.add(this.activeRoll); + } else { + this.activeRoll.geometry.dispose(); + this.activeRoll.geometry = new THREE.CylinderGeometry(this.rollRadius, this.rollRadius, 1.4, 32); + } + + this.activeRoll.position.set( + this.playerGroup.position.x, + 0.5 + this.rollRadius, + this.playerGroup.position.z - 0.5 - this.rollRadius + ); + + this.activeRoll.rotation.x -= 0.2; + + if(Math.random() < 0.3) { + this.spawnParticles(this.playerGroup.position.x, 0.5, this.playerGroup.position.z - 1, 0xf4a261, 2); + } + } else { + this.blade.position.y = 0.5; + this.handle.position.y = 0.7; + } + } + + private gameOver() { + this.ngZone.run(() => { + this.sessionPoints += this.levelPoints; + this.gameState = 'LOSE'; + this.tools.playSound('sfx_8'); + }); + // Camera shake effect + const shake = setInterval(() => { + this.camera.position.x = 4 + (Math.random() - 0.5); + this.camera.position.y = 5 + (Math.random() - 0.5); + }, 50); + setTimeout(() => { + clearInterval(shake); + this.camera.position.x = 4; + this.camera.position.y = 5; + }, 500); + } + + private animate(): void { + this.animationFrameId = requestAnimationFrame(() => this.animate()); + if (this.tools.isWindowBlurred) return; + + if (this.gameState === 'PLAYING') { + // Speed scales slowly over the level + const progress = Math.abs(this.playerGroup.position.z) / this.trackLength; + this.speed = this.baseSpeed + (progress * 0.2); + + this.playerGroup.position.z -= this.speed; + + // Smooth camera follow + this.camera.position.x += (4 - this.camera.position.x) * 0.1; + this.camera.position.y += (6 - this.camera.position.y) * 0.1; + this.camera.position.z = this.playerGroup.position.z + 8; + this.camera.lookAt(0, 0, this.playerGroup.position.z - 5); + + this.updateCarving(); + + // Coin collision (Player only) + for (let j = this.coins.length - 1; j >= 0; j--) { + let coin = this.coins[j]; + if (coin.active) { + coin.mesh.rotation.z += 0.05; // animate coin + if (Math.abs(this.playerGroup.position.z - coin.mesh.position.z) < 1.0) { + coin.active = false; + this.scene.remove(coin.mesh); + this.spawnParticles(coin.mesh.position.x, coin.mesh.position.y, coin.mesh.position.z, 0xf1c40f, 10); + this.ngZone.run(() => { + this.sessionPoints += 100; + }); + this.createFloatingText("+100", coin.mesh.position, "#f1c40f"); + this.tools.playSound('sfx_4'); // Or a custom coin sound + } + } + } + + // Launched Rolls collision + for (let i = this.launchedRolls.length - 1; i >= 0; i--) { + let r = this.launchedRolls[i]; + r.mesh.position.z -= r.speed; + r.mesh.rotation.x -= 0.3; + + let hit = false; + + // Multiplier stairs collision check + if (this.multiplierStairs && r.mesh.position.z < this.finishLineZ - 5) { + let hitStep = 1; + const diffZ = Math.abs(r.mesh.position.z - (this.finishLineZ - 5)); + hitStep = Math.floor(diffZ / 4) + 1; // 4 is step depth + if (hitStep > 5) hitStep = 5; // max x5 + + // Check if roll is large enough to reach this step (simple height check) + if (r.mesh.position.y < (hitStep * 1.5)) { + // Hit the stairs! + const multiplier = hitStep; + const bonusPoints = multiplier * 500; + this.ngZone.run(() => { + this.levelPoints += bonusPoints; + this.tools.playSound('sfx_4'); + }); + const bonusStr = this.tools.spiral_roll[this.tools.lang]?.spiral_roll_bonus || 'BONUS!'; + this.createFloatingText(`+${bonusPoints} ${bonusStr}`, r.mesh.position, "#2ecc71"); + this.scene.remove(r.mesh); + this.launchedRolls.splice(i, 1); + continue; + } + } + + for (let j = this.obstacles.length - 1; j >= 0; j--) { + let obs = this.obstacles[j]; + if (obs.active && Math.abs(r.mesh.position.z - obs.mesh.position.z) < (r.radius + 0.5)) { + obs.active = false; + this.scene.remove(obs.mesh); + + let color = 0xc0392b; + if(obs.type === 'stone') color = 0x7f8c8d; + if(obs.type === 'enemy') color = 0x8e44ad; + if(obs.type === 'wall') color = 0xe6b981; + + this.spawnParticles(obs.mesh.position.x, obs.mesh.position.y, obs.mesh.position.z, color, 15); + this.tools.playSound('sfx_4'); + + const points = 50 * r.combo; + this.ngZone.run(() => { this.levelPoints += points; }); + this.createFloatingText(`+${points}`, obs.mesh.position); + r.combo++; // Combo goes up! + + if (obs.type === 'stone' || obs.type === 'wall') { + r.radius -= 1.5; // Heavy reduction + } else { + r.radius -= 1.0; + } + + if (r.radius < 0.5) { + hit = true; + } else { + r.mesh.geometry.dispose(); + r.mesh.geometry = new THREE.CylinderGeometry(r.radius, r.radius, 1.4, 32); + r.mesh.position.y = 0.5 + r.radius; + } + } + } + + if (hit || r.mesh.position.z < this.playerGroup.position.z - 250) { + this.scene.remove(r.mesh); + this.launchedRolls.splice(i, 1); + } + } + + // Player Obstacle Collision + for (let j = this.obstacles.length - 1; j >= 0; j--) { + let obs = this.obstacles[j]; + if (obs.active && this.playerGroup.position.z <= obs.mesh.position.z + 0.5 && this.playerGroup.position.z >= obs.mesh.position.z - 0.5) { + this.spawnParticles(this.playerGroup.position.x, 1, this.playerGroup.position.z, 0xbdc3c7, 10); + this.gameOver(); + } + } + + // Enemy movement + this.obstacles.forEach(obs => { + if (obs.active && obs.type === 'enemy') { + obs.mesh.position.x = Math.sin(Date.now() * 0.002 + obs.mesh.position.z) * 1.5; // wiggle + } + }); + + // End condition: Level ends when player touches the end. + if (this.playerGroup.position.z <= this.finishLine.position.z) { + this.speed = 0; + + // Add flat bonus and any potential active rolls instantly + this.ngZone.run(() => { + this.levelPoints += 500; + this.sessionPoints += this.levelPoints; + this.gameState = 'WIN'; + this.tools.playSound('sfx_4'); + }); + } + } + + // Update Particles + for (let i = this.particles.length - 1; i >= 0; i--) { + let p = this.particles[i]; + p.mesh.position.x += p.vx; + p.mesh.position.y += p.vy; + p.mesh.position.z += p.vz; + p.vy -= 0.02; + p.life -= 0.03; + + if (p.life <= 0) { + this.scene.remove(p.mesh); + p.mesh.geometry.dispose(); + (p.mesh.material as THREE.Material).dispose(); + this.particles.splice(i, 1); + } else { + p.mesh.scale.setScalar(p.life); + (p.mesh.material as THREE.MeshBasicMaterial).opacity = p.life; + } + } + + // Update Floating Text + for (let i = this.floatingTexts.length - 1; i >= 0; i--) { + let f = this.floatingTexts[i]; + f.sprite.position.y += 0.05; + f.life -= 0.02; + if (f.life <= 0) { + this.scene.remove(f.sprite); + (f.sprite.material as THREE.Material).dispose(); + this.floatingTexts.splice(i, 1); + } else { + (f.sprite.material as THREE.SpriteMaterial).opacity = f.life; + } + } + + if (this.renderer && this.scene && this.camera) { + this.renderer.render(this.scene, this.camera); + } + } + + private onResize(): void { + if (!this.camera || !this.renderer) return; + const container = this.gameContainer.nativeElement; + const width = container.clientWidth || window.innerWidth; + const height = container.clientHeight || window.innerHeight; + this.camera.aspect = width / height; + this.camera.updateProjectionMatrix(); + this.renderer.setSize(width, height); + } + + private stopLoop(): void { + if (this.animationFrameId !== null) { + cancelAnimationFrame(this.animationFrameId); + this.animationFrameId = null; + } + } +} diff --git a/src/app/games/stack_colors/stack_colors.component.css b/src/app/games/stack_colors/stack_colors.component.css new file mode 100644 index 0000000..8ad04a2 --- /dev/null +++ b/src/app/games/stack_colors/stack_colors.component.css @@ -0,0 +1,137 @@ +.stack-colors-wrapper { + position: relative; + width: 100vw; + height: 100vh; + overflow: hidden; + background-color: #87CEEB; + font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; + user-select: none; + touch-action: none; +} + +#game-container { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: 1; +} + +.ui-layer { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + pointer-events: none; + display: flex; + flex-direction: column; + justify-content: space-between; + z-index: 10; +} + +.hud { + padding: 20px; + display: flex; + justify-content: space-between; + font-size: 2em; + font-weight: bold; + color: white; + text-shadow: 2px 2px 4px rgba(0,0,0,0.5); +} + +.screen { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(0, 0, 0, 0.6); + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + pointer-events: auto; + backdrop-filter: blur(4px); + z-index: 20; +} + +.screen h1 { + font-size: 4em; + color: #fff; + margin: 0 0 10px 0; + text-transform: uppercase; + letter-spacing: 2px; + text-shadow: 0 4px 10px rgba(0,0,0,0.5); + text-align: center; +} + +.screen p { + font-size: 1.5em; + color: #ddd; + margin-bottom: 30px; + text-align: center; + white-space: pre-line; +} + +.btn { + background: #FF4081; + color: white; + border: none; + padding: 15px 50px; + border-radius: 30px; + font-size: 1.5em; + font-weight: bold; + cursor: pointer; + box-shadow: 0 6px 15px rgba(255, 64, 129, 0.4); + transition: transform 0.1s; +} + +.btn:active { + transform: scale(0.95); +} + +#kickUI { + position: absolute; + bottom: 20%; + left: 50%; + transform: translateX(-50%); + display: flex; + flex-direction: column; + align-items: center; + pointer-events: auto; +} + +.kick-btn { + background: #ffeb3b; + color: #333; + border: none; + width: 120px; + height: 120px; + border-radius: 50%; + font-size: 1.5em; + font-weight: bold; + box-shadow: 0 10px 0 #fbc02d, 0 15px 20px rgba(0,0,0,0.3); + cursor: pointer; +} +.kick-btn:active { + transform: translateY(10px); + box-shadow: 0 0 0 #fbc02d, 0 5px 10px rgba(0,0,0,0.3); +} + +.power-bar-container { + width: 200px; + height: 20px; + background: rgba(0,0,0,0.5); + border-radius: 10px; + margin-bottom: 20px; + overflow: hidden; + border: 2px solid white; +} + +#powerBar { + height: 100%; + background: linear-gradient(90deg, #4CAF50, #FFEB3B, #F44336); + transition: width 0.1s; +} diff --git a/src/app/games/stack_colors/stack_colors.component.html b/src/app/games/stack_colors/stack_colors.component.html new file mode 100644 index 0000000..ff8ad98 --- /dev/null +++ b/src/app/games/stack_colors/stack_colors.component.html @@ -0,0 +1,46 @@ +
+
+ +
+
+
{{tools.stack_colors[tools.lang]?.stack_colors_session || 'Session: '}} {{sessionPoints}}
+
{{tools.stack_colors[tools.lang]?.stack_colors_score || 'Score: '}} {{levelPoints}}
+
{{tools.stack_colors[tools.lang]?.stack_colors_level_lbl || 'Level: '}} {{level}}
+
{{tools.stack_colors[tools.lang]?.stack_colors_stack || 'Stack: '}} {{stack.length}}
+
+ + @if (gameState === 'PREP_KICK') { +
+

{{tools.stack_colors[tools.lang]?.stack_colors_tap_kick || 'TAP TO KICK!'}}

+
+
+
+ +
+ } +
+ + @if (gameState === 'START') { +
+

{{tools.stack_colors[tools.lang]?.stack_colors_title || 'Stack Colors!'}}

+

{{tools.stack_colors[tools.lang]?.stack_colors_inst || 'Drag to move.\nCollect matching colors.\nAvoid wrong colors.'}}

+ +
+ } + + @if (gameState === 'WIN') { +
+

{{tools.stack_colors[tools.lang]?.stack_colors_level_complete || 'LEVEL COMPLETE'}}

+

{{tools.stack_colors[tools.lang]?.stack_colors_final_score || 'Final Score: '}} {{levelPoints}}

+ +
+ } + + @if (gameState === 'LOSE') { +
+

{{tools.stack_colors[tools.lang]?.stack_colors_game_over || 'GAME OVER'}}

+

{{tools.stack_colors[tools.lang]?.stack_colors_final_score || 'Final Score: '}} {{levelPoints}}

+ +
+ } +
diff --git a/src/app/games/stack_colors/stack_colors.component.ts b/src/app/games/stack_colors/stack_colors.component.ts new file mode 100644 index 0000000..0355043 --- /dev/null +++ b/src/app/games/stack_colors/stack_colors.component.ts @@ -0,0 +1,612 @@ +import { Component, OnInit, OnDestroy, AfterViewInit, ViewChild, ElementRef, inject, NgZone } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import * as THREE from 'three'; +import { ToolsService } from '../../services/tools.service'; + +interface Collectible { + mesh: THREE.Mesh; + colorName: string; + collected: boolean; +} + +@Component({ + selector: 'app-stack-colors', + standalone: true, + imports: [CommonModule], + templateUrl: './stack_colors.component.html', + styleUrl: './stack_colors.component.css' +}) +export class StackColorsComponent implements OnInit, AfterViewInit, OnDestroy { + tools: ToolsService = inject(ToolsService); + private ngZone: NgZone = inject(NgZone); + + @ViewChild('gameContainer') gameContainer!: ElementRef; + + gameState: 'START' | 'PLAYING' | 'PREP_KICK' | 'KICKING' | 'WIN' | 'LOSE' = 'START'; + sessionPoints = 0; + levelPoints = 0; + level = 0; + + private scene!: THREE.Scene; + private camera!: THREE.PerspectiveCamera; + private renderer!: THREE.WebGLRenderer; + private playerGroup!: THREE.Group; + private character!: THREE.Mesh; + stack: THREE.Mesh[] = []; + private flyingStackGroup!: THREE.Group; + + private currentColor = 'orange'; + private colorMap: Record = { + orange: 0xFF9800, + blue: 0x2196F3, + green: 0x4CAF50 + }; + + private collectibles: Collectible[] = []; + private multipliers: THREE.Object3D[] = []; + private floatingTexts: Array<{ sprite: THREE.Sprite; life: number }> = []; + + private trackLength = 160; + private isDragging = false; + private targetX = 0; + private animationFrameId: number | null = null; + private speed = 0.35; + private keys = { left: false, right: false }; + private shakeOffset = new THREE.Vector3(); + private shakeStrength = 0; + + // Kick Mechanics + kickPower = 0; + private kickDecayInterval: any; + private stackVelocity = { y: 0, z: 0 }; + + private onPointerDownBound = this.onPointerDown.bind(this); + private onPointerMoveBound = this.onPointerMove.bind(this); + private onPointerUpBound = this.onPointerUp.bind(this); + private onResizeBound = this.onResize.bind(this); + private onKeyDownBound = this.onKeyDown.bind(this); + private onKeyUpBound = this.onKeyUp.bind(this); + + ngOnInit(): void { + this.tools.setTitle("stack_colors" as any); + this.tools.actPage = "stack_colors" as any; + } + + ngAfterViewInit(): void { + this.init3D(); + window.addEventListener('keydown', this.onKeyDownBound); + window.addEventListener('keyup', this.onKeyUpBound); + } + + ngOnDestroy(): void { + this.stopLoop(); + if (this.kickDecayInterval) clearInterval(this.kickDecayInterval); + + window.removeEventListener('resize', this.onResizeBound); + window.removeEventListener('pointerup', this.onPointerUpBound); + window.removeEventListener('keydown', this.onKeyDownBound); + window.removeEventListener('keyup', this.onKeyUpBound); + + if (this.renderer) { + this.renderer.dispose(); + const dom = this.gameContainer?.nativeElement; + if (dom && dom.contains(this.renderer.domElement)) { + dom.removeChild(this.renderer.domElement); + } + } + this.tools.leaveMinigame('stack_colors', this.sessionPoints, this.level); + } + + startGame(): void { + if (this.gameState === 'START' || this.gameState === 'LOSE') { + this.levelPoints = 0; + } + this.gameState = 'PLAYING'; + this.resetLevel(); + } + + nextLevel(): void { + this.level++; + this.gameState = 'PLAYING'; + this.resetLevel(); + } + + private init3D(): void { + const container = this.gameContainer.nativeElement; + const width = container.clientWidth || window.innerWidth; + const height = container.clientHeight || window.innerHeight; + + this.scene = new THREE.Scene(); + this.scene.background = new THREE.Color(0x87CEEB); + this.scene.fog = new THREE.Fog(0x87CEEB, 20, 100); + + this.camera = new THREE.PerspectiveCamera(60, width / height, 0.1, 1000); + this.camera.position.set(0, 8, 12); + this.camera.lookAt(0, 1, -5); + + this.renderer = new THREE.WebGLRenderer({ antialias: true }); + this.renderer.setSize(width, height); + this.renderer.shadowMap.enabled = true; + container.appendChild(this.renderer.domElement); + + const ambientLight = new THREE.AmbientLight(0xffffff, 0.7); + this.scene.add(ambientLight); + + const dirLight = new THREE.DirectionalLight(0xffffff, 0.8); + dirLight.position.set(10, 20, 10); + dirLight.castShadow = true; + this.scene.add(dirLight); + + this.flyingStackGroup = new THREE.Group(); + this.scene.add(this.flyingStackGroup); + + this.playerGroup = new THREE.Group(); + this.playerGroup.position.set(0, 0, 0); + this.scene.add(this.playerGroup); + + const charGeo = new THREE.CylinderGeometry(0.5, 0.5, 1.5, 16); + const charMat = new THREE.MeshLambertMaterial({ color: this.colorMap[this.currentColor] }); + this.character = new THREE.Mesh(charGeo, charMat); + this.character.position.y = 0.75; + this.character.castShadow = true; + this.playerGroup.add(this.character); + + container.addEventListener('pointerdown', this.onPointerDownBound); + window.addEventListener('pointermove', this.onPointerMoveBound); + window.addEventListener('pointerup', this.onPointerUpBound); + window.addEventListener('resize', this.onResizeBound); + + this.ngZone.runOutsideAngular(() => { + this.animate(); + }); + } + + private createFloatingText(text: string, position: THREE.Vector3, color: string = "white") { + const canvas = document.createElement('canvas'); + canvas.width = 512; + canvas.height = 256; + const context = canvas.getContext('2d')!; + context.font = "Bold 80px Arial"; + context.fillStyle = color; + context.strokeStyle = "black"; + context.lineWidth = 6; + context.textAlign = "center"; + context.strokeText(text, 256, 128); + context.fillText(text, 256, 128); + + const texture = new THREE.CanvasTexture(canvas); + const spriteMaterial = new THREE.SpriteMaterial({ map: texture, transparent: true }); + const sprite = new THREE.Sprite(spriteMaterial); + sprite.position.copy(position); + sprite.position.y += 2; + sprite.scale.set(6, 3, 1); + this.scene.add(sprite); + + this.floatingTexts.push({ sprite, life: 1.0 }); + } + + private resetLevel(): void { + this.levelPoints = 0; + this.collectibles.forEach(c => this.scene.remove(c.mesh)); + this.collectibles = []; + this.multipliers.forEach(m => this.scene.remove(m)); + this.multipliers = []; + this.stack.forEach(s => this.playerGroup.remove(s)); + this.stack = []; + + // Clear flying group + while(this.flyingStackGroup.children.length > 0){ + this.flyingStackGroup.remove(this.flyingStackGroup.children[0]); + } + this.flyingStackGroup.position.set(0,0,0); + this.flyingStackGroup.rotation.set(0,0,0); + + this.playerGroup.position.set(0, 0, 0); + this.targetX = 0; + this.kickPower = 0; + this.currentColor = 'orange'; + (this.character.material as THREE.MeshLambertMaterial).color.setHex(this.colorMap[this.currentColor]); + this.updateCharacterHeight(); + + this.trackLength = 160 + this.level * 40; + this.speed = 0.35 + (this.level * 0.02); + + if (this.scene.getObjectByName("track")) { + const oldTrack = this.scene.getObjectByName("track") as THREE.Mesh; + this.scene.remove(oldTrack); + oldTrack.geometry.dispose(); + } + + const trackGeo = new THREE.BoxGeometry(6, 1, this.trackLength + 100); + const trackMat = new THREE.MeshLambertMaterial({ color: 0xFAFAFA }); + const track = new THREE.Mesh(trackGeo, trackMat); + track.position.set(0, -0.5, -this.trackLength / 2 + 10); + track.receiveShadow = true; + track.name = "track"; + this.scene.add(track); + + const colors = ['orange', 'blue', 'green']; + let expectedColor = 'orange'; + let rowCount = 0; + let noMatchRowCount = 0; + + for (let z = -15; z > -this.trackLength; z -= 4) { + const progress = Math.abs(z) / this.trackLength; + const difficulty = this.level * 0.1 + progress * 0.5; + + if (z % 40 === 0) { + // Guarantee color changes at gates by picking from the other colors + const otherColors = colors.filter(c => c !== expectedColor); + const nextCol = otherColors[Math.floor(Math.random() * otherColors.length)]; + const lineGeo = new THREE.BoxGeometry(6, 0.1, 1); + const lineMat = new THREE.MeshBasicMaterial({ color: this.colorMap[nextCol], transparent: true, opacity: 0.5 }); + const line = new THREE.Mesh(lineGeo, lineMat); + line.position.set(0, 0.05, z); + line.userData = { colorName: nextCol, passed: false }; + this.scene.add(line); + this.multipliers.push(line); + + expectedColor = nextCol; + rowCount = 0; + noMatchRowCount = 0; + continue; + } + + let rowColors: string[] = []; + if (rowCount < 2) { + // First 2 rows after start or gate are purely the player's color + rowColors = [expectedColor, expectedColor, expectedColor]; + noMatchRowCount = 0; + } else { + let matchProb = 0.8 - (difficulty * 0.4); + if (matchProb < 0.2) matchProb = 0.2; + + // At max 3 rows in a row without the same color + if (noMatchRowCount >= 3) { + matchProb = 1.0; + } + + if (Math.random() < matchProb) { + // Spawn expected color + const quantityPattern = Math.random(); + const otherColors = colors.filter(c => c !== expectedColor); + + if (quantityPattern > difficulty) { + // 3 blocks of expected color + rowColors = [expectedColor, expectedColor, expectedColor]; + } else if (quantityPattern > difficulty / 2) { + // 2 expected, 1 different + const diffColor = otherColors[Math.floor(Math.random() * otherColors.length)]; + rowColors = [expectedColor, expectedColor, diffColor]; + } else { + // 1 expected, 2 different + const diff1 = otherColors[0]; + const diff2 = otherColors[1]; + rowColors = [expectedColor, diff1, diff2]; + } + noMatchRowCount = 0; + } else { + // 0 blocks of expected color + const otherColors = colors.filter(c => c !== expectedColor); + const diff1 = otherColors[0]; + const diff2 = otherColors[1]; + rowColors = [diff1, diff2, Math.random() > 0.5 ? diff1 : diff2]; + noMatchRowCount++; + } + + rowColors.sort(() => 0.5 - Math.random()); + } + + const xPositions = [-2, 0, 2]; + for (let i = 0; i < 3; i++) { + const cName = rowColors[i]; + const geo = new THREE.BoxGeometry(1.4, 0.4, 0.8); + const mat = new THREE.MeshLambertMaterial({ color: this.colorMap[cName] }); + const mesh = new THREE.Mesh(geo, mat); + mesh.position.set(xPositions[i], 0.2, z); + mesh.castShadow = true; + this.scene.add(mesh); + this.collectibles.push({ mesh, colorName: cName, collected: false }); + } + rowCount++; + } + + // Multiplier Zones at end + const multVals = [1, 2, 3, 5, 10]; + for (let i = 0; i < multVals.length; i++) { + const mz = -this.trackLength - 5 - i * 10; + const geo = new THREE.PlaneGeometry(6, 10); + const hue = (i * 45) % 360; + const mat = new THREE.MeshBasicMaterial({ color: `hsl(${hue}, 80%, 50%)` }); + const mesh = new THREE.Mesh(geo, mat); + mesh.rotation.x = -Math.PI / 2; + mesh.position.set(0, 0.01, mz); + mesh.userData = { multiplier: multVals[i] }; + this.scene.add(mesh); + this.multipliers.push(mesh); + + // Add Text + const canvas = document.createElement('canvas'); + canvas.width = 128; canvas.height = 128; + const ctx = canvas.getContext('2d')!; + ctx.font = "Bold 60px Arial"; ctx.fillStyle = "white"; ctx.textAlign = "center"; + ctx.fillText(`x${multVals[i]}`, 64, 80); + const tex = new THREE.CanvasTexture(canvas); + const spriteMat = new THREE.SpriteMaterial({map: tex}); + const sprite = new THREE.Sprite(spriteMat); + sprite.position.set(0, 1, mz); + this.scene.add(sprite); + this.multipliers.push(sprite); + } + } + + private triggerCameraShake() { + this.shakeStrength = 0.5; // Initial strength + } + + private onPointerDown(e: PointerEvent): void { + if (this.gameState === 'PLAYING') { + this.isDragging = true; + } + } + + private onPointerMove(e: PointerEvent): void { + if (!this.isDragging || this.gameState !== 'PLAYING') return; + const container = this.gameContainer.nativeElement; + const rect = container.getBoundingClientRect(); + const nx = ((e.clientX - rect.left) / rect.width) * 2 - 1; + this.targetX = Math.max(-2.2, Math.min(2.2, nx * 3)); + } + + private onPointerUp(): void { + this.isDragging = false; + } + + private onKeyDown(e: KeyboardEvent): void { + if (e.code === 'Space' && !e.repeat) { + if (this.gameState === 'START' || this.gameState === 'LOSE') { + this.ngZone.run(() => this.startGame()); + } else if (this.gameState === 'WIN') { + this.ngZone.run(() => this.nextLevel()); + } else if (this.gameState === 'PREP_KICK') { + this.addKickPower(e as any); + } + } + if (e.code === 'ArrowLeft' || e.code === 'KeyA') this.keys.left = true; + if (e.code === 'ArrowRight' || e.code === 'KeyD') this.keys.right = true; + } + + private onKeyUp(e: KeyboardEvent): void { + if (e.code === 'ArrowLeft' || e.code === 'KeyA') this.keys.left = false; + if (e.code === 'ArrowRight' || e.code === 'KeyD') this.keys.right = false; + } + + public addKickPower(e: Event) { + if (e) { + e.stopPropagation(); + e.preventDefault(); + } + if (this.gameState === 'PREP_KICK') { + this.ngZone.run(() => { + this.kickPower += 15; + if (this.kickPower > 100) this.kickPower = 100; + }); + } + } + + private prepKick() { + this.ngZone.run(() => { + this.gameState = 'PREP_KICK'; + this.kickPower = 0; + }); + + if (this.kickDecayInterval) clearInterval(this.kickDecayInterval); + this.kickDecayInterval = setInterval(() => { + this.ngZone.run(() => { + this.kickPower -= 1; + if(this.kickPower < 0) this.kickPower = 0; + }); + }, 50); + + setTimeout(() => { + this.executeKick(); + }, 3000); + } + + private executeKick() { + if (this.kickDecayInterval) clearInterval(this.kickDecayInterval); + + this.ngZone.run(() => { + this.gameState = 'KICKING'; + }); + + // Transfer stack to flying group + while(this.stack.length > 0) { + let b = this.stack.shift()!; + let worldPos = new THREE.Vector3(); + b.getWorldPosition(worldPos); + b.position.copy(worldPos); + this.flyingStackGroup.add(b); + } + this.playerGroup.remove(...this.playerGroup.children.filter(c => c !== this.character)); + + let powerMult = (this.kickPower / 100); + this.stackVelocity.y = 0.5 + (powerMult * 1.5); + this.stackVelocity.z = -1.0 - (powerMult * 2.0); + } + + private changePlayerColor(newColorName: string) { + this.currentColor = newColorName; + (this.character.material as THREE.MeshLambertMaterial).color.setHex(this.colorMap[this.currentColor]); + this.stack.forEach(b => (b.material as THREE.MeshLambertMaterial).color.setHex(this.colorMap[this.currentColor])); + } + + private updateCharacterHeight() { + this.character.position.y = (this.stack.length * 0.4) + 0.75; + } + + private gameOver() { + this.ngZone.run(() => { + this.sessionPoints += this.levelPoints; + this.gameState = 'LOSE'; + this.tools.playSound('sfx_8'); + }); + } + + private animate(): void { + this.animationFrameId = requestAnimationFrame(() => this.animate()); + if (this.tools.isWindowBlurred) return; + + if (this.gameState === 'PLAYING') { + this.playerGroup.position.z -= this.speed; + + // Keyboard input + if (this.keys.left) this.targetX -= 0.15; + if (this.keys.right) this.targetX += 0.15; + this.targetX = Math.max(-2.2, Math.min(2.2, this.targetX)); + + this.playerGroup.position.x += (this.targetX - this.playerGroup.position.x) * 0.2; + + // Gate collisions + this.multipliers.forEach(m => { + if (m.userData && m.userData['colorName'] && !m.userData['passed'] && this.playerGroup.position.z < m.position.z) { + m.userData['passed'] = true; + this.changePlayerColor(m.userData['colorName']); + } + }); + + const playerBox = new THREE.Box3().setFromObject(this.character); + // Extend box downwards to catch blocks + playerBox.min.y = 0; + + this.collectibles.forEach(c => { + if (!c.collected) { + const colBox = new THREE.Box3().setFromObject(c.mesh); + if (playerBox.intersectsBox(colBox)) { + c.collected = true; + if (c.colorName === this.currentColor) { + this.scene.remove(c.mesh); + const stackHeight = this.stack.length * 0.4 + 0.2; + c.mesh.position.set(0, stackHeight, 0); + this.playerGroup.add(c.mesh); + this.stack.push(c.mesh); + this.updateCharacterHeight(); + + this.ngZone.run(() => { + this.levelPoints += 5; + }); + this.tools.playSound('sfx_1'); + } else { + this.scene.remove(c.mesh); + this.triggerCameraShake(); + + if (this.stack.length > 0) { + const popped = this.stack.pop(); + if (popped) this.playerGroup.remove(popped); + this.updateCharacterHeight(); + this.tools.playSound('sfx_1'); + } else { + this.gameOver(); + } + } + } + } + }); + + if (this.playerGroup.position.z <= -this.trackLength) { + this.prepKick(); + } + + let camTargetX = this.playerGroup.position.x * 0.5; + let camTargetY = this.character.position.y + 7; + let camTargetZ = this.playerGroup.position.z + 11; + + if (this.shakeStrength > 0) { + this.shakeOffset.set( + (Math.random() - 0.5) * this.shakeStrength, + (Math.random() - 0.5) * this.shakeStrength, + (Math.random() - 0.5) * this.shakeStrength + ); + this.shakeStrength -= 0.05; // Decay + if (this.shakeStrength < 0) this.shakeStrength = 0; + } + + this.camera.position.x += (camTargetX - this.camera.position.x) * 0.1 + this.shakeOffset.x; + this.camera.position.y += (camTargetY - this.camera.position.y) * 0.1 + this.shakeOffset.y; + this.camera.position.z = camTargetZ + this.shakeOffset.z; + this.camera.lookAt(this.playerGroup.position.x, this.character.position.y, this.playerGroup.position.z - 5); + + } else if (this.gameState === 'KICKING') { + this.stackVelocity.y -= 0.05; // Gravity + + this.flyingStackGroup.position.y += this.stackVelocity.y; + this.flyingStackGroup.position.z += this.stackVelocity.z; + + this.flyingStackGroup.rotation.x -= 0.1; + + this.camera.position.z += this.stackVelocity.z * 0.8; + this.camera.lookAt(this.flyingStackGroup.position); + + if (this.flyingStackGroup.position.y <= 0) { + this.flyingStackGroup.position.y = 0; + + let finalZ = this.flyingStackGroup.position.z; + let mult = 1; + + this.multipliers.forEach(m => { + if (m.userData && m.userData['multiplier']) { + let mZ = m.position.z; + if (finalZ < mZ + 5 && finalZ > mZ - 5) { + mult = m.userData['multiplier']; + } + } + }); + + this.ngZone.run(() => { + const bonusStr = this.tools.stack_colors[this.tools.lang]?.stack_colors_bonus || 'BONUS!'; + const bonusPts = mult * 200; + this.levelPoints += bonusPts; + this.sessionPoints += this.levelPoints; + this.gameState = 'WIN'; + this.createFloatingText(`+${bonusPts} ${bonusStr}`, this.flyingStackGroup.position, "#2ecc71"); + this.tools.playSound('sfx_4'); + }); + } + } + + // Update Floating Text + for (let i = this.floatingTexts.length - 1; i >= 0; i--) { + let f = this.floatingTexts[i]; + f.sprite.position.y += 0.05; + f.life -= 0.02; + if (f.life <= 0) { + this.scene.remove(f.sprite); + (f.sprite.material as THREE.Material).dispose(); + this.floatingTexts.splice(i, 1); + } else { + (f.sprite.material as THREE.SpriteMaterial).opacity = f.life; + } + } + + if (this.renderer && this.scene && this.camera) { + this.renderer.render(this.scene, this.camera); + } + } + + private onResize(): void { + if (!this.camera || !this.renderer) return; + const container = this.gameContainer.nativeElement; + const width = container.clientWidth || window.innerWidth; + const height = container.clientHeight || window.innerHeight; + this.camera.aspect = width / height; + this.camera.updateProjectionMatrix(); + this.renderer.setSize(width, height); + } + + private stopLoop(): void { + if (this.animationFrameId !== null) { + cancelAnimationFrame(this.animationFrameId); + this.animationFrameId = null; + } + } +} diff --git a/src/app/guards/guard.guard.ts b/src/app/guards/guard.guard.ts index 3624bf1..6b26741 100644 --- a/src/app/guards/guard.guard.ts +++ b/src/app/guards/guard.guard.ts @@ -1,11 +1,37 @@ import { CanActivateFn } from '@angular/router'; +function getSubPath(url: string, prefixes: string[]): string { + for (const prefix of prefixes) { + const regex = new RegExp(`^\\/${prefix}(\\/|$)`); + if (regex.test(url)) { + const remaining = url.replace(regex, ''); + return remaining ? remaining : ''; + } + } + return ''; +} + export const developmentGuard: CanActivateFn = (route, state) => { - window.location.href = "/CheemsBonkGame/development"; + const sub = getSubPath(state.url, ['development', 'dev']); + window.location.href = "/CheemsBonkGame/dev/" + sub; + return false; +}; + +export const devGuard: CanActivateFn = (route, state) => { + const sub = getSubPath(state.url, ['dev', 'development']); + window.location.href = "/CheemsBonkGame/dev/" + sub; return false; }; export const testingGuard: CanActivateFn = (route, state) => { - window.location.href = "/CheemsBonkGame/test"; + const sub = getSubPath(state.url, ['test']); + window.location.href = "/CheemsBonkGame/test/" + sub; return false; }; + +export const appGuard: CanActivateFn = (route, state) => { + const sub = getSubPath(state.url, ['app']); + window.location.href = "/CheemsBonkGame/app/" + sub; + return false; +}; + diff --git a/src/app/pages/closet/closet.component.css b/src/app/pages/closet/closet.component.css index e69de29..eb9ae13 100644 --- a/src/app/pages/closet/closet.component.css +++ b/src/app/pages/closet/closet.component.css @@ -0,0 +1,142 @@ +.tabs-header { + display: flex; + flex-wrap: wrap; + justify-content: center; + gap: 0.75rem; + margin: 1.5rem 0; +} + +.tab-btn { + padding: 0.75rem 1.5rem; + border-radius: 50px; + border: 2px solid rgba(255, 209, 102, 0.3); + font-weight: 900; + cursor: pointer; + transition: all 0.25s cubic-bezier(0.34, 1.56, 0.64, 1); + background: rgba(0, 0, 0, 0.2); + color: inherit; +} + +.tab-btn.active { + background: #ffd166; + color: #1a1612; + transform: scale(1.08); + box-shadow: 0 4px 15px rgba(255, 209, 102, 0.5); +} + +.tab-btn.theme-light.active { + background: #9c5c14; + color: #fff; + box-shadow: 0 4px 15px rgba(156, 92, 20, 0.5); +} + +.tab-btn.theme-contrast.active { + background: #ffff00; + color: #000000; + border: 2px solid #ffff00; + box-shadow: none; +} + +.shop-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); + gap: 1.5rem; + width: 95%; + max-width: 1000px; + margin: 0 auto 3rem auto; +} + +.shop-card { + display: flex; + flex-direction: column; + align-items: center; + justify-content: space-between; + padding: 1.25rem; + border-radius: 18px; + cursor: pointer; + transition: all 0.25s cubic-bezier(0.34, 1.56, 0.64, 1); + background: rgba(65, 55, 45, 0.65); + border: 2px solid transparent; + box-shadow: 0 6px 18px rgba(0, 0, 0, 0.3); +} + +.shop-card:hover { + transform: translateY(-5px) scale(1.03); + box-shadow: 0 10px 25px rgba(0, 0, 0, 0.45); +} + +.shop-card.theme-light { + background: rgba(255, 248, 235, 0.85); + border-color: rgba(156, 92, 20, 0.2); +} + +.shop-card.theme-contrast { + background: #000000; + border: 2px solid #ffffff; + color: #ffffff; +} + +.shop-card.theme-contrast:hover { + border-color: #ffff00; +} + +.item-img { + width: 110px; + height: 110px; + object-fit: contain; + margin-bottom: 0.75rem; +} + +.item-icon { + width: 60px; + height: 60px; + object-fit: contain; + margin: 1rem 0; +} + +.item-info { + display: flex; + flex-direction: column; + align-items: center; + gap: 0.5rem; + width: 100%; +} + +.item-name { + font-weight: 900; + font-size: 1em; + text-align: center; +} + +.item-desc { + font-size: 0.85em; + text-align: center; + opacity: 0.8; +} + +.status-badge { + padding: 0.3rem 0.85rem; + border-radius: 50px; + font-size: 0.85em; + font-weight: 900; + text-transform: uppercase; + letter-spacing: 0.5px; +} + +.active-badge { + background: rgba(255, 209, 102, 0.3); + color: #ffd166; + border: 1px solid #ffd166; +} + +.unlocked-badge { + background: rgba(100, 255, 100, 0.2); + color: #55ff55; + border: 1px solid #55ff55; +} + +.cost-badge { + background: rgba(255, 100, 100, 0.2); + color: #ff8888; + border: 1px solid #ff8888; +} diff --git a/src/app/pages/closet/closet.component.html b/src/app/pages/closet/closet.component.html index e69de29..b4828b9 100644 --- a/src/app/pages/closet/closet.component.html +++ b/src/app/pages/closet/closet.component.html @@ -0,0 +1,96 @@ +
+
+ + + +
+ + @if (activeTab === 'cheems') { +
+ @for (skin of unlockedCheemsSkins; track $index) { +
+ +
+ {{tools.getCheemsName(skin)}} + @if (tools.getCheemsDescription(skin)) { + {{tools.getCheemsDescription(skin)}} + } + @if (tools.selectedCheems === skin.id) { + {{tools.closet[tools.lang].selected}} + } @else { + {{tools.closet[tools.lang].equip}} + } +
+
+ } +
+ } + + @if (activeTab === 'sounds') { +
+ @for (sound of unlockedSoundEffects; track $index) { +
+ +
+ {{tools.getSoundName(sound)}} + @if (tools.getSoundDescription(sound)) { + {{tools.getSoundDescription(sound)}} + } + @if (tools.selectedSound === sound.id) { + {{tools.closet[tools.lang].selected}} + } @else { + {{tools.closet[tools.lang].equip}} + } +
+
+ } +
+ } + + @if (activeTab === 'music') { +
+ @for (track of unlockedMusicTracks; track $index) { +
+ @if (track.id === 0) { + + } @else { + + } +
+ {{tools.getMusicName(track)}} + @if (tools.getMusicDescription(track)) { + {{tools.getMusicDescription(track)}} + } + @if (tools.selectedMusic === track.id) { + {{tools.closet[tools.lang].selected}} + } @else { + {{tools.closet[tools.lang].equip}} + } +
+
+ } +
+ } +
diff --git a/src/app/pages/closet/closet.component.ts b/src/app/pages/closet/closet.component.ts index b9b1638..aca7681 100644 --- a/src/app/pages/closet/closet.component.ts +++ b/src/app/pages/closet/closet.component.ts @@ -1,17 +1,47 @@ import { Component, inject, OnInit } from '@angular/core'; import { ToolsService } from '../../services/tools.service'; +import { CheemsSkinItem, SoundEffectItem, MusicTrackItem } from '../../services/constants.service'; @Component({ - selector: 'app-closet', - imports: [], - templateUrl: './closet.component.html', - styleUrl: './closet.component.css' + selector: 'app-closet', + imports: [], + templateUrl: './closet.component.html', + styleUrl: './closet.component.css' }) export class ClosetComponent implements OnInit { tools: ToolsService = inject(ToolsService); + activeTab: 'cheems' | 'sounds' | 'music' = 'cheems'; ngOnInit(): void { this.tools.setTitle("closet"); this.tools.actPage = "closet"; } + + setTab(tab: 'cheems' | 'sounds' | 'music'): void { + this.activeTab = tab; + } + + get unlockedCheemsSkins(): CheemsSkinItem[] { + return this.tools.cheemsSkins.filter(skin => this.tools.isCheemsUnlocked(skin.id)); + } + + get unlockedSoundEffects(): SoundEffectItem[] { + return this.tools.soundEffects.filter(sound => this.tools.isSoundUnlocked(sound.id)); + } + + get unlockedMusicTracks(): MusicTrackItem[] { + return this.tools.musicTracks.filter(track => this.tools.isMusicUnlocked(track.id)); + } + + onSelectCheems(skin: CheemsSkinItem): void { + this.tools.buyOrSelectCheems(skin); + } + + onSelectSound(sound: SoundEffectItem): void { + this.tools.buyOrSelectSound(sound); + } + + onSelectMusic(track: MusicTrackItem): void { + this.tools.buyOrSelectMusic(track); + } } diff --git a/src/app/pages/dev-settings/dev-settings.component.css b/src/app/pages/dev-settings/dev-settings.component.css index e69de29..f93d80b 100644 --- a/src/app/pages/dev-settings/dev-settings.component.css +++ b/src/app/pages/dev-settings/dev-settings.component.css @@ -0,0 +1,30 @@ +.dev-box { + display: flex; + flex-direction: column; + align-items: center; + gap: 2rem; + width: 90%; + max-width: 650px; + margin: 2.5rem auto; + padding: 2.5rem; +} + +.dev-title { + font-weight: 900; + font-size: 1.5em; + text-align: center; +} + +.dev-actions { + display: flex; + flex-direction: column; + gap: 1.25rem; + width: 100%; + max-width: 400px; +} + +.dev-btn { + width: 100%; + padding: 1rem 1.5rem; + font-size: 1.1em; +} diff --git a/src/app/pages/dev-settings/dev-settings.component.html b/src/app/pages/dev-settings/dev-settings.component.html index e69de29..622e237 100644 --- a/src/app/pages/dev-settings/dev-settings.component.html +++ b/src/app/pages/dev-settings/dev-settings.component.html @@ -0,0 +1,44 @@ +
+
+

{{tools.dev[tools.lang].title}}

+ +
+ +
+ + +
+ + +
+ DogeCoins ({{tools.dogeCoins}}) +
+ + +
+
+ + +
+ Points ({{tools.points}}) +
+ + +
+
+ + +
+ MG Coins ({{tools.minigameCoins}}) +
+ + +
+
+
+
+
diff --git a/src/app/pages/dev-settings/dev-settings.component.ts b/src/app/pages/dev-settings/dev-settings.component.ts index e290bf3..1f60c46 100644 --- a/src/app/pages/dev-settings/dev-settings.component.ts +++ b/src/app/pages/dev-settings/dev-settings.component.ts @@ -2,10 +2,10 @@ import { Component, inject, OnInit } from '@angular/core'; import { ToolsService } from '../../services/tools.service'; @Component({ - selector: 'app-dev-settings', - imports: [], - templateUrl: './dev-settings.component.html', - styleUrl: './dev-settings.component.css' + selector: 'app-dev-settings', + imports: [], + templateUrl: './dev-settings.component.html', + styleUrl: './dev-settings.component.css' }) export class DevSettingsComponent implements OnInit { tools: ToolsService = inject(ToolsService); @@ -14,4 +14,48 @@ export class DevSettingsComponent implements OnInit { this.tools.setTitle("devSettings"); this.tools.actPage = "devSettings"; } + + resetToZero(): void { + this.tools.resetToZero(); + } + + unlockAll(): void { + this.tools.unlockAll(); + } + + modifyDogeCoins(amount: number): void { + this.tools.dogeCoins += amount; + if (amount > 0) { + this.tools.totalDogeCoinsEarned += amount; + this.tools.saveData("lifetime_dg", String(this.tools.totalDogeCoinsEarned)); + } + if (this.tools.dogeCoins < 0) this.tools.dogeCoins = 0; + this.tools.saveData("dg", String(this.tools.dogeCoins)); + this.tools.showToast(this.tools.dev[this.tools.lang].success || "Success"); + this.tools.playSound('4'); + } + + modifyPoints(amount: number): void { + if (amount > 0) { + this.tools.updateScore(amount); + } else { + this.tools.points += amount; + if (this.tools.points < 0) this.tools.points = 0; + this.tools.saveData("points", String(this.tools.points)); + } + this.tools.showToast(this.tools.dev[this.tools.lang].success || "Success"); + this.tools.playSound('4'); + } + + modifyMinigameCoins(amount: number): void { + if (amount > 0) { + this.tools.addMinigameCoins(amount); + } else { + this.tools.minigameCoins += amount; + if (this.tools.minigameCoins < 0) this.tools.minigameCoins = 0; + this.tools.saveData("mg", String(this.tools.minigameCoins)); + } + this.tools.showToast(this.tools.dev[this.tools.lang].success || "Success"); + this.tools.playSound('4'); + } } diff --git a/src/app/pages/gallery/gallery.component.css b/src/app/pages/gallery/gallery.component.css new file mode 100644 index 0000000..6234dbb --- /dev/null +++ b/src/app/pages/gallery/gallery.component.css @@ -0,0 +1,425 @@ +.container { + padding-top: 10vh; + display: flex; + flex-direction: column; + align-items: center; + position: relative; + padding-bottom: 5rem; +} + +.header h1 { + font-size: 2.5rem; + font-weight: 900; + margin: 0; + text-transform: uppercase; + text-shadow: 2px 2px 0 #000; +} + +/* Tabs */ +.tabs-header { + display: flex; + flex-wrap: wrap; + justify-content: center; + gap: 0.75rem; + margin: 1.5rem 0; +} + +.tab-btn { + padding: 0.75rem 1.5rem; + border-radius: 50px; + border: 2px solid rgba(255, 209, 102, 0.3); + font-weight: 900; + cursor: pointer; + transition: all 0.25s cubic-bezier(0.34, 1.56, 0.64, 1); + background: rgba(0, 0, 0, 0.2); + color: inherit; +} + +.tab-btn.active { + background: #ffd166; + color: #1a1612; + transform: scale(1.08); + box-shadow: 0 4px 15px rgba(255, 209, 102, 0.5); +} + +.tab-btn.theme-light.active { + background: #9c5c14; + color: #fff; + box-shadow: 0 4px 15px rgba(156, 92, 20, 0.5); +} + +.tab-btn.theme-contrast.active { + background: #ffff00; + color: #000000; + border: 2px solid #ffff00; + box-shadow: none; +} + +/* Viewer */ +.viewer-container { + width: 95%; + max-width: 800px; + background: rgba(65, 55, 45, 0.65); + border: 2px solid transparent; + border-radius: 18px; + padding: 2rem; + display: flex; + flex-direction: column; + align-items: center; + box-shadow: 0 6px 18px rgba(0, 0, 0, 0.3); + margin: 0 auto; +} + +.viewer-container.theme-light { + background: rgba(255, 248, 235, 0.85); + border-color: rgba(156, 92, 20, 0.2); +} + +.viewer-container.theme-contrast { + background: #000000; + border: 2px solid #ffffff; + color: #ffffff; +} + +.viewer-header { + text-align: center; + margin-bottom: 2rem; +} + +.viewer-header h2 { + font-size: 1.8rem; + margin: 0 0 0.5rem 0; + color: #ffd166; +} + +.theme-light .viewer-header h2 { + color: #9c5c14; +} + +.theme-contrast .viewer-header h2 { + color: #ffff00; +} + +.viewer-header .desc { + opacity: 0.8; + font-size: 0.95rem; + margin: 0; +} + +.skins-display { + display: flex; + justify-content: center; + gap: 2rem; + width: 100%; + margin-bottom: 2rem; +} + +.skin-box { + display: flex; + flex-direction: column; + align-items: center; + gap: 1rem; + background: rgba(0, 0, 0, 0.3); + padding: 1.5rem; + border-radius: 16px; + flex: 1; + max-width: 300px; + box-shadow: inset 0 4px 10px rgba(0,0,0,0.2); +} + +.theme-light .skin-box { + background: rgba(0, 0, 0, 0.05); +} + +.skin-label { + font-weight: 900; + text-transform: uppercase; + font-size: 1rem; + opacity: 0.9; + letter-spacing: 1px; +} + +.viewer-img { + width: 150px; + height: 150px; + object-fit: contain; +} + +/* Controls */ +.viewer-controls, .audio-controls { + display: flex; + align-items: center; + justify-content: center; + gap: 1rem; + margin-top: 1rem; + width: 100%; +} + +.control-btn { + background: rgba(0,0,0,0.4); + border: 2px solid rgba(255, 209, 102, 0.3); + color: white; + width: 50px; + height: 50px; + border-radius: 50%; + font-size: 1.2rem; + cursor: pointer; + display: flex; + justify-content: center; + align-items: center; + transition: all 0.2s cubic-bezier(0.34, 1.56, 0.64, 1); +} + +.control-btn:hover { + background: rgba(255, 209, 102, 0.2); + border-color: #ffd166; + transform: scale(1.1); +} + +.control-btn:active { + transform: scale(0.9); +} + +.secondary-btn { + width: 65px; + height: 45px; + border-radius: 20px; + font-size: 0.95rem; + font-weight: bold; +} + +.play-btn { + width: 90px; + height: 60px; + border-radius: 30px; + font-size: 1.1rem; + font-weight: 900; + background: #ffd166; + color: #1a1612; + border-color: #ffd166; +} + +.play-btn:hover { + background: #ffb703; + color: #1a1612; + transform: scale(1.08); +} + +.theme-light .control-btn { + background: rgba(156, 92, 20, 0.1); + border-color: rgba(156, 92, 20, 0.3); + color: #9c5c14; +} +.theme-light .control-btn:hover { + background: rgba(156, 92, 20, 0.2); + border-color: #9c5c14; +} +.theme-light .play-btn { + background: #9c5c14; + color: white; +} +.theme-light .play-btn:hover { + background: #7a460c; + color: white; +} + +.theme-contrast .control-btn { + background: #000; + border-color: #fff; + color: #fff; +} +.theme-contrast .control-btn:hover { + border-color: #ff0; + color: #ff0; +} +.theme-contrast .play-btn { + background: #ff0; + color: #000; + border-color: #ff0; +} + +.counter-display { + margin-top: 1.5rem; + text-align: center; +} + +.counter { + font-weight: 900; + font-size: 1.2rem; + opacity: 0.8; +} + +.audio-player { + width: 100%; + display: flex; + flex-direction: column; + gap: 1.5rem; +} + +.time-slider-container { + display: flex; + align-items: center; + gap: 1rem; + width: 100%; + font-family: monospace; + font-size: 1.1rem; + font-weight: bold; +} + +.time-slider { + flex: 1; + cursor: pointer; + height: 8px; + border-radius: 4px; + appearance: none; + -webkit-appearance: none; + background: rgba(0,0,0,0.5); + border: 1px solid rgba(255,255,255,0.1); +} + +.theme-light .time-slider { + background: rgba(0,0,0,0.1); + border-color: rgba(0,0,0,0.1); +} + +.time-slider::-webkit-slider-thumb { + -webkit-appearance: none; + width: 20px; + height: 20px; + border-radius: 50%; + background: #ffd166; + cursor: pointer; + box-shadow: 0 2px 5px rgba(0,0,0,0.5); +} + +.theme-light .time-slider::-webkit-slider-thumb { + background: #9c5c14; +} + +.theme-contrast .time-slider::-webkit-slider-thumb { + background: #ff0; + border: 2px solid #000; +} + +.no-items { + opacity: 0.6; + margin-top: 2rem; + font-style: italic; + font-size: 1.2rem; +} + +/* Fullscreen Overlay */ +.fullscreen-overlay { + position: fixed; + top: 0; + left: 0; + width: 100vw; + height: 100vh; + background: rgba(0, 0, 0, 0.9); + backdrop-filter: blur(8px); + z-index: 9999; + display: flex; + justify-content: center; + align-items: center; + cursor: zoom-out; +} + +.fullscreen-img { + max-width: 90vw; + max-height: 90vh; + object-fit: contain; + animation: zoomIn 0.2s ease-out; +} + +@keyframes zoomIn { + from { transform: scale(0.8); opacity: 0; } + to { transform: scale(1); opacity: 1; } +} + +.clickable { + cursor: zoom-in; + transition: transform 0.2s; +} + +.clickable:hover { + transform: scale(1.05); +} + +/* Volume Slider */ +.volume-slider-container { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + gap: 0.5rem; + height: 80px; + margin-left: 1rem; +} + +.volume-slider { + appearance: slider-vertical; + -webkit-appearance: slider-vertical; + writing-mode: bt-lr; + width: 8px; + height: 60px; + border-radius: 4px; + background: rgba(0,0,0,0.5); + cursor: pointer; +} + +.theme-light .volume-slider { + background: rgba(0,0,0,0.1); +} + +@media (max-width: 600px) { + .skins-display { + flex-direction: column; + align-items: center; + } + .viewer-img { + width: 120px; + height: 120px; + } + .audio-controls { + gap: 0.5rem; + flex-wrap: wrap; + } + .control-btn { + width: 45px; + height: 45px; + } + .secondary-btn { + width: 60px; + height: 40px; + font-size: 0.85rem; + } + .play-btn { + width: 80px; + height: 50px; + } + .volume-slider-container { + flex-direction: row; + height: auto; + margin-left: 0; + margin-top: 1rem; + width: 100%; + } + .volume-slider { + appearance: none; + -webkit-appearance: none; + writing-mode: horizontal-tb; + width: 100px; + height: 8px; + } + .volume-slider::-webkit-slider-thumb { + -webkit-appearance: none; + width: 15px; + height: 15px; + border-radius: 50%; + background: #ffd166; + cursor: pointer; + } + .theme-light .volume-slider::-webkit-slider-thumb { + background: #9c5c14; + } +} diff --git a/src/app/pages/gallery/gallery.component.html b/src/app/pages/gallery/gallery.component.html new file mode 100644 index 0000000..b1c2fdf --- /dev/null +++ b/src/app/pages/gallery/gallery.component.html @@ -0,0 +1,133 @@ +
+ @if (fullScreenImg) { +
+ Fullscreen Image +
+ } +
+

{{tools.gallery[tools.lang]?.title || 'Gallery'}}

+
+ +
+ + + +
+ + @if (activeSection === 'skins') { + @if (unlockedCheemsSkins.length > 0) { +
+
+

{{tools.getCheemsName(unlockedCheemsSkins[currentIndex])}}

+

{{tools.getCheemsDescription(unlockedCheemsSkins[currentIndex])}}

+
+ +
+
+ {{tools.gallery[tools.lang]?.normalSkin || 'Normal'}} + Normal Skin +
+
+ {{tools.gallery[tools.lang]?.hitSkin || 'Hit'}} + Hit Skin +
+
+ +
+ + {{currentIndex + 1}} / {{unlockedCheemsSkins.length}} + +
+
+ } @else { +

No skins unlocked yet.

+ } + } + + @if (activeSection === 'sfx' || activeSection === 'music') { + @if ((activeSection === 'sfx' && unlockedSoundEffects.length > 0) || (activeSection === 'music' && unlockedMusicTracks.length > 0)) { +
+
+

{{currentAudioName}}

+

{{currentAudioDesc}}

+
+ +
+ @if (currentAudioCover) { +
+ Music Cover +
+ } + + + + @if (activeSection !== 'sfx') { +
+ {{formatTime(currentTime)}} + + {{formatTime(duration)}} +
+ } + +
+ + + @if (activeSection !== 'sfx') { + + } + + + + @if (activeSection !== 'sfx') { + + } + + + + @if (activeSection !== 'sfx') { +
+ 🔊 + +
+ } +
+ +
+ + {{currentIndex + 1}} / {{activeSection === 'sfx' ? unlockedSoundEffects.length : unlockedMusicTracks.length}} + +
+
+
+ } @else { +

No media unlocked yet.

+ } + } +
diff --git a/src/app/pages/gallery/gallery.component.ts b/src/app/pages/gallery/gallery.component.ts new file mode 100644 index 0000000..663c055 --- /dev/null +++ b/src/app/pages/gallery/gallery.component.ts @@ -0,0 +1,228 @@ +import { Component, ElementRef, OnDestroy, OnInit, ViewChild } from '@angular/core'; +import { ToolsService } from '../../services/tools.service'; +import { CommonModule } from '@angular/common'; +import { CheemsSkinItem, MusicTrackItem, SoundEffectItem } from '../../services/constants.service'; + +@Component({ + selector: 'app-gallery', + standalone: true, + imports: [CommonModule], + templateUrl: './gallery.component.html', + styleUrls: ['./gallery.component.css'] +}) +export class GalleryComponent implements OnInit, OnDestroy { + @ViewChild('audioPlayer') audioPlayer!: ElementRef; + + activeSection: 'skins' | 'sfx' | 'music' = 'skins'; + currentIndex: number = 0; + + isPlaying: boolean = false; + currentTime: number = 0; + duration: number = 0; + currentVolume: number = 1; + + fullScreenImg: string | null = null; + + constructor(public tools: ToolsService) {} + + ngOnInit(): void { + this.tools.actPage = "gallery" as any; + } + + ngOnDestroy(): void { + this.resumeBackgroundMusic(); + } + + get unlockedCheemsSkins(): CheemsSkinItem[] { + return this.tools.cheemsSkins.filter(skin => skin.default || this.tools.unlockedCheems[skin.storageKey]); + } + + get unlockedSoundEffects(): SoundEffectItem[] { + return this.tools.soundEffects.filter(sound => sound.default || this.tools.unlockedSounds[sound.storageKey]); + } + + get unlockedMusicTracks(): MusicTrackItem[] { + // Only show valid tracks + return this.tools.musicTracks.filter(track => (track.default || this.tools.unlockedMusic[track.storageKey]) && track.id !== 'music_0'); + } + + openSection(section: 'skins' | 'sfx' | 'music'): void { + this.activeSection = section; + this.currentIndex = 0; + + // Stop current audio if switching away + if (this.audioPlayer?.nativeElement) { + this.audioPlayer.nativeElement.pause(); + this.audioPlayer.nativeElement.currentTime = 0; + this.isPlaying = false; + } + + if (section === 'sfx' || section === 'music') { + this.pauseBackgroundMusic(); + this.loadAudio(); + } else { + this.resumeBackgroundMusic(); + } + } + + openFullScreen(imgUrl: string): void { + this.fullScreenImg = imgUrl; + } + + closeFullScreen(): void { + this.fullScreenImg = null; + } + + private pauseBackgroundMusic(): void { + this.tools.pauseBackground(); + } + + private resumeBackgroundMusic(): void { + this.tools.resumeBackground(); + } + + nextItem(): void { + let listLength = 0; + if (this.activeSection === 'skins') listLength = this.unlockedCheemsSkins.length; + if (this.activeSection === 'sfx') listLength = this.unlockedSoundEffects.length; + if (this.activeSection === 'music') listLength = this.unlockedMusicTracks.length; + + if (listLength > 0) { + this.currentIndex = (this.currentIndex + 1) % listLength; + if (this.activeSection !== 'skins') this.loadAudio(); + } + } + + prevItem(): void { + let listLength = 0; + if (this.activeSection === 'skins') listLength = this.unlockedCheemsSkins.length; + if (this.activeSection === 'sfx') listLength = this.unlockedSoundEffects.length; + if (this.activeSection === 'music') listLength = this.unlockedMusicTracks.length; + + if (listLength > 0) { + this.currentIndex = (this.currentIndex - 1 + listLength) % listLength; + if (this.activeSection !== 'skins') this.loadAudio(); + } + } + + loadAudio(): void { + this.isPlaying = false; + this.currentTime = 0; + this.duration = 0; + if (this.audioPlayer?.nativeElement) { + this.audioPlayer.nativeElement.pause(); + } + setTimeout(() => { + if (this.audioPlayer?.nativeElement) { + this.audioPlayer.nativeElement.currentTime = 0; + this.audioPlayer.nativeElement.load(); + this.audioPlayer.nativeElement.volume = this.currentVolume; + } + }); + } + + get currentAudioSrc(): string { + if (this.activeSection === 'sfx' && this.unlockedSoundEffects.length > 0) { + const sfx = this.unlockedSoundEffects[this.currentIndex]; + return sfx.basePath + (sfx.file || (sfx.files ? sfx.files[0] : '')); + } else if (this.activeSection === 'music' && this.unlockedMusicTracks.length > 0) { + const music = this.unlockedMusicTracks[this.currentIndex]; + return music.basePath + music.file; + } + return ''; + } + + get currentAudioName(): string { + if (this.activeSection === 'sfx' && this.unlockedSoundEffects.length > 0) { + return this.tools.getSoundName(this.unlockedSoundEffects[this.currentIndex]); + } else if (this.activeSection === 'music' && this.unlockedMusicTracks.length > 0) { + return this.tools.getMusicName(this.unlockedMusicTracks[this.currentIndex]); + } + return ''; + } + + get currentAudioCover(): string | null { + if (this.activeSection === 'music' && this.unlockedMusicTracks.length > 0) { + return this.unlockedMusicTracks[this.currentIndex].cover || 'img/music/no_image.png'; + } + return null; + } + + get currentAudioDesc(): string { + if (this.activeSection === 'sfx' && this.unlockedSoundEffects.length > 0) { + return this.tools.getSoundDescription(this.unlockedSoundEffects[this.currentIndex]); + } else if (this.activeSection === 'music' && this.unlockedMusicTracks.length > 0) { + return this.tools.getMusicDescription(this.unlockedMusicTracks[this.currentIndex]); + } + return ''; + } + + togglePlay(): void { + if (this.activeSection === 'sfx' && this.unlockedSoundEffects.length > 0) { + this.tools.playSound(this.unlockedSoundEffects[this.currentIndex].id); + return; + } + + if (this.audioPlayer?.nativeElement) { + if (!this.audioPlayer.nativeElement.paused) { + this.audioPlayer.nativeElement.pause(); + } else { + if (this.audioPlayer.nativeElement.currentTime >= (this.audioPlayer.nativeElement.duration || 0)) { + this.audioPlayer.nativeElement.currentTime = 0; + } + this.audioPlayer.nativeElement.play(); + } + } + } + + skip(seconds: number): void { + if (this.audioPlayer?.nativeElement) { + let newTime = this.audioPlayer.nativeElement.currentTime + seconds; + const dur = this.audioPlayer.nativeElement.duration || 0; + if (newTime > dur) newTime = dur; + if (newTime < 0) newTime = 0; + this.audioPlayer.nativeElement.currentTime = newTime; + } + } + + onVolumeChange(event: any): void { + this.currentVolume = event.target.value; + if (this.audioPlayer?.nativeElement) { + this.audioPlayer.nativeElement.volume = this.currentVolume; + } + } + + onLoadedMetadata(event: any): void { + this.duration = event.target.duration || 0; + } + + onAudioPlay(): void { + this.isPlaying = true; + } + + onAudioPause(): void { + this.isPlaying = false; + } + + onTimeUpdate(event: any): void { + this.currentTime = event.target.currentTime; + this.duration = event.target.duration || 0; + } + + onAudioEnded(): void { + this.isPlaying = false; + } + + onSeek(event: any): void { + if (this.audioPlayer?.nativeElement) { + this.audioPlayer.nativeElement.currentTime = event.target.value; + } + } + + formatTime(seconds: number): string { + if (isNaN(seconds)) return "0:00"; + const mins = Math.floor(seconds / 60); + const secs = Math.floor(seconds % 60); + return `${mins}:${secs < 10 ? '0' : ''}${secs}`; + } +} diff --git a/src/app/pages/game/game.component.css b/src/app/pages/game/game.component.css index df8f2e7..0164bfe 100644 --- a/src/app/pages/game/game.component.css +++ b/src/app/pages/game/game.component.css @@ -1,5 +1,89 @@ -.img-container img { - width: 99%; - height: 80vh; +.game-container { + width: 100%; + min-height: calc(100vh - 150px); + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + position: relative; + cursor: pointer; + user-select: none; + -webkit-user-select: none; + overflow: hidden; + padding: 2rem; +} + +.img-wrapper { + display: flex; + align-items: center; + justify-content: center; + width: 70vw; + max-width: 420px; + height: 60vh; + max-height: 420px; + transition: transform 0.08s cubic-bezier(0.34, 1.56, 0.64, 1); + filter: drop-shadow(0 20px 30px rgba(0, 0, 0, 0.45)); +} + +.img-wrapper.bonked { + transform: scale(0.92) rotate(-3deg); +} + +.cheems-img { + width: 100%; + height: 100%; + object-fit: contain; + pointer-events: none; +} + +.hint-text { + margin-top: 1.5rem; + font-weight: 900; + opacity: 0.85; text-align: center; + letter-spacing: 0.5px; + animation: pulseHint 2s infinite ease-in-out; +} + +@keyframes pulseHint { + 0%, 100% { transform: scale(1); opacity: 0.85; } + 50% { transform: scale(1.05); opacity: 1; } +} + +/* Floating +1 animation */ +.floating-plus { + position: fixed; + pointer-events: none; + font-weight: 900; + font-size: 2.2rem; + z-index: 1000; + transform: translate(-50%, -50%); + animation: floatUp 0.8s ease-out forwards; + text-shadow: 0 3px 10px rgba(0, 0, 0, 0.7); +} + +.floating-plus.theme-dark { + color: #ffd166; +} + +.floating-plus.theme-light { + color: #9c5c14; +} + +.floating-plus.theme-contrast { + color: #00ffff; +} + +@keyframes floatUp { + 0% { + opacity: 1; + transform: translate(-50%, -50%) scale(0.8); + } + 50% { + transform: translate(-50%, -100px) scale(1.3); + } + 100% { + opacity: 0; + transform: translate(-50%, -150px) scale(1); + } } \ No newline at end of file diff --git a/src/app/pages/game/game.component.html b/src/app/pages/game/game.component.html index df8aa13..7b4e5d6 100644 --- a/src/app/pages/game/game.component.html +++ b/src/app/pages/game/game.component.html @@ -1,7 +1,25 @@ -
- @if (clicked) { - - } @else { - +
+
+ @if (clicked) { + Cheems Hit + } @else { + Cheems + } +
+ +
+ {{tools.game[tools.lang].tapToBonk}} +
+ + @for (score of floatingScores; track score.id) { +
+ +{{score.value}} +
}
\ No newline at end of file diff --git a/src/app/pages/game/game.component.ts b/src/app/pages/game/game.component.ts index 4d70776..220bf03 100644 --- a/src/app/pages/game/game.component.ts +++ b/src/app/pages/game/game.component.ts @@ -1,45 +1,82 @@ -import { Component, inject, OnInit } from '@angular/core'; +import { Component, inject, OnInit, OnDestroy } from '@angular/core'; import { ToolsService } from '../../services/tools.service'; +interface FloatingScore { + id: number; + x: number; + y: number; + value: number; +} + @Component({ - selector: 'app-game', - imports: [], - templateUrl: './game.component.html', - styleUrl: './game.component.css' + selector: 'app-game', + imports: [], + templateUrl: './game.component.html', + styleUrl: './game.component.css' }) -export class GameComponent implements OnInit { +export class GameComponent implements OnInit, OnDestroy { tools: ToolsService = inject(ToolsService); clicked: boolean = false; + floatingScores: FloatingScore[] = []; + private nextScoreId: number = 0; + private clickTimeout: any = null; + + private onKeyUpBound = this.onKeyUp.bind(this); ngOnInit(): void { this.tools.setTitle("game"); this.tools.actPage = "game"; - document.addEventListener('keyup', this.onKeyUp.bind(this)); - document.addEventListener('touchend', this.onTouchEnd.bind(this)); + document.addEventListener('keyup', this.onKeyUpBound); } - onKeyUp(event: KeyboardEvent): void { - if (event.key === " ") { - this.onClick(false, event); + ngOnDestroy(): void { + document.removeEventListener('keyup', this.onKeyUpBound); + if (this.clickTimeout) { + clearTimeout(this.clickTimeout); } } - onTouchEnd(event: TouchEvent): void { - this.onClick(false, event); + onKeyUp(event: KeyboardEvent): void { + if (event.code === "Space") { + this.onClick(false, event); + } } onClick(calledDirectly: boolean, event: any = null): void { - if (calledDirectly || !calledDirectly && event.touches === undefined) { - this.clickCheems(); + if (event && event.preventDefault) { + event.preventDefault(); + } + let x = window.innerWidth / 2; + let y = window.innerHeight / 2; + if (event) { + if (event.clientX && event.clientY) { + x = event.clientX; + y = event.clientY; + } else if (event.changedTouches && event.changedTouches.length > 0) { + x = event.changedTouches[0].clientX; + y = event.changedTouches[0].clientY; + } } + this.clickCheems(x, y); } - clickCheems(): void { + clickCheems(x: number, y: number): void { this.clicked = true; - this.tools.updateScore(1); + const gained = this.tools.getActiveMultiplier(); + this.tools.updateScore(gained); this.tools.playSound(); + + const scoreId = this.nextScoreId++; + this.floatingScores.push({ id: scoreId, x, y, value: gained }); setTimeout(() => { + this.floatingScores = this.floatingScores.filter(item => item.id !== scoreId); + }, 800); + + if (this.clickTimeout) { + clearTimeout(this.clickTimeout); + } + this.clickTimeout = setTimeout(() => { this.clicked = false; - }, 600); + }, 250); } } diff --git a/src/app/pages/licenses/licenses.component.css b/src/app/pages/licenses/licenses.component.css new file mode 100644 index 0000000..c74592f --- /dev/null +++ b/src/app/pages/licenses/licenses.component.css @@ -0,0 +1,60 @@ +.licenses-box { + padding: 20px; + border-radius: 12px; + box-shadow: 0 4px 10px rgba(0,0,0,0.2); + margin: 20px auto; + max-width: 800px; + height: 70vh; + overflow-y: auto; + display: block; /* Override .group flex centering to fix top overflow cutoff */ +} + +.licenses-title { + text-align: center; + margin-bottom: 20px; + font-size: 1.8rem; + font-weight: bold; +} + +.licenses-content { + padding: 0 10px; +} + +.licenses-content h3 { + margin-top: 20px; + margin-bottom: 10px; + border-bottom: 1px solid rgba(255, 255, 255, 0.2); + padding-bottom: 5px; +} + +.theme-light .licenses-content h3 { + border-bottom: 1px solid rgba(0, 0, 0, 0.2); +} + +.licenses-content ul { + list-style-type: none; + padding-left: 0; +} + +.licenses-content li { + margin-bottom: 12px; + line-height: 1.4; + word-break: break-word; +} + +.licenses-content a { + color: #3498db; + text-decoration: none; +} + +.licenses-content a:hover { + text-decoration: underline; +} + +.theme-dark .licenses-content a { + color: #5dade2; +} + +.theme-light .licenses-content a { + color: #2980b9; +} diff --git a/src/app/pages/licenses/licenses.component.html b/src/app/pages/licenses/licenses.component.html new file mode 100644 index 0000000..01c2f6b --- /dev/null +++ b/src/app/pages/licenses/licenses.component.html @@ -0,0 +1,58 @@ +
+
+

{{tools.pageName[tools.lang]?.licenses || 'Licenses'}}

+ +
+

SVG & Icons

+ + +

Music

+ +

AI Generated Music

+
    +
  • Bonk The Amber - {{tools.licensesPage[tools.lang]?.aiGeneratedSong}}
  • +
  • Bonk The Avatar - {{tools.licensesPage[tools.lang]?.aiGeneratedSong}}
  • +
  • Bonus Level Bounce - {{tools.licensesPage[tools.lang]?.aiGeneratedSong}}
  • +
  • Button Smash Routine - {{tools.licensesPage[tools.lang]?.aiGeneratedSong}}
  • +
  • Cheems Chan Bonk - {{tools.licensesPage[tools.lang]?.aiGeneratedSong}}
  • +
  • Click For A Bonk - {{tools.licensesPage[tools.lang]?.aiGeneratedSong}}
  • +
  • Hardwood Strike - {{tools.licensesPage[tools.lang]?.aiGeneratedSong}}
  • +
  • Perfect Round - {{tools.licensesPage[tools.lang]?.aiGeneratedSong}}
  • +
  • Pocket Change Victory - {{tools.licensesPage[tools.lang]?.aiGeneratedSong}}
  • +
  • Quick Loot Run - {{tools.licensesPage[tools.lang]?.aiGeneratedSong}}
  • +
  • Target In The Sight - {{tools.licensesPage[tools.lang]?.aiGeneratedSong}}
  • +
  • The Hammer Falls - {{tools.licensesPage[tools.lang]?.aiGeneratedSong}}
  • +
  • The Late Commute - {{tools.licensesPage[tools.lang]?.aiGeneratedSong}}
  • +
  • The Unwritten Page - {{tools.licensesPage[tools.lang]?.aiGeneratedSong}}
  • +
  • Where The Path Bends - {{tools.licensesPage[tools.lang]?.aiGeneratedSong}}
  • +
+

AI Generated Images

+
    +
  • Cheems Minecraft - {{tools.licensesPage[tools.lang]?.aiGeneratedImage}}
  • +
  • Cheems not a dog - {{tools.licensesPage[tools.lang]?.aiGeneratedImage}}
  • +
  • Cheems not a plumber - {{tools.licensesPage[tools.lang]?.aiGeneratedImage}}
  • +
  • Cheems not ai - {{tools.licensesPage[tools.lang]?.aiGeneratedImage}}
  • +
  • Cheems realistic - {{tools.licensesPage[tools.lang]?.aiGeneratedImage}}
  • +
+
+
+
diff --git a/src/app/pages/licenses/licenses.component.ts b/src/app/pages/licenses/licenses.component.ts new file mode 100644 index 0000000..650bdf6 --- /dev/null +++ b/src/app/pages/licenses/licenses.component.ts @@ -0,0 +1,17 @@ +import { Component, inject, OnInit } from '@angular/core'; +import { ToolsService } from '../../services/tools.service'; + +@Component({ + selector: 'app-licenses', + imports: [], + templateUrl: './licenses.component.html', + styleUrl: './licenses.component.css' +}) +export class LicensesComponent implements OnInit { + tools: ToolsService = inject(ToolsService); + + ngOnInit(): void { + this.tools.setTitle("licenses"); + this.tools.actPage = "licenses"; + } +} diff --git a/src/app/pages/menu/menu.component.css b/src/app/pages/menu/menu.component.css index e69de29..1761311 100644 --- a/src/app/pages/menu/menu.component.css +++ b/src/app/pages/menu/menu.component.css @@ -0,0 +1,109 @@ +.menu-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); + gap: 1.25rem; + width: 95%; + max-width: 900px; + margin: 2rem auto; + padding: 2rem; +} + +.menu-card { + display: flex; + flex-direction: row; + align-items: center; + gap: 1rem; + padding: 1.15rem; + border-radius: 16px; + cursor: pointer; + transition: all 0.25s cubic-bezier(0.34, 1.56, 0.64, 1); + box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2); + border: 1px solid transparent; +} + +.menu-card:hover { + transform: translateY(-4px) scale(1.02); + box-shadow: 0 8px 25px rgba(0, 0, 0, 0.35); +} + +.menu-card:active { + transform: translateY(1px) scale(0.98); +} + +.menu-icon { + width: 44px; + height: 44px; + object-fit: contain; + flex-shrink: 0; +} + +.coin-glow { + filter: drop-shadow(0 0 8px rgba(255, 209, 102, 0.7)); +} + +.card-content { + display: flex; + flex-direction: column; +} + +.card-title { + font-weight: 900; + font-size: 1.1em; +} + +.card-sub { + font-size: 0.85em; + opacity: 0.8; +} + +/* Theme specific cards */ +.menu-card.theme-dark { + background: linear-gradient(145deg, rgba(80, 68, 55, 0.85), rgba(50, 42, 33, 0.95)); + border: 1px solid rgba(255, 209, 102, 0.25); + color: rgb(245, 235, 220); +} + +.menu-card.theme-light { + background: linear-gradient(145deg, rgba(255, 245, 230, 0.9), rgba(240, 225, 195, 0.95)); + border: 1px solid rgba(156, 92, 20, 0.3); + color: rgb(70, 45, 20); +} + +.menu-card.theme-contrast { + background: #000000; + border: 2px solid #ffffff; + color: #ffffff; +} + +.menu-card.theme-contrast:hover { + border-color: #ffff00; + color: #ffff00; +} + +/* Dogecoin special card */ +.dogecoin-card.theme-dark { + background: linear-gradient(145deg, rgba(120, 95, 40, 0.9), rgba(75, 55, 20, 0.95)); + border-color: #ffd166; +} + +.dogecoin-card.theme-light { + background: linear-gradient(145deg, rgba(255, 225, 160, 0.95), rgba(245, 205, 130, 0.95)); + border-color: #9c5c14; +} + +.dogecoin-card.theme-contrast { + border-color: #ffff00; + color: #ffff00; +} + +/* Developer card */ +.dev-card { + border-style: dashed !important; +} + +@media (max-width: 600px) { + .menu-grid { + grid-template-columns: 1fr; + padding: 1.25rem; + } +} diff --git a/src/app/pages/menu/menu.component.html b/src/app/pages/menu/menu.component.html index cfb01bd..5438f4b 100644 --- a/src/app/pages/menu/menu.component.html +++ b/src/app/pages/menu/menu.component.html @@ -1,18 +1,69 @@ -
    - -
  • - {{tools.pageName[tools.lang].closet}} -
  • -
  • - {{tools.pageName[tools.lang].devSettings}} -
  • -
  • - {{tools.pageName[tools.lang].onWork}} -
  • -
  • - {{tools.pageName[tools.lang].p404}} -
  • -
  • - {{tools.pageName[tools.lang].settings}} -
  • -
\ No newline at end of file +
+ +
\ No newline at end of file diff --git a/src/app/pages/menu/menu.component.ts b/src/app/pages/menu/menu.component.ts index 85ad3b6..eceea16 100644 --- a/src/app/pages/menu/menu.component.ts +++ b/src/app/pages/menu/menu.component.ts @@ -1,19 +1,23 @@ import { Component, inject, OnInit } from '@angular/core'; import { ToolsService } from '../../services/tools.service'; -import { TextContainerComponent } from "../../components/text-container/text-container.component"; @Component({ - selector: 'app-menu', - imports: [TextContainerComponent], - templateUrl: './menu.component.html', - styleUrl: './menu.component.css' + selector: 'app-menu', + imports: [], + templateUrl: './menu.component.html', + styleUrl: './menu.component.css' }) export class MenuComponent implements OnInit { tools: ToolsService = inject(ToolsService); - + dailyPrice: number = 100; ngOnInit(): void { this.tools.setTitle("menu"); - this.tools.actPage = "menu" + this.tools.actPage = "menu"; + this.dailyPrice = this.tools.getDailyDogeCoinPrice(); + } + + buyDogeCoin(): void { + this.tools.buyDogeCoin(); } } diff --git a/src/app/pages/minigames/minigames.component.css b/src/app/pages/minigames/minigames.component.css new file mode 100644 index 0000000..e829ea4 --- /dev/null +++ b/src/app/pages/minigames/minigames.component.css @@ -0,0 +1,76 @@ +.menu-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); + gap: 1.25rem; + width: 95%; + max-width: 900px; + margin: 2rem auto; + padding: 2rem; +} + +.menu-card { + display: flex; + flex-direction: row; + align-items: center; + gap: 1rem; + padding: 1.15rem; + border-radius: 16px; + cursor: pointer; + transition: all 0.25s cubic-bezier(0.34, 1.56, 0.64, 1); + box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2); + border: 1px solid transparent; +} + +.menu-card:hover { + transform: translateY(-4px) scale(1.02); + box-shadow: 0 8px 25px rgba(0, 0, 0, 0.35); +} + +.menu-card:active { + transform: translateY(1px) scale(0.98); +} + +.menu-icon { + width: 44px; + height: 44px; + object-fit: contain; + flex-shrink: 0; +} + +.coin-glow { + filter: drop-shadow(0 0 8px rgba(255, 209, 102, 0.7)); +} + +.card-content { + display: flex; + flex-direction: column; +} + +.card-title { + font-weight: 900; + font-size: 1.1em; +} + +.menu-card.theme-dark { + background: rgba(30, 30, 40, 0.7); + color: #ffffff; + border-color: rgba(255, 255, 255, 0.08); +} + +.menu-card.theme-light { + background: rgba(255, 255, 255, 0.85); + color: #2b2d42; + border-color: rgba(0, 0, 0, 0.08); +} + +.menu-card.theme-doge { + background: rgba(60, 40, 15, 0.75); + color: #fff8e7; + border-color: rgba(255, 215, 0, 0.2); +} + +.menu-card.theme-red { + background: rgba(50, 15, 20, 0.75); + color: #ffe6e8; + border-color: rgba(255, 100, 100, 0.2); +} diff --git a/src/app/pages/minigames/minigames.component.html b/src/app/pages/minigames/minigames.component.html new file mode 100644 index 0000000..9a44ef5 --- /dev/null +++ b/src/app/pages/minigames/minigames.component.html @@ -0,0 +1,17 @@ +
+ +
diff --git a/src/app/pages/minigames/minigames.component.ts b/src/app/pages/minigames/minigames.component.ts new file mode 100644 index 0000000..d1a9f89 --- /dev/null +++ b/src/app/pages/minigames/minigames.component.ts @@ -0,0 +1,45 @@ +import { Component, inject, OnInit } from '@angular/core'; +import { ToolsService } from '../../services/tools.service'; + +interface MinigameItem { + id: string; + key: string; + defaultTitle: string; +} + +@Component({ + selector: 'app-minigames', + imports: [], + templateUrl: './minigames.component.html', + styleUrl: './minigames.component.css' +}) +export class MinigamesComponent implements OnInit { + tools: ToolsService = inject(ToolsService); + + gamesList: MinigameItem[] = [ + { id: 'block_breaker', key: 'title', defaultTitle: 'Merge Diggers' }, + { id: 'attack_hole', key: 'attack_hole_title', defaultTitle: 'Attack Hole' }, + { id: 'doge_rescue', key: 'doge_rescue_title', defaultTitle: 'Doge Rescue' }, + { id: 'flappy_dunk', key: 'flappy_dunk_title', defaultTitle: 'Flappy Dunk' }, + { id: 'helix_jump', key: 'helix_jump_title', defaultTitle: 'Helix Jump' }, + { id: 'magic_sort', key: 'magic_sort_title', defaultTitle: 'Magic Sort' }, + { id: 'mob_control', key: 'mob_control_title', defaultTitle: 'Mob Control' }, + { id: 'paper_io', key: 'paper_io_title', defaultTitle: 'Paper.io' }, + { id: 'spiral_roll', key: 'spiral_roll_title', defaultTitle: 'Spiral Roll' }, + { id: 'stack_colors', key: 'stack_colors_title', defaultTitle: 'Stack Colors' } + ]; + + ngOnInit(): void { + this.tools.setTitle("minigames"); + this.tools.actPage = "minigames"; + } + + openMinigame(id: string): void { + if (this.tools.isMinigameUnlocked(id)) { + this.tools.redirect('minigames/' + id); + } else { + this.tools.showToast(this.tools.minigames[this.tools.lang]?.buyMinigameInShop || "Unlock this Minigame in the Shop first!"); + this.tools.playSound('sfx_8'); + } + } +} diff --git a/src/app/pages/onwork-page/onwork-page.component.css b/src/app/pages/onwork-page/onwork-page.component.css index e69de29..e493c82 100644 --- a/src/app/pages/onwork-page/onwork-page.component.css +++ b/src/app/pages/onwork-page/onwork-page.component.css @@ -0,0 +1,32 @@ +.work-box { + display: flex; + flex-direction: column; + align-items: center; + gap: 1.5rem; + max-width: 500px; + margin: 3rem auto; + text-align: center; + padding: 2.5rem; +} + +.work-img { + width: 150px; + height: 150px; + object-fit: contain; + filter: drop-shadow(0 10px 20px rgba(0, 0, 0, 0.4)); +} + +.work-title { + font-weight: 900; + font-size: 1.5em; +} + +.work-msg { + opacity: 0.85; + line-height: 1.4; +} + +.work-btn { + margin-top: 1rem; + padding: 0.75rem 2rem; +} diff --git a/src/app/pages/onwork-page/onwork-page.component.html b/src/app/pages/onwork-page/onwork-page.component.html index e69de29..69ebfce 100644 --- a/src/app/pages/onwork-page/onwork-page.component.html +++ b/src/app/pages/onwork-page/onwork-page.component.html @@ -0,0 +1,10 @@ +
+
+ Under Construction +

{{tools.onWork[tools.lang].title}}

+

{{tools.onWork[tools.lang].message}}

+ +
+
diff --git a/src/app/pages/p404/p404.component.css b/src/app/pages/p404/p404.component.css index e69de29..e493c82 100644 --- a/src/app/pages/p404/p404.component.css +++ b/src/app/pages/p404/p404.component.css @@ -0,0 +1,32 @@ +.work-box { + display: flex; + flex-direction: column; + align-items: center; + gap: 1.5rem; + max-width: 500px; + margin: 3rem auto; + text-align: center; + padding: 2.5rem; +} + +.work-img { + width: 150px; + height: 150px; + object-fit: contain; + filter: drop-shadow(0 10px 20px rgba(0, 0, 0, 0.4)); +} + +.work-title { + font-weight: 900; + font-size: 1.5em; +} + +.work-msg { + opacity: 0.85; + line-height: 1.4; +} + +.work-btn { + margin-top: 1rem; + padding: 0.75rem 2rem; +} diff --git a/src/app/pages/p404/p404.component.html b/src/app/pages/p404/p404.component.html index e69de29..0c0e53c 100644 --- a/src/app/pages/p404/p404.component.html +++ b/src/app/pages/p404/p404.component.html @@ -0,0 +1,10 @@ +
+
+ 404 Cheems +

{{tools.p404[tools.lang].title}}

+

{{tools.p404[tools.lang].message}}

+ +
+
diff --git a/src/app/pages/settings/settings.component.css b/src/app/pages/settings/settings.component.css index e69de29..e524f0f 100644 --- a/src/app/pages/settings/settings.component.css +++ b/src/app/pages/settings/settings.component.css @@ -0,0 +1,90 @@ +.settings-box { + display: flex; + flex-direction: column; + gap: 2rem; + width: 90%; + max-width: 750px; + margin: 2rem auto; + padding: 2.5rem; +} + +.setting-row { + display: flex; + flex-direction: column; + align-items: center; + gap: 0.85rem; + width: 100%; + border-bottom: 1px solid rgba(255, 255, 255, 0.15); + padding-bottom: 1.5rem; +} + +.setting-row:last-child { + border-bottom: none; + padding-bottom: 0; +} + +.setting-label { + font-weight: 900; + font-size: 1.1em; +} + +.options-group { + display: flex; + flex-wrap: wrap; + justify-content: center; + gap: 0.75rem; + width: 100%; +} + +.lang-select { + padding: 0.75rem 1.5rem; + font-size: 1.1em; + cursor: pointer; + width: 80%; + max-width: 350px; + text-align: center; + border-radius: 14px; + outline: none; + font-weight: 700; +} + +.lang-select option { + background-color: #2d2823; + color: #ffd166; + font-weight: bold; +} + +body.theme-light .lang-select option { + background-color: #fffaf0; + color: #5a3505; +} + +body.theme-contrast .lang-select option { + background-color: #000000; + color: #ffff00; +} + +.active-opt { + background: #ffd166 !important; + color: #1a1612 !important; + transform: scale(1.05); + box-shadow: 0 4px 15px rgba(255, 209, 102, 0.5) !important; +} + +body.theme-light .active-opt { + background: #9c5c14 !important; + color: #ffffff !important; + box-shadow: 0 4px 15px rgba(156, 92, 20, 0.5) !important; +} + +body.theme-contrast .active-opt { + background: #ffff00 !important; + color: #000000 !important; + border: 2px solid #ffff00 !important; + box-shadow: none !important; +} + +input[type=range] { + width: 80%; + max-width: 350px; +} diff --git a/src/app/pages/settings/settings.component.html b/src/app/pages/settings/settings.component.html index 13f757d..f78fe88 100644 --- a/src/app/pages/settings/settings.component.html +++ b/src/app/pages/settings/settings.component.html @@ -1 +1,98 @@ - \ No newline at end of file +
+
+ +
+ {{tools.options[tools.lang].changeLang.button}} + +
+ + +
+ {{tools.options[tools.lang].musicVolume}} ({{tools.musVol}}%) + +
+ + +
+ {{tools.options[tools.lang].effectsVolume}} ({{tools.effVol}}%) + +
+ + +
+ {{tools.options[tools.lang].appTheme}} +
+ + + +
+
+ + +
+ {{tools.options[tools.lang].fontSize}} +
+ + + + + +
+
+ + +
+ {{tools.options[tools.lang].saveManagement}} +
+ + + + +
+
+
+
\ No newline at end of file diff --git a/src/app/pages/settings/settings.component.ts b/src/app/pages/settings/settings.component.ts index c4e08ea..dab7e7a 100644 --- a/src/app/pages/settings/settings.component.ts +++ b/src/app/pages/settings/settings.component.ts @@ -2,10 +2,10 @@ import { Component, inject, OnInit } from '@angular/core'; import { ToolsService } from '../../services/tools.service'; @Component({ - selector: 'app-settings', - imports: [], - templateUrl: './settings.component.html', - styleUrl: './settings.component.css' + selector: 'app-settings', + imports: [], + templateUrl: './settings.component.html', + styleUrl: './settings.component.css' }) export class SettingsComponent implements OnInit { tools: ToolsService = inject(ToolsService); @@ -13,10 +13,51 @@ export class SettingsComponent implements OnInit { ngOnInit(): void { this.tools.setTitle("settings"); this.tools.actPage = "settings"; - console.log(this.tools.lang) + } + + onMusicVolumeChange(event: any): void { + const value = +event.target.value; + this.tools.setMusicVolume(value); + } + + onEffectsVolumeChange(event: any): void { + const value = +event.target.value; + this.tools.setEffectVolume(value); } changeLanguage(): void { this.tools.changeLanguage(); } + + onLanguageChange(event: any): void { + const key = event.target.value; + this.tools.setLanguage(key); + } + + selectTheme(index: number): void { + this.tools.switchTheme(index); + } + + selectFontSize(index: number): void { + this.tools.setAccessibility(index); + } + + deleteProgress(): void { + if (confirm(this.tools.options[this.tools.lang].deleteProgressConfirm)) { + this.tools.resetToZero(); + } + } + + exportSave(): void { + this.tools.exportSave(); + } + + onFileSelected(event: any): void { + const file = event.target.files[0]; + if (file) { + if (confirm(this.tools.options[this.tools.lang].importSaveConfirm)) { + this.tools.importSave(file); + } + } + } } diff --git a/src/app/pages/shop/shop.component.css b/src/app/pages/shop/shop.component.css new file mode 100644 index 0000000..13b4099 --- /dev/null +++ b/src/app/pages/shop/shop.component.css @@ -0,0 +1,1090 @@ +.shop-container { + max-width: 1100px; + margin: 0 auto; + padding: 2rem 1.5rem 6rem; + color: var(--text-color, #ffffff); + min-height: 85vh; +} + +.shop-header { + text-align: center; + margin-bottom: 2rem; +} + +.shop-title { + font-size: 2.5rem; + font-weight: 800; + margin-bottom: 0.5rem; + background: linear-gradient(135deg, #ffd700, #ff8c00); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + text-shadow: 0 2px 10px rgba(255, 215, 0, 0.2); +} + +.shop-subtitle { + font-size: 1.1rem; + opacity: 0.85; + max-width: 600px; + margin: 0 auto; +} + +/* ======================================== + Section Navigation Buttons + ======================================== */ +.shop-nav-bar { + display: flex; + flex-wrap: wrap; + justify-content: center; + gap: 0.6rem; + margin-bottom: 2rem; + padding: 0.75rem; + background: rgba(255, 255, 255, 0.04); + border-radius: 16px; + border: 1px solid rgba(255, 255, 255, 0.08); +} + +.shop-nav-btn { + padding: 0.6rem 1.2rem; + border-radius: 50px; + font-weight: 700; + font-size: 0.85rem; + cursor: pointer; + border: 2px solid transparent; + background: rgba(255, 255, 255, 0.08); + color: rgba(255, 255, 255, 0.85); + transition: all 0.25s cubic-bezier(0.34, 1.56, 0.64, 1); + backdrop-filter: blur(4px); + letter-spacing: 0.3px; +} + +.shop-nav-btn:hover { + transform: translateY(-2px) scale(1.05); +} + +.shop-nav-btn:active { + transform: translateY(1px) scale(0.97); +} + +/* Per-section accent colors for nav buttons */ +.nav-dogecoin { + border-color: rgba(255, 215, 0, 0.4); + color: #ffd700; +} +.nav-dogecoin:hover { + background: rgba(255, 215, 0, 0.2); + box-shadow: 0 4px 15px rgba(255, 215, 0, 0.3); +} + +.nav-booster { + border-color: rgba(0, 200, 255, 0.4); + color: #00c8ff; +} +.nav-booster:hover { + background: rgba(0, 200, 255, 0.2); + box-shadow: 0 4px 15px rgba(0, 200, 255, 0.3); +} + +.nav-cheems { + border-color: rgba(255, 120, 200, 0.4); + color: #ff78c8; +} +.nav-cheems:hover { + background: rgba(255, 120, 200, 0.2); + box-shadow: 0 4px 15px rgba(255, 120, 200, 0.3); +} + +.nav-sound { + border-color: rgba(0, 230, 130, 0.4); + color: #00e682; +} +.nav-sound:hover { + background: rgba(0, 230, 130, 0.2); + box-shadow: 0 4px 15px rgba(0, 230, 130, 0.3); +} + +.nav-music { + border-color: rgba(180, 120, 255, 0.4); + color: #b478ff; +} +.nav-music:hover { + background: rgba(180, 120, 255, 0.2); + box-shadow: 0 4px 15px rgba(180, 120, 255, 0.3); +} + +.nav-minigames { + border-color: rgba(255, 140, 0, 0.4); + color: #ff8c00; +} +.nav-minigames:hover { + background: rgba(255, 140, 0, 0.2); + box-shadow: 0 4px 15px rgba(255, 140, 0, 0.3); +} + +/* ======================================== + Section Separators / Indicators + ======================================== */ +.section-separator { + display: flex; + align-items: center; + gap: 1rem; + margin: 2.5rem 0 1.5rem; + padding: 0; +} + +.section-separator::before, +.section-separator::after { + content: ''; + flex: 1; + height: 2px; + border-radius: 2px; +} + +.section-title { + font-size: 1.4rem; + font-weight: 800; + letter-spacing: 0.5px; + text-transform: uppercase; + white-space: nowrap; + padding: 0.5rem 1.2rem; + border-radius: 50px; + border: 2px solid transparent; + background: rgba(255, 255, 255, 0.06); + backdrop-filter: blur(6px); +} + +/* Section-specific separator colors */ +.dogecoin-title { + color: #ffd700; + border-color: rgba(255, 215, 0, 0.4); + background: rgba(255, 215, 0, 0.08); +} +.section-separator:has(.dogecoin-title)::before, +.section-separator:has(.dogecoin-title)::after { + background: linear-gradient(90deg, transparent, rgba(255, 215, 0, 0.5), transparent); +} + +.booster-title { + color: #00c8ff; + border-color: rgba(0, 200, 255, 0.4); + background: rgba(0, 200, 255, 0.08); +} +.section-separator:has(.booster-title)::before, +.section-separator:has(.booster-title)::after { + background: linear-gradient(90deg, transparent, rgba(0, 200, 255, 0.5), transparent); +} + +.cheems-title { + color: #ff78c8; + border-color: rgba(255, 120, 200, 0.4); + background: rgba(255, 120, 200, 0.08); +} +.section-separator:has(.cheems-title)::before, +.section-separator:has(.cheems-title)::after { + background: linear-gradient(90deg, transparent, rgba(255, 120, 200, 0.5), transparent); +} + +.sound-title { + color: #00e682; + border-color: rgba(0, 230, 130, 0.4); + background: rgba(0, 230, 130, 0.08); +} +.section-separator:has(.sound-title)::before, +.section-separator:has(.sound-title)::after { + background: linear-gradient(90deg, transparent, rgba(0, 230, 130, 0.5), transparent); +} + +.music-title { + color: #b478ff; + border-color: rgba(180, 120, 255, 0.4); + background: rgba(180, 120, 255, 0.08); +} +.section-separator:has(.music-title)::before, +.section-separator:has(.music-title)::after { + background: linear-gradient(90deg, transparent, rgba(180, 120, 255, 0.5), transparent); +} + +/* ======================================== + Active Booster Banner + ======================================== */ +.active-booster-banner { + display: flex; + align-items: center; + justify-content: center; + gap: 1rem; + background: linear-gradient(135deg, rgba(255, 140, 0, 0.25), rgba(255, 215, 0, 0.15)); + border: 2px solid #ffd700; + border-radius: 16px; + padding: 1rem 1.5rem; + margin-bottom: 2rem; + box-shadow: 0 0 25px rgba(255, 215, 0, 0.3); + animation: boosterPulse 2s infinite ease-in-out; +} + +@keyframes boosterPulse { + 0%, 100% { box-shadow: 0 0 20px rgba(255, 215, 0, 0.3); } + 50% { box-shadow: 0 0 35px rgba(255, 215, 0, 0.6); } +} + +.booster-banner-icon { + font-size: 2.2rem; +} + +.booster-banner-content { + display: flex; + flex-wrap: wrap; + align-items: center; + gap: 1.5rem; + font-size: 1.1rem; +} + +.booster-banner-timer { + background: rgba(0, 0, 0, 0.4); + padding: 0.4rem 0.8rem; + border-radius: 8px; + font-weight: 700; + color: #ffd700; + border: 1px solid rgba(255, 215, 0, 0.4); +} + +/* ======================================== + Balance Bar + ======================================== */ +.shop-balance-bar { + display: flex; + justify-content: center; + gap: 2.5rem; + margin-bottom: 2.5rem; + background: rgba(255, 255, 255, 0.05); + backdrop-filter: blur(10px); + border: 1px solid rgba(255, 255, 255, 0.12); + padding: 0.9rem 2rem; + border-radius: 50px; + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.2); +} + +.balance-item { + display: flex; + align-items: center; + gap: 0.6rem; + font-size: 1.1rem; +} + +.balance-label { + opacity: 0.7; + font-weight: 500; +} + +.balance-value { + font-weight: 800; + font-size: 1.25rem; + display: flex; + align-items: center; + gap: 0.4rem; +} + +.points-val { + color: #ffd700; +} + +.doge-val { + color: #ff9900; +} + +.mini-coin-icon { + width: 24px; + height: 24px; + object-fit: contain; +} + +/* ======================================== + Shop Grid & Cards + ======================================== */ +.shop-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); + gap: 1.8rem; +} + +.shop-card { + background: rgba(255, 255, 255, 0.07); + backdrop-filter: blur(12px); + border: 1px solid rgba(255, 255, 255, 0.15); + border-radius: 20px; + padding: 1.5rem; + display: flex; + flex-direction: column; + justify-content: space-between; + transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1); + box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.25); + position: relative; + overflow: hidden; +} + +.shop-card:hover { + transform: translateY(-6px); + box-shadow: 0 14px 40px 0 rgba(0, 0, 0, 0.4); + border-color: rgba(255, 215, 0, 0.4); +} + +.shop-card.coin-card { + background: linear-gradient(135deg, rgba(255, 215, 0, 0.12), rgba(255, 140, 0, 0.06)); + border-color: rgba(255, 215, 0, 0.35); +} +.shop-card.coin-card:hover { + border-color: rgba(255, 215, 0, 0.6); + box-shadow: 0 14px 40px rgba(255, 215, 0, 0.15); +} + +.shop-card.booster-card { + background: linear-gradient(135deg, rgba(0, 200, 255, 0.08), rgba(120, 0, 255, 0.08)); + border-color: rgba(0, 200, 255, 0.25); +} +.shop-card.booster-card:hover { + border-color: rgba(0, 200, 255, 0.5); + box-shadow: 0 14px 40px rgba(0, 200, 255, 0.12); +} + +/* Cheems Skins card color */ +.shop-card.cheems-card { + background: linear-gradient(135deg, rgba(255, 120, 200, 0.08), rgba(255, 80, 160, 0.05)); + border-color: rgba(255, 120, 200, 0.25); +} +.shop-card.cheems-card:hover { + border-color: rgba(255, 120, 200, 0.5); + box-shadow: 0 14px 40px rgba(255, 120, 200, 0.12); +} + +/* Sound Effects card color */ +.shop-card.sound-card { + background: linear-gradient(135deg, rgba(0, 230, 130, 0.08), rgba(0, 180, 100, 0.05)); + border-color: rgba(0, 230, 130, 0.25); +} +.shop-card.sound-card:hover { + border-color: rgba(0, 230, 130, 0.5); + box-shadow: 0 14px 40px rgba(0, 230, 130, 0.12); +} + +/* Music card color */ +.shop-card.music-card { + background: linear-gradient(135deg, rgba(180, 120, 255, 0.08), rgba(140, 80, 220, 0.05)); + border-color: rgba(180, 120, 255, 0.25); +} +.shop-card.music-card:hover { + border-color: rgba(180, 120, 255, 0.5); + box-shadow: 0 14px 40px rgba(180, 120, 255, 0.12); +} + +/* DogeCoin to Minigame Points exchange (Silver / Plate style) */ +.shop-card.currency-dgc-to-mg-card { + background: linear-gradient(135deg, rgba(220, 225, 230, 0.15), rgba(160, 170, 185, 0.08)); + border-color: rgba(200, 210, 225, 0.4); +} +.shop-card.currency-dgc-to-mg-card:hover { + border-color: rgba(230, 240, 255, 0.8); + box-shadow: 0 14px 40px rgba(200, 220, 240, 0.25); +} +.shop-card.currency-dgc-to-mg-card .item-name { + color: #e2e8f0; +} + +/* Minigame Points to DogeCoin exchange (Golden style) */ +.shop-card.currency-mg-to-dgc-card { + background: linear-gradient(135deg, rgba(255, 215, 0, 0.18), rgba(255, 140, 0, 0.1)); + border-color: rgba(255, 215, 0, 0.5); +} +.shop-card.currency-mg-to-dgc-card:hover { + border-color: rgba(255, 215, 0, 0.85); + box-shadow: 0 14px 40px rgba(255, 215, 0, 0.3); +} +.shop-card.currency-mg-to-dgc-card .item-name { + color: #ffd700; +} + +.shop-card-icon-wrapper { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 1.2rem; +} + +.shop-card-icon { + width: 56px; + height: 56px; + object-fit: contain; + filter: drop-shadow(0 4px 8px rgba(0, 0, 0, 0.3)); +} + +.shop-card-emoji { + font-size: 3rem; +} + +.multiplier-badge { + background: linear-gradient(135deg, #00c6ff, #0072ff); + color: #fff; + font-weight: 800; + font-size: 1rem; + padding: 0.3rem 0.8rem; + border-radius: 50px; + box-shadow: 0 2px 10px rgba(0, 114, 255, 0.4); +} + +.shop-card-info { + flex-grow: 1; + margin-bottom: 1.5rem; +} + +.item-name { + font-size: 1.35rem; + font-weight: 700; + margin-bottom: 0.5rem; + color: #fff; +} + +.item-desc { + font-size: 0.95rem; + opacity: 0.8; + line-height: 1.45; +} + +.shop-card-footer { + display: flex; + align-items: center; + justify-content: space-between; + border-top: 1px solid rgba(255, 255, 255, 0.1); + padding-top: 1.2rem; +} + +.item-cost { + display: flex; + flex-direction: column; +} + +.cost-label { + font-size: 0.75rem; + opacity: 0.6; + text-transform: uppercase; +} + +.cost-val { + font-size: 1.3rem; + font-weight: 800; + color: #ffd700; +} + +.buy-btn { + background: linear-gradient(135deg, #ffd700, #ff8c00); + color: #111; + border: none; + padding: 0.65rem 1.6rem; + font-size: 1rem; + font-weight: 800; + border-radius: 12px; + cursor: pointer; + transition: all 0.2s ease; + box-shadow: 0 4px 15px rgba(255, 140, 0, 0.3); +} + +.buy-btn:hover:not(:disabled) { + transform: scale(1.05); + box-shadow: 0 6px 20px rgba(255, 140, 0, 0.5); + background: linear-gradient(135deg, #ffe033, #ff991a); +} + +.buy-btn:active:not(:disabled) { + transform: scale(0.97); +} + +.buy-btn:disabled { + background: rgba(255, 255, 255, 0.15); + color: rgba(255, 255, 255, 0.4); + cursor: not-allowed; + box-shadow: none; +} + +/* ======================================== + Daily Limit & Free Cost Badges + ======================================== */ +.daily-limit-badge { + display: inline-block; + background: rgba(245, 158, 11, 0.2); + color: #fbbf24; + border: 1px solid rgba(245, 158, 11, 0.4); + border-radius: 20px; + padding: 0.25rem 0.65rem; + font-size: 0.75rem; + font-weight: 700; + margin-top: 0.5rem; +} + +.daily-limit-badge.limit-reached { + background: rgba(239, 68, 68, 0.2); + color: #f87171; + border-color: rgba(239, 68, 68, 0.4); +} + +.cost-val.free-cost { + color: #10b981; + font-weight: 900; +} + +/* ======================================== + Back to Top Button (Fixed / Floating) + ======================================== */ +.back-to-top-btn { + position: fixed; + bottom: 2rem; + right: 2rem; + z-index: 1000; + width: 50px; + height: 50px; + border-radius: 50%; + border: none; + font-size: 1.5rem; + font-weight: 900; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + transition: all 0.3s cubic-bezier(0.34, 1.56, 0.64, 1); + opacity: 0; + pointer-events: none; + transform: translateY(20px) scale(0.8); + + /* Dark theme default */ + background: linear-gradient(135deg, #ffd700, #ff8c00); + color: #111; + box-shadow: 0 6px 25px rgba(255, 140, 0, 0.4); +} + +.back-to-top-btn.visible { + opacity: 1; + pointer-events: auto; + transform: translateY(0) scale(1); +} + +.back-to-top-btn:hover { + transform: translateY(-3px) scale(1.1); + box-shadow: 0 10px 35px rgba(255, 140, 0, 0.6); +} + +.back-to-top-btn:active { + transform: translateY(0) scale(0.95); +} + +/* Back to top — Light theme */ +.back-to-top-btn.theme-light { + background: linear-gradient(135deg, #b35900, #d97706); + color: #fff; + box-shadow: 0 6px 25px rgba(180, 100, 0, 0.35); +} +.back-to-top-btn.theme-light:hover { + box-shadow: 0 10px 35px rgba(180, 100, 0, 0.55); +} + +/* Back to top — Contrast theme */ +.back-to-top-btn.theme-contrast { + background: #000000; + color: #ffff00; + border: 2px solid #ffff00; + box-shadow: none; +} +.back-to-top-btn.theme-contrast:hover { + background: #ffff00; + color: #000000; +} + +/* ======================================== + Responsive + ======================================== */ +@media (max-width: 600px) { + .shop-balance-bar { + flex-direction: column; + align-items: center; + gap: 0.8rem; + border-radius: 20px; + } + .shop-title { + font-size: 2rem; + } + .booster-banner-content { + flex-direction: column; + gap: 0.5rem; + text-align: center; + } + .shop-nav-bar { + gap: 0.4rem; + padding: 0.5rem; + } + .shop-nav-btn { + padding: 0.5rem 0.9rem; + font-size: 0.78rem; + } + .section-title { + font-size: 1.1rem; + padding: 0.4rem 1rem; + } + .back-to-top-btn { + bottom: 1.2rem; + right: 1.2rem; + width: 44px; + height: 44px; + font-size: 1.3rem; + } +} + +/* ======================================== + THEME: LIGHT MODE + ======================================== */ +.shop-container.theme-light { + color: #2b1f14; +} + +.shop-container.theme-light .shop-title { + background: linear-gradient(135deg, #b35900, #d97706); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + text-shadow: none; +} + +.shop-container.theme-light .shop-subtitle { + color: #4a3525; + opacity: 0.95; + font-weight: 600; +} + +/* Light — Nav bar */ +.shop-container.theme-light .shop-nav-bar { + background: rgba(180, 120, 50, 0.08); + border-color: rgba(180, 120, 50, 0.2); +} + +.shop-container.theme-light .shop-nav-btn { + background: rgba(255, 255, 255, 0.7); + color: #4a3525; + border-color: rgba(180, 120, 50, 0.25); +} + +.shop-container.theme-light .nav-dogecoin { + color: #b35900; + border-color: rgba(179, 89, 0, 0.4); +} +.shop-container.theme-light .nav-dogecoin:hover { + background: rgba(179, 89, 0, 0.12); + box-shadow: 0 4px 12px rgba(179, 89, 0, 0.2); +} + +.shop-container.theme-light .nav-booster { + color: #0072cc; + border-color: rgba(0, 114, 204, 0.4); +} +.shop-container.theme-light .nav-booster:hover { + background: rgba(0, 114, 204, 0.1); + box-shadow: 0 4px 12px rgba(0, 114, 204, 0.2); +} + +.shop-container.theme-light .nav-cheems { + color: #c2185b; + border-color: rgba(194, 24, 91, 0.4); +} +.shop-container.theme-light .nav-cheems:hover { + background: rgba(194, 24, 91, 0.1); + box-shadow: 0 4px 12px rgba(194, 24, 91, 0.2); +} + +.shop-container.theme-light .nav-sound { + color: #00875a; + border-color: rgba(0, 135, 90, 0.4); +} +.shop-container.theme-light .nav-sound:hover { + background: rgba(0, 135, 90, 0.1); + box-shadow: 0 4px 12px rgba(0, 135, 90, 0.2); +} + +.shop-container.theme-light .nav-music { + color: #6a1b9a; + border-color: rgba(106, 27, 154, 0.4); +} +.shop-container.theme-light .nav-music:hover { + background: rgba(106, 27, 154, 0.1); + box-shadow: 0 4px 12px rgba(106, 27, 154, 0.2); +} + +/* Light — Section separators */ +.shop-container.theme-light .section-title { + background: rgba(255, 255, 255, 0.8); +} + +.shop-container.theme-light .dogecoin-title { + color: #b35900; + border-color: rgba(179, 89, 0, 0.4); +} +.shop-container.theme-light .section-separator:has(.dogecoin-title)::before, +.shop-container.theme-light .section-separator:has(.dogecoin-title)::after { + background: linear-gradient(90deg, transparent, rgba(179, 89, 0, 0.4), transparent); +} + +.shop-container.theme-light .booster-title { + color: #0072cc; + border-color: rgba(0, 114, 204, 0.4); +} +.shop-container.theme-light .section-separator:has(.booster-title)::before, +.shop-container.theme-light .section-separator:has(.booster-title)::after { + background: linear-gradient(90deg, transparent, rgba(0, 114, 204, 0.4), transparent); +} + +.shop-container.theme-light .cheems-title { + color: #c2185b; + border-color: rgba(194, 24, 91, 0.4); +} +.shop-container.theme-light .section-separator:has(.cheems-title)::before, +.shop-container.theme-light .section-separator:has(.cheems-title)::after { + background: linear-gradient(90deg, transparent, rgba(194, 24, 91, 0.4), transparent); +} + +.shop-container.theme-light .sound-title { + color: #00875a; + border-color: rgba(0, 135, 90, 0.4); +} +.shop-container.theme-light .section-separator:has(.sound-title)::before, +.shop-container.theme-light .section-separator:has(.sound-title)::after { + background: linear-gradient(90deg, transparent, rgba(0, 135, 90, 0.4), transparent); +} + +.shop-container.theme-light .music-title { + color: #6a1b9a; + border-color: rgba(106, 27, 154, 0.4); +} +.shop-container.theme-light .section-separator:has(.music-title)::before, +.shop-container.theme-light .section-separator:has(.music-title)::after { + background: linear-gradient(90deg, transparent, rgba(106, 27, 154, 0.4), transparent); +} + +/* Light — Balance bar */ +.shop-container.theme-light .shop-balance-bar { + background: rgba(255, 255, 255, 0.85); + border: 2px solid rgba(180, 120, 50, 0.35); + box-shadow: 0 4px 20px rgba(100, 70, 30, 0.15); +} + +.shop-container.theme-light .balance-label { + color: #4a3525; + opacity: 0.9; +} + +.shop-container.theme-light .points-val { + color: #b35900; +} + +.shop-container.theme-light .doge-val { + color: #d97706; +} + +/* Light — Cards */ +.shop-container.theme-light .shop-card { + background: rgba(255, 255, 255, 0.9); + border: 2px solid rgba(180, 120, 50, 0.35); + color: #2b1f14; + box-shadow: 0 8px 24px rgba(100, 70, 30, 0.15); +} + +.shop-container.theme-light .shop-card.coin-card { + background: linear-gradient(135deg, rgba(255, 245, 210, 0.95), rgba(255, 235, 180, 0.95)); + border-color: #d97706; +} + +.shop-container.theme-light .shop-card.booster-card { + background: linear-gradient(135deg, rgba(230, 248, 255, 0.95), rgba(240, 235, 255, 0.95)); + border-color: #0072ff; +} + +.shop-container.theme-light .shop-card.cheems-card { + background: linear-gradient(135deg, rgba(255, 230, 245, 0.95), rgba(255, 215, 240, 0.95)); + border-color: #c2185b; +} + +.shop-container.theme-light .shop-card.sound-card { + background: linear-gradient(135deg, rgba(220, 255, 240, 0.95), rgba(200, 245, 225, 0.95)); + border-color: #00875a; +} + +.shop-container.theme-light .shop-card.music-card { + background: linear-gradient(135deg, rgba(240, 225, 255, 0.95), rgba(230, 210, 255, 0.95)); + border-color: #6a1b9a; +} + +.shop-container.theme-light .item-name { + color: #1a120b; + font-weight: 800; +} + +.shop-container.theme-light .item-desc { + color: #3d2c1e; + opacity: 0.95; + font-weight: 500; +} + +.shop-container.theme-light .cost-label { + color: #5c432d; + opacity: 0.85; + font-weight: 700; +} + +.shop-container.theme-light .cost-val { + color: #b35900; + font-weight: 900; +} + +.shop-container.theme-light .shop-card-footer { + border-top-color: rgba(180, 120, 50, 0.25); +} + +.shop-container.theme-light .active-booster-banner { + background: linear-gradient(135deg, rgba(255, 235, 180, 0.95), rgba(255, 215, 130, 0.95)); + border: 2px solid #b35900; + color: #1a120b; + box-shadow: 0 4px 20px rgba(180, 120, 50, 0.25); +} + +.shop-container.theme-light .booster-banner-timer { + background: #fff; + color: #b35900; + border-color: #b35900; +} + +.shop-container.theme-light .daily-limit-badge { + background: rgba(180, 120, 50, 0.15); + color: #8c4600; + border-color: rgba(180, 120, 50, 0.4); +} + +.shop-container.theme-light .daily-limit-badge.limit-reached { + background: rgba(220, 38, 38, 0.15); + color: #b91c1c; + border-color: rgba(220, 38, 38, 0.4); +} + +.shop-container.theme-light .cost-val.free-cost { + color: #059669; +} + +.shop-container.theme-light .buy-btn { + background: linear-gradient(135deg, #b35900, #d97706); + color: #fff; +} +.shop-container.theme-light .buy-btn:hover:not(:disabled) { + background: linear-gradient(135deg, #cc6600, #e08a0f); +} +.shop-container.theme-light .buy-btn:disabled { + background: rgba(180, 120, 50, 0.2); + color: rgba(100, 70, 30, 0.5); +} + +/* ======================================== + THEME: HIGH CONTRAST + ======================================== */ +.shop-container.theme-contrast { + color: #ffffff; +} + +.shop-container.theme-contrast .shop-title { + background: none; + -webkit-background-clip: unset; + -webkit-text-fill-color: #ffff00; + text-shadow: none; +} + +.shop-container.theme-contrast .shop-subtitle { + color: #ffffff; + opacity: 1; +} + +/* Contrast — Nav bar */ +.shop-container.theme-contrast .shop-nav-bar { + background: #000000; + border: 2px solid #ffffff; + border-radius: 12px; +} + +.shop-container.theme-contrast .shop-nav-btn { + background: #000000; + color: #ffff00; + border: 2px solid #ffff00; + border-radius: 50px; + backdrop-filter: none; +} +.shop-container.theme-contrast .shop-nav-btn:hover { + background: #ffff00; + color: #000000; + box-shadow: none; +} + +/* Override per-section colors in contrast — all buttons use yellow */ +.shop-container.theme-contrast .nav-dogecoin, +.shop-container.theme-contrast .nav-booster, +.shop-container.theme-contrast .nav-cheems, +.shop-container.theme-contrast .nav-sound, +.shop-container.theme-contrast .nav-music { + color: #ffff00; + border-color: #ffff00; +} +.shop-container.theme-contrast .nav-dogecoin:hover, +.shop-container.theme-contrast .nav-booster:hover, +.shop-container.theme-contrast .nav-cheems:hover, +.shop-container.theme-contrast .nav-sound:hover, +.shop-container.theme-contrast .nav-music:hover { + background: #ffff00; + color: #000000; + box-shadow: none; +} + +/* Contrast — Section separators */ +.shop-container.theme-contrast .section-separator::before, +.shop-container.theme-contrast .section-separator::after { + background: #ffffff !important; + height: 2px; +} + +.shop-container.theme-contrast .section-title { + background: #000000; + color: #ffff00; + border: 2px solid #ffff00; +} + +/* Override all section title colors in contrast */ +.shop-container.theme-contrast .dogecoin-title, +.shop-container.theme-contrast .booster-title, +.shop-container.theme-contrast .cheems-title, +.shop-container.theme-contrast .sound-title, +.shop-container.theme-contrast .music-title { + color: #ffff00; + border-color: #ffff00; + background: #000000; +} + +/* Contrast — Balance bar */ +.shop-container.theme-contrast .shop-balance-bar { + background: #000000; + border: 2px solid #ffffff; + box-shadow: none; + backdrop-filter: none; +} + +.shop-container.theme-contrast .balance-label { + color: #ffffff; + opacity: 1; +} + +.shop-container.theme-contrast .points-val { + color: #ffff00; +} + +.shop-container.theme-contrast .doge-val { + color: #ffff00; +} + +/* Contrast — Cards */ +.shop-container.theme-contrast .shop-card { + background: #000000; + border: 2px solid #ffffff; + color: #ffffff; + box-shadow: none; + backdrop-filter: none; +} + +.shop-container.theme-contrast .shop-card:hover { + border-color: #ffff00; + box-shadow: none; +} + +/* All card type variants collapse to same contrast style */ +.shop-container.theme-contrast .shop-card.coin-card, +.shop-container.theme-contrast .shop-card.booster-card, +.shop-container.theme-contrast .shop-card.cheems-card, +.shop-container.theme-contrast .shop-card.sound-card, +.shop-container.theme-contrast .shop-card.music-card { + background: #000000; + border-color: #ffffff; +} +.shop-container.theme-contrast .shop-card.coin-card:hover, +.shop-container.theme-contrast .shop-card.booster-card:hover, +.shop-container.theme-contrast .shop-card.cheems-card:hover, +.shop-container.theme-contrast .shop-card.sound-card:hover, +.shop-container.theme-contrast .shop-card.music-card:hover { + border-color: #ffff00; +} + +.shop-container.theme-contrast .item-name { + color: #ffffff; +} + +.shop-container.theme-contrast .item-desc { + color: #ffffff; + opacity: 1; +} + +.shop-container.theme-contrast .cost-val { + color: #ffff00; +} + +.shop-container.theme-contrast .cost-label { + color: #ffffff; + opacity: 1; +} + +.shop-container.theme-contrast .shop-card-footer { + border-top-color: #ffffff; +} + +.shop-container.theme-contrast .multiplier-badge { + background: #000000; + color: #ffff00; + border: 2px solid #ffff00; + box-shadow: none; +} + +.shop-container.theme-contrast .buy-btn { + background: #000000; + color: #ffff00; + border: 2px solid #ffff00; + box-shadow: none; +} +.shop-container.theme-contrast .buy-btn:hover:not(:disabled) { + background: #ffff00; + color: #000000; + box-shadow: none; +} +.shop-container.theme-contrast .buy-btn:disabled { + background: #000000; + color: #666666; + border-color: #666666; + box-shadow: none; +} + +.shop-container.theme-contrast .active-booster-banner { + background: #000000; + border: 2px solid #ffff00; + color: #ffffff; + box-shadow: none; + animation: none; +} + +.shop-container.theme-contrast .booster-banner-timer { + background: #000000; + color: #ffff00; + border-color: #ffff00; +} + +.shop-container.theme-contrast .daily-limit-badge { + background: #000000; + color: #ffff00; + border: 2px solid #ffff00; +} + +.shop-container.theme-contrast .daily-limit-badge.limit-reached { + color: #ff4444; + border-color: #ff4444; +} + +.shop-container.theme-contrast .cost-val.free-cost { + color: #00ff00; +} diff --git a/src/app/pages/shop/shop.component.html b/src/app/pages/shop/shop.component.html new file mode 100644 index 0000000..1cb0f08 --- /dev/null +++ b/src/app/pages/shop/shop.component.html @@ -0,0 +1,217 @@ +
+ +
+

{{tools.shop[tools.lang]?.title || 'Shop'}}

+

{{tools.shop[tools.lang]?.subtitle}}

+
+ + +
+ @if (dogecoinItems.length > 0) { + + } + @if (minigameItems.length > 0) { + + } + @if (boosterItems.length > 0) { + + } + @if (cheemsItems.length > 0) { + + } + @if (soundItems.length > 0) { + + } + @if (musicItems.length > 0) { + + } +
+ + + @if (tools.getBoosterRemainingSeconds() > 0) { +
+
+
+ + {{tools.shop[tools.lang]?.activeBooster || 'Active Booster:'}} + x{{tools.getActiveMultiplier()}} {{tools.shop[tools.lang]?.pointsPerClick || 'Points per Click'}} + + + ⏳ {{tools.getBoosterFormattedTime()}} {{tools.shop[tools.lang]?.remaining || 'remaining'}} + +
+
+ } + + +
+
+ Points: + {{tools.points | number}} Pts +
+
+ DogeCoins: + + DogeCoin + {{tools.dogeCoins}} + +
+
+ Minigame Pts: + 🎮 {{tools.minigameCoins | number}} +
+
+ + + +
+
+ @if (item.icon.endsWith('.svg') || item.icon.endsWith('.png')) { + + } @else { + {{item.icon}} + } + @if (item.type === 'booster') { + x{{item.multiplier || 1}} + } +
+ +
+

{{tools.getShopItemName(item)}}

+

{{tools.getShopItemDesc(item)}}

+ @if (tools.isLifetimeLimitReached(item)) { +
+ {{tools.shop[tools.lang]?.purchased || 'Purchased'}} +
+ } @else if (item.dailyLimit && item.dailyLimit > 0) { +
+ {{tools.getRemainingDailyLimit(item)}} / {{item.dailyLimit}} {{tools.shop[tools.lang]?.remainingToday || 'left today'}} +
+ } +
+ + +
+
+ + + @if (dogecoinItems.length > 0) { +
+

{{tools.shop[tools.lang]?.currencySection || 'Currency'}}

+
+
+ @for (item of dogecoinItems; track item.id) { + + } +
+ } + + + @if (minigameItems.length > 0) { +
+

{{tools.shop[tools.lang]?.minigamesSection || 'Minigames'}}

+
+
+ @for (item of minigameItems; track item.id) { + + } +
+ } + + + @if (boosterItems.length > 0) { +
+

{{tools.shop[tools.lang]?.boosterSection || 'Boosters'}}

+
+
+ @for (item of boosterItems; track item.id) { + + } +
+ } + + + @if (cheemsItems.length > 0) { +
+

{{tools.shop[tools.lang]?.cheemsSection || 'Cheems Skins'}}

+
+
+ @for (item of cheemsItems; track item.id) { + + } +
+ } + + + @if (soundItems.length > 0) { +
+

{{tools.shop[tools.lang]?.sfxSection || 'Sound Effects'}}

+
+
+ @for (item of soundItems; track item.id) { + + } +
+ } + + + @if (musicItems.length > 0) { +
+

{{tools.shop[tools.lang]?.musicSection || 'Background Music'}}

+
+
+ @for (item of musicItems; track item.id) { + + } +
+ } + + + +
diff --git a/src/app/pages/shop/shop.component.ts b/src/app/pages/shop/shop.component.ts new file mode 100644 index 0000000..6c7b556 --- /dev/null +++ b/src/app/pages/shop/shop.component.ts @@ -0,0 +1,219 @@ +import { Component, inject, OnInit, OnDestroy, HostListener } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { ToolsService } from '../../services/tools.service'; +import { ShopItem } from '../../services/constants.service'; + +@Component({ + selector: 'app-shop', + standalone: true, + imports: [CommonModule], + templateUrl: './shop.component.html', + styleUrl: './shop.component.css' +}) +export class ShopComponent implements OnInit, OnDestroy { + tools: ToolsService = inject(ToolsService); + dailyPrice: number = 100; + showScrollTop: boolean = false; + private timerInterval: any = null; + + ngOnInit(): void { + this.tools.setTitle("shop"); + this.tools.actPage = "shop"; + this.dailyPrice = this.tools.getDailyDogeCoinPrice(); + if (this.tools.shopItems.length === 0) { + this.tools.loadShopItems(); + } + this.timerInterval = setInterval(() => { + // Refresh component for live timer updates + }, 1000); + } + + ngOnDestroy(): void { + if (this.timerInterval) { + clearInterval(this.timerInterval); + } + } + + @HostListener('window:scroll') + onWindowScroll(): void { + this.showScrollTop = window.scrollY > 300; + } + + buyItem(item: ShopItem): void { + if (!this.tools.canBuyDailyLimit(item)) { + this.tools.showToast(this.tools.shop[this.tools.lang]?.dailyLimitReached || "Daily limit reached!"); + return; + } + + if (this.tools.isLifetimeLimitReached(item)) { + return; + } + + if (item.type === 'dogecoin') { + const coinsGiven = item.coinsGiven || 1; + this.tools.buyDogeCoin(item.cost, coinsGiven, item.id); + } else if (item.type === 'currency') { + const ptsCost = item.cost || 0; + const coinCost = item.costCoins || 0; + const mgCost = item.costMinigames || 0; + if (this.tools.points >= ptsCost && this.tools.dogeCoins >= coinCost && this.tools.minigameCoins >= mgCost) { + this.tools.points -= ptsCost; + this.tools.dogeCoins -= coinCost; + this.tools.minigameCoins -= mgCost; + if (item.coinsGiven) { + this.tools.dogeCoins += item.coinsGiven; + } + if (item.minigameCoinsGiven) { + this.tools.addMinigameCoins(item.minigameCoinsGiven); + } + this.tools.saveData("points", String(this.tools.points)); + this.tools.saveData("dg", String(this.tools.dogeCoins)); + this.tools.saveData("mg", String(this.tools.minigameCoins)); + this.tools.recordDailyPurchase(item.id); + this.tools.showToast(this.tools.closet[this.tools.lang]?.purchased || "Purchased!"); + this.tools.playSound('sfx_4'); + } else { + this.tools.showToast(this.tools.shop[this.tools.lang]?.notEnoughCoins || "Not enough currency!"); + } + } else if (item.type === 'minigame') { + const ptsCost = item.cost || 0; + const coinCost = item.costCoins || 0; + const mgCost = item.costMinigames || 0; + if (this.tools.points >= ptsCost && this.tools.dogeCoins >= coinCost && this.tools.minigameCoins >= mgCost) { + this.tools.points -= ptsCost; + this.tools.dogeCoins -= coinCost; + this.tools.minigameCoins -= mgCost; + this.tools.saveData("points", String(this.tools.points)); + this.tools.saveData("dg", String(this.tools.dogeCoins)); + this.tools.saveData("mg", String(this.tools.minigameCoins)); + const target = String(item.targetId || item.id); + this.tools.unlockedMinigames[target] = true; + this.tools.saveUnlockedMinigames(); + this.tools.recordLifetimePurchase(item.id); + this.tools.showToast(this.tools.closet[this.tools.lang]?.purchased || "Purchased!"); + this.tools.playSound('sfx_4'); + } else { + this.tools.showToast(this.tools.shop[this.tools.lang]?.notEnoughCoins || "Not enough currency!"); + } + } else if (item.type === 'booster') { + const ptsCost = item.cost || 0; + const coinCost = item.costCoins || 0; + if (this.tools.points >= ptsCost && this.tools.dogeCoins >= coinCost) { + const isOverride = this.tools.boosterEndTime !== 0 && this.tools.getBoosterRemainingSeconds() > 0 && this.tools.boosterMultiplier !== item.multiplier; + if (isOverride) { + const warningTemplate = this.tools.shop[this.tools.lang]?.boosterOverrideWarning || "Warning! You already have an active x{current} booster. Buying a x{new} booster will override your remaining time. Do you want to continue?"; + const warningMsg = warningTemplate + .replace('{current}', String(this.tools.boosterMultiplier)) + .replace('{new}', String(item.multiplier || 1)); + if (!confirm(warningMsg)) { + return; + } + } + this.tools.points -= ptsCost; + this.tools.dogeCoins -= coinCost; + this.tools.saveData("points", String(this.tools.points)); + this.tools.saveData("dg", String(this.tools.dogeCoins)); + this.tools.recordDailyPurchase(item.id); + this.tools.activateBooster(item.multiplier || 1, item.durationMin || 0); + } else { + if (this.tools.points < ptsCost) { + this.tools.showToast(this.tools.shop[this.tools.lang]?.needMorePoints || "Not enough points!"); + } else { + this.tools.showToast(this.tools.shop[this.tools.lang]?.notEnoughCoins || "Not enough DogeCoins!"); + } + } + } else if (item.type === 'cheems' || item.type === 'sound' || item.type === 'music') { + this.tools.buyShopUnlockableItem(item); + } + } + + canBuy(item: ShopItem): boolean { + if (this.tools.isLifetimeLimitReached(item)) { + return false; + } + if (!this.tools.canBuyDailyLimit(item)) { + return false; + } + const ptsCost = item.cost !== undefined ? item.cost : (item.type === 'dogecoin' ? this.dailyPrice : 0); + const coinsCost = item.costCoins || 0; + const mgCost = item.costMinigames || 0; + return this.tools.points >= ptsCost && this.tools.dogeCoins >= coinsCost && this.tools.minigameCoins >= mgCost; + } + + formatItemCost(item: ShopItem): string { + const ptsCost = item.cost !== undefined ? item.cost : (item.type === 'dogecoin' ? this.dailyPrice : 0); + const coinsCost = item.costCoins || 0; + const mgCost = item.costMinigames || 0; + + if (ptsCost === 0 && coinsCost === 0 && mgCost === 0) { + return this.tools.shop[this.tools.lang]?.free || "Free"; + } + + const parts: string[] = []; + if (ptsCost > 0) { + parts.push(`${ptsCost.toLocaleString()} Pts`); + } + if (coinsCost > 0) { + parts.push(`${coinsCost.toLocaleString()} DGC`); + } + if (mgCost > 0) { + parts.push(`${mgCost.toLocaleString()} MG`); + } + return parts.join(' + '); + } + + get dogecoinItems(): ShopItem[] { + return this.tools.shopItems.filter(i => i.type === 'dogecoin' || i.type === 'currency'); + } + + get minigameItems(): ShopItem[] { + return this.tools.shopItems.filter(i => i.type === 'minigame'); + } + + get boosterItems(): ShopItem[] { + return this.tools.shopItems.filter(i => i.type === 'booster'); + } + + get cheemsItems(): ShopItem[] { + return this.tools.shopItems.filter(i => i.type === 'cheems'); + } + + get soundItems(): ShopItem[] { + return this.tools.shopItems.filter(i => i.type === 'sound'); + } + + get musicItems(): ShopItem[] { + return this.tools.shopItems.filter(i => i.type === 'music'); + } + + scrollToSection(sectionId: string): void { + const el = document.getElementById(sectionId); + if (el) { + el.scrollIntoView({ behavior: 'smooth', block: 'start' }); + } + } + + scrollToTop(): void { + window.scrollTo({ top: 0, behavior: 'smooth' }); + const el = document.getElementById('shop-top'); + if (el) { + el.scrollIntoView({ behavior: 'smooth', block: 'start' }); + } + } + + getShopCardIcon(item: ShopItem): string { + if (this.tools.isLifetimeLimitReached(item)) { + return item.icon; + } + if (item.type === 'cheems') { + return 'img/cheems/locked-cheems.png'; + } + if (item.type === 'sound') { + return 'img/icons/black-sound-svgrepo-com.svg'; + } + if (item.type === 'music') { + return 'img/icons/black-music-svgrepo-com.svg'; + } + return item.icon; + } +} diff --git a/src/app/pages/stats/stats.component.css b/src/app/pages/stats/stats.component.css new file mode 100644 index 0000000..d98fafc --- /dev/null +++ b/src/app/pages/stats/stats.component.css @@ -0,0 +1,63 @@ +.stats-box { + padding: 20px; + border-radius: 12px; + box-shadow: 0 4px 10px rgba(0,0,0,0.2); + margin: 20px auto; + max-width: 600px; +} + +.stats-title { + text-align: center; + margin-bottom: 20px; + font-size: 1.8rem; + font-weight: bold; +} + +.stats-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); + gap: 15px; +} + +.stat-card { + padding: 15px; + border-radius: 8px; + text-align: center; + box-shadow: inset 0 2px 4px rgba(0,0,0,0.1); +} + +.theme-dark .stat-card { + background-color: rgba(255, 255, 255, 0.05); +} + +.theme-light .stat-card { + background-color: rgba(0, 0, 0, 0.05); +} + +.theme-contrast .stat-card { + background-color: transparent; + border: 1px solid #fff; +} + +.stat-label { + font-size: 1rem; + opacity: 0.8; + margin-bottom: 8px; +} + +.stat-value { + font-size: 1.5rem; + font-weight: bold; +} + +.text-gold { + color: #f1c40f; +} + +.text-orange { + color: #e67e22; +} + +.text-blue { + color: #3498db; +} diff --git a/src/app/pages/stats/stats.component.html b/src/app/pages/stats/stats.component.html new file mode 100644 index 0000000..d69c540 --- /dev/null +++ b/src/app/pages/stats/stats.component.html @@ -0,0 +1,31 @@ +
+
+

{{tools.stats[tools.lang]?.title || 'Statistics'}}

+ +
+ +
+
{{tools.stats[tools.lang]?.highScore || 'Highest Combo'}}
+
{{tools.highScore}}
+
+ + +
+
{{tools.stats[tools.lang]?.totalTouches || 'Total Touches'}}
+
{{tools.totalScore}}
+
+ + +
+
{{tools.stats[tools.lang]?.lifetimeDogeCoins || 'Lifetime DogeCoins'}}
+
{{tools.totalDogeCoinsEarned}}
+
+ + +
+
{{tools.stats[tools.lang]?.lifetimeMinigameCoins || 'Lifetime MG Coins'}}
+
{{tools.totalMinigameCoinsEarned}}
+
+
+
+
diff --git a/src/app/pages/stats/stats.component.ts b/src/app/pages/stats/stats.component.ts new file mode 100644 index 0000000..b6b28ff --- /dev/null +++ b/src/app/pages/stats/stats.component.ts @@ -0,0 +1,17 @@ +import { Component, inject, OnInit } from '@angular/core'; +import { ToolsService } from '../../services/tools.service'; + +@Component({ + selector: 'app-stats', + imports: [], + templateUrl: './stats.component.html', + styleUrl: './stats.component.css' +}) +export class StatsComponent implements OnInit { + tools: ToolsService = inject(ToolsService); + + ngOnInit(): void { + this.tools.setTitle("stats"); + this.tools.actPage = "stats"; + } +} diff --git a/src/app/services/constants.service.ts b/src/app/services/constants.service.ts index dae0c40..9d0ce0a 100644 --- a/src/app/services/constants.service.ts +++ b/src/app/services/constants.service.ts @@ -1,70 +1,482 @@ import { Injectable } from '@angular/core'; export interface PageName { - [key: string]: { - closet: string; - devSettings: string; - game: string; - menu: string; - onWork: string; - p404: string; - settings: string; - }; + closet: string; + devSettings: string; + game: string; + menu: string; + onWork: string; + p404: string; + settings: string; + offline: string; + shop: string; + block_breaker?: string; + attack_hole?: string; + doge_rescue?: string; + flappy_dunk?: string; + helix_jump?: string; + magic_sort?: string; + mob_control?: string; + paper_io?: string; + spiral_roll?: string; + stack_colors?: string; + minigames?: string; + stats?: string; + licenses?: string; } +export function createLangMap(base: T): Record { + return new Proxy({} as Record, { + get(target, prop: string) { + if (!(prop in target)) { + target[prop] = JSON.parse(JSON.stringify(base)); + } + return target[prop]; + } + }); +} + +export interface CheemsSkinItem { + id: string; + nameKey?: string; + nameEs?: string; + nameEn?: string; + img: string; + imgUrl?: string; + hitImg?: string; + hitImgUrl?: string; + cost?: number; + default?: boolean; + storageKey: string; + description?: string; +} + +export interface SoundEffectItem { + id: string; + nameKey?: string; + name?: string; + cost?: number; + default?: boolean; + storageKey: string; + file?: string; + files?: string[]; + basePath?: string; + description?: string; +} + +export interface MusicTrackItem { + id: string | number; + nameKey?: string; + name?: string; + file: string; + basePath?: string; + url?: string; + default?: boolean; + cost?: number; + storageKey: string; + description?: string; + cover?: string; +} + +export interface LanguageItem { + key: string; + name: string; +} + +export const AVAILABLE_LANGUAGES: Array = [ + { key: 'es', name: 'Español' }, + { key: 'en', name: 'English' } +]; + export const showCoins: Array = [ - "game", "dev-settings" + "game", "dev-settings", "closet", "menu", "block_breaker", "attack_hole", "doge_rescue", "flappy_dunk", "helix_jump", "magic_sort", "mob_control", "paper_io", "spiral_roll", "stack_colors", "minigames" ]; export const pageName: PageName = { - es: { - closet: "Armario", - devSettings: "Opciones de desarrollador", - game: "Juego de Cheems Bonk", - menu: "Menu", - onWork: "En desarrollo", - p404: "Error 404", - settings: "Opciones" + closet: "", + devSettings: "", + game: "", + menu: "", + onWork: "", + p404: "", + settings: "", + offline: "", + shop: "", + block_breaker: "", + attack_hole: "", + doge_rescue: "", + flappy_dunk: "", + helix_jump: "", + magic_sort: "", + mob_control: "", + paper_io: "", + spiral_roll: "", + stack_colors: "", + minigames: "", + stats: "", + licenses: "" +}; + +export const menuText = { + minigames: "", + settings: "", + offline: "", + shop: "", + closet: "", + stats: "", + licenses: "", + devMenu: "", + buyDogeCoin: "", + buyDogeCoinSub: "", + buyDogeCoinSuccess: "", + buyDogeCoinFail: "" +}; + +export const minigamesText = { + title: "", + block_breaker_title: "", + attack_hole_title: "", + doge_rescue_title: "", + flappy_dunk_title: "", + helix_jump_title: "", + magic_sort_title: "", + mob_control_title: "", + paper_io_title: "", + spiral_roll_title: "", + stack_colors_title: "", + playerLevel: "", + lvl: "", + trash: "", + lane1: "", + lane2: "", + lane3: "", + lane4: "", + lane5: "", + dropTools: "", + digging: "", + buyShovel: "", + buyPickaxe: "", + levelCleared: "", + levelClearedDesc: "", + nextLevel: "", + levelFailed: "", + levelFailedDesc: "", + tryAgain: "", + startGame: "", + score: "", + best: "", + time: "", + level: "", + youWin: "", + gameOver: "", + playAgain: "", + restart: "", + victory: "", + defeat: "", + convertedPointsToast: "", + attack_hole_level: "", + attack_hole_session_points: "", + attack_hole_level_points: "", + attack_hole_attack: "", + attack_hole_inst: "", + doge_rescue_inst: "", + flappy_dunk_inst: "", + helix_jump_inst: "", + magic_sort_inst: "", + mob_control_inst: "", + paper_io_inst: "", + spiral_roll_inst: "", + stack_colors_inst: "" +}; + +export const optionsText = { + changeLang: { + button: "" + }, + musicVolume: "", + effectsVolume: "", + appTheme: "", + themes: { + light: "", + dark: "", + contrast: "" }, - en: { - closet: "Closet", - devSettings: "Developer settings", - game: "Cheems Bonk Game", - menu: "Menu", - onWork: "On development", - p404: "Error 404", - settings: "Settings" + fontSize: "", + sizes: { + smaller: "", + small: "", + normal: "", + big: "", + max: "" }, + saveManagement: "", + deleteProgress: "", + deleteProgressConfirm: "", + exportSave: "", + importSave: "", + importSaveConfirm: "" }; -export const optionsText = { - es: { - changeLang: { - button: "Cambiar idioma" - } +export const statsText = { + title: "", + highScore: "", + totalTouches: "", + lifetimePoints: "", + lifetimeDogeCoins: "", + lifetimeMinigameCoins: "" +}; + +export const gameText = { + navbar: { + highScore: "", + actScore: "", + totalScore: "" }, - en: { - changeLang: { - button: "Change Language" - } - } + tapToBonk: "" +}; + +export const closetText = { + title: "", + cheemsSection: "", + soundsSection: "", + musicSection: "", + selected: "", + equipped: "", + purchased: "", + cost: "", + free: "", + buy: "", + equip: "", + needMoreCoins: "", + itemBought: "", + itemSelected: "" +}; + +export const devText = { + title: "", + resetToZero: "", + unlockAll: "", + giveDogeCoins: "", + givePoints: "", + success: "", + unlocked: "", + locked: "" +}; + +export const onWorkText = { + title: "", + message: "", + backToMenu: "" +}; + +export const p404Text = { + title: "", + message: "", + backToGame: "" +}; + +export const flappy_dunkText = { + title: "", + instructions_finite: "", + instructions_infinite: "", + tapToPlay: "", + gameOver: "", + scoreLabel: "", + playAgain: "" +}; + +export const magic_sortText = { + title: "", + instructions: "", + startGame: "", + levelCleared: "", + nextLevel: "", + levelPrefix: "", + restart: "" +}; + +export const offlineText = { + title: "", + subtitle: "", + downloadAll: "", + essentialsTitle: "", + essentialsDesc: "", + sfxTitle: "", + sfxDesc: "", + musicTitle: "", + musicDesc: "", + downloaded: "", + download: "", + downloading: "", + successToast: "", + errorToast: "", + checkForUpdates: "", + minigamesTitle: "", + minigamesDesc: "" +}; + +export interface OfflineCategory { + id: 'essentials' | 'sfx' | 'music' | 'minigames'; + titleKey: string; + descKey: string; + sizeLabel: string; + urls: string[]; } -export const gameText = { - es: { - navbar: { - highScore: "Mayor puntaje de toques", - actScore: "Toques actuales", - totalScore: "Toques totales" - } +export const OFFLINE_CATEGORIES: OfflineCategory[] = [ + { + id: 'essentials', + titleKey: 'essentialsTitle', + descKey: 'essentialsDesc', + sizeLabel: '~9.5 MB', + urls: [ + '/', + 'index.html', + 'favicon.ico', + 'manifest.webmanifest', + 'data/closet.json', + 'data/cheems.json', + 'data/sound_effects.json', + 'data/music.json', + 'lang/texts.en.lang', + 'lang/texts.es.lang', + 'img/dogecoin-min.png', + 'img/dogecoin-min.svg', + 'img/dogecoin.png', + 'img/dogecoin.svg', + 'img/favicon.ico', + 'img/cheems/3d.png', + 'img/cheems/adult.png', + 'img/cheems/black.png', + 'img/cheems/elegant.png', + 'img/cheems/kid.png', + 'img/cheems/little.png', + 'img/cheems/locked-cheems.png', + 'img/cheems/mamado.png', + 'img/cheems/normal.png', + 'img/cheems/pixelart.png', + 'img/hit/3d.png', + 'img/hit/adult.png', + 'img/hit/black.png', + 'img/hit/elegant.png', + 'img/hit/kid.png', + 'img/hit/little.png', + 'img/hit/mamado.png', + 'img/hit/normal.png', + 'img/hit/pixelart.png', + 'img/icons/application-svgrepo-com.svg', + 'img/icons/black-music-svgrepo-com.svg', + 'img/icons/black-sound-svgrepo-com.svg', + 'img/icons/earphone-svgrepo-com.svg', + 'img/icons/front-page-svgrepo-com.svg', + 'img/icons/link-svgrepo-com.svg', + 'img/icons/lock-keyhole-minimalistic-svgrepo-com.svg', + 'img/icons/lock-keyhole-minimalistic-unlocked-svgrepo-com.svg', + 'img/icons/menu-svgrepo-com.svg', + 'img/icons/music-svgrepo-com.svg', + 'img/icons/personal-svgrepo-com.svg', + 'img/icons/picture-svgrepo-com.svg', + 'img/icons/play-svgrepo-com.svg', + 'img/icons/report-svgrepo-com.svg', + 'img/icons/set-up-svgrepo-com.svg', + 'img/icons/shopping-svgrepo-com.svg', + 'img/icons/sound-svgrepo-com.svg', + 'img/icons/the-internet-svgrepo-com.svg', + 'img/icons/trophy-svgrepo-com.svg', + 'img/icons/volume-cross-svgrepo-com.svg', + 'img/icons/volume-loud-svgrepo-com.svg', + 'img/icons/volume-small-svgrepo-com.svg', + 'img/icons/pwa/icon-144x144.png', + 'img/icons/pwa/icon-192x192.png', + 'img/icons/pwa/icon-512x512.png', + 'img/icons/pwa/icon-72x72.png' + ] }, - en: { - navbar: { - highScore: "Highest touch score", - actScore: "Current touches", - totalScore: "Total touches" - } + { + id: 'sfx', + titleKey: 'sfxTitle', + descKey: 'sfxDesc', + sizeLabel: '~550 KB', + urls: [ + 'sound/discord-connect.ogg', + 'sound/discord-disconnect.ogg', + 'sound/discord-msg.ogg', + 'sound/hello.ogg', + 'sound/hit-minecraft.ogg', + 'sound/hit.ogg', + 'sound/hurt-minecraft.ogg', + 'sound/hurt-roblox.ogg', + 'sound/levelup1.ogg', + 'sound/levelup2.ogg', + 'sound/no.ogg', + 'sound/pato.ogg', + 'sound/peluche.ogg', + 'sound/splat.ogg', + 'sound/windows-error.ogg', + 'sound/menu/Desaparecer.ogg', + 'sound/menu/deslis.ogg', + 'sound/menu/teclas.ogg' + ] + }, + { + id: 'music', + titleKey: 'musicTitle', + descKey: 'musicDesc', + sizeLabel: '~119 MB', + urls: [ + 'sound/music/A_Jazz_Piano.ogg', + 'sound/music/Jack_Bootleg.ogg', + 'sound/music/Magic_night.ogg', + 'sound/music/Minimalism_No10.ogg', + 'sound/music/Minimalism_No9.ogg', + 'sound/music/TETRIS (Joey iLLah Bootleg) (Final).wav', + 'sound/music/When_you_smile.ogg', + 'sound/music/believe-me-143530.mp3', + 'sound/music/city-streets-background-version-166003.mp3', + 'sound/music/coffee-shop-189585.mp3', + 'sound/music/electro-summer-positive-party-141081.mp3', + 'sound/music/separation-185196.mp3', + 'sound/music/titanium-170190.mp3', + 'sound/music/trap-future-bass-royalty-free-music-167020.mp3' + ] + }, + { + id: 'minigames', + titleKey: 'minigamesTitle', + descKey: 'minigamesDesc', + sizeLabel: '~500 KB', + urls: [ + 'games/paper_io/data/bots.json' + ] } +]; + +export const CHEEMS_SKINS: Array = []; + +export const SOUND_EFFECTS: Array = []; + +export const MUSIC_TRACKS: Array = []; + +export interface ShopItem { + id: string; + type: 'dogecoin' | 'currency' | 'minigame' | 'booster' | 'cheems' | 'sound' | 'music'; + targetId?: string | number; + nameKey?: string; + nameEs?: string; + nameEn?: string; + descKey?: string; + descEs?: string; + descEn?: string; + cost: number; + costCoins?: number; + costMinigames?: number; + multiplier?: number; + durationMin?: number; + coinsGiven?: number; + minigameCoinsGiven?: number; + icon: string; + dailyLimit?: number; + oneTimePurchase?: boolean; } @Injectable({ @@ -73,3 +485,35 @@ export const gameText = { export class TranslationsService { constructor() { } } + +export const attack_holeText = { + title: "" +}; + +export const block_breakerText = { + title: "" +}; + +export const doge_rescueText = { + title: "" +}; + +export const helix_jumpText = { + title: "" +}; + +export const mob_controlText = { + title: "" +}; + +export const paper_ioText = { + title: "" +}; + +export const spiral_rollText = { + title: "" +}; + +export const stack_colorsText = { + title: "" +}; diff --git a/src/app/services/tools.service.ts b/src/app/services/tools.service.ts index 1dc39c1..28830e1 100644 --- a/src/app/services/tools.service.ts +++ b/src/app/services/tools.service.ts @@ -1,28 +1,138 @@ import { Injectable } from '@angular/core'; import { Title } from '@angular/platform-browser'; import { NavigationStart, Router } from '@angular/router'; -import { gameText, optionsText, PageName, pageName } from './constants.service'; - +import { + gameText, + optionsText, + PageName, + pageName, + menuText, + closetText, + devText, + onWorkText, + p404Text, + minigamesText, + statsText, + CHEEMS_SKINS, + SOUND_EFFECTS, + MUSIC_TRACKS, + CheemsSkinItem, + SoundEffectItem, + MusicTrackItem, + createLangMap, + AVAILABLE_LANGUAGES, + LanguageItem, + offlineText, + OfflineCategory, + OFFLINE_CATEGORIES, + ShopItem, + flappy_dunkText, + magic_sortText, + attack_holeText, + block_breakerText, + doge_rescueText, + helix_jumpText, + mob_controlText, + paper_ioText, + spiral_rollText, + stack_colorsText +} from './constants.service'; @Injectable({ providedIn: 'root' }) export class ToolsService { fontSize: string = "text-normal"; - themeColor: string = "theme-light"; - actPage: keyof PageName[""] = "game"; - lang: string = "en"; - selectedCheems: string = "normal"; - selectedSound: string = "hit"; + themeColor: string = "theme-dark"; + actPage: keyof PageName = "game"; + lang: string = "es"; + selectedCheems: string = "cheems_normal"; + selectedSound: string = "sfx_1"; + selectedMusic: string = "music_1"; actScore: number = 0; + points: number = 0; highScore: number = 0; totalScore: number = 0; dogeCoins: number = 0; + minigameCoins: number = 50; + sessionPoints: number = 0; + + totalPointsEarned: number = 0; + totalDogeCoinsEarned: number = 0; + totalMinigameCoinsEarned: number = 0; + + effVol: number = 100; + musVol: number = 50; + + devMenuUnlocked: boolean = false; + private devClickCount: number = 0; + + unlockedCheems: Record = {}; + unlockedSounds: Record = {}; + unlockedMusic: Record = {}; + unlockedMinigames: Record = {}; + + game: any = createLangMap(gameText); + options: any = createLangMap(optionsText); + menu: any = createLangMap(menuText); + closet: any = createLangMap(closetText); + dev: any = createLangMap(devText); + onWork: any = createLangMap(onWorkText); + p404: any = createLangMap(p404Text); + offline: any = createLangMap(offlineText); + shop: any = {}; + gallery: any = {}; + licensesPage: any = {}; + minigames: any = createLangMap(minigamesText); + stats: any = createLangMap(statsText); + pageName: any = createLangMap(pageName); + flappy_dunk: any = createLangMap(flappy_dunkText); + magic_sort: any = createLangMap(magic_sortText); + attack_hole: any = createLangMap(attack_holeText); + block_breaker: any = createLangMap(block_breakerText); + doge_rescue: any = createLangMap(doge_rescueText); + helix_jump: any = createLangMap(helix_jumpText); + mob_control: any = createLangMap(mob_controlText); + paper_io: any = createLangMap(paper_ioText); + spiral_roll: any = createLangMap(spiral_rollText); + stack_colors: any = createLangMap(stack_colorsText); + offlineCategories: Array = OFFLINE_CATEGORIES; + shopItemsText: Record> = {}; + itemsText: Record> = {}; + shopItems: Array = []; + boosterEndTime: number = 0; + boosterMultiplier: number = 1; + minigameConversions: Record = { + 'block_breaker': { points: 100, mgPoints: 10, levelMgPoints: 5 }, + 'attack_hole': { points: 100, mgPoints: 10, levelMgPoints: 5 }, + 'doge_rescue': { points: 10, mgPoints: 10, levelMgPoints: 5 }, + 'flappy_dunk': { points: 10, mgPoints: 10, levelMgPoints: 5 }, + 'helix_jump': { points: 100, mgPoints: 10, levelMgPoints: 5 }, + 'magic_sort': { points: 10, mgPoints: 10, levelMgPoints: 5 }, + 'mob_control': { points: 100, mgPoints: 10, levelMgPoints: 5 }, + 'paper_io': { points: 100, mgPoints: 10, levelMgPoints: 5 }, + 'spiral_roll': { points: 100, mgPoints: 10, levelMgPoints: 5 }, + 'stack_colors': { points: 100, mgPoints: 10, levelMgPoints: 5 } + }; + private audioCtx: AudioContext | null = null; + private musicSource: AudioBufferSourceNode | null = null; + private musicGain: GainNode | null = null; + private currentMusicBuffer: AudioBuffer | null = null; + private currentMusicFile: string = ""; + public isWindowBlurred: boolean = false; + public isBackgroundMusicPaused: boolean = false; + + availableLanguages: Array = AVAILABLE_LANGUAGES; - game: any = gameText; - options: any = optionsText; - pageName: PageName = pageName; + cheemsSkins: Array = CHEEMS_SKINS; + soundEffects: Array = SOUND_EFFECTS; + musicTracks: Array = MUSIC_TRACKS; + + private musicAudio: HTMLAudioElement = new Audio(); + + toastMessage: string = ""; + private toastTimer: any = null; constructor(private titleInt: Title, private router: Router) { this.router.events.subscribe((event) => { @@ -32,17 +142,238 @@ export class ToolsService { } } }); + + this.musicAudio.loop = true; + this.musicAudio.addEventListener('ended', () => { + if (String(this.selectedMusic) !== '0') { + this.musicAudio.play().catch(() => {}); + } + }); + + const resumeMusicOnInteraction = () => { + if (String(this.selectedMusic) !== '0' && this.musicAudio.paused && !this.isBackgroundMusicPaused) { + this.playMusic(this.selectedMusic); + } + }; + document.addEventListener('click', resumeMusicOnInteraction, { passive: true }); + document.addEventListener('touchstart', resumeMusicOnInteraction, { passive: true }); + document.addEventListener('keydown', resumeMusicOnInteraction, { passive: true }); + } + + private readonly PREFIX = "CheemsBonkGame115_"; + + saveData(key: string, value: string): void { + localStorage.setItem(this.PREFIX + key, value); + } + + loadData(key: string): string | null { + return localStorage.getItem(this.PREFIX + key); + } + + deleteData(key: string): void { + localStorage.removeItem(this.PREFIX + key); + } + + parseArrayString(str: string): string[] { + if (!str) return []; + return str.split(';').filter(s => s.trim().length > 0); + } + + stringifyArray(arr: string[]): string { + if (!arr || arr.length === 0) return ""; + return arr.join(';'); + } + + parseObjectString(str: string): Record { + if (!str) return {}; + const obj: Record = {}; + const pairs = str.split(','); + for (const p of pairs) { + if (!p) continue; + const idx = p.indexOf(':'); + if (idx !== -1) { + obj[p.substring(0, idx)] = p.substring(idx + 1); + } + } + return obj; + } + + stringifyObject(obj: Record): string { + if (!obj) return ""; + const pairs: string[] = []; + for (const key of Object.keys(obj)) { + pairs.push(`${key}:${obj[key]}`); + } + return pairs.join(','); + } + + parseArrayOfObjectsString(str: string): Record[] { + if (!str) return []; + const items = str.split(';'); + const result: Record[] = []; + for (const item of items) { + if (item.trim().length > 0) { + result.push(this.parseObjectString(item)); + } + } + return result; } - setTitle(page: keyof PageName[""]): void { - let title = pageName[this.lang][page]; + stringifyArrayOfObjects(arr: Record[]): string { + if (!arr || arr.length === 0) return ""; + const strings = arr.map(obj => this.stringifyObject(obj)); + return strings.join(';') + (strings.length > 0 ? ';' : ''); + } + + setTitle(page: string): void { + let title = this.pageName[this.lang]?.[page] || "Cheems Bonk Game"; this.titleInt.setTitle(title); } - changeLanguage() { - this.lang === 'es' ? this.lang = 'en' : this.lang = 'es'; - localStorage.setItem("CheemsBonkLang", this.lang); - this.reload(); + changeLanguage(): void { + const currentIdx = this.availableLanguages.findIndex(l => l.key === this.lang); + const nextIdx = (currentIdx + 1) % this.availableLanguages.length; + this.setLanguage(this.availableLanguages[nextIdx].key); + } + + setLanguage(key: string): void { + if (this.availableLanguages.some(l => l.key === key)) { + this.lang = key; + this.saveData("language", this.lang); + this.loadLanguageFile(this.lang); + this.setTitle(this.actPage); + } + } + + async loadLanguageFile(langCode: string): Promise { + try { + const res = await fetch(`lang/texts.${langCode}.lang`); + if (res.ok) { + const data = await res.json(); + if (data.pageName) this.pageName[langCode] = { ...this.pageName[langCode], ...data.pageName }; + if (data.game) this.game[langCode] = { + ...this.game[langCode], + ...data.game, + navbar: { ...this.game[langCode]?.navbar, ...data.game?.navbar } + }; + if (data.options) this.options[langCode] = { + ...this.options[langCode], + ...data.options, + changeLang: { ...this.options[langCode]?.changeLang, ...data.options?.changeLang }, + themes: { ...this.options[langCode]?.themes, ...data.options?.themes }, + sizes: { ...this.options[langCode]?.sizes, ...data.options?.sizes } + }; + if (data.menu) this.menu[langCode] = { ...this.menu[langCode], ...data.menu }; + if (data.closet) this.closet[langCode] = { ...this.closet[langCode], ...data.closet }; + if (data.dev) this.dev[langCode] = { ...this.dev[langCode], ...data.dev }; + if (data.onWork) this.onWork[langCode] = { ...this.onWork[langCode], ...data.onWork }; + if (data.p404) this.p404[langCode] = { ...this.p404[langCode], ...data.p404 }; + if (data.offline) this.offline[langCode] = { ...this.offline[langCode], ...data.offline }; + if (data.shop) this.shop[langCode] = { ...this.shop[langCode], ...data.shop }; + if (data.minigames) this.minigames[langCode] = { ...this.minigames[langCode], ...data.minigames }; + if (data.flappy_dunk) this.flappy_dunk[langCode] = { ...this.flappy_dunk[langCode], ...data.flappy_dunk }; + if (data.magic_sort) this.magic_sort[langCode] = { ...this.magic_sort[langCode], ...data.magic_sort }; + if (data.attack_hole) this.attack_hole[langCode] = { ...this.attack_hole[langCode], ...data.attack_hole }; + if (data.block_breaker) this.block_breaker[langCode] = { ...this.block_breaker[langCode], ...data.block_breaker }; + if (data.doge_rescue) this.doge_rescue[langCode] = { ...this.doge_rescue[langCode], ...data.doge_rescue }; + if (data.helix_jump) this.helix_jump[langCode] = { ...this.helix_jump[langCode], ...data.helix_jump }; + if (data.mob_control) this.mob_control[langCode] = { ...this.mob_control[langCode], ...data.mob_control }; + if (data.paper_io) this.paper_io[langCode] = { ...this.paper_io[langCode], ...data.paper_io }; + if (data.spiral_roll) this.spiral_roll[langCode] = { ...this.spiral_roll[langCode], ...data.spiral_roll }; + if (data.stack_colors) this.stack_colors[langCode] = { ...this.stack_colors[langCode], ...data.stack_colors }; + if (data.gallery) this.gallery[langCode] = { ...this.gallery[langCode], ...data.gallery }; + if (data.licensesPage) this.licensesPage[langCode] = { ...this.licensesPage[langCode], ...data.licensesPage }; + if (data.shopItemsText) this.shopItemsText[langCode] = { ...this.shopItemsText[langCode], ...data.shopItemsText }; + if (data.itemsText) this.itemsText[langCode] = { ...this.itemsText[langCode], ...data.itemsText }; + } + } catch (err) { + console.warn(`Could not load language file lang/texts.${langCode}.lang`, err); + } + } + + async loadClosetPrices(): Promise { + try { + const [cheemsRes, soundsRes, musicRes, closetRes] = await Promise.all([ + fetch('data/cheems.json').catch(() => null), + fetch('data/sound_effects.json').catch(() => null), + fetch('data/music.json').catch(() => null), + fetch('data/closet.json').catch(() => null) + ]); + + const cheemsCatalog: Array = cheemsRes && cheemsRes.ok ? await cheemsRes.json() : []; + const soundsCatalog: Array = soundsRes && soundsRes.ok ? await soundsRes.json() : []; + const musicCatalog: Array = musicRes && musicRes.ok ? await musicRes.json() : []; + + let closetData: any = null; + if (closetRes && closetRes.ok) { + closetData = await closetRes.json(); + } + + if (closetData) { + this.cheemsSkins = this.buildItemsList(closetData.cheems, cheemsCatalog); + this.soundEffects = this.buildItemsList(closetData.sounds, soundsCatalog); + this.musicTracks = this.buildItemsList(closetData.music, musicCatalog); + } else { + this.cheemsSkins = [...cheemsCatalog]; + this.soundEffects = [...soundsCatalog]; + this.musicTracks = [...musicCatalog]; + } + + this.loadUnlocks(); + this.appendUnlockableShopItems(); + this.playMusic(this.selectedMusic); + } catch (err) { + console.warn('Could not load data/closet.json or data/ items, using default arrays', err); + } + } + + private buildItemsList( + closetSection: any, + catalog: Array + ): Array { + const result: Array = []; + if (!closetSection || !catalog || catalog.length === 0) { + return result; + } + + if (Array.isArray(closetSection)) { + for (const entry of closetSection) { + let itemId: any; + let overrideCost: number | undefined; + + if (typeof entry === 'object' && entry !== null) { + itemId = entry.id; + if (entry.cost !== undefined) { + overrideCost = Number(entry.cost); + } + } else { + itemId = entry; + } + + const found = catalog.find(item => String(item.id) === String(itemId)); + if (found) { + const itemCopy = { ...found }; + if (overrideCost !== undefined && !isNaN(overrideCost)) { + itemCopy.cost = overrideCost; + } + result.push(itemCopy); + } + } + } else if (typeof closetSection === 'object' && closetSection !== null) { + for (const key of Object.keys(closetSection)) { + const found = catalog.find(item => String(item.id) === String(key)); + if (found) { + const itemCopy = { ...found }; + const overrideCost = Number(closetSection[key]); + if (!isNaN(overrideCost)) { + itemCopy.cost = overrideCost; + } + result.push(itemCopy); + } + } + } + + return result; } redirect(url: string): void { @@ -53,87 +384,1186 @@ export class ToolsService { window.location.reload(); } - redirectBack(fromSystem:boolean=false): void { - if (["devSettings", "closet", "settings", "onWork"].includes(this.actPage)) { + redirectBack(fromSystem: boolean = false): void { + const minigamePages = ["block_breaker", "attack_hole", "doge_rescue", "flappy_dunk", "helix_jump", "magic_sort", "mob_control", "paper_io", "spiral_roll", "stack_colors"]; + if (minigamePages.includes(this.actPage as string)) { + this.redirect("minigames"); + } else if (["devSettings", "closet", "gallery", "settings", "onWork", "shop", "minigames", "stats", "licenses"].includes(this.actPage as string)) { this.redirect("menu"); - } - else if (["menu", "p404"].includes(this.actPage)) { - this.redirect("game"); - } - else if (["game"].includes(this.actPage)) { + } else if (["menu", "p404"].includes(this.actPage as string)) { + this.redirect("game"); + } else if (["game"].includes(this.actPage as string)) { fromSystem ? this.redirect("game") : this.redirect("menu"); } } + showToast(message: string, durationMs: number = 3000): void { + if (this.toastTimer) { + clearTimeout(this.toastTimer); + } + this.toastMessage = message; + this.toastTimer = setTimeout(() => { + this.toastMessage = ""; + }, durationMs); + } + updateScore(value: number): void { - this.actScore += value; - this.totalScore += value; - if (this.actScore >= this.highScore) { + let finalValue = value * this.boosterMultiplier; + this.actScore += finalValue; + this.points += finalValue; + this.totalScore += finalValue; + this.totalPointsEarned += finalValue; + + if (this.actScore > this.highScore) { this.highScore = this.actScore; } - localStorage.setItem("CheemsBonkTotalScore", JSON.stringify(this.totalScore)); - localStorage.setItem("CheemsBonkHighScore", JSON.stringify(this.highScore)); + + this.saveData("points", String(this.points)); + this.saveData("total_score", String(this.totalScore)); + this.saveData("high_score", String(this.highScore)); + this.saveData("lifetime_points", String(this.totalPointsEarned)); + + } - playSound(): void { - let sfx = new Audio("sound/"+this.selectedSound+".ogg"); - sfx.play(); + addMinigameCoins(amount: number): void { + this.minigameCoins = Math.floor(this.minigameCoins + amount); + this.totalMinigameCoinsEarned += amount; + this.saveData("mg", String(this.minigameCoins)); + this.saveData("lifetime_mg", String(this.totalMinigameCoinsEarned)); + document.cookie = `CheemsAppLiMinigameCoins=${this.minigameCoins}; path=/; max-age=31536000`; + } + + spendMinigameCoins(amount: number): boolean { + if (this.minigameCoins >= amount) { + this.minigameCoins = Math.floor(this.minigameCoins - amount); + this.saveData("mg", String(this.minigameCoins)); + document.cookie = `CheemsAppLiMinigameCoins=${this.minigameCoins}; path=/; max-age=31536000`; + return true; + } + return false; + } + + isMinigameUnlocked(id: string): boolean { + const key = id.replace('minigames/', '').replace(/-/g, '_'); + return !!this.unlockedMinigames[key]; + } + + async loadMinigamesConfig(): Promise { + try { + const res = await fetch("data/minigames.json"); + if (res.ok) { + const data = await res.json(); + if (Array.isArray(data)) { + data.forEach(item => { + if (item && item.id) { + this.minigameConversions[item.id] = item; + } + }); + } + } + } catch (err) { + console.warn("Could not load data/minigames.json", err); + } } + leaveMinigame(gameId: string, gamePoints: number, gameLevel: number = 0): void { + if ((!gamePoints || gamePoints <= 0) && (!gameLevel || gameLevel <= 0)) return; + const cfg = this.minigameConversions[gameId] || { points: 100, mgPoints: 10, levelMgPoints: 5 }; + const levelMult = cfg.levelMgPoints || 5; + const earnedFromPoints = gamePoints > 0 ? Math.floor((gamePoints / cfg.points) * cfg.mgPoints) : 0; + const earnedFromLevel = gameLevel > 0 ? (gameLevel * levelMult) : 0; + const totalEarned = earnedFromPoints + earnedFromLevel; + if (totalEarned > 0) { + this.addMinigameCoins(totalEarned); + let template = this.minigames[this.lang]?.convertedPointsToast || "Converted {0} game points to +{1} MG Coins!"; + let msg = template.replace("{0}", String(Math.floor(gamePoints))).replace("{1}", String(totalEarned)); + if (gameLevel > 0) { + msg = msg.replace("game points", "points & level " + gameLevel); + msg = msg.replace("puntos del juego", "puntos y nivel " + gameLevel); + } + this.showToast(msg, 4000); + this.playSound("sfx_4"); + } + } + getDailyDogeCoinPrice(priceType: number = 1): number { + const d = new Date(); + const yyyy = d.getFullYear(); + const mm = String(d.getMonth() + 1).padStart(2, '0'); + const dd = String(d.getDate()).padStart(2, '0'); + const dateNum = Number(`${yyyy}${mm}${dd}`); + const product = dateNum * Math.PI; + const str = (product.toString().replace('.', '') + '00000000000000000000').slice(0, 30); + let digits = ""; + switch (priceType) { + case 2: + digits = str.slice(1, 4); + break; + case 3: + digits = str.slice(4, 7); + break; + case 4: + digits = str.slice(11, 14); + break; + case 1: + default: + digits = str.slice(8, 11); + break; + } + const price = parseInt(digits, 10); + return (!isNaN(price) && price > 0) ? price : 100; + } + buyDogeCoin(customCost?: number, coinsAmount: number = 1, itemId: string = "dogecoin_daily"): boolean { + const cost = customCost !== undefined ? customCost : this.getDailyDogeCoinPrice(); + const coinsToAdd = (coinsAmount && coinsAmount > 0) ? coinsAmount : 1; + if (this.points >= cost) { + this.points -= cost; + this.dogeCoins += coinsToAdd; + this.totalDogeCoinsEarned += coinsToAdd; + this.saveData("points", String(this.points)); + this.saveData("dg", String(this.dogeCoins)); + this.saveData("lifetime_dg", String(this.totalDogeCoinsEarned)); + this.recordDailyPurchase(itemId); + let successMsg = this.menu[this.lang]?.buyDogeCoinSuccess || `You bought ${coinsToAdd} DogeCoin(s)!`; + if (coinsToAdd !== 1) { + successMsg = successMsg.replace('1 DogeCoin', `${coinsToAdd} DogeCoins`); + } + this.showToast(successMsg); + this.playSound(); + return true; + } else { + this.showToast(this.menu[this.lang].buyDogeCoinFail); + this.playSound('sfx_8'); + return false; + } + } + + registerDevClick(): void { + this.devClickCount++; + if (this.devClickCount === 5) { + this.devMenuUnlocked = !this.devMenuUnlocked; + this.saveData("dev_menu", String(this.devMenuUnlocked)); + if (this.devMenuUnlocked) { + this.showToast(this.dev[this.lang].unlocked); + } else { + this.showToast(this.dev[this.lang].locked); + } + this.devClickCount = 0; + this.playSound('sfx_4'); + } + } + + playSound(customSoundId?: string): void { + if (this.isWindowBlurred) return; + const soundToPlay = customSoundId || this.selectedSound; + const item = this.soundEffects.find(s => String(s.id) === String(soundToPlay)); + + let file = "hit.ogg"; + let basePath = "sound/"; + + if (item) { + if (item.basePath) basePath = item.basePath; + if (item.files && item.files.length > 0) { + const idx = Math.floor(Math.random() * item.files.length); + file = item.files[idx]; + } else if (item.file) { + file = item.file; + } + } + + const sfx = new Audio(basePath + file); + sfx.volume = this.effVol / 100; + sfx.play().catch(() => {}); + } + + playMusic(songId?: string | number): void { + const trackId = songId !== undefined ? songId : this.selectedMusic; + const track = this.musicTracks.find(t => String(t.id) === String(trackId)); + if (!track || String(track.id) === '0' || !track.file) { + this.stopBackgroundMusic(); + return; + } + const basePath = track.basePath || "sound/music/"; + const fullPath = track.url || (basePath + track.file); + this.playBackgroundMusic(track.file, fullPath); + } + + async playBackgroundMusic(file: string, customUrl?: string): Promise { + if (!file || this.musVol <= 0 || String(this.selectedMusic) === '0') { + this.stopBackgroundMusic(); + return; + } + + const targetSrc = customUrl || ("sound/music/" + file); + try { + if (!this.audioCtx) { + this.audioCtx = new (window.AudioContext || (window as any).webkitAudioContext)(); + } + if (this.currentMusicFile !== file) { + this.currentMusicFile = file; + const res = await fetch(targetSrc); + if (res.ok) { + const arrayBuf = await res.arrayBuffer(); + const audioBuf = await this.audioCtx.decodeAudioData(arrayBuf); + this.currentMusicBuffer = audioBuf; + this.startWebAudioMusic(); + return; + } + } else { + if (this.audioCtx.state === 'suspended' && !this.isWindowBlurred) { + this.audioCtx.resume().catch(() => {}); + } + return; + } + } catch (e) { + console.warn("Web Audio API failed, falling back to HTMLAudioElement", e); + } + + if (!this.musicAudio.src.endsWith(targetSrc)) { + this.musicAudio.src = targetSrc; + this.musicAudio.loop = true; + this.musicAudio.load(); + } + this.musicAudio.volume = this.musVol / 100; + if (!this.isWindowBlurred) { + this.musicAudio.play().catch(() => {}); + } + } + + startWebAudioMusic(): void { + if (!this.audioCtx || !this.currentMusicBuffer) return; + if (this.musicSource) { + try { this.musicSource.stop(); } catch {} + this.musicSource.disconnect(); + } + if (!this.musicGain) { + this.musicGain = this.audioCtx.createGain(); + this.musicGain.connect(this.audioCtx.destination); + } + this.musicGain.gain.value = this.musVol / 100; + this.musicSource = this.audioCtx.createBufferSource(); + this.musicSource.buffer = this.currentMusicBuffer; + this.musicSource.loop = true; + this.musicSource.connect(this.musicGain); + if (!this.isWindowBlurred) { + this.musicSource.start(0); + } + } + + stopBackgroundMusic(): void { + if (this.musicSource) { + try { this.musicSource.stop(); } catch {} + this.musicSource = null; + } + if (!this.musicAudio.paused) { + this.musicAudio.pause(); + this.musicAudio.src = ""; + } + } + + setMusicVolume(vol: number): void { + this.musVol = Math.max(0, Math.min(100, vol)); + this.musicAudio.volume = this.musVol / 100; + if (this.musicGain && this.audioCtx) { + this.musicGain.gain.value = this.musVol / 100; + } + this.saveData("music_volume", String(this.musVol)); + if (this.musVol === 0) { + if (this.audioCtx && this.audioCtx.state === 'running') { + this.audioCtx.suspend().catch(() => {}); + } + this.musicAudio.pause(); + } else if (!this.isWindowBlurred && String(this.selectedMusic) !== '0') { + if (this.audioCtx && this.audioCtx.state === 'suspended') { + this.audioCtx.resume().catch(() => {}); + } + if (this.musicAudio.paused && this.musicAudio.src) { + this.musicAudio.play().catch(() => {}); + } + } + } + + setEffectVolume(vol: number): void { + this.effVol = Math.max(0, Math.min(100, vol)); + this.saveData("sfx_volume", String(this.effVol)); + } + + switchTheme(themeIndex: number): void { + switch (themeIndex) { + case 0: this.themeColor = "theme-light"; break; + case 1: this.themeColor = "theme-dark"; break; + case 2: this.themeColor = "theme-contrast"; break; + default: this.themeColor = "theme-dark"; break; + } + this.saveData("app_theme", String(themeIndex)); + document.body.className = `${this.themeColor} ${this.fontSize}`; + } + + setAccessibility(sizeIndex: number): void { + switch (sizeIndex) { + case 0: this.fontSize = "text-smaller"; break; + case 1: this.fontSize = "text-small"; break; + case 2: this.fontSize = "text-normal"; break; + case 3: this.fontSize = "text-big"; break; + case 4: this.fontSize = "text-max"; break; + default: this.fontSize = "text-normal"; break; + } + this.saveData("font_size", String(sizeIndex)); + const sizeMap = ["12px", "14px", "16px", "19px", "22px"]; + document.documentElement.style.fontSize = sizeMap[sizeIndex] || "16px"; + document.body.className = `${this.themeColor} ${this.fontSize}`; + } + + isCheemsUnlocked(id: string): boolean { + if (id === 'normal' || id === 'cheems_normal') return true; + const item = this.cheemsSkins.find(s => s.id === id); + if (!item) return false; + return !!this.unlockedCheems[item.storageKey]; + } + + buyOrSelectCheems(skin: CheemsSkinItem): boolean { + if (this.isCheemsUnlocked(skin.id)) { + this.selectedCheems = skin.id; + this.saveData("selected_cheems", skin.id); + + this.showToast(this.closet[this.lang]?.itemSelected || "Selected!"); + this.playSound(); + return true; + } else { + this.showToast(this.closet[this.lang]?.buyInShop || "Buy this item in the Shop!"); + this.playSound('sfx_8'); + return false; + } + } + + isSoundUnlocked(id: string): boolean { + if (id === '1' || id === 'sfx_1') return true; + const item = this.soundEffects.find(s => String(s.id) === String(id)); + if (!item) return false; + return !!this.unlockedSounds[item.storageKey]; + } + + buyOrSelectSound(sound: SoundEffectItem): boolean { + if (this.isSoundUnlocked(sound.id)) { + this.selectedSound = sound.id; + this.saveData("selected_sfx", sound.id); + + this.showToast(this.closet[this.lang]?.itemSelected || "Selected!"); + this.playSound(sound.id); + return true; + } else { + this.showToast(this.closet[this.lang]?.buyInShop || "Buy this item in the Shop!"); + this.playSound('sfx_8'); + return false; + } + } + + isMusicUnlocked(id: any): boolean { + if (String(id) === '0' || String(id) === '1' || id === 'music_0' || id === 'music_1') return true; + const item = this.musicTracks.find(m => String(m.id) === String(id)); + if (!item) return false; + return !!this.unlockedMusic[item.storageKey]; + } + + buyOrSelectMusic(track: MusicTrackItem): boolean { + if (this.isMusicUnlocked(track.id)) { + this.selectMusic(track); + return true; + } else { + this.showToast(this.closet[this.lang]?.buyInShop || "Buy this item in the Shop!"); + this.playSound('sfx_8'); + return false; + } + } + + selectMusic(track: MusicTrackItem): void { + this.selectedMusic = track.id as any; + this.saveData("selected_music", String(track.id)); + this.playMusic(track.id); + this.showToast(this.closet[this.lang].itemSelected); + } + + unlockAll(): void { + this.actScore = 999999; + this.points = 999999; + this.totalScore = 999999; + this.highScore = 999999; + this.dogeCoins = 999999; + this.minigameCoins = 999999; + const allMinigames = ['block_breaker', 'attack_hole', 'doge_rescue', 'flappy_dunk', 'helix_jump', 'magic_sort', 'mob_control', 'paper_io', 'spiral_roll', 'stack_colors']; + allMinigames.forEach(id => { + this.unlockedMinigames[id] = true; + }); + this.saveUnlockedMinigames(); + this.minigameCoins = 999999; + this.saveData("mg", "999999"); + this.cheemsSkins.forEach(s => { + this.unlockedCheems[s.storageKey] = true; + }); + this.saveUnlockedCheems(); + this.soundEffects.forEach(s => { + this.unlockedSounds[s.storageKey] = true; + }); + this.saveUnlockedSounds(); + this.musicTracks.forEach(s => { + this.unlockedMusic[s.storageKey] = true; + }); + this.saveUnlockedMusic(); + + this.saveData("points", String(this.points)); + this.saveData("total_score", String(this.totalScore)); + this.saveData("high_score", String(this.highScore)); + this.saveData("dg", String(this.dogeCoins)); + this.showToast(this.dev[this.lang].success); + this.playSound('sfx_4'); + } + + resetToZero(): void { + this.actScore = 0; + this.points = 0; + this.totalScore = 0; + this.highScore = 0; + this.dogeCoins = 0; + this.minigameCoins = 0; + this.totalPointsEarned = 0; + this.totalDogeCoinsEarned = 0; + this.totalMinigameCoinsEarned = 0; + this.unlockedMinigames = {}; + + this.saveData("mg", "0"); + this.deleteData("unlocked_minigames"); + + this.selectedCheems = "cheems_normal"; + this.selectedSound = "sfx_1"; + this.selectedMusic = "music_1"; + this.effVol = 100; + this.musVol = 50; + this.themeColor = "theme-dark"; + this.fontSize = "text-normal"; + this.unlockedCheems = {}; + this.unlockedSounds = {}; + this.unlockedMusic = {}; + this.cheemsSkins.forEach(s => { + const isDef = !s.default; + this.unlockedCheems[s.storageKey] = !isDef; + }); + this.saveUnlockedCheems(); + + this.soundEffects.forEach(s => { + const isDef = !s.default; + this.unlockedSounds[s.storageKey] = !isDef; + }); + this.saveUnlockedSounds(); + + this.musicTracks.forEach(s => { + const isDef = s.default || s.cost === 0; + this.unlockedMusic[s.storageKey] = isDef; + }); + this.saveUnlockedMusic(); + + this.saveData("points", "0"); + this.saveData("total_score", "0"); + this.saveData("high_score", "0"); + this.saveData("dg", "0"); + this.saveData("lifetime_points", "0"); + this.saveData("lifetime_dg", "0"); + this.saveData("lifetime_mg", "0"); + + this.deleteData("lifetime_purchases"); + this.deleteData("daily_purchases_limit"); + + this.boosterMultiplier = 1; + this.boosterEndTime = 0; + this.saveData("active_booster", "multiplier:1,end_time:0"); + + this.saveData("selected_cheems", "cheems_normal"); + this.saveData("selected_sfx", "sfx_1"); + this.saveData("selected_music", "music_1"); + this.saveData("music_volume", "50"); + this.saveData("sfx_volume", "100"); + this.saveData("app_theme", "1"); + this.saveData("font_size", "2"); + + this.showToast(this.dev[this.lang].success); + this.playSound(); + this.currentMusicFile = ""; + this.playMusic(); + this.redirect('game'); + } loadApp(): void { this.loadSettings(); + this.loadLanguageFile(this.lang); + this.loadClosetPrices(); + this.loadShopItems(); + this.loadMinigamesConfig(); + this.loadBoosterState(); + this.setupWindowFocusListeners(); this.loadCheems(); this.loadSounds(); + this.loadMusic(); this.loadScore(); + this.loadUnlocks(); + this.loadDevMenu(); } loadSettings(): void { - let savedLang = localStorage.getItem("CheemsBonkLang"); - let lang: string = savedLang === null ? "en" : savedLang; - this.lang = lang; + const savedLang = this.loadData("language"); + this.lang = savedLang && this.availableLanguages.some(l => l.key === savedLang) ? savedLang : "es"; + + const savedTheme = this.loadData("app_theme"); + const themeIdx = savedTheme !== null ? +savedTheme : 1; + this.switchTheme(themeIdx); + + const savedSize = this.loadData("font_size"); + const sizeIdx = savedSize !== null ? +savedSize : 2; + this.setAccessibility(sizeIdx); + + const savedMusVol = this.loadData("music_volume"); + this.musVol = savedMusVol !== null ? +savedMusVol : 50; + + const savedEffVol = this.loadData("sfx_volume"); + this.effVol = savedEffVol !== null ? +savedEffVol : 100; } loadCheems(): void { - let savedCheems = localStorage.getItem("CheemsBonkCheems"); - let cheems: string = savedCheems === null ? "normal" : savedCheems; - this.selectedCheems = cheems; + const savedCheems = this.loadData("selected_cheems"); + this.selectedCheems = savedCheems ? savedCheems.replace(/"/g, '') : "cheems_normal"; } loadSounds(): void { - let savedSound = localStorage.getItem("CheemsBonkSound"); - let sound: string = savedSound === null ? "hit" : savedSound; - this.selectedSound = sound; + const savedSound = this.loadData("selected_sfx"); + this.selectedSound = savedSound ? savedSound.replace(/"/g, '') : "sfx_1"; + } + + loadMusic(): void { + const savedMusic = this.loadData("selected_music"); + this.selectedMusic = savedMusic ? savedMusic.replace(/"/g, '') : "music_1"; + this.playMusic(this.selectedMusic); } loadScore(): void { - let totalScore = localStorage.getItem("CheemsBonkTotalScore"); - let highScore = localStorage.getItem("CheemsBonkHighScore"); - let dogeCoins = localStorage.getItem("CheemsBonkDogeCoins"); - let total: number = totalScore === null ? 0 : this.parseNumber(totalScore); - let high: number = highScore === null ? 0 : this.parseNumber(highScore); - let dc: number = dogeCoins === null ? 0 : this.parseNumber(dogeCoins); - this.highScore = high; - this.totalScore = total; - this.dogeCoins = dc; + const totalScore = this.loadData("total_score"); + const highScore = this.loadData("high_score"); + const savedPoints = this.loadData("points"); + const dogeCoins = this.loadData("dg"); + + this.highScore = highScore ? this.parseNumber(highScore) : 0; + this.totalScore = totalScore ? this.parseNumber(totalScore) : 0; + this.points = savedPoints ? this.parseNumber(savedPoints) : 0; + this.dogeCoins = dogeCoins ? this.parseNumber(dogeCoins) : 0; + + const tPoints = this.loadData("lifetime_points"); + this.totalPointsEarned = tPoints ? this.parseNumber(tPoints) : this.totalScore; + + const tDGC = this.loadData("lifetime_dg"); + this.totalDogeCoinsEarned = tDGC ? this.parseNumber(tDGC) : this.dogeCoins; + + const tMG = this.loadData("lifetime_mg"); + this.totalMinigameCoinsEarned = tMG ? this.parseNumber(tMG) : this.minigameCoins; + + let mgCoins = this.loadData("mg"); + if (!mgCoins) { + const match = document.cookie.match(/(^| )CheemsAppLiMinigameCoins=([^;]+)/); + if (match) mgCoins = match[2]; + } + this.minigameCoins = mgCoins ? this.parseNumber(mgCoins) : 0; + + this.actScore = 0; + localStorage.setItem("CheemsAppLiActPoints", "0"); + } + + loadUnlocks(): void { + const allMinigames = ['block_breaker', 'attack_hole', 'doge_rescue', 'flappy_dunk', 'helix_jump', 'magic_sort', 'mob_control', 'paper_io', 'spiral_roll', 'stack_colors']; + const unlockedMgs = this.parseArrayString(this.loadData("unlocked_minigames") || ""); + allMinigames.forEach(id => { + this.unlockedMinigames[id] = unlockedMgs.includes(id); + }); + + const unlockedChms = this.parseArrayString(this.loadData("unlocked_cheems") || ""); + this.cheemsSkins.forEach(s => { + this.unlockedCheems[s.storageKey] = s.default || unlockedChms.includes(s.id); + }); + + const unlockedSnds = this.parseArrayString(this.loadData("unlocked_sfx") || ""); + this.soundEffects.forEach(s => { + this.unlockedSounds[s.storageKey] = s.default || unlockedSnds.includes(String(s.id)); + }); + + const unlockedMsc = this.parseArrayString(this.loadData("unlocked_music") || ""); + this.musicTracks.forEach(s => { + this.unlockedMusic[s.storageKey] = s.default || s.cost === 0 || unlockedMsc.includes(String(s.id)); + }); + } + + saveUnlockedMinigames(): void { + const list = Object.keys(this.unlockedMinigames).filter(k => this.unlockedMinigames[k]); + this.saveData("unlocked_minigames", this.stringifyArray(list)); + } + + saveUnlockedCheems(): void { + const list = this.cheemsSkins.filter(s => this.unlockedCheems[s.storageKey] && !s.default).map(s => s.id); + this.saveData("unlocked_cheems", this.stringifyArray(list)); + } + + saveUnlockedSounds(): void { + const list = this.soundEffects.filter(s => this.unlockedSounds[s.storageKey] && !s.default).map(s => String(s.id)); + this.saveData("unlocked_sfx", this.stringifyArray(list)); + } + + saveUnlockedMusic(): void { + const list = this.musicTracks.filter(s => this.unlockedMusic[s.storageKey] && !s.default && s.cost !== 0).map(s => String(s.id)); + this.saveData("unlocked_music", this.stringifyArray(list)); + } + + loadDevMenu(): void { + const stored = this.loadData("dev_menu"); + this.devMenuUnlocked = stored ? stored.replace(/"/g, '') === 'true' : false; } parseNumber(value: string): number { - return +value + return +value.replace(/"/g, '') || 0; } parseString(value: any): string { - return value+"" + return String(value); } - async sleep(time:number): Promise { + async sleep(time: number): Promise { return new Promise(resolve => setTimeout(resolve, time)); } + + async checkCategoryCached(category: OfflineCategory): Promise { + if (!('caches' in window)) return false; + try { + const cache = await caches.open('cheems-bonk-offline-v1'); + for (const url of category.urls) { + const match = await cache.match(url); + if (!match) { + return localStorage.getItem(`cheems_offline_cached_${category.id}`) === 'true'; + } + } + return true; + } catch { + return localStorage.getItem(`cheems_offline_cached_${category.id}`) === 'true'; + } + } + + async cacheCategory(category: OfflineCategory, onProgress?: (progress: number) => void): Promise { + if (!('caches' in window)) return false; + try { + const cache = await caches.open('cheems-bonk-offline-v1'); + let completed = 0; + for (const url of category.urls) { + try { + const res = await fetch(url); + if (res.ok) { + await cache.put(url, res); + } + } catch (e) { + console.warn(`Failed to cache ${url}`, e); + } + completed++; + if (onProgress) { + onProgress(Math.round((completed / category.urls.length) * 100)); + } + } + localStorage.setItem(`cheems_offline_cached_${category.id}`, 'true'); + return true; + } catch (err) { + console.error("Error caching category:", err); + return false; + } + } + + loadBoosterState(): void { + const multStr = this.loadData("active_booster"); + if (multStr) { + const b = this.parseObjectString(multStr); + this.boosterMultiplier = b['multiplier'] ? parseInt(b['multiplier']) : 1; + this.boosterEndTime = b['end_time'] ? parseInt(b['end_time']) : 0; + } else { + this.boosterMultiplier = 1; + this.boosterEndTime = 0; + } + } + + async loadShopItems(): Promise { + try { + const res = await fetch("data/shop.json"); + if (res.ok) { + const rawItems = await res.json(); + + this.shopItems = rawItems.map((item: any) => ({ + ...item, + cost: this.evaluatePriceExpression(item.cost), + costCoins: this.evaluatePriceExpression(item.costCoins), + coinsGiven: item.coinsGiven !== undefined ? this.evaluatePriceExpression(item.coinsGiven) : undefined, + dailyLimit: item.dailyLimit !== undefined ? this.evaluatePriceExpression(item.dailyLimit) : undefined + })); + } + } catch (err) { + console.warn("Could not load data/shop.json", err); + } + this.appendUnlockableShopItems(); + } + + private evaluatePriceExpression(expression: string | number | undefined): number { + if (expression === undefined || expression === null) return 0; + if (typeof expression === 'number') return Math.max(0, Math.round(expression)); + if (typeof expression !== 'string') return 0; + + try { + let parsedStr = expression; + + parsedStr = parsedStr.replace(/\$\{daily_price_1\}/g, String(this.getDailyDogeCoinPrice(1))); + parsedStr = parsedStr.replace(/\$\{daily_price_2\}/g, String(this.getDailyDogeCoinPrice(2))); + parsedStr = parsedStr.replace(/\$\{daily_price_3\}/g, String(this.getDailyDogeCoinPrice(3))); + parsedStr = parsedStr.replace(/\$\{daily_price_4\}/g, String(this.getDailyDogeCoinPrice(4))); + + parsedStr = parsedStr.replace(/\$\{daily_price\}/g, String(this.getDailyDogeCoinPrice(1))); + + if (/[^0-9\+\-\*\/\%\.\s\(\)]/.test(parsedStr)) { + console.warn("Invalid characters in price expression:", parsedStr); + return 0; + } + + const result = new Function(`return (${parsedStr})`)(); + + const num = Number(result); + if (isNaN(num)) return 0; + return Math.max(0, Math.round(num)); + } catch (e) { + console.warn("Could not evaluate price expression:", expression, e); + return 0; + } + } + + getActiveMultiplier(): number { + const now = Date.now(); + if (now < this.boosterEndTime) { + return this.boosterMultiplier; + } else if (this.boosterEndTime !== 0) { + this.boosterEndTime = 0; + this.boosterMultiplier = 1; + this.saveData("active_booster", "multiplier:1,end_time:0"); + } + return 1; + } + + getBoosterRemainingSeconds(): number { + const now = Date.now(); + if (now < this.boosterEndTime) { + return Math.max(0, Math.ceil((this.boosterEndTime - now) / 1000)); + } + return 0; + } + + getBoosterFormattedTime(): string { + const totalSeconds = this.getBoosterRemainingSeconds(); + if (totalSeconds <= 60) { + return String(totalSeconds).padStart(2, '0'); + } + const secs = totalSeconds % 60; + const totalMinutes = Math.floor(totalSeconds / 60); + if (totalSeconds <= 3600) { + return `${String(totalMinutes).padStart(2, '0')}:${String(secs).padStart(2, '0')}`; + } + const mins = totalMinutes % 60; + const totalHours = Math.floor(totalMinutes / 60); + if (totalSeconds <= 86400) { + return `${String(totalHours).padStart(2, '0')}:${String(mins).padStart(2, '0')}:${String(secs).padStart(2, '0')}`; + } + const hours = totalHours % 24; + const days = Math.floor(totalHours / 24); + return `${days} ${String(hours).padStart(2, '0')}:${String(mins).padStart(2, '0')}:${String(secs).padStart(2, '0')}`; + } + + activateBooster(multiplier: number, durationMin: number): void { + const durationMs = durationMin * 60 * 1000; + const now = Date.now(); + if (now < this.boosterEndTime && this.boosterMultiplier === multiplier) { + this.boosterEndTime += durationMs; + } else { + this.boosterEndTime = now + durationMs; + this.boosterMultiplier = multiplier; + } + this.saveData("active_booster", `multiplier:${this.boosterMultiplier},end_time:${this.boosterEndTime}`); + this.showToast(this.shop[this.lang]?.boosterActivated || "Booster activated!"); + this.playSound(); + } + + getDailyPurchaseCount(itemId: string): number { + const today = new Date().toISOString().slice(0, 10); + const storedStr = this.loadData("daily_purchases_limit"); + if (!storedStr) return 0; + const purchasesArr = this.parseArrayOfObjectsString(storedStr); + const itemData = purchasesArr.find(p => p['id'] === itemId); + if (itemData && itemData['date'] === today) { + return parseInt(itemData['count']) || 0; + } + return 0; + } + + recordDailyPurchase(itemId: string): void { + const today = new Date().toISOString().slice(0, 10); + const storedStr = this.loadData("daily_purchases_limit"); + const purchasesArr = this.parseArrayOfObjectsString(storedStr || ""); + const itemData = purchasesArr.find(p => p['id'] === itemId); + if (itemData) { + if (itemData['date'] === today) { + itemData['count'] = String((parseInt(itemData['count']) || 0) + 1); + } else { + itemData['date'] = today; + itemData['count'] = "1"; + } + } else { + purchasesArr.push({ id: itemId, count: "1", date: today }); + } + this.saveData("daily_purchases_limit", this.stringifyArrayOfObjects(purchasesArr)); + } + + canBuyDailyLimit(item: ShopItem): boolean { + if (!item.dailyLimit || item.dailyLimit <= 0) { + return true; + } + return this.getDailyPurchaseCount(item.id) < item.dailyLimit; + } + + getRemainingDailyLimit(item: ShopItem): number { + if (!item.dailyLimit || item.dailyLimit <= 0) { + return 0; + } + return Math.max(0, item.dailyLimit - this.getDailyPurchaseCount(item.id)); + } + + getLifetimePurchaseCount(itemId: string): number { + const stored = this.loadData("lifetime_purchases"); + const arr = this.parseArrayString(stored || ""); + return arr.includes(itemId) ? 1 : 0; + } + + recordLifetimePurchase(itemId: string): void { + const stored = this.loadData("lifetime_purchases"); + const arr = this.parseArrayString(stored || ""); + if (!arr.includes(itemId)) { + arr.push(itemId); + this.saveData("lifetime_purchases", this.stringifyArray(arr)); + } + } + + isLifetimeLimitReached(item: ShopItem): boolean { + if (item.type === 'cheems') { + const target = String(item.targetId !== undefined ? item.targetId : item.id); + return this.isCheemsUnlocked(target); + } + if (item.type === 'sound') { + const target = String(item.targetId !== undefined ? item.targetId : item.id); + return this.isSoundUnlocked(target); + } + if (item.type === 'music') { + const target = String(item.targetId !== undefined ? item.targetId : item.id); + return this.isMusicUnlocked(target); + } + if (item.oneTimePurchase) { + return this.getLifetimePurchaseCount(item.id) >= 1; + } + return false; + } + + appendUnlockableShopItems(): void { + if (!this.cheemsSkins.length && !this.soundEffects.length && !this.musicTracks.length) { + return; + } + + this.cheemsSkins.forEach(skin => { + if (!skin.default && skin.id !== 'cheems_normal' && skin.id !== 'normal' && !this.shopItems.some(i => i.id === skin.id)) { + this.shopItems.push({ + id: skin.id, + type: 'cheems', + targetId: skin.id, + nameKey: skin.nameKey, + cost: 0, + costCoins: skin.cost, + icon: this.getCheemsImg(skin.id), + oneTimePurchase: true + }); + } + }); + + this.soundEffects.forEach(sound => { + if (!sound.default && sound.id !== 'sfx_1' && sound.id !== '1' && !this.shopItems.some(i => i.id === sound.id)) { + this.shopItems.push({ + id: sound.id, + type: 'sound', + targetId: sound.id, + nameKey: sound.nameKey, + cost: 0, + costCoins: sound.cost, + icon: "img/icons/sound-svgrepo-com.svg", + oneTimePurchase: true + }); + } + }); + + this.musicTracks.forEach(track => { + if (!track.default && String(track.id) !== 'music_0' && String(track.id) !== 'music_1' && String(track.id) !== '0' && String(track.id) !== '1' && !this.shopItems.some(i => i.id === String(track.id))) { + this.shopItems.push({ + id: String(track.id), + type: 'music', + targetId: track.id, + nameKey: track.nameKey, + cost: 0, + costCoins: track.cost, + icon: "img/icons/music-svgrepo-com.svg", + oneTimePurchase: true + }); + } + }); + } + + buyShopUnlockableItem(item: ShopItem): boolean { + if (this.isLifetimeLimitReached(item)) { + this.showToast(this.shop[this.lang]?.alreadyPurchased || "Already purchased!"); + return false; + } + const ptsCost = item.cost || 0; + const coinCost = item.costCoins || 0; + if (this.points >= ptsCost && this.dogeCoins >= coinCost) { + this.points -= ptsCost; + this.dogeCoins -= coinCost; + this.saveData("points", String(this.points)); + this.saveData("dg", String(this.dogeCoins)); + + if (item.type === 'cheems') { + const targetId = String(item.targetId !== undefined ? item.targetId : item.id); + const skin = this.cheemsSkins.find(s => s.id === targetId); + if (skin) { + this.unlockedCheems[skin.storageKey] = true; + this.saveUnlockedCheems(); + } + } else if (item.type === 'sound') { + const targetId = String(item.targetId !== undefined ? item.targetId : item.id); + const sound = this.soundEffects.find(s => String(s.id) === targetId); + if (sound) { + this.unlockedSounds[sound.storageKey] = true; + this.saveUnlockedSounds(); + } + } else if (item.type === 'music') { + const targetId = String(item.targetId !== undefined ? item.targetId : item.id); + const track = this.musicTracks.find(m => String(m.id) === targetId); + if (track) { + this.unlockedMusic[track.storageKey] = true; + this.saveUnlockedMusic(); + } + } + + this.recordDailyPurchase(item.id); + this.recordLifetimePurchase(item.id); + this.showToast(this.shop[this.lang]?.itemBoughtGoToCloset || "Item purchased! Go to Closet to equip."); + this.playSound(); + return true; + } else { + if (this.points < ptsCost) { + this.showToast(this.shop[this.lang]?.needMorePoints || "Not enough points!"); + } else { + this.showToast(this.shop[this.lang]?.needMoreCoins || "Need more DogeCoins!"); + } + this.playSound('sfx_8'); + return false; + } + } + + + private setupWindowFocusListeners(): void { + document.addEventListener('visibilitychange', () => { + if (document.hidden) { + this.pauseAllAudioForBlur(); + } else { + this.resumeAllAudioForFocus(); + } + }); + + window.addEventListener('blur', () => { + this.pauseAllAudioForBlur(); + }); + + window.addEventListener('focus', () => { + if (!document.hidden) { + this.resumeAllAudioForFocus(); + } + }); + } + + private pauseAllAudioForBlur(): void { + if (this.isWindowBlurred) return; + this.isWindowBlurred = true; + if (this.audioCtx && this.audioCtx.state === 'running') { + this.audioCtx.suspend().catch(() => {}); + } + if (!this.musicAudio.paused) { + this.musicAudio.pause(); + } + } + + private resumeAllAudioForFocus(): void { + if (!this.isWindowBlurred) return; + this.isWindowBlurred = false; + this.resumeBackground(); + } + + public pauseBackground(): void { + this.isBackgroundMusicPaused = true; + if (this.audioCtx && this.audioCtx.state === 'running') { + this.audioCtx.suspend().catch(() => {}); + } + if (!this.musicAudio.paused) { + this.musicAudio.pause(); + } + } + + public resumeBackground(): void { + this.isBackgroundMusicPaused = false; + if (String(this.selectedMusic) !== '0' && this.musVol > 0) { + if (this.audioCtx && this.audioCtx.state === 'suspended') { + this.audioCtx.resume().catch(() => {}); + } else if (this.musicAudio.paused && this.musicAudio.src) { + this.musicAudio.play().catch(() => {}); + } + } + } + + getCheemsImg(id: string): string { + const skin = this.cheemsSkins.find(s => s.id === id); + if (skin?.imgUrl) return skin.imgUrl; + return "img/cheems/" + (skin?.img || id + ".png"); + } + + getCheemsHitImg(id: string): string { + const skin = this.cheemsSkins.find(s => s.id === id); + if (skin?.hitImgUrl) return skin.hitImgUrl; + return "img/hit/" + (skin?.hitImg || skin?.img || id + ".png"); + } + + getShopItemName(item: ShopItem): string { + if (item.nameKey && this.shopItemsText[this.lang]?.[item.nameKey]) { + return this.shopItemsText[this.lang][item.nameKey]; + } + if (item.nameKey && this.itemsText[this.lang]?.[item.nameKey]) { + return this.itemsText[this.lang][item.nameKey]; + } + return this.lang === 'es' ? (item.nameEs || item.nameEn || item.id) : (item.nameEn || item.nameEs || item.id); + } + + getShopItemDesc(item: ShopItem): string { + if (item.descKey && this.shopItemsText[this.lang]?.[item.descKey]) { + return this.shopItemsText[this.lang][item.descKey]; + } + return this.lang === 'es' ? (item.descEs || item.descEn || '') : (item.descEn || item.descEs || ''); + } + + getCheemsName(skin: CheemsSkinItem): string { + if (skin.nameKey && this.itemsText[this.lang]?.[skin.nameKey]) { + return this.itemsText[this.lang][skin.nameKey]; + } + return this.lang === 'es' ? (skin.nameEs || skin.nameEn || skin.id) : (skin.nameEn || skin.nameEs || skin.id); + } + + getCheemsDescription(skin: CheemsSkinItem): string { + if (skin.description && this.itemsText[this.lang]?.[skin.description]) { + return this.itemsText[this.lang][skin.description]; + } + return ''; + } + + getSoundName(sound: SoundEffectItem): string { + if (sound.nameKey && this.itemsText[this.lang]?.[sound.nameKey]) { + return this.itemsText[this.lang][sound.nameKey]; + } + return sound.name || sound.id; + } + + getSoundDescription(sound: SoundEffectItem): string { + if (sound.description && this.itemsText[this.lang]?.[sound.description]) { + return this.itemsText[this.lang][sound.description]; + } + return ''; + } + + getMusicName(track: MusicTrackItem): string { + if (track.nameKey && this.itemsText[this.lang]?.[track.nameKey]) { + return this.itemsText[this.lang][track.nameKey]; + } + return track.name || String(track.id); + } + + getMusicDescription(track: MusicTrackItem): string { + if (track.description && this.itemsText[this.lang]?.[track.description]) { + return this.itemsText[this.lang][track.description]; + } + return ''; + } + + + exportSave(): void { + const saveData: Record = {}; + for (let i = 0; i < localStorage.length; i++) { + const key = localStorage.key(i); + if (key && key.startsWith(this.PREFIX)) { + saveData[key] = localStorage.getItem(key) || ''; + } + } + const jsonStr = JSON.stringify(saveData); + const obfuscated = btoa(encodeURIComponent(jsonStr)); + + const blob = new Blob([obfuscated], { type: 'application/octet-stream' }); + const url = window.URL.createObjectURL(blob); + const a = document.createElement('a'); + a.href = url; + a.download = 'cheems_save.dat'; + document.body.appendChild(a); + a.click(); + document.body.removeChild(a); + window.URL.revokeObjectURL(url); + } + + importSave(file: File): void { + const reader = new FileReader(); + reader.onload = (e) => { + try { + const result = e.target?.result as string; + const jsonStr = decodeURIComponent(atob(result)); + const saveData = JSON.parse(jsonStr); + + for (let i = localStorage.length - 1; i >= 0; i--) { + const key = localStorage.key(i); + if (key && key.startsWith(this.PREFIX)) { + localStorage.removeItem(key); + } + } + + for (const key of Object.keys(saveData)) { + if (key.startsWith(this.PREFIX)) { + localStorage.setItem(key, saveData[key]); + } + } + + this.showToast(this.dev[this.lang].success || "Success"); + setTimeout(() => { + location.reload(); + }, 1000); + } catch (err) { + console.error("Save import failed", err); + this.showToast("Import failed! Invalid save file."); + } + }; + reader.readAsText(file); + } } diff --git a/src/styles.css b/src/styles.css index 10cb353..1af0ee0 100644 --- a/src/styles.css +++ b/src/styles.css @@ -1,42 +1,235 @@ -/*Fonts*/ -@font-face { - font-family: 'Kalam'; - src: url('/fonts/Kalam-Regular.ttf') format('truetype'); +/* Root font sizes scaled by documentElement.style.fontSize */ +* { + box-sizing: border-box; + margin: 0; + padding: 0; + font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif; } -/*App*/ -html { +body { + min-height: 100vh; + overflow-x: clip; + transition: background 0.3s ease, color 0.3s ease; user-select: none; - font-family: Kalam, Arial, Helvetica, sans-serif; + -webkit-user-select: none; } -.icon { - height: 100%; - width: auto; + +/* Font Size Classes */ +.text-smaller { font-size: 0.8rem; } +.text-small { font-size: 0.95rem; } +.text-normal { font-size: 1.1rem; } +.text-big { font-size: 1.35rem; } +.text-max { font-size: 1.6rem; } + +body.text-smaller { font-size: 0.8rem; } +body.text-small { font-size: 0.95rem; } +body.text-normal { font-size: 1.1rem; } +body.text-big { font-size: 1.35rem; } +body.text-max { font-size: 1.6rem; } + +button, input, select, textarea { + font-size: 1em; +} + +/* Themes (Background & Base Colors) */ +body.theme-dark { + background: radial-gradient(circle at 50% 20%, rgb(45, 40, 35) 0%, rgb(24, 21, 18) 100%); + color: rgb(240, 235, 225); +} + +body.theme-light { + background: radial-gradient(circle at 50% 20%, rgb(255, 250, 240) 0%, rgb(235, 220, 195) 100%); + color: rgb(50, 35, 20); +} + +body.theme-contrast { + background: #000000; + color: #ffffff; +} + +/* Theme Utilities for text */ +.color-text.theme-dark { color: #ffd166; } +.color-text.theme-light { color: #9c5c14; } +.color-text.theme-contrast { color: #ffff00; } + +/* Premium Glassmorphic Cards & Groups */ +.group { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + width: 90%; + max-width: 850px; + margin: 1.5rem auto; + padding: 1.75rem; + border-radius: 20px; + box-shadow: 0 10px 30px rgba(0, 0, 0, 0.25); + backdrop-filter: blur(12px); + -webkit-backdrop-filter: blur(12px); + transition: transform 0.25s ease, box-shadow 0.25s ease, border-color 0.25s ease; +} + +.group.theme-dark { + background: rgba(65, 55, 45, 0.65); + border: 2px solid rgba(255, 209, 102, 0.25); + box-shadow: 0 12px 36px rgba(0, 0, 0, 0.45); +} + +.group.theme-light { + background: rgba(255, 248, 235, 0.75); + border: 2px solid rgba(156, 92, 20, 0.3); + box-shadow: 0 12px 36px rgba(100, 70, 30, 0.15); +} + +.group.theme-contrast { + background: #000000; + border: 2px solid #ffffff; + box-shadow: none; + backdrop-filter: none; + -webkit-backdrop-filter: none; + color: #ffffff; +} + +/* Grid & Layout Utilities */ +.container { + width: 100%; + min-height: calc(100vh - 120px); + display: flex; + flex-direction: column; + align-items: center; + justify-content: flex-start; + padding: 1rem; +} + +.flex-right { + display: flex; + flex-direction: row; + flex-wrap: wrap; + align-items: center; + justify-content: space-around; + width: 100%; + margin: 0.75rem 0; + gap: 1rem; } -/*Accesibility*/ -.text-normal { - font-size: 14pt; +.flex-right.center { + justify-content: center; } -.text-big { - font-size: 18pt; + +/* Premium Buttons & Cards */ +.btn-card { + display: flex; + flex-direction: row; + align-items: center; + justify-content: center; + gap: 0.75rem; + padding: 0.85rem 1.5rem; + border-radius: 14px; + font-weight: bold; + font-size: 1em; + cursor: pointer; + transition: all 0.2s cubic-bezier(0.34, 1.56, 0.64, 1); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); + text-align: center; +} + +.btn-card:hover { + transform: translateY(-3px) scale(1.03); + box-shadow: 0 8px 20px rgba(0, 0, 0, 0.25); +} + +.btn-card:active { + transform: translateY(1px) scale(0.98); +} + +.btn-card.theme-dark { + background: linear-gradient(135deg, rgba(90, 75, 55, 0.9), rgba(65, 50, 35, 0.95)); + border: 1px solid rgba(255, 209, 102, 0.4); + color: #ffd166; +} + +.btn-card.theme-light { + background: linear-gradient(135deg, rgba(255, 235, 200, 0.9), rgba(245, 215, 165, 0.95)); + border: 1px solid rgba(156, 92, 20, 0.5); + color: #5a3505; +} + +.btn-card.theme-contrast { + background: #000000; + border: 2px solid #ffff00; + color: #ffff00; + box-shadow: none; } -.text-bigger { - font-size: 24pt; + +.btn-card.theme-contrast:hover { + background: #ffff00; + color: #000000; +} + +/* Selected Items in Closet */ +.selected-cheems { + border-radius: 50%; + transform: scale(1.15); + box-shadow: 0 0 25px rgba(255, 209, 102, 0.8); + transition: all 0.3s cubic-bezier(0.34, 1.56, 0.64, 1); } -.text-small { - font-size: 12pt; + +.selected-cheems.theme-dark { + background: radial-gradient(circle, rgba(255, 209, 102, 0.4) 0%, transparent 70%); } -.text-smaller { - font-size: 8pt; + +.selected-cheems.theme-light { + background: radial-gradient(circle, rgba(156, 92, 20, 0.3) 0%, transparent 70%); + box-shadow: 0 0 25px rgba(156, 92, 20, 0.6); } -.color-text.theme-contrast { - color: rgb(255, 255, 0); +.selected-cheems.theme-contrast { + border: 2px solid #ffff00; + box-shadow: none; } -.color-text.theme-dark { - color: rgb(145, 145, 72); + +/* Toast Popup */ +.toast-popup { + position: fixed; + bottom: 2rem; + left: 50%; + transform: translateX(-50%); + background: rgba(26, 22, 18, 0.95); + color: #ffd166; + border: 2px solid #ffd166; + padding: 1rem 2rem; + border-radius: 50px; + font-weight: 900; + font-size: 1em; + z-index: 9999; + box-shadow: 0 10px 25px rgba(0, 0, 0, 0.5); + animation: slideUpToast 0.3s cubic-bezier(0.34, 1.56, 0.64, 1); + backdrop-filter: blur(10px); + -webkit-backdrop-filter: blur(10px); } -.color-text.theme-light { - color: rgb(194, 194, 72); + +.toast-popup.theme-light { + background: rgba(255, 245, 230, 0.95); + color: #9c5c14; + border-color: #9c5c14; +} + +.toast-popup.theme-contrast { + background: #000000; + color: #ffff00; + border: 2px solid #ffff00; + box-shadow: none; + backdrop-filter: none; + -webkit-backdrop-filter: none; +} + +@keyframes slideUpToast { + from { + opacity: 0; + transform: translate(-50%, 20px) scale(0.9); + } + to { + opacity: 1; + transform: translate(-50%, 0) scale(1); + } } \ No newline at end of file