3 Commits

Author SHA1 Message Date
Kristian Ollikainen
b4a1f6d31f Merge a54cf759fa into 32341574dc 2025-10-25 03:57:46 +03:00
DatCaptainHorse
a54cf759fa Fixed multi-controllers, optimize and improve code in relay and nestri-server 2025-10-25 03:57:26 +03:00
DatCaptainHorse
67f9a7d0a0 Restructure protobufs and use them everywhere 2025-10-21 18:41:45 +03:00
54 changed files with 2429 additions and 2518 deletions

View File

@@ -3,14 +3,14 @@ variable "BASE_IMAGE" {
} }
group "default" { group "default" {
targets = ["runner-base", "runner-builder"] targets = ["runner"]
} }
target "runner-base" { target "runner-base" {
dockerfile = "containerfiles/runner-base.Containerfile" dockerfile = "containerfiles/runner-base.Containerfile"
context = "." context = "."
args = { args = {
BASE_IMAGE = BASE_IMAGE BASE_IMAGE = "${BASE_IMAGE}"
} }
cache-from = ["type=gha,scope=runner-base-pr"] cache-from = ["type=gha,scope=runner-base-pr"]
cache-to = ["type=gha,scope=runner-base-pr,mode=max"] cache-to = ["type=gha,scope=runner-base-pr,mode=max"]
@@ -30,3 +30,19 @@ target "runner-builder" {
runner-base = "target:runner-base" runner-base = "target:runner-base"
} }
} }
target "runner" {
dockerfile = "containerfiles/runner.Containerfile"
context = "."
args = {
RUNNER_BASE_IMAGE = "runner-base:latest"
RUNNER_BUILDER_IMAGE = "runner-builder:latest"
}
cache-from = ["type=gha,scope=runner-pr"]
cache-to = ["type=gha,scope=runner-pr,mode=max"]
tags = ["nestri-runner"]
contexts = {
runner-base = "target:runner-base"
runner-builder = "target:runner-builder"
}
}

View File

@@ -1,83 +0,0 @@
name: Build Nestri standalone playsite
on:
pull_request:
paths:
- "containerfiles/playsite.Containerfile"
- ".github/workflows/play-standalone.yml"
- "packages/play-standalone/**"
- "packages/input/**"
push:
branches: [ dev, production ]
paths:
- "containerfiles/playsite.Containerfile"
- ".github/workflows/play-standalone.yml"
- "packages/play-standalone/**"
- "packages/input/**"
tags:
- v*.*.*
release:
types: [ created ]
env:
REGISTRY: ghcr.io
IMAGE_NAME: nestrilabs/nestri
BASE_TAG_PREFIX: playsite
jobs:
build-docker-pr:
name: Build image on PR
runs-on: ubuntu-latest
if: ${{ github.event_name == 'pull_request' }}
steps:
- name: Checkout repo
uses: actions/checkout@v4
- name: Setup Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build Docker image
uses: docker/build-push-action@v5
with:
file: containerfiles/playsite.Containerfile
context: ./
push: false
load: true
tags: nestri:playsite
build-and-push-docker:
name: Build and push image
if: ${{ github.ref == 'refs/heads/dev' || github.ref == 'refs/heads/production' }}
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout repo
uses: actions/checkout@v4
- name: Log into registry ${{ env.REGISTRY }}
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ github.token }}
- name: Extract Container metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}/${{ env.BASE_TAG_PREFIX }}
#
#tag on release, and a nightly build for 'dev'
tags: |
type=raw,value=nightly,enable={{is_default_branch}}
type=raw,value={{branch}}
type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', 'production') }}
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
- name: Build Docker image
uses: docker/build-push-action@v5
with:
file: containerfiles/playsite.Containerfile
context: ./
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}

View File

@@ -1,5 +1,6 @@
name: Build Nestri relay #Tabs not spaces, you moron :)
name: Build nestri:relay
on: on:
pull_request: pull_request:
paths: paths:

View File

@@ -1,73 +0,0 @@
name: Build Nestri runner base images
on: [ workflow_call ]
env:
REGISTRY: ghcr.io
IMAGE_NAME: nestrilabs/nestri
BASE_IMAGE: docker.io/cachyos/cachyos:latest
jobs:
build-and-push-bases:
name: Build and push images
if: ${{ github.ref == 'refs/heads/production' || github.ref == 'refs/heads/dev' }}
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
strategy:
matrix:
variant:
- { suffix: "v2", base: "docker.io/cachyos/cachyos:latest" }
- { suffix: "v3", base: "docker.io/cachyos/cachyos-v3:latest" }
#- { suffix: "v4", base: "docker.io/cachyos/cachyos-v4:latest" } # Disabled until GHA has this
steps:
- name: Checkout repo
uses: actions/checkout@v4
- name: Log into registry ${{ env.REGISTRY }}
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ github.token }}
- name: Setup Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Set Swap Space
uses: pierotofy/set-swap-space@master
with:
swap-size-gb: 20
- name: Build and push runner-base image
uses: docker/build-push-action@v6
with:
file: containerfiles/runner-base.Containerfile
context: ./
push: true
tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}/runner-base:latest-${{ matrix.variant.suffix }}
build-args: |
BASE_IMAGE=${{ matrix.variant.base }}
cache-from: type=gha,scope=runner-base-${{ matrix.variant.suffix }},mode=max
cache-to: type=gha,scope=runner-base-${{ matrix.variant.suffix }},mode=max
pull: true
- name: Build and push runner-builder image
uses: docker/build-push-action@v6
with:
file: containerfiles/runner-builder.Containerfile
context: ./
push: true
tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}/runner-builder:latest-${{ matrix.variant.suffix }}
build-args: |
RUNNER_BASE_IMAGE=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}/runner-base:latest-${{ matrix.variant.suffix }}
cache-from: type=gha,scope=runner-builder-${{ matrix.variant.suffix }},mode=max
cache-to: type=gha,scope=runner-builder-${{ matrix.variant.suffix }},mode=max
- name: Build and push runner-common image
uses: docker/build-push-action@v6
with:
file: containerfiles/runner-common.Containerfile
context: ./
push: true
tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}/runner-common:latest-${{ matrix.variant.suffix }}
build-args: |
RUNNER_BASE_IMAGE=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}/runner-base:latest-${{ matrix.variant.suffix }}
RUNNER_BUILDER_IMAGE=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}/runner-builder:latest-${{ matrix.variant.suffix }}
cache-from: type=gha,scope=runner-common-${{ matrix.variant.suffix }},mode=max
cache-to: type=gha,scope=runner-common-${{ matrix.variant.suffix }},mode=max

View File

@@ -1,86 +0,0 @@
name: Build Nestri runner image variants
on:
workflow_dispatch:
schedule:
- cron: 7 0 * * 1,3,6 # Nightlies
push:
branches: [ dev, production ]
paths:
- "containerfiles/*runner.Containerfile"
- ".github/workflows/runner-variants.yml"
- "packages/scripts/**"
- "packages/configs/**"
tags:
- v*.*.*
release:
types: [ created ]
env:
REGISTRY: ghcr.io
IMAGE_NAME: nestrilabs/nestri
jobs:
bases:
uses: ./.github/workflows/runner-bases.yml
permissions:
contents: read
packages: write
build-and-push-variants:
needs: [ bases ]
name: Build and push images
if: ${{ github.ref == 'refs/heads/production' || github.ref == 'refs/heads/dev' }}
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
strategy:
matrix:
variant:
- { suffix: "v2", base: "docker.io/cachyos/cachyos:latest" }
- { suffix: "v3", base: "docker.io/cachyos/cachyos-v3:latest" }
#- { suffix: "v4", base: "docker.io/cachyos/cachyos-v4:latest" } # Disabled until GHA has this
runner:
- steam
- heroic
- minecraft
# ADD MORE HERE AS NEEDED #
steps:
- name: Checkout repo
uses: actions/checkout@v4
- name: Log into registry ${{ env.REGISTRY }}
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ github.token }}
- name: Extract runner metadata
id: meta-runner
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}/runner
tags: |
type=raw,value=nightly-${{ matrix.runner }}-${{ matrix.variant.suffix }},enable={{is_default_branch}}
type=raw,value={{branch}}-${{ matrix.runner }}-${{ matrix.variant.suffix }}
type=raw,value=latest-${{ matrix.runner }}-${{ matrix.variant.suffix }},enable=${{ github.ref == format('refs/heads/{0}', 'production') }}
type=semver,pattern={{version}}-${{ matrix.runner }}-${{ matrix.variant.suffix }}
type=semver,pattern={{major}}.{{minor}}-${{ matrix.runner }}-${{ matrix.variant.suffix }}
type=semver,pattern={{major}}-${{ matrix.runner }}-${{ matrix.variant.suffix }}
- name: Setup Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Set Swap Space
uses: pierotofy/set-swap-space@master
with:
swap-size-gb: 20
- name: Build and push runner image
uses: docker/build-push-action@v6
with:
file: containerfiles/${{ matrix.runner }}-runner.Containerfile
context: ./
push: true
tags: ${{ steps.meta-runner.outputs.tags }}
labels: ${{ steps.meta-runner.outputs.labels }}
build-args: |
RUNNER_COMMON_IMAGE=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}/runner-common:latest-${{ matrix.variant.suffix }}
cache-from: type=gha,scope=runner-${{ matrix.runner }}-${{ matrix.variant.suffix }},mode=max
cache-to: type=gha,scope=runner-${{ matrix.runner }}-${{ matrix.variant.suffix }},mode=max

148
.github/workflows/runner.yml vendored Normal file
View File

@@ -0,0 +1,148 @@
#Tabs not spaces, you moron :)
name: Build nestri-runner
on:
pull_request:
paths:
- "containerfiles/runner*.Containerfile"
- "packages/scripts/**"
- "packages/server/**"
- ".github/workflows/runner.yml"
schedule:
- cron: 7 0 * * 1,3,6 # Regularly to keep that build cache warm
push:
branches: [dev, production]
paths:
- "containerfiles/runner*.Containerfile"
- ".github/workflows/runner.yml"
- "packages/scripts/**"
- "packages/server/**"
tags:
- v*.*.*
release:
types: [created]
env:
REGISTRY: ghcr.io
IMAGE_NAME: nestrilabs/nestri
BASE_IMAGE: docker.io/cachyos/cachyos:latest
# This makes our release ci quit prematurely
# concurrency:
# group: ci-${{ github.ref }}
# cancel-in-progress: true
jobs:
build-docker-pr:
name: Build images on PR
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
if: ${{ github.event_name == 'pull_request' }}
steps:
-
name: Setup Docker Buildx
uses: docker/setup-buildx-action@v3
-
name: Set Swap Space
uses: pierotofy/set-swap-space@master
with:
swap-size-gb: 20
-
name: Build images using bake
uses: docker/bake-action@v6
env:
BASE_IMAGE: ${{ env.BASE_IMAGE }}
with:
files: |
./.github/workflows/docker-bake.hcl
targets: runner
push: false
load: true
build-and-push-docker:
name: Build and push images
if: ${{ github.ref == 'refs/heads/production' || github.ref == 'refs/heads/dev' }}
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
strategy:
matrix:
variant:
- { suffix: "", base: "docker.io/cachyos/cachyos:latest" }
- { suffix: "-v3", base: "docker.io/cachyos/cachyos-v3:latest" }
#- { suffix: "-v4", base: "docker.io/cachyos/cachyos-v4:latest" } # Disabled until GHA has this
steps:
-
name: Checkout repo
uses: actions/checkout@v4
-
name: Log into registry ${{ env.REGISTRY }}
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ github.token }}
-
name: Extract runner metadata
id: meta-runner
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}/runner
tags: |
type=raw,value=nightly${{ matrix.variant.suffix }},enable={{is_default_branch}}
type=raw,value={{branch}}${{ matrix.variant.suffix }}
type=raw,value=latest${{ matrix.variant.suffix }},enable=${{ github.ref == format('refs/heads/{0}', 'production') }}
type=semver,pattern={{version}}${{ matrix.variant.suffix }}
type=semver,pattern={{major}}.{{minor}}${{ matrix.variant.suffix }}
type=semver,pattern={{major}}${{ matrix.variant.suffix }}
-
name: Setup Docker Buildx
uses: docker/setup-buildx-action@v3
-
name: Set Swap Space
uses: pierotofy/set-swap-space@master
with:
swap-size-gb: 20
-
name: Build and push runner-base image
uses: docker/build-push-action@v6
with:
file: containerfiles/runner-base.Containerfile
context: ./
push: true
tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}/runner-base:latest${{ matrix.variant.suffix }}
build-args: |
BASE_IMAGE=${{ matrix.variant.base }}
cache-from: type=gha,scope=runner-base${{ matrix.variant.suffix }},mode=max
cache-to: type=gha,scope=runner-base${{ matrix.variant.suffix }},mode=max
pull: ${{ github.event_name == 'schedule' }}
-
name: Build and push runner-builder image
uses: docker/build-push-action@v6
with:
file: containerfiles/runner-builder.Containerfile
context: ./
push: true
tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}/runner-builder:latest${{ matrix.variant.suffix }}
build-args: |
RUNNER_BASE_IMAGE=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}/runner-base:latest${{ matrix.variant.suffix }}
cache-from: type=gha,scope=runner-builder${{ matrix.variant.suffix }},mode=max
cache-to: type=gha,scope=runner-builder${{ matrix.variant.suffix }},mode=max
-
name: Build and push runner image
uses: docker/build-push-action@v6
with:
file: containerfiles/runner.Containerfile
context: ./
push: true
tags: ${{ steps.meta-runner.outputs.tags }}
labels: ${{ steps.meta-runner.outputs.labels }}
build-args: |
RUNNER_BASE_IMAGE=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}/runner-base:latest${{ matrix.variant.suffix }}
RUNNER_BUILDER_IMAGE=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}/runner-builder:latest${{ matrix.variant.suffix }}
cache-from: type=gha,scope=runner${{ matrix.variant.suffix }},mode=max
cache-to: type=gha,scope=runner${{ matrix.variant.suffix }},mode=max

View File

@@ -15,4 +15,3 @@ plugins:
# Rust (nestri-server) # Rust (nestri-server)
- remote: buf.build/community/neoeinstein-prost - remote: buf.build/community/neoeinstein-prost
out: packages/server/src/proto out: packages/server/src/proto
opt: flat_output_dir=true

341
bun.lock
View File

@@ -1,6 +1,5 @@
{ {
"lockfileVersion": 1, "lockfileVersion": 1,
"configVersion": 0,
"workspaces": { "workspaces": {
"": { "": {
"name": "nestri", "name": "nestri",
@@ -89,23 +88,23 @@
"name": "@nestri/input", "name": "@nestri/input",
"version": "0.0.0", "version": "0.0.0",
"dependencies": { "dependencies": {
"@bufbuild/protobuf": "^2.10.0", "@bufbuild/protobuf": "^2.2.3",
"@chainsafe/libp2p-noise": "^17.0.0", "@chainsafe/libp2p-noise": "^16.1.3",
"@chainsafe/libp2p-quic": "^1.1.3", "@chainsafe/libp2p-yamux": "^7.0.1",
"@chainsafe/libp2p-yamux": "^8.0.1", "@libp2p/identify": "^3.0.32",
"@libp2p/identify": "^4.0.5", "@libp2p/interface": "^2.10.2",
"@libp2p/interface": "^3.0.2", "@libp2p/ping": "^2.0.32",
"@libp2p/ping": "^3.0.5", "@libp2p/websockets": "^9.2.13",
"@libp2p/utils": "^7.0.5", "@multiformats/multiaddr": "^12.4.0",
"@libp2p/websockets": "^10.0.6", "it-length-prefixed": "^10.0.1",
"@libp2p/webtransport": "^6.0.7", "it-pipe": "^3.0.1",
"@multiformats/multiaddr": "^13.0.1", "libp2p": "^2.8.8",
"libp2p": "^3.0.6",
"uint8arraylist": "^2.4.8", "uint8arraylist": "^2.4.8",
"uint8arrays": "^5.1.0",
}, },
"devDependencies": { "devDependencies": {
"@bufbuild/buf": "^1.59.0", "@bufbuild/buf": "^1.50.0",
"@bufbuild/protoc-gen-es": "^2.10.0", "@bufbuild/protoc-gen-es": "^2.2.3",
}, },
}, },
"packages/moq": { "packages/moq": {
@@ -123,9 +122,9 @@
"name": "play-standalone", "name": "play-standalone",
"version": "0.0.1", "version": "0.0.1",
"dependencies": { "dependencies": {
"@astrojs/node": "9.5.0", "@astrojs/node": "^9.4.2",
"@nestri/input": "*", "@nestri/input": "*",
"astro": "5.15.1", "astro": "5.13.2",
}, },
}, },
"packages/www": { "packages/www": {
@@ -204,11 +203,11 @@
"@astrojs/compiler": ["@astrojs/compiler@2.12.2", "", {}, "sha512-w2zfvhjNCkNMmMMOn5b0J8+OmUaBL1o40ipMvqcG6NRpdC+lKxmTi48DT8Xw0SzJ3AfmeFLB45zXZXtmbsjcgw=="], "@astrojs/compiler": ["@astrojs/compiler@2.12.2", "", {}, "sha512-w2zfvhjNCkNMmMMOn5b0J8+OmUaBL1o40ipMvqcG6NRpdC+lKxmTi48DT8Xw0SzJ3AfmeFLB45zXZXtmbsjcgw=="],
"@astrojs/internal-helpers": ["@astrojs/internal-helpers@0.7.4", "", {}, "sha512-lDA9MqE8WGi7T/t2BMi+EAXhs4Vcvr94Gqx3q15cFEz8oFZMO4/SFBqYr/UcmNlvW+35alowkVj+w9VhLvs5Cw=="], "@astrojs/internal-helpers": ["@astrojs/internal-helpers@0.7.2", "", {}, "sha512-KCkCqR3Goym79soqEtbtLzJfqhTWMyVaizUi35FLzgGSzBotSw8DB1qwsu7U96ihOJgYhDk2nVPz+3LnXPeX6g=="],
"@astrojs/markdown-remark": ["@astrojs/markdown-remark@6.3.8", "", { "dependencies": { "@astrojs/internal-helpers": "0.7.4", "@astrojs/prism": "3.3.0", "github-slugger": "^2.0.0", "hast-util-from-html": "^2.0.3", "hast-util-to-text": "^4.0.2", "import-meta-resolve": "^4.2.0", "js-yaml": "^4.1.0", "mdast-util-definitions": "^6.0.0", "rehype-raw": "^7.0.0", "rehype-stringify": "^10.0.1", "remark-gfm": "^4.0.1", "remark-parse": "^11.0.0", "remark-rehype": "^11.1.2", "remark-smartypants": "^3.0.2", "shiki": "^3.13.0", "smol-toml": "^1.4.2", "unified": "^11.0.5", "unist-util-remove-position": "^5.0.0", "unist-util-visit": "^5.0.0", "unist-util-visit-parents": "^6.0.1", "vfile": "^6.0.3" } }, "sha512-uFNyFWadnULWK2cOw4n0hLKeu+xaVWeuECdP10cQ3K2fkybtTlhb7J7TcScdjmS8Yps7oje9S/ehYMfZrhrgCg=="], "@astrojs/markdown-remark": ["@astrojs/markdown-remark@6.3.6", "", { "dependencies": { "@astrojs/internal-helpers": "0.7.2", "@astrojs/prism": "3.3.0", "github-slugger": "^2.0.0", "hast-util-from-html": "^2.0.3", "hast-util-to-text": "^4.0.2", "import-meta-resolve": "^4.1.0", "js-yaml": "^4.1.0", "mdast-util-definitions": "^6.0.0", "rehype-raw": "^7.0.0", "rehype-stringify": "^10.0.1", "remark-gfm": "^4.0.1", "remark-parse": "^11.0.0", "remark-rehype": "^11.1.2", "remark-smartypants": "^3.0.2", "shiki": "^3.2.1", "smol-toml": "^1.3.4", "unified": "^11.0.5", "unist-util-remove-position": "^5.0.0", "unist-util-visit": "^5.0.0", "unist-util-visit-parents": "^6.0.1", "vfile": "^6.0.3" } }, "sha512-bwylYktCTsLMVoCOEHbn2GSUA3c5KT/qilekBKA3CBng0bo1TYjNZPr761vxumRk9kJGqTOtU+fgCAp5Vwokug=="],
"@astrojs/node": ["@astrojs/node@9.5.0", "", { "dependencies": { "@astrojs/internal-helpers": "0.7.4", "send": "^1.2.0", "server-destroy": "^1.0.1" }, "peerDependencies": { "astro": "^5.14.3" } }, "sha512-x1whLIatmCefaqJA8FjfI+P6FStF+bqmmrib0OUGM1M3cZhAXKLgPx6UF2AzQ3JgpXgCWYM24MHtraPvZhhyLQ=="], "@astrojs/node": ["@astrojs/node@9.4.3", "", { "dependencies": { "@astrojs/internal-helpers": "0.7.2", "send": "^1.2.0", "server-destroy": "^1.0.1" }, "peerDependencies": { "astro": "^5.7.0" } }, "sha512-P9BQHY8wQU1y9obknXzxV5SS3EpdaRnuDuHKr3RFC7t+2AzcMXeVmMJprQGijnQ8VdijJ8aS7+12tx325TURMQ=="],
"@astrojs/prism": ["@astrojs/prism@3.3.0", "", { "dependencies": { "prismjs": "^1.30.0" } }, "sha512-q8VwfU/fDZNoDOf+r7jUnMC2//H2l0TuQ6FkGJL8vD8nw/q5KiL3DS1KKBI3QhI9UQhpJ5dc7AtqfbXWuOgLCQ=="], "@astrojs/prism": ["@astrojs/prism@3.3.0", "", { "dependencies": { "prismjs": "^1.30.0" } }, "sha512-q8VwfU/fDZNoDOf+r7jUnMC2//H2l0TuQ6FkGJL8vD8nw/q5KiL3DS1KKBI3QhI9UQhpJ5dc7AtqfbXWuOgLCQ=="],
@@ -362,29 +361,29 @@
"@badrap/valita": ["@badrap/valita@0.3.11", "", {}, "sha512-oak0W8bycFjnrLeVCVvZqkOWTGh74wCPKUxGLJyhRukRs+V/hQdfZp1eDcQE4Gf3UrtJWfR/Ou4Xe0DZqJZ2FA=="], "@badrap/valita": ["@badrap/valita@0.3.11", "", {}, "sha512-oak0W8bycFjnrLeVCVvZqkOWTGh74wCPKUxGLJyhRukRs+V/hQdfZp1eDcQE4Gf3UrtJWfR/Ou4Xe0DZqJZ2FA=="],
"@bufbuild/buf": ["@bufbuild/buf@1.59.0", "", { "optionalDependencies": { "@bufbuild/buf-darwin-arm64": "1.59.0", "@bufbuild/buf-darwin-x64": "1.59.0", "@bufbuild/buf-linux-aarch64": "1.59.0", "@bufbuild/buf-linux-armv7": "1.59.0", "@bufbuild/buf-linux-x64": "1.59.0", "@bufbuild/buf-win32-arm64": "1.59.0", "@bufbuild/buf-win32-x64": "1.59.0" }, "bin": { "buf": "bin/buf", "protoc-gen-buf-breaking": "bin/protoc-gen-buf-breaking", "protoc-gen-buf-lint": "bin/protoc-gen-buf-lint" } }, "sha512-VdLuGnFp1OKJaiMevlLow6Jcvv9omOyM02Qa1zexl8dBB4Ac2ggz6bpT3Zb06tmCnqd8tFrI/Im1fbom3CznlQ=="], "@bufbuild/buf": ["@bufbuild/buf@1.50.0", "", { "optionalDependencies": { "@bufbuild/buf-darwin-arm64": "1.50.0", "@bufbuild/buf-darwin-x64": "1.50.0", "@bufbuild/buf-linux-aarch64": "1.50.0", "@bufbuild/buf-linux-armv7": "1.50.0", "@bufbuild/buf-linux-x64": "1.50.0", "@bufbuild/buf-win32-arm64": "1.50.0", "@bufbuild/buf-win32-x64": "1.50.0" }, "bin": { "buf": "bin/buf", "protoc-gen-buf-breaking": "bin/protoc-gen-buf-breaking", "protoc-gen-buf-lint": "bin/protoc-gen-buf-lint" } }, "sha512-XcdB5/Ls8k1eVcgNwUsRZEhCqiHgsnN+uEk/aDh0urGeiWc/dN6c89ZnAnI9/v0AZWzp6/rowoZhThlTl+D0bw=="],
"@bufbuild/buf-darwin-arm64": ["@bufbuild/buf-darwin-arm64@1.59.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-d3JTxBCibC+C94JU0jwLMgo/WBhaAHBIRzZXaZ3Y8KREjTj3jhzAlelGZmCtQJyyE0l6DFSm3lQgMblJ5qlq/w=="], "@bufbuild/buf-darwin-arm64": ["@bufbuild/buf-darwin-arm64@1.50.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-ldj1s0hMhZlz0N4+fqs9jGqC7jKAcsfLNp8kM+G+6XTPh8GWA/U1sYRdHhAlv1+3STfWhGxAhrNGRRVvvimALQ=="],
"@bufbuild/buf-darwin-x64": ["@bufbuild/buf-darwin-x64@1.59.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-eFnFB96GM6KjP5S8QFqjufjlMF41CVnXjkR8cIfR5jUXdwl1vf5S82Zv+cK1+Uogqhmt7AVBntd5Z+xmz4NKaw=="], "@bufbuild/buf-darwin-x64": ["@bufbuild/buf-darwin-x64@1.50.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-0ODFAnDVr0UOIUHGrI3vA3Cycec186BP5PFOuW6bALxBVN52Lqjjj+/+bVhvbBQlYo3rkxOtxEdoWGHZJrHhHA=="],
"@bufbuild/buf-linux-aarch64": ["@bufbuild/buf-linux-aarch64@1.59.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-g6DxTcJM29SBvqe42ll7HpkmTfecuG+PZYTysaxON9Y59fwtflhuLDpNqGhxWehHMkH11bFfpNeCGKjpGbVvkw=="], "@bufbuild/buf-linux-aarch64": ["@bufbuild/buf-linux-aarch64@1.50.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-Dp0YzLOW7O+C8bAm6/Q2HSrTYpDs2SxQXx+dBNxUotMpzx+uaUvqXb3EGr7s07ro+FsT0sFjzKTBcuCwkj+guQ=="],
"@bufbuild/buf-linux-armv7": ["@bufbuild/buf-linux-armv7@1.59.0", "", { "os": "linux", "cpu": "arm" }, "sha512-C92s+gmKnAyCzN7MdbtukRXOiW7e0hkeQrOie17vF6qWXPk2r9ix0WXZvg5gZr9R4zD8pOYwRVwYiB9zFXZOaA=="], "@bufbuild/buf-linux-armv7": ["@bufbuild/buf-linux-armv7@1.50.0", "", { "os": "linux", "cpu": "arm" }, "sha512-EMYRKSJ4kZo+OiHvMTYM+O27lf/okaf+bk1agRUTmBccp+qoGEC0R3DB/powFf/FURkUF7vKUS4T0GC/4n8OVA=="],
"@bufbuild/buf-linux-x64": ["@bufbuild/buf-linux-x64@1.59.0", "", { "os": "linux", "cpu": "x64" }, "sha512-Pzc3TFm1t2fZ5uT7jkYBjyuLNKo5ji/wRl/lLLvOlTFRyqsSZBkFNQcJGHoHSej1yDWau16VMrAh0GN1rZfvAg=="], "@bufbuild/buf-linux-x64": ["@bufbuild/buf-linux-x64@1.50.0", "", { "os": "linux", "cpu": "x64" }, "sha512-1G6ZQLXYoCXl8ZmCivUuknc6BiMz2bMtfpzYurFhj9wCIQTZsgepTBoiXHTcEdu2fjYAFxRGo4o+ZALU1umY0g=="],
"@bufbuild/buf-win32-arm64": ["@bufbuild/buf-win32-arm64@1.59.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-hS5VThgYNqbMFgY9SibDA/RXBdegw12jgrT2H+Tzaa2rvlSADck9ZAq9rwf2H0IvFJOqtR75Lejb+5Fx2rThpQ=="], "@bufbuild/buf-win32-arm64": ["@bufbuild/buf-win32-arm64@1.50.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-KpbI+f0TnGaa4KlPQXCLx8ZWKfO2pMD1kvVjAaktmm9OUoP9HrvZJ11tDEiFEFbrKbapCIhCCC3XWaldEDJWcA=="],
"@bufbuild/buf-win32-x64": ["@bufbuild/buf-win32-x64@1.59.0", "", { "os": "win32", "cpu": "x64" }, "sha512-JAGSF3oaKC2L/TelqvjB1N7oB5pTiviVr8mxiaxHyv4HpvcxCVdiO+iw0goRhZb4QHhYYswk2gLMezWHBxtR/g=="], "@bufbuild/buf-win32-x64": ["@bufbuild/buf-win32-x64@1.50.0", "", { "os": "win32", "cpu": "x64" }, "sha512-gA9aVuZYfh3pmWNYxmnK6thlcqyu2ht8haFhdB0w14Rtj200FAsMmzF7CPWvXQrV5g0pqXPwoMjZigT4OJHOXg=="],
"@bufbuild/protobuf": ["@bufbuild/protobuf@2.10.0", "", {}, "sha512-fdRs9PSrBF7QUntpZpq6BTw58fhgGJojgg39m9oFOJGZT+nip9b0so5cYY1oWl5pvemDLr0cPPsH46vwThEbpQ=="], "@bufbuild/protobuf": ["@bufbuild/protobuf@2.2.3", "", {}, "sha512-tFQoXHJdkEOSwj5tRIZSPNUuXK3RaR7T1nUrPgbYX1pUbvqqaaZAsfo+NXBPsz5rZMSKVFrgK1WL8Q/MSLvprg=="],
"@bufbuild/protoc-gen-es": ["@bufbuild/protoc-gen-es@2.10.0", "", { "dependencies": { "@bufbuild/protobuf": "2.10.0", "@bufbuild/protoplugin": "2.10.0" }, "bin": { "protoc-gen-es": "bin/protoc-gen-es" } }, "sha512-g3xtuxeMkbacn8/qWQ8NbHBA8unLAvGD7sjcXV1/lfO4iCfd6hYL1Z+rn2yLQZE/JEkG+GPZoIs7m5KI5VYaMw=="], "@bufbuild/protoc-gen-es": ["@bufbuild/protoc-gen-es@2.2.3", "", { "dependencies": { "@bufbuild/protobuf": "^2.2.3", "@bufbuild/protoplugin": "2.2.3" }, "bin": { "protoc-gen-es": "bin/protoc-gen-es" } }, "sha512-hdhIV9NmwXXy24DcbnArauv6L5Dv2PjkO9gz2DUhiZ9HPRpP+rmpT8zo5LohjJiuA7YIQGGKKWSKpRg+xcdLSQ=="],
"@bufbuild/protoplugin": ["@bufbuild/protoplugin@2.10.0", "", { "dependencies": { "@bufbuild/protobuf": "2.10.0", "@typescript/vfs": "^1.5.2", "typescript": "5.4.5" } }, "sha512-GPJOZ1Gp9/Ci3MXP3yI7+q4G7IhB5cSpbLjsfnBILxtNx69I9+ix3r9P7JfewHvqMjtPe6L+YWX1LPBGNfZMGw=="], "@bufbuild/protoplugin": ["@bufbuild/protoplugin@2.2.3", "", { "dependencies": { "@bufbuild/protobuf": "2.2.3", "@typescript/vfs": "^1.5.2", "typescript": "5.4.5" } }, "sha512-UsV7mj6NJTZrqIYJK+jNFnnj5tOS7wgNXKyMjebFEpf+OX6pfXE+nx+QPjumOfu4GxdVPfEDnKuwISgqlXSQqw=="],
"@capsizecss/unpack": ["@capsizecss/unpack@3.0.0", "", { "dependencies": { "fontkit": "^2.0.2" } }, "sha512-+ntATQe1AlL7nTOYjwjj6w3299CgRot48wL761TUGYpYgAou3AaONZazp0PKZyCyWhudWsjhq1nvRHOvbMzhTA=="], "@capsizecss/unpack": ["@capsizecss/unpack@2.4.0", "", { "dependencies": { "blob-to-buffer": "^1.2.8", "cross-fetch": "^3.0.4", "fontkit": "^2.0.2" } }, "sha512-GrSU71meACqcmIUxPYOJvGKF0yryjN/L1aCuE9DViCTJI7bfkjgYDPD1zbNDcINJwSSP6UaBZY9GAbYDO7re0Q=="],
"@cbor-extract/cbor-extract-darwin-arm64": ["@cbor-extract/cbor-extract-darwin-arm64@2.2.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-P7swiOAdF7aSi0H+tHtHtr6zrpF3aAq/W9FXx5HektRvLTM2O89xCyXF3pk7pLc7QpaY7AoaE8UowVf9QBdh3w=="], "@cbor-extract/cbor-extract-darwin-arm64": ["@cbor-extract/cbor-extract-darwin-arm64@2.2.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-P7swiOAdF7aSi0H+tHtHtr6zrpF3aAq/W9FXx5HektRvLTM2O89xCyXF3pk7pLc7QpaY7AoaE8UowVf9QBdh3w=="],
@@ -404,25 +403,9 @@
"@chainsafe/is-ip": ["@chainsafe/is-ip@2.1.0", "", {}, "sha512-KIjt+6IfysQ4GCv66xihEitBjvhU/bixbbbFxdJ1sqCp4uJ0wuZiYBPhksZoy4lfaF0k9cwNzY5upEW/VWdw3w=="], "@chainsafe/is-ip": ["@chainsafe/is-ip@2.1.0", "", {}, "sha512-KIjt+6IfysQ4GCv66xihEitBjvhU/bixbbbFxdJ1sqCp4uJ0wuZiYBPhksZoy4lfaF0k9cwNzY5upEW/VWdw3w=="],
"@chainsafe/libp2p-noise": ["@chainsafe/libp2p-noise@17.0.0", "", { "dependencies": { "@chainsafe/as-chacha20poly1305": "^0.1.0", "@chainsafe/as-sha256": "^1.2.0", "@libp2p/crypto": "^5.1.9", "@libp2p/interface": "^3.0.0", "@libp2p/peer-id": "^6.0.0", "@libp2p/utils": "^7.0.0", "@noble/ciphers": "^2.0.1", "@noble/curves": "^2.0.1", "@noble/hashes": "^2.0.1", "protons-runtime": "^5.6.0", "uint8arraylist": "^2.4.8", "uint8arrays": "^5.1.0", "wherearewe": "^2.0.1" } }, "sha512-vwrmY2Y+L1xYhIDiEpl61KHxwrLCZoXzTpwhyk34u+3+6zCAZPL3GxH3i2cs+u5IYNoyLptORdH17RKFXy7upA=="], "@chainsafe/libp2p-noise": ["@chainsafe/libp2p-noise@16.1.4", "", { "dependencies": { "@chainsafe/as-chacha20poly1305": "^0.1.0", "@chainsafe/as-sha256": "^1.0.0", "@libp2p/crypto": "^5.0.0", "@libp2p/interface": "^2.9.0", "@libp2p/peer-id": "^5.0.0", "@noble/ciphers": "^1.1.3", "@noble/curves": "^1.1.0", "@noble/hashes": "^1.3.1", "it-length-prefixed": "^10.0.1", "it-length-prefixed-stream": "^2.0.1", "it-pair": "^2.0.6", "it-pipe": "^3.0.1", "it-stream-types": "^2.0.1", "protons-runtime": "^5.5.0", "uint8arraylist": "^2.4.3", "uint8arrays": "^5.0.0", "wherearewe": "^2.0.1" } }, "sha512-f4FlyRVndcs4PoioOIZWrFc6wfO/mrAj7H63o0+eA0O2xhcoRkxHh6zna4W+WtScaF/Ua/UULgiNGuKNpLvLlQ=="],
"@chainsafe/libp2p-quic": ["@chainsafe/libp2p-quic@1.1.3", "", { "dependencies": { "@libp2p/crypto": "^5.1.7", "@libp2p/interface": "^2.10.5", "@libp2p/utils": "^6.7.1", "@multiformats/multiaddr": "^12.4.0", "@multiformats/multiaddr-matcher": "^2.0.1", "it-stream-types": "^2.0.2", "race-signal": "^1.1.3", "uint8arraylist": "^2.4.8" }, "optionalDependencies": { "@chainsafe/libp2p-quic-darwin-arm64": "1.1.3", "@chainsafe/libp2p-quic-darwin-x64": "1.1.3", "@chainsafe/libp2p-quic-linux-arm64-gnu": "1.1.3", "@chainsafe/libp2p-quic-linux-arm64-musl": "1.1.3", "@chainsafe/libp2p-quic-linux-x64-gnu": "1.1.3", "@chainsafe/libp2p-quic-linux-x64-musl": "1.1.3", "@chainsafe/libp2p-quic-win32-x64-msvc": "1.1.3" } }, "sha512-Y9F2vGPW5ZhvYYAcDC4dF6i92h+pch+BAXC1yfO2AX2KLyg8rVlECOkEffeStp06DL4knPZLN+Qi10EgOVfwwA=="], "@chainsafe/libp2p-yamux": ["@chainsafe/libp2p-yamux@7.0.4", "", { "dependencies": { "@libp2p/interface": "^2.0.0", "@libp2p/utils": "^6.0.0", "get-iterator": "^2.0.1", "it-foreach": "^2.0.6", "it-pushable": "^3.2.3", "it-stream-types": "^2.0.1", "race-signal": "^1.1.3", "uint8arraylist": "^2.4.8" } }, "sha512-Qw+EB9ew/9hRCq9V702gkm5xXThFHQ3Bdvh01M+enI1RScriSDWFGod02dwNHUxsYRc743i49sLlHp0edC7hSQ=="],
"@chainsafe/libp2p-quic-darwin-arm64": ["@chainsafe/libp2p-quic-darwin-arm64@1.1.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-L9Ta/CalkCiKC910thxR6GfqD0Tmm8QfSbZ5eTY7sGUuYYeE5/73UOlNzVHZxEWid7uceYHBYETTAUkdSsy+RQ=="],
"@chainsafe/libp2p-quic-darwin-x64": ["@chainsafe/libp2p-quic-darwin-x64@1.1.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-hxE4wL/PQop/r6OLpzeJJ3c4WDtfk7zWBKhX2Zjul0jHc5v04a1DRTEmugooaqeU7UNnBQkBsqiHcA8efuhNqg=="],
"@chainsafe/libp2p-quic-linux-arm64-gnu": ["@chainsafe/libp2p-quic-linux-arm64-gnu@1.1.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-XUyafb32UHdkuhgNYATnoBj81YfRlVl1MDW+OPHD3XPsIYkloUHlPD9Y2cBH9m17K0lvhe/3KndeQ3WLZ2syNA=="],
"@chainsafe/libp2p-quic-linux-arm64-musl": ["@chainsafe/libp2p-quic-linux-arm64-musl@1.1.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-cmYfa3heaSUN/ts4P1Y1N72Oi7frQdufDC8KzBOgD5WVSLnpXw4Nq8mVt6kf7WU1FLC6FUffKuz3mRWse1gGVg=="],
"@chainsafe/libp2p-quic-linux-x64-gnu": ["@chainsafe/libp2p-quic-linux-x64-gnu@1.1.3", "", { "os": "linux", "cpu": "x64" }, "sha512-ZS4CtINANQeBvqVHAoWqW9SRfxZ9R5xbM1bQUPjjPsNWdIgu0vCjiIkRYqkaL9cJvVHJPguNhu/NwC6whkdWww=="],
"@chainsafe/libp2p-quic-linux-x64-musl": ["@chainsafe/libp2p-quic-linux-x64-musl@1.1.3", "", { "os": "linux", "cpu": "x64" }, "sha512-LRi33YOHa/s/KSVRV4iCK+Cz8VBg2J8j3KrUEPtUp3aQvxYYvA/YkbRBcRNOyvEz6natzYA8LOycQsJTrVt4MA=="],
"@chainsafe/libp2p-quic-win32-x64-msvc": ["@chainsafe/libp2p-quic-win32-x64-msvc@1.1.3", "", { "os": "win32", "cpu": "x64" }, "sha512-zm2h1lYkhHEcVrzO/D0NyPwf5yj0/4zWwltaHXl4fdQMy8kqJCm8zcyZmBRfniDX8/03a2svbYPZdTDtb7FSTw=="],
"@chainsafe/libp2p-yamux": ["@chainsafe/libp2p-yamux@8.0.1", "", { "dependencies": { "@libp2p/interface": "^3.0.0", "@libp2p/utils": "^7.0.0", "race-signal": "^2.0.0", "uint8arraylist": "^2.4.8" } }, "sha512-pJsqmUg1cZRJZn/luAtQaq0uLcVfExo51Rg7iRtAEceNYtsKUi/exfegnvTBzTnF1CGmTzVEV3MCLsRhqiNyoA=="],
"@chainsafe/netmask": ["@chainsafe/netmask@2.0.0", "", { "dependencies": { "@chainsafe/is-ip": "^2.0.1" } }, "sha512-I3Z+6SWUoaljh3TBzCnCxjlUyN8tA+NAk5L6m9IxvCf1BENQTePzPMis97CoN/iMW1St3WN+AWCCRp+TTBRiDg=="], "@chainsafe/netmask": ["@chainsafe/netmask@2.0.0", "", { "dependencies": { "@chainsafe/is-ip": "^2.0.1" } }, "sha512-I3Z+6SWUoaljh3TBzCnCxjlUyN8tA+NAk5L6m9IxvCf1BENQTePzPMis97CoN/iMW1St3WN+AWCCRp+TTBRiDg=="],
@@ -614,33 +597,31 @@
"@leichtgewicht/ip-codec": ["@leichtgewicht/ip-codec@2.0.5", "", {}, "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw=="], "@leichtgewicht/ip-codec": ["@leichtgewicht/ip-codec@2.0.5", "", {}, "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw=="],
"@libp2p/crypto": ["@libp2p/crypto@5.1.10", "", { "dependencies": { "@libp2p/interface": "^3.0.0", "@noble/curves": "^2.0.1", "@noble/hashes": "^2.0.1", "multiformats": "^13.4.0", "protons-runtime": "^5.6.0", "uint8arraylist": "^2.4.8", "uint8arrays": "^5.1.0" } }, "sha512-kfQwQUV4iLV9tE7C6IjUd61XWEIrg4WBqGIDjeMoUhRPDGQ3z+eIIuIEaBRDEXr8nWd0YZuCprN1AunajHmbfg=="], "@libp2p/crypto": ["@libp2p/crypto@5.1.7", "", { "dependencies": { "@libp2p/interface": "^2.10.5", "@noble/curves": "^1.9.1", "@noble/hashes": "^1.8.0", "multiformats": "^13.3.6", "protons-runtime": "^5.5.0", "uint8arraylist": "^2.4.8", "uint8arrays": "^5.1.0" } }, "sha512-7DO0piidLEKfCuNfS420BlHG0e2tH7W/zugdsPSiC/1Apa/s1B1dBkaIEgfDkGjrRP4S/8Or86Rtq7zXeEu67g=="],
"@libp2p/identify": ["@libp2p/identify@4.0.5", "", { "dependencies": { "@libp2p/crypto": "^5.1.12", "@libp2p/interface": "^3.0.2", "@libp2p/interface-internal": "^3.0.5", "@libp2p/peer-id": "^6.0.3", "@libp2p/peer-record": "^9.0.3", "@libp2p/utils": "^7.0.5", "@multiformats/multiaddr": "^13.0.1", "@multiformats/multiaddr-matcher": "^3.0.1", "it-drain": "^3.0.10", "it-parallel": "^3.0.13", "main-event": "^1.0.1", "protons-runtime": "^5.6.0", "uint8arraylist": "^2.4.8", "uint8arrays": "^5.1.0" } }, "sha512-p25fw5+w0OjsAgxJWWZhUY25hYGyfFlA1ifycE6DFnPuhYHosZx69/2Q30rq4kZgSEBCepGcj32cKRhWCn0L9A=="], "@libp2p/identify": ["@libp2p/identify@3.0.37", "", { "dependencies": { "@libp2p/crypto": "^5.1.7", "@libp2p/interface": "^2.10.5", "@libp2p/interface-internal": "^2.3.18", "@libp2p/peer-id": "^5.1.8", "@libp2p/peer-record": "^8.0.34", "@libp2p/utils": "^6.7.1", "@multiformats/multiaddr": "^12.4.4", "@multiformats/multiaddr-matcher": "^1.7.2", "it-drain": "^3.0.9", "it-parallel": "^3.0.11", "it-protobuf-stream": "^2.0.2", "main-event": "^1.0.1", "protons-runtime": "^5.5.0", "uint8arraylist": "^2.4.8", "uint8arrays": "^5.1.0" } }, "sha512-oDdNZaP6a0eH3UIXBee4gOeOT4U4krfOAbqfqe/pM6exQqTyvzv21lOuFvC5EKgOYw63NoNPw1Iwnk36hDBpTg=="],
"@libp2p/interface": ["@libp2p/interface@3.0.2", "", { "dependencies": { "@multiformats/dns": "^1.0.6", "@multiformats/multiaddr": "^13.0.1", "main-event": "^1.0.1", "multiformats": "^13.4.0", "progress-events": "^1.0.1", "uint8arraylist": "^2.4.8" } }, "sha512-nb3H0eu9RPCBjwWUCafSL3TpFmt1Jhe4zgWlV98VrrWhtxg8xaunbEWzfVnU+R2TvV8IAljGw80OcqSst3gBlw=="], "@libp2p/interface": ["@libp2p/interface@2.10.5", "", { "dependencies": { "@multiformats/dns": "^1.0.6", "@multiformats/multiaddr": "^12.4.4", "it-pushable": "^3.2.3", "it-stream-types": "^2.0.2", "main-event": "^1.0.1", "multiformats": "^13.3.6", "progress-events": "^1.0.1", "uint8arraylist": "^2.4.8" } }, "sha512-Z52n04Mph/myGdwyExbFi5S/HqrmZ9JOmfLc2v4r2Cik3GRdw98vrGH19PFvvwjLwAjaqsweCtlGaBzAz09YDw=="],
"@libp2p/interface-internal": ["@libp2p/interface-internal@3.0.5", "", { "dependencies": { "@libp2p/interface": "^3.0.2", "@libp2p/peer-collections": "^7.0.5", "@multiformats/multiaddr": "^13.0.1", "progress-events": "^1.0.1" } }, "sha512-gaarewSLKpH5iMkXPmUctDk8SoBf/fXL/wNkpfHqHXtzP6Z4Hhm6eFc/DpL8NfCe+tLf1Cdmg3jOsxfdBS3IoA=="], "@libp2p/interface-internal": ["@libp2p/interface-internal@2.3.18", "", { "dependencies": { "@libp2p/interface": "^2.10.5", "@libp2p/peer-collections": "^6.0.34", "@multiformats/multiaddr": "^12.4.4", "progress-events": "^1.0.1" } }, "sha512-tnZ20IFASXLbDc2JxeUPZNIXDuN5Ge7be6BU458WLvmquf93NlSqZkWs6xFdi+0yXUrw7GGTgzIP5v+1LnDUmA=="],
"@libp2p/logger": ["@libp2p/logger@6.0.5", "", { "dependencies": { "@libp2p/interface": "^3.0.2", "@multiformats/multiaddr": "^13.0.1", "interface-datastore": "^9.0.1", "multiformats": "^13.4.0", "weald": "^1.0.6" } }, "sha512-4HdUwusPh57KKSY0v0YMYw6T2wl93svOLFNJuosy2xLto9zty1KWkrjaEFyF6jF0a7zBd1k5trjJsDXo8OKDxw=="], "@libp2p/logger": ["@libp2p/logger@5.1.21", "", { "dependencies": { "@libp2p/interface": "^2.10.5", "@multiformats/multiaddr": "^12.4.4", "interface-datastore": "^8.3.1", "multiformats": "^13.3.6", "weald": "^1.0.4" } }, "sha512-V1TWlZM5BuKkiGQ7En4qOnseVP82JwDIpIfNjceUZz1ArL32A5HXJjLQnJchkZ3VW8PVciJzUos/vP6slhPY6Q=="],
"@libp2p/multistream-select": ["@libp2p/multistream-select@7.0.5", "", { "dependencies": { "@libp2p/interface": "^3.0.2", "@libp2p/utils": "^7.0.5", "it-length-prefixed": "^10.0.1", "uint8arraylist": "^2.4.8", "uint8arrays": "^5.1.0" } }, "sha512-OXAv32VtxGYk88VX4jmUgD6Xo58xGgm1oKTNC1ieJ7PbNITfyr/LqOnruuw+/JwQ2LsE806ddOMM8aMV24RMIg=="], "@libp2p/multistream-select": ["@libp2p/multistream-select@6.0.28", "", { "dependencies": { "@libp2p/interface": "^2.10.5", "it-length-prefixed": "^10.0.1", "it-length-prefixed-stream": "^2.0.2", "it-stream-types": "^2.0.2", "p-defer": "^4.0.1", "race-signal": "^1.1.3", "uint8-varint": "^2.0.4", "uint8arraylist": "^2.4.8", "uint8arrays": "^5.1.0" } }, "sha512-ILu65FAX2Hak7x40DXb0gYptF6BmlGGW2kNgGeKIcNeseuvsAkBPO8k0CHwr8MU5mnHamTiweLJh5jD0iVZJ1A=="],
"@libp2p/peer-collections": ["@libp2p/peer-collections@7.0.5", "", { "dependencies": { "@libp2p/interface": "^3.0.2", "@libp2p/peer-id": "^6.0.3", "@libp2p/utils": "^7.0.5", "multiformats": "^13.4.0" } }, "sha512-mUkVDAHyxGr8fAI+aa+kf6izP4BI3qqIvuMQQpppYRG3feptmiRqSulbt/UpXoIepLp/1hIlAeZ+QyAMBZ7EpA=="], "@libp2p/peer-collections": ["@libp2p/peer-collections@6.0.34", "", { "dependencies": { "@libp2p/interface": "^2.10.5", "@libp2p/peer-id": "^5.1.8", "@libp2p/utils": "^6.7.1", "multiformats": "^13.3.6" } }, "sha512-rw8gDGhou4sF6W6i9ntmRARFePX19Dw9MMVpZHr6Kx9q2kvBJq91IXUzsXP06roexEOu1CUlZwxtUAqOBy+Eww=="],
"@libp2p/peer-id": ["@libp2p/peer-id@6.0.3", "", { "dependencies": { "@libp2p/crypto": "^5.1.12", "@libp2p/interface": "^3.0.2", "multiformats": "^13.4.0", "uint8arrays": "^5.1.0" } }, "sha512-kNecI7YYeh55Jrx+ra0AxEx5CfpKB4/i+4rBJ8jRyLaMgJvwhTC055mZrKv+rUWEEfp/9VqCnDKQ8cVoDbDydA=="], "@libp2p/peer-id": ["@libp2p/peer-id@5.1.8", "", { "dependencies": { "@libp2p/crypto": "^5.1.7", "@libp2p/interface": "^2.10.5", "multiformats": "^13.3.6", "uint8arrays": "^5.1.0" } }, "sha512-pGaM4BwjnXdGtAtd84L4/wuABpsnFYE+AQ+h3GxNFme0IsTaTVKWd1jBBE5YFeKHBHGUOhF3TlHsdjFfjQA7TA=="],
"@libp2p/peer-record": ["@libp2p/peer-record@9.0.3", "", { "dependencies": { "@libp2p/crypto": "^5.1.12", "@libp2p/interface": "^3.0.2", "@libp2p/peer-id": "^6.0.3", "@multiformats/multiaddr": "^13.0.1", "multiformats": "^13.4.0", "protons-runtime": "^5.6.0", "uint8-varint": "^2.0.4", "uint8arraylist": "^2.4.8", "uint8arrays": "^5.1.0" } }, "sha512-W1K/fdyLDZpxEEcS08JafyNyDUAKHhdjxdt2M7ZwDtBbRrM9RFseZaGHufpMEgPZxne6RriLpJp1NLeFPF9bZA=="], "@libp2p/peer-record": ["@libp2p/peer-record@8.0.34", "", { "dependencies": { "@libp2p/crypto": "^5.1.7", "@libp2p/interface": "^2.10.5", "@libp2p/peer-id": "^5.1.8", "@libp2p/utils": "^6.7.1", "@multiformats/multiaddr": "^12.4.4", "multiformats": "^13.3.6", "protons-runtime": "^5.5.0", "uint8-varint": "^2.0.4", "uint8arraylist": "^2.4.8", "uint8arrays": "^5.1.0" } }, "sha512-GqvRBpvclscoKuF0JUfLyZTv+BwzICBBe50LFiAKio8LijZMBr43b+AcEaSEwFWDwlWmaKU73q8EQLrCb/e67Q=="],
"@libp2p/peer-store": ["@libp2p/peer-store@12.0.5", "", { "dependencies": { "@libp2p/crypto": "^5.1.12", "@libp2p/interface": "^3.0.2", "@libp2p/peer-collections": "^7.0.5", "@libp2p/peer-id": "^6.0.3", "@libp2p/peer-record": "^9.0.3", "@multiformats/multiaddr": "^13.0.1", "interface-datastore": "^9.0.1", "it-all": "^3.0.9", "main-event": "^1.0.1", "mortice": "^3.3.1", "multiformats": "^13.4.0", "protons-runtime": "^5.6.0", "uint8arraylist": "^2.4.8", "uint8arrays": "^5.1.0" } }, "sha512-hRv3SQZTpB6XFl+suyl0aD2OiLYQIA+UZ4SvCuXCYfIQd8TCSSUbcj1dICrK8aorDVus3ycyMqHAMmbts/5ndA=="], "@libp2p/peer-store": ["@libp2p/peer-store@11.2.6", "", { "dependencies": { "@libp2p/crypto": "^5.1.7", "@libp2p/interface": "^2.10.5", "@libp2p/peer-collections": "^6.0.34", "@libp2p/peer-id": "^5.1.8", "@libp2p/peer-record": "^8.0.34", "@multiformats/multiaddr": "^12.4.4", "interface-datastore": "^8.3.1", "it-all": "^3.0.8", "main-event": "^1.0.1", "mortice": "^3.2.1", "multiformats": "^13.3.6", "protons-runtime": "^5.5.0", "uint8arraylist": "^2.4.8", "uint8arrays": "^5.1.0" } }, "sha512-3Lc982/7drqlXa51s9l1/DFHD48zzIjMMYajxFM2KbobyStH+lztYnFc3kNGB9sZijULaW1480PvbTMm9WaJ0g=="],
"@libp2p/ping": ["@libp2p/ping@3.0.5", "", { "dependencies": { "@libp2p/crypto": "^5.1.12", "@libp2p/interface": "^3.0.2", "@libp2p/interface-internal": "^3.0.5", "@multiformats/multiaddr": "^13.0.1", "p-event": "^7.0.0", "race-signal": "^2.0.0", "uint8arraylist": "^2.4.8", "uint8arrays": "^5.1.0" } }, "sha512-/1WPyBtKg8yzM2iZ+XylH88S6Z964dggiFgBLtnAEU4kqF1gGFWI/GHOVXltSWKUulnooxpEBf7F8x1jn80MVQ=="], "@libp2p/ping": ["@libp2p/ping@2.0.36", "", { "dependencies": { "@libp2p/crypto": "^5.1.7", "@libp2p/interface": "^2.10.5", "@libp2p/interface-internal": "^2.3.18", "@multiformats/multiaddr": "^12.4.4", "it-byte-stream": "^2.0.2", "main-event": "^1.0.1", "uint8arrays": "^5.1.0" } }, "sha512-susC5yMBZhMDz+jIjX7RvQ7NXNL5L4fkRzPhwu+1eLbwNXTYZtDd7fJ53p40I5Ur/A+DgtCpIk03X2nrHPc5Jg=="],
"@libp2p/utils": ["@libp2p/utils@7.0.5", "", { "dependencies": { "@chainsafe/is-ip": "^2.1.0", "@chainsafe/netmask": "^2.0.0", "@libp2p/crypto": "^5.1.12", "@libp2p/interface": "^3.0.2", "@libp2p/logger": "^6.0.5", "@multiformats/multiaddr": "^13.0.1", "@sindresorhus/fnv1a": "^3.1.0", "any-signal": "^4.1.1", "cborg": "^4.2.14", "delay": "^6.0.0", "is-loopback-addr": "^2.0.2", "it-length-prefixed": "^10.0.1", "it-pipe": "^3.0.1", "it-pushable": "^3.2.3", "it-stream-types": "^2.0.2", "main-event": "^1.0.1", "netmask": "^2.0.2", "p-defer": "^4.0.1", "p-event": "^7.0.0", "race-signal": "^2.0.0", "uint8-varint": "^2.0.4", "uint8arraylist": "^2.4.8", "uint8arrays": "^5.1.0" } }, "sha512-SmefnIdRXjLh9SdJ8nIL0LFvBqVuti3kujzk0/4Xj8mvAEzYl7h/Ge5VU6PHpzat9CZMplGQGGfr/vxX1WuckQ=="], "@libp2p/utils": ["@libp2p/utils@6.7.1", "", { "dependencies": { "@chainsafe/is-ip": "^2.1.0", "@chainsafe/netmask": "^2.0.0", "@libp2p/crypto": "^5.1.7", "@libp2p/interface": "^2.10.5", "@libp2p/logger": "^5.1.21", "@multiformats/multiaddr": "^12.4.4", "@sindresorhus/fnv1a": "^3.1.0", "any-signal": "^4.1.1", "delay": "^6.0.0", "get-iterator": "^2.0.1", "is-loopback-addr": "^2.0.2", "is-plain-obj": "^4.1.0", "it-foreach": "^2.1.3", "it-pipe": "^3.0.1", "it-pushable": "^3.2.3", "it-stream-types": "^2.0.2", "main-event": "^1.0.1", "netmask": "^2.0.2", "p-defer": "^4.0.1", "race-event": "^1.3.0", "race-signal": "^1.1.3", "uint8arraylist": "^2.4.8", "uint8arrays": "^5.1.0" } }, "sha512-x3WImvw4unmx1ZeAedj8AkRe4UImUlkw0ZItYAiKiekElMNUXwv+Yt48dI/LmB38JIof8sng29XvUeCVU3F6OA=="],
"@libp2p/websockets": ["@libp2p/websockets@10.0.6", "", { "dependencies": { "@libp2p/interface": "^3.0.2", "@libp2p/utils": "^7.0.5", "@multiformats/multiaddr": "^13.0.1", "@multiformats/multiaddr-matcher": "^3.0.1", "@multiformats/multiaddr-to-uri": "^12.0.0", "main-event": "^1.0.1", "p-event": "^7.0.0", "progress-events": "^1.0.1", "uint8arraylist": "^2.4.8", "uint8arrays": "^5.1.0", "ws": "^8.18.3" } }, "sha512-rHsV3IR9fTsKUV/dexzmA1CIsIzkqgc5npwgUepXdrejTHhCZfmDSo52fdEsN4kfoWlOK4RmDxXrgQxxkrQeSw=="], "@libp2p/websockets": ["@libp2p/websockets@9.2.17", "", { "dependencies": { "@libp2p/interface": "^2.10.5", "@libp2p/utils": "^6.7.1", "@multiformats/multiaddr": "^12.4.4", "@multiformats/multiaddr-matcher": "^1.7.2", "@multiformats/multiaddr-to-uri": "^11.0.0", "@types/ws": "^8.18.1", "it-ws": "^6.1.5", "main-event": "^1.0.1", "p-defer": "^4.0.1", "p-event": "^6.0.1", "progress-events": "^1.0.1", "race-signal": "^1.1.3", "ws": "^8.18.2" } }, "sha512-PNhLFZA+DyV8xynCphrl4H4a1mVRIe6ZPKqLt9UwWr9Ye0ecjgVcL38uDo0XAZkx+NO3S+YspCx8yquJnDyi2A=="],
"@libp2p/webtransport": ["@libp2p/webtransport@6.0.7", "", { "dependencies": { "@chainsafe/libp2p-noise": "^17.0.0", "@libp2p/interface": "^3.0.2", "@libp2p/peer-id": "^6.0.3", "@libp2p/utils": "^7.0.5", "@multiformats/multiaddr": "^13.0.1", "@multiformats/multiaddr-matcher": "^3.0.1", "multiformats": "^13.3.6", "progress-events": "^1.0.1", "race-signal": "^2.0.0", "uint8arraylist": "^2.4.8", "uint8arrays": "^5.1.0" } }, "sha512-N9w2RXygo93Bg1PaQJTsjPmx+itMhUXhvJrRvBWqvzDoNbjCEZ8ofJKjPGzWr0eNIXsF57rHrCHF1devBDjE4g=="],
"@logdna/tail-file": ["@logdna/tail-file@2.2.0", "", {}, "sha512-XGSsWDweP80Fks16lwkAUIr54ICyBs6PsI4mpfTLQaWgEJRtY9xEV+PeyDpJ+sJEGZxqINlpmAwe/6tS1pP8Ng=="], "@logdna/tail-file": ["@logdna/tail-file@2.2.0", "", {}, "sha512-XGSsWDweP80Fks16lwkAUIr54ICyBs6PsI4mpfTLQaWgEJRtY9xEV+PeyDpJ+sJEGZxqINlpmAwe/6tS1pP8Ng=="],
@@ -660,11 +641,11 @@
"@multiformats/dns": ["@multiformats/dns@1.0.6", "", { "dependencies": { "@types/dns-packet": "^5.6.5", "buffer": "^6.0.3", "dns-packet": "^5.6.1", "hashlru": "^2.3.0", "p-queue": "^8.0.1", "progress-events": "^1.0.0", "uint8arrays": "^5.0.2" } }, "sha512-nt/5UqjMPtyvkG9BQYdJ4GfLK3nMqGpFZOzf4hAmIa0sJh2LlS9YKXZ4FgwBDsaHvzZqR/rUFIywIc7pkHNNuw=="], "@multiformats/dns": ["@multiformats/dns@1.0.6", "", { "dependencies": { "@types/dns-packet": "^5.6.5", "buffer": "^6.0.3", "dns-packet": "^5.6.1", "hashlru": "^2.3.0", "p-queue": "^8.0.1", "progress-events": "^1.0.0", "uint8arrays": "^5.0.2" } }, "sha512-nt/5UqjMPtyvkG9BQYdJ4GfLK3nMqGpFZOzf4hAmIa0sJh2LlS9YKXZ4FgwBDsaHvzZqR/rUFIywIc7pkHNNuw=="],
"@multiformats/multiaddr": ["@multiformats/multiaddr@13.0.1", "", { "dependencies": { "@chainsafe/is-ip": "^2.0.1", "multiformats": "^13.0.0", "uint8-varint": "^2.0.1", "uint8arrays": "^5.0.0" } }, "sha512-XToN915cnfr6Lr9EdGWakGJbPT0ghpg/850HvdC+zFX8XvpLZElwa8synCiwa8TuvKNnny6m8j8NVBNCxhIO3g=="], "@multiformats/multiaddr": ["@multiformats/multiaddr@12.5.1", "", { "dependencies": { "@chainsafe/is-ip": "^2.0.1", "@chainsafe/netmask": "^2.0.0", "@multiformats/dns": "^1.0.3", "abort-error": "^1.0.1", "multiformats": "^13.0.0", "uint8-varint": "^2.0.1", "uint8arrays": "^5.0.0" } }, "sha512-+DDlr9LIRUS8KncI1TX/FfUn8F2dl6BIxJgshS/yFQCNB5IAF0OGzcwB39g5NLE22s4qqDePv0Qof6HdpJ/4aQ=="],
"@multiformats/multiaddr-matcher": ["@multiformats/multiaddr-matcher@2.0.2", "", { "dependencies": { "@multiformats/multiaddr": "^12.0.0" } }, "sha512-si7EZCI93mfBJKKRkh+u2bB9W6W5APVN3XfdwuseEJ0OS7ysg0Jno9SuAi0bRzsl5OEFESoF71SjsRqgp8PXAA=="], "@multiformats/multiaddr-matcher": ["@multiformats/multiaddr-matcher@1.7.2", "", { "dependencies": { "@chainsafe/is-ip": "^2.0.1", "@multiformats/multiaddr": "^12.0.0", "multiformats": "^13.0.0" } }, "sha512-BJzHOBAAxGZKw+FY/MzeIKGKERAW/1XOrpj61wgzZVvR/iksyGTQhliyTgmuakpBJPSsCxlrk3eLemVhZuJIFQ=="],
"@multiformats/multiaddr-to-uri": ["@multiformats/multiaddr-to-uri@12.0.0", "", { "dependencies": { "@multiformats/multiaddr": "^13.0.0" } }, "sha512-3uIEBCiy8tfzxYYBl81x1tISiNBQ7mHU4pGjippbJRoQYHzy/ZdZM/7JvTldr8pc/dzpkaNJxnsuxxlhsPOJsA=="], "@multiformats/multiaddr-to-uri": ["@multiformats/multiaddr-to-uri@11.0.2", "", { "dependencies": { "@multiformats/multiaddr": "^12.3.0" } }, "sha512-SiLFD54zeOJ0qMgo9xv1Tl9O5YktDKAVDP4q4hL16mSq4O4sfFNagNADz8eAofxd6TfQUzGQ3TkRRG9IY2uHRg=="],
"@neondatabase/serverless": ["@neondatabase/serverless@1.0.1", "", { "dependencies": { "@types/node": "^22.15.30", "@types/pg": "^8.8.0" } }, "sha512-O6yC5TT0jbw86VZVkmnzCZJB0hfxBl0JJz6f+3KHoZabjb/X08r9eFA+vuY06z1/qaovykvdkrXYq3SPUuvogA=="], "@neondatabase/serverless": ["@neondatabase/serverless@1.0.1", "", { "dependencies": { "@types/node": "^22.15.30", "@types/pg": "^8.8.0" } }, "sha512-O6yC5TT0jbw86VZVkmnzCZJB0hfxBl0JJz6f+3KHoZabjb/X08r9eFA+vuY06z1/qaovykvdkrXYq3SPUuvogA=="],
@@ -682,11 +663,11 @@
"@nestri/zero": ["@nestri/zero@workspace:packages/zero"], "@nestri/zero": ["@nestri/zero@workspace:packages/zero"],
"@noble/ciphers": ["@noble/ciphers@2.0.1", "", {}, "sha512-xHK3XHPUW8DTAobU+G0XT+/w+JLM7/8k1UFdB5xg/zTFPnFCobhftzw8wl4Lw2aq/Rvir5pxfZV5fEazmeCJ2g=="], "@noble/ciphers": ["@noble/ciphers@1.3.0", "", {}, "sha512-2I0gnIVPtfnMw9ee9h1dJG7tp81+8Ob3OJb3Mv37rx5L40/b0i7djjCVvGOVqc9AEIQyvyu1i6ypKdFw8R8gQw=="],
"@noble/curves": ["@noble/curves@2.0.1", "", { "dependencies": { "@noble/hashes": "2.0.1" } }, "sha512-vs1Az2OOTBiP4q0pwjW5aF0xp9n4MxVrmkFBxc6EKZc6ddYx5gaZiAsZoq0uRRXWbi3AT/sBqn05eRPtn1JCPw=="], "@noble/curves": ["@noble/curves@1.9.0", "", { "dependencies": { "@noble/hashes": "1.8.0" } }, "sha512-7YDlXiNMdO1YZeH6t/kvopHHbIZzlxrCV9WLqCY6QhcXOoXiNCMDqJIglZ9Yjx5+w7Dz30TITFrlTjnRg7sKEg=="],
"@noble/hashes": ["@noble/hashes@2.0.1", "", {}, "sha512-XlOlEbQcE9fmuXxrVTXCTlG2nlRXa9Rj3rr5Ue/+tX+nmkgbX720YHh0VR3hBF9xDvwnb8D2shVGOwNx+ulArw=="], "@noble/hashes": ["@noble/hashes@1.8.0", "", {}, "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A=="],
"@npmcli/agent": ["@npmcli/agent@2.2.2", "", { "dependencies": { "agent-base": "^7.1.0", "http-proxy-agent": "^7.0.0", "https-proxy-agent": "^7.0.1", "lru-cache": "^10.0.1", "socks-proxy-agent": "^8.0.3" } }, "sha512-OrcNPXdpSl9UX7qPVRWbmWMCSXrcDa2M9DvrbOTj7ao1S4PlqVFYv9/yLKMkrJKZ/V5A/kDBC690or307i26Og=="], "@npmcli/agent": ["@npmcli/agent@2.2.2", "", { "dependencies": { "agent-base": "^7.1.0", "http-proxy-agent": "^7.0.0", "https-proxy-agent": "^7.0.1", "lru-cache": "^10.0.1", "socks-proxy-agent": "^8.0.3" } }, "sha512-OrcNPXdpSl9UX7qPVRWbmWMCSXrcDa2M9DvrbOTj7ao1S4PlqVFYv9/yLKMkrJKZ/V5A/kDBC690or307i26Og=="],
@@ -928,7 +909,7 @@
"@rocicorp/zero-sqlite3": ["@rocicorp/zero-sqlite3@1.0.4", "", { "dependencies": { "bindings": "^1.5.0", "prebuild-install": "^7.1.1" }, "bin": { "zero-sqlite3": "shell.ps1" } }, "sha512-bm+VUdF4CnKVjUj/dSCmVu0hjcyXaF/nKkw2rNhZUjGeBOMRy/hh8z/32h311es4dxCVvcZ3+QHQHMxF2YG5Kw=="], "@rocicorp/zero-sqlite3": ["@rocicorp/zero-sqlite3@1.0.4", "", { "dependencies": { "bindings": "^1.5.0", "prebuild-install": "^7.1.1" }, "bin": { "zero-sqlite3": "shell.ps1" } }, "sha512-bm+VUdF4CnKVjUj/dSCmVu0hjcyXaF/nKkw2rNhZUjGeBOMRy/hh8z/32h311es4dxCVvcZ3+QHQHMxF2YG5Kw=="],
"@rollup/pluginutils": ["@rollup/pluginutils@5.3.0", "", { "dependencies": { "@types/estree": "^1.0.0", "estree-walker": "^2.0.2", "picomatch": "^4.0.2" }, "peerDependencies": { "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" }, "optionalPeers": ["rollup"] }, "sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q=="], "@rollup/pluginutils": ["@rollup/pluginutils@5.1.4", "", { "dependencies": { "@types/estree": "^1.0.0", "estree-walker": "^2.0.2", "picomatch": "^4.0.2" }, "peerDependencies": { "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" }, "optionalPeers": ["rollup"] }, "sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ=="],
"@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.38.0", "", { "os": "android", "cpu": "arm" }, "sha512-ldomqc4/jDZu/xpYU+aRxo3V4mGCV9HeTgUBANI3oIQMOL+SsxB+S2lxMpkFp5UamSS3XuTMQVbsS24R4J4Qjg=="], "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.38.0", "", { "os": "android", "cpu": "arm" }, "sha512-ldomqc4/jDZu/xpYU+aRxo3V4mGCV9HeTgUBANI3oIQMOL+SsxB+S2lxMpkFp5UamSS3XuTMQVbsS24R4J4Qjg=="],
@@ -970,17 +951,17 @@
"@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.38.0", "", { "os": "win32", "cpu": "x64" }, "sha512-jjqy3uWlecfB98Psxb5cD6Fny9Fupv9LrDSPTQZUROqjvZmcCqNu4UMl7qqhlUUGpwiAkotj6GYu4SZdcr/nLw=="], "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.38.0", "", { "os": "win32", "cpu": "x64" }, "sha512-jjqy3uWlecfB98Psxb5cD6Fny9Fupv9LrDSPTQZUROqjvZmcCqNu4UMl7qqhlUUGpwiAkotj6GYu4SZdcr/nLw=="],
"@shikijs/core": ["@shikijs/core@3.13.0", "", { "dependencies": { "@shikijs/types": "3.13.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "sha512-3P8rGsg2Eh2qIHekwuQjzWhKI4jV97PhvYjYUzGqjvJfqdQPz+nMlfWahU24GZAyW1FxFI1sYjyhfh5CoLmIUA=="], "@shikijs/core": ["@shikijs/core@3.12.2", "", { "dependencies": { "@shikijs/types": "3.12.2", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "sha512-L1Safnhra3tX/oJK5kYHaWmLEBJi1irASwewzY3taX5ibyXyMkkSDZlq01qigjryOBwrXSdFgTiZ3ryzSNeu7Q=="],
"@shikijs/engine-javascript": ["@shikijs/engine-javascript@3.13.0", "", { "dependencies": { "@shikijs/types": "3.13.0", "@shikijs/vscode-textmate": "^10.0.2", "oniguruma-to-es": "^4.3.3" } }, "sha512-Ty7xv32XCp8u0eQt8rItpMs6rU9Ki6LJ1dQOW3V/56PKDcpvfHPnYFbsx5FFUP2Yim34m/UkazidamMNVR4vKg=="], "@shikijs/engine-javascript": ["@shikijs/engine-javascript@3.12.2", "", { "dependencies": { "@shikijs/types": "3.12.2", "@shikijs/vscode-textmate": "^10.0.2", "oniguruma-to-es": "^4.3.3" } }, "sha512-Nm3/azSsaVS7hk6EwtHEnTythjQfwvrO5tKqMlaH9TwG1P+PNaR8M0EAKZ+GaH2DFwvcr4iSfTveyxMIvXEHMw=="],
"@shikijs/engine-oniguruma": ["@shikijs/engine-oniguruma@3.13.0", "", { "dependencies": { "@shikijs/types": "3.13.0", "@shikijs/vscode-textmate": "^10.0.2" } }, "sha512-O42rBGr4UDSlhT2ZFMxqM7QzIU+IcpoTMzb3W7AlziI1ZF7R8eS2M0yt5Ry35nnnTX/LTLXFPUjRFCIW+Operg=="], "@shikijs/engine-oniguruma": ["@shikijs/engine-oniguruma@3.12.2", "", { "dependencies": { "@shikijs/types": "3.12.2", "@shikijs/vscode-textmate": "^10.0.2" } }, "sha512-hozwnFHsLvujK4/CPVHNo3Bcg2EsnG8krI/ZQ2FlBlCRpPZW4XAEQmEwqegJsypsTAN9ehu2tEYe30lYKSZW/w=="],
"@shikijs/langs": ["@shikijs/langs@3.13.0", "", { "dependencies": { "@shikijs/types": "3.13.0" } }, "sha512-672c3WAETDYHwrRP0yLy3W1QYB89Hbpj+pO4KhxK6FzIrDI2FoEXNiNCut6BQmEApYLfuYfpgOZaqbY+E9b8wQ=="], "@shikijs/langs": ["@shikijs/langs@3.12.2", "", { "dependencies": { "@shikijs/types": "3.12.2" } }, "sha512-bVx5PfuZHDSHoBal+KzJZGheFuyH4qwwcwG/n+MsWno5cTlKmaNtTsGzJpHYQ8YPbB5BdEdKU1rga5/6JGY8ww=="],
"@shikijs/themes": ["@shikijs/themes@3.13.0", "", { "dependencies": { "@shikijs/types": "3.13.0" } }, "sha512-Vxw1Nm1/Od8jyA7QuAenaV78BG2nSr3/gCGdBkLpfLscddCkzkL36Q5b67SrLLfvAJTOUzW39x4FHVCFriPVgg=="], "@shikijs/themes": ["@shikijs/themes@3.12.2", "", { "dependencies": { "@shikijs/types": "3.12.2" } }, "sha512-fTR3QAgnwYpfGczpIbzPjlRnxyONJOerguQv1iwpyQZ9QXX4qy/XFQqXlf17XTsorxnHoJGbH/LXBvwtqDsF5A=="],
"@shikijs/types": ["@shikijs/types@3.13.0", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-oM9P+NCFri/mmQ8LoFGVfVyemm5Hi27330zuOBp0annwJdKH1kOLndw3zCtAVDehPLg9fKqoEx3Ht/wNZxolfw=="], "@shikijs/types": ["@shikijs/types@3.12.2", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-K5UIBzxCyv0YoxN3LMrKB9zuhp1bV+LgewxuVwHdl4Gz5oePoUFrr9EfgJlGlDeXCU1b/yhdnXeuRvAnz8HN8Q=="],
"@shikijs/vscode-textmate": ["@shikijs/vscode-textmate@10.0.2", "", {}, "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg=="], "@shikijs/vscode-textmate": ["@shikijs/vscode-textmate@10.0.2", "", {}, "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg=="],
@@ -1150,7 +1131,7 @@
"@types/basic-auth": ["@types/basic-auth@1.1.8", "", { "dependencies": { "@types/node": "*" } }, "sha512-dKcUeixGuZn8pBjcUrf1N7x5K6lWuKuwHHitM2IZ4vwZUDWEhhNtwCWiba8jTA9zn0GQQ+fTFkWpKx8pOU/enw=="], "@types/basic-auth": ["@types/basic-auth@1.1.8", "", { "dependencies": { "@types/node": "*" } }, "sha512-dKcUeixGuZn8pBjcUrf1N7x5K6lWuKuwHHitM2IZ4vwZUDWEhhNtwCWiba8jTA9zn0GQQ+fTFkWpKx8pOU/enw=="],
"@types/bun": ["@types/bun@1.3.3", "", { "dependencies": { "bun-types": "1.3.3" } }, "sha512-ogrKbJ2X5N0kWLLFKeytG0eHDleBYtngtlbu9cyBKFtNL3cnpDZkNdQj8flVf6WTZUX5ulI9AY1oa7ljhSrp+g=="], "@types/bun": ["@types/bun@1.2.22", "", { "dependencies": { "bun-types": "1.2.22" } }, "sha512-5A/KrKos2ZcN0c6ljRSOa1fYIyCKhZfIVYeuyb4snnvomnpFqC0tTsEkdqNxbAgExV384OETQ//WAjl3XbYqQA=="],
"@types/bunyan": ["@types/bunyan@1.8.11", "", { "dependencies": { "@types/node": "*" } }, "sha512-758fRH7umIMk5qt5ELmRMff4mLDlN+xyYzC+dkPTdKwbSkJFvz6xwyScrytPU0QIBbRRwbiE8/BIg8bpajerNQ=="], "@types/bunyan": ["@types/bunyan@1.8.11", "", { "dependencies": { "@types/node": "*" } }, "sha512-758fRH7umIMk5qt5ELmRMff4mLDlN+xyYzC+dkPTdKwbSkJFvz6xwyScrytPU0QIBbRRwbiE8/BIg8bpajerNQ=="],
@@ -1200,8 +1181,12 @@
"@types/pngjs": ["@types/pngjs@6.0.5", "", { "dependencies": { "@types/node": "*" } }, "sha512-0k5eKfrA83JOZPppLtS2C7OUtyNAl2wKNxfyYl9Q5g9lPkgBl/9hNyAu6HuEH2J4XmIv2znEpkDd0SaZVxW6iQ=="], "@types/pngjs": ["@types/pngjs@6.0.5", "", { "dependencies": { "@types/node": "*" } }, "sha512-0k5eKfrA83JOZPppLtS2C7OUtyNAl2wKNxfyYl9Q5g9lPkgBl/9hNyAu6HuEH2J4XmIv2znEpkDd0SaZVxW6iQ=="],
"@types/prop-types": ["@types/prop-types@15.7.14", "", {}, "sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ=="],
"@types/qrcode": ["@types/qrcode@1.5.5", "", { "dependencies": { "@types/node": "*" } }, "sha512-CdfBi/e3Qk+3Z/fXYShipBT13OJ2fDO2Q2w5CIP5anLTLIndQG9z6P1cnm+8zCWSpm5dnxMFd/uREtb0EXuQzg=="], "@types/qrcode": ["@types/qrcode@1.5.5", "", { "dependencies": { "@types/node": "*" } }, "sha512-CdfBi/e3Qk+3Z/fXYShipBT13OJ2fDO2Q2w5CIP5anLTLIndQG9z6P1cnm+8zCWSpm5dnxMFd/uREtb0EXuQzg=="],
"@types/react": ["@types/react@18.3.18", "", { "dependencies": { "@types/prop-types": "*", "csstype": "^3.0.2" } }, "sha512-t4yC+vtgnkYjNSKlFx1jkAhH8LgTo2N/7Qvi83kdEaUtMDiwpbLAktKDaAMlRcJ5eSxZkH74eEGt1ky31d7kfQ=="],
"@types/readable-stream": ["@types/readable-stream@4.0.18", "", { "dependencies": { "@types/node": "*", "safe-buffer": "~5.1.1" } }, "sha512-21jK/1j+Wg+7jVw1xnSwy/2Q1VgVjWuFssbYGTREPUBeZ+rqVFl2udq0IkxzPC0ZhOzVceUbyIACFZKLqKEBlA=="], "@types/readable-stream": ["@types/readable-stream@4.0.18", "", { "dependencies": { "@types/node": "*", "safe-buffer": "~5.1.1" } }, "sha512-21jK/1j+Wg+7jVw1xnSwy/2Q1VgVjWuFssbYGTREPUBeZ+rqVFl2udq0IkxzPC0ZhOzVceUbyIACFZKLqKEBlA=="],
"@types/request": ["@types/request@2.48.12", "", { "dependencies": { "@types/caseless": "*", "@types/node": "*", "@types/tough-cookie": "*", "form-data": "^2.5.0" } }, "sha512-G3sY+NpsA9jnwm0ixhAFQSJ3Q9JkpLZpJbI3GMv0mIAT0y3mRabYeINzal5WOChIiaTEGQYlHOKgkaM9EisWHw=="], "@types/request": ["@types/request@2.48.12", "", { "dependencies": { "@types/caseless": "*", "@types/node": "*", "@types/tough-cookie": "*", "form-data": "^2.5.0" } }, "sha512-G3sY+NpsA9jnwm0ixhAFQSJ3Q9JkpLZpJbI3GMv0mIAT0y3mRabYeINzal5WOChIiaTEGQYlHOKgkaM9EisWHw=="],
@@ -1308,7 +1293,7 @@
"assert-plus": ["assert-plus@1.0.0", "", {}, "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw=="], "assert-plus": ["assert-plus@1.0.0", "", {}, "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw=="],
"astro": ["astro@5.15.1", "", { "dependencies": { "@astrojs/compiler": "^2.12.2", "@astrojs/internal-helpers": "0.7.4", "@astrojs/markdown-remark": "6.3.8", "@astrojs/telemetry": "3.3.0", "@capsizecss/unpack": "^3.0.0", "@oslojs/encoding": "^1.1.0", "@rollup/pluginutils": "^5.2.0", "acorn": "^8.15.0", "aria-query": "^5.3.2", "axobject-query": "^4.1.0", "boxen": "8.0.1", "ci-info": "^4.3.0", "clsx": "^2.1.1", "common-ancestor-path": "^1.0.1", "cookie": "^1.0.2", "cssesc": "^3.0.0", "debug": "^4.4.1", "deterministic-object-hash": "^2.0.2", "devalue": "^5.3.2", "diff": "^5.2.0", "dlv": "^1.1.3", "dset": "^3.1.4", "es-module-lexer": "^1.7.0", "esbuild": "^0.25.0", "estree-walker": "^3.0.3", "flattie": "^1.1.1", "fontace": "~0.3.0", "github-slugger": "^2.0.0", "html-escaper": "3.0.3", "http-cache-semantics": "^4.2.0", "import-meta-resolve": "^4.2.0", "js-yaml": "^4.1.0", "magic-string": "^0.30.18", "magicast": "^0.3.5", "mrmime": "^2.0.1", "neotraverse": "^0.6.18", "p-limit": "^6.2.0", "p-queue": "^8.1.0", "package-manager-detector": "^1.3.0", "picocolors": "^1.1.1", "picomatch": "^4.0.3", "prompts": "^2.4.2", "rehype": "^13.0.2", "semver": "^7.7.2", "shiki": "^3.12.0", "smol-toml": "^1.4.2", "tinyexec": "^1.0.1", "tinyglobby": "^0.2.14", "tsconfck": "^3.1.6", "ultrahtml": "^1.6.0", "unifont": "~0.6.0", "unist-util-visit": "^5.0.0", "unstorage": "^1.17.0", "vfile": "^6.0.3", "vite": "^6.3.6", "vitefu": "^1.1.1", "xxhash-wasm": "^1.1.0", "yargs-parser": "^21.1.1", "yocto-spinner": "^0.2.3", "zod": "^3.25.76", "zod-to-json-schema": "^3.24.6", "zod-to-ts": "^1.2.0" }, "optionalDependencies": { "sharp": "^0.34.0" }, "bin": { "astro": "astro.js" } }, "sha512-VM679M1qxOjGo6q3vKYDNDddkALGgMopG93IwbEXd3Buc2xVLuuPj4HNziNugSbPQx5S6UReMp5uzw10EJN81A=="], "astro": ["astro@5.13.2", "", { "dependencies": { "@astrojs/compiler": "^2.12.2", "@astrojs/internal-helpers": "0.7.2", "@astrojs/markdown-remark": "6.3.6", "@astrojs/telemetry": "3.3.0", "@capsizecss/unpack": "^2.4.0", "@oslojs/encoding": "^1.1.0", "@rollup/pluginutils": "^5.1.4", "acorn": "^8.14.1", "aria-query": "^5.3.2", "axobject-query": "^4.1.0", "boxen": "8.0.1", "ci-info": "^4.2.0", "clsx": "^2.1.1", "common-ancestor-path": "^1.0.1", "cookie": "^1.0.2", "cssesc": "^3.0.0", "debug": "^4.4.0", "deterministic-object-hash": "^2.0.2", "devalue": "^5.1.1", "diff": "^5.2.0", "dlv": "^1.1.3", "dset": "^3.1.4", "es-module-lexer": "^1.6.0", "esbuild": "^0.25.0", "estree-walker": "^3.0.3", "flattie": "^1.1.1", "fontace": "~0.3.0", "github-slugger": "^2.0.0", "html-escaper": "3.0.3", "http-cache-semantics": "^4.1.1", "import-meta-resolve": "^4.1.0", "js-yaml": "^4.1.0", "kleur": "^4.1.5", "magic-string": "^0.30.17", "magicast": "^0.3.5", "mrmime": "^2.0.1", "neotraverse": "^0.6.18", "p-limit": "^6.2.0", "p-queue": "^8.1.0", "package-manager-detector": "^1.1.0", "picomatch": "^4.0.2", "prompts": "^2.4.2", "rehype": "^13.0.2", "semver": "^7.7.1", "shiki": "^3.2.1", "smol-toml": "^1.3.4", "tinyexec": "^0.3.2", "tinyglobby": "^0.2.12", "tsconfck": "^3.1.5", "ultrahtml": "^1.6.0", "unifont": "~0.5.0", "unist-util-visit": "^5.0.0", "unstorage": "^1.15.0", "vfile": "^6.0.3", "vite": "^6.3.4", "vitefu": "^1.0.6", "xxhash-wasm": "^1.1.0", "yargs-parser": "^21.1.1", "yocto-spinner": "^0.2.1", "zod": "^3.24.4", "zod-to-json-schema": "^3.24.5", "zod-to-ts": "^1.2.0" }, "optionalDependencies": { "sharp": "^0.33.3" }, "bin": { "astro": "astro.js" } }, "sha512-yjcXY0Ua3EwjpVd3GoUXa65HQ6qgmURBptA+M9GzE0oYvgfuyM7bIbH8IR/TWIbdefVUJR5b7nZ0oVnMytmyfQ=="],
"async": ["async@2.6.4", "", { "dependencies": { "lodash": "^4.17.14" } }, "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA=="], "async": ["async@2.6.4", "", { "dependencies": { "lodash": "^4.17.14" } }, "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA=="],
@@ -1360,6 +1345,8 @@
"bl": ["bl@6.0.20", "", { "dependencies": { "@types/readable-stream": "^4.0.0", "buffer": "^6.0.3", "inherits": "^2.0.4", "readable-stream": "^4.2.0" } }, "sha512-JMP0loH6ApbpT4Aa9oU5NqAkdDvcyc8koeuK8i5mYoBCVj3XCXG0uweGNN2m6DqaCO2yRHdm+MjCeTsR5VsmcA=="], "bl": ["bl@6.0.20", "", { "dependencies": { "@types/readable-stream": "^4.0.0", "buffer": "^6.0.3", "inherits": "^2.0.4", "readable-stream": "^4.2.0" } }, "sha512-JMP0loH6ApbpT4Aa9oU5NqAkdDvcyc8koeuK8i5mYoBCVj3XCXG0uweGNN2m6DqaCO2yRHdm+MjCeTsR5VsmcA=="],
"blob-to-buffer": ["blob-to-buffer@1.2.9", "", {}, "sha512-BF033y5fN6OCofD3vgHmNtwZWRcq9NLyyxyILx9hfMy1sXYy4ojFl765hJ2lP0YaN2fuxPaLO2Vzzoxy0FLFFA=="],
"body-parser": ["body-parser@2.1.0", "", { "dependencies": { "bytes": "^3.1.2", "content-type": "^1.0.5", "debug": "^4.4.0", "http-errors": "^2.0.0", "iconv-lite": "^0.5.2", "on-finished": "^2.4.1", "qs": "^6.14.0", "raw-body": "^3.0.0", "type-is": "^2.0.0" } }, "sha512-/hPxh61E+ll0Ujp24Ilm64cykicul1ypfwjVttduAiEdtnJFvLePSrIPk+HMImtNv5270wOGCb1Tns2rybMkoQ=="], "body-parser": ["body-parser@2.1.0", "", { "dependencies": { "bytes": "^3.1.2", "content-type": "^1.0.5", "debug": "^4.4.0", "http-errors": "^2.0.0", "iconv-lite": "^0.5.2", "on-finished": "^2.4.1", "qs": "^6.14.0", "raw-body": "^3.0.0", "type-is": "^2.0.0" } }, "sha512-/hPxh61E+ll0Ujp24Ilm64cykicul1ypfwjVttduAiEdtnJFvLePSrIPk+HMImtNv5270wOGCb1Tns2rybMkoQ=="],
"body-scroll-lock-upgrade": ["body-scroll-lock-upgrade@1.1.0", "", {}, "sha512-nnfVAS+tB7CS9RaksuHVTpgHWHF7fE/ptIBJnwZrMqImIvWJF1OGcLnMpBhC6qhkx9oelvyxmWXwmIJXCV98Sw=="], "body-scroll-lock-upgrade": ["body-scroll-lock-upgrade@1.1.0", "", {}, "sha512-nnfVAS+tB7CS9RaksuHVTpgHWHF7fE/ptIBJnwZrMqImIvWJF1OGcLnMpBhC6qhkx9oelvyxmWXwmIJXCV98Sw=="],
@@ -1410,8 +1397,6 @@
"cbor-x": ["cbor-x@1.6.0", "", { "optionalDependencies": { "cbor-extract": "^2.2.0" } }, "sha512-0kareyRwHSkL6ws5VXHEf8uY1liitysCVJjlmhaLG+IXLqhSaOO+t63coaso7yjwEzWZzLy8fJo06gZDVQM9Qg=="], "cbor-x": ["cbor-x@1.6.0", "", { "optionalDependencies": { "cbor-extract": "^2.2.0" } }, "sha512-0kareyRwHSkL6ws5VXHEf8uY1liitysCVJjlmhaLG+IXLqhSaOO+t63coaso7yjwEzWZzLy8fJo06gZDVQM9Qg=="],
"cborg": ["cborg@4.2.18", "", { "bin": { "cborg": "lib/bin.js" } }, "sha512-uzhkd5HOaLccokqeZa5B0Qz7/aa9C12pmUq5yU3vcy6I6OhTKdPHSzOuBPZfcoQHdcx8Emz/dWZbPNNfF/puvg=="],
"ccount": ["ccount@2.0.1", "", {}, "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg=="], "ccount": ["ccount@2.0.1", "", {}, "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg=="],
"chalk": ["chalk@5.4.1", "", {}, "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w=="], "chalk": ["chalk@5.4.1", "", {}, "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w=="],
@@ -1430,7 +1415,7 @@
"chownr": ["chownr@2.0.0", "", {}, "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ=="], "chownr": ["chownr@2.0.0", "", {}, "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ=="],
"ci-info": ["ci-info@4.3.1", "", {}, "sha512-Wdy2Igu8OcBpI2pZePZ5oWjPC38tmDVx5WKUXKwlLYkA0ozo85sLsLvkBbBn/sZaSCMFOGZJ14fvW9t5/d7kdA=="], "ci-info": ["ci-info@4.2.0", "", {}, "sha512-cYY9mypksY8NRqgDB1XD1RiJL338v/551niynFTGkZOO2LHuB2OmOYxDIe/ttN9AHwrqdum1360G3ald0W9kCg=="],
"cjs-module-lexer": ["cjs-module-lexer@1.4.3", "", {}, "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q=="], "cjs-module-lexer": ["cjs-module-lexer@1.4.3", "", {}, "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q=="],
@@ -1498,6 +1483,8 @@
"create-require": ["create-require@1.1.1", "", {}, "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ=="], "create-require": ["create-require@1.1.1", "", {}, "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ=="],
"cross-fetch": ["cross-fetch@3.2.0", "", { "dependencies": { "node-fetch": "^2.7.0" } }, "sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q=="],
"cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="], "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],
"crossws": ["crossws@0.3.5", "", { "dependencies": { "uncrypto": "^0.1.3" } }, "sha512-ojKiDvcmByhwa8YYqbQI/hg7MEU0NC03+pSdEq4ZUnZR9xXpwk7E43SMNGkn+JxJGPFtNvQ48+vV2p+P1ml5PA=="], "crossws": ["crossws@0.3.5", "", { "dependencies": { "uncrypto": "^0.1.3" } }, "sha512-ojKiDvcmByhwa8YYqbQI/hg7MEU0NC03+pSdEq4ZUnZR9xXpwk7E43SMNGkn+JxJGPFtNvQ48+vV2p+P1ml5PA=="],
@@ -1518,7 +1505,7 @@
"dashdash": ["dashdash@1.14.1", "", { "dependencies": { "assert-plus": "^1.0.0" } }, "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g=="], "dashdash": ["dashdash@1.14.1", "", { "dependencies": { "assert-plus": "^1.0.0" } }, "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g=="],
"datastore-core": ["datastore-core@11.0.2", "", { "dependencies": { "@libp2p/logger": "^6.0.0", "interface-datastore": "^9.0.0", "interface-store": "^7.0.0", "it-drain": "^3.0.9", "it-filter": "^3.1.3", "it-map": "^3.1.3", "it-merge": "^3.0.11", "it-pipe": "^3.0.1", "it-sort": "^3.0.8", "it-take": "^3.0.8" } }, "sha512-0pN4hMcaCWcnUBo5OL/8j14Lt1l/p1v2VvzryRYeJAKRLqnFrzy2FhAQ7y0yTA63ki760ImQHfm2XlZrfIdFpQ=="], "datastore-core": ["datastore-core@10.0.4", "", { "dependencies": { "@libp2p/logger": "^5.1.18", "interface-datastore": "^8.0.0", "interface-store": "^6.0.0", "it-drain": "^3.0.9", "it-filter": "^3.1.3", "it-map": "^3.1.3", "it-merge": "^3.0.11", "it-pipe": "^3.0.1", "it-sort": "^3.0.8", "it-take": "^3.0.8" } }, "sha512-IctgCO0GA7GHG7aRm3JRruibCsfvN4EXNnNIlLCZMKIv0TPkdAL5UFV3/xTYFYrrZ1jRNrXZNZRvfcVf/R+rAw=="],
"db0": ["db0@0.3.1", "", { "peerDependencies": { "@electric-sql/pglite": "*", "@libsql/client": "*", "better-sqlite3": "*", "drizzle-orm": "*", "mysql2": "*", "sqlite3": "*" }, "optionalPeers": ["@electric-sql/pglite", "@libsql/client", "better-sqlite3", "drizzle-orm", "mysql2", "sqlite3"] }, "sha512-3RogPLE2LLq6t4YiFCREyl572aBjkfMvfwPyN51df00TbPbryL3XqBYuJ/j6mgPssPK8AKfYdLxizaO5UG10sA=="], "db0": ["db0@0.3.1", "", { "peerDependencies": { "@electric-sql/pglite": "*", "@libsql/client": "*", "better-sqlite3": "*", "drizzle-orm": "*", "mysql2": "*", "sqlite3": "*" }, "optionalPeers": ["@electric-sql/pglite", "@libsql/client", "better-sqlite3", "drizzle-orm", "mysql2", "sqlite3"] }, "sha512-3RogPLE2LLq6t4YiFCREyl572aBjkfMvfwPyN51df00TbPbryL3XqBYuJ/j6mgPssPK8AKfYdLxizaO5UG10sA=="],
@@ -1562,7 +1549,7 @@
"deterministic-object-hash": ["deterministic-object-hash@2.0.2", "", { "dependencies": { "base-64": "^1.0.0" } }, "sha512-KxektNH63SrbfUyDiwXqRb1rLwKt33AmMv+5Nhsw1kqZ13SJBRTgZHtGbE+hH3a1mVW1cz+4pqSWVPAtLVXTzQ=="], "deterministic-object-hash": ["deterministic-object-hash@2.0.2", "", { "dependencies": { "base-64": "^1.0.0" } }, "sha512-KxektNH63SrbfUyDiwXqRb1rLwKt33AmMv+5Nhsw1kqZ13SJBRTgZHtGbE+hH3a1mVW1cz+4pqSWVPAtLVXTzQ=="],
"devalue": ["devalue@5.4.1", "", {}, "sha512-YtoaOfsqjbZQKGIMRYDWKjUmSB4VJ/RElB+bXZawQAQYAo4xu08GKTMVlsZDTF6R2MbAgjcAQRPI5eIyRAT2OQ=="], "devalue": ["devalue@5.1.1", "", {}, "sha512-maua5KUiapvEwiEAe+XnlZ3Rh0GD+qI1J/nb9vrJc3muPXvcF/8gXYTWF76+5DAqHyDUtOIImEuo0YKE9mshVw=="],
"devlop": ["devlop@1.1.0", "", { "dependencies": { "dequal": "^2.0.0" } }, "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA=="], "devlop": ["devlop@1.1.0", "", { "dependencies": { "dequal": "^2.0.0" } }, "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA=="],
@@ -1628,7 +1615,7 @@
"es-errors": ["es-errors@1.3.0", "", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="], "es-errors": ["es-errors@1.3.0", "", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="],
"es-module-lexer": ["es-module-lexer@1.7.0", "", {}, "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA=="], "es-module-lexer": ["es-module-lexer@1.6.0", "", {}, "sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ=="],
"es-object-atoms": ["es-object-atoms@1.1.1", "", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA=="], "es-object-atoms": ["es-object-atoms@1.1.1", "", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA=="],
@@ -1692,6 +1679,8 @@
"eval": ["eval@0.1.8", "", { "dependencies": { "@types/node": "*", "require-like": ">= 0.1.1" } }, "sha512-EzV94NYKoO09GLXGjXj9JIlXijVck4ONSr5wiCWDvhsvj5jxSrzTmRU/9C1DyB6uToszLs8aifA6NQ7lEQdvFw=="], "eval": ["eval@0.1.8", "", { "dependencies": { "@types/node": "*", "require-like": ">= 0.1.1" } }, "sha512-EzV94NYKoO09GLXGjXj9JIlXijVck4ONSr5wiCWDvhsvj5jxSrzTmRU/9C1DyB6uToszLs8aifA6NQ7lEQdvFw=="],
"event-iterator": ["event-iterator@2.0.0", "", {}, "sha512-KGft0ldl31BZVV//jj+IAIGCxkvvUkkON+ScH6zfoX+l+omX6001ggyRSpI0Io2Hlro0ThXotswCtfzS8UkIiQ=="],
"event-target-shim": ["event-target-shim@5.0.1", "", {}, "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ=="], "event-target-shim": ["event-target-shim@5.0.1", "", {}, "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ=="],
"eventemitter3": ["eventemitter3@5.0.1", "", {}, "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA=="], "eventemitter3": ["eventemitter3@5.0.1", "", {}, "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA=="],
@@ -1890,7 +1879,7 @@
"htmlparser2": ["htmlparser2@8.0.2", "", { "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.3", "domutils": "^3.0.1", "entities": "^4.4.0" } }, "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA=="], "htmlparser2": ["htmlparser2@8.0.2", "", { "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.3", "domutils": "^3.0.1", "entities": "^4.4.0" } }, "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA=="],
"http-cache-semantics": ["http-cache-semantics@4.2.0", "", {}, "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ=="], "http-cache-semantics": ["http-cache-semantics@4.1.1", "", {}, "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ=="],
"http-errors": ["http-errors@2.0.0", "", { "dependencies": { "depd": "2.0.0", "inherits": "2.0.4", "setprototypeof": "1.2.0", "statuses": "2.0.1", "toidentifier": "1.0.1" } }, "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ=="], "http-errors": ["http-errors@2.0.0", "", { "dependencies": { "depd": "2.0.0", "inherits": "2.0.4", "setprototypeof": "1.2.0", "statuses": "2.0.1", "toidentifier": "1.0.1" } }, "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ=="],
@@ -1928,9 +1917,9 @@
"ini": ["ini@2.0.0", "", {}, "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA=="], "ini": ["ini@2.0.0", "", {}, "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA=="],
"interface-datastore": ["interface-datastore@9.0.2", "", { "dependencies": { "interface-store": "^7.0.0", "uint8arrays": "^5.1.0" } }, "sha512-jebn+GV/5LTDDoyicNIB4D9O0QszpPqT09Z/MpEWvf3RekjVKpXJCDguM5Au2fwIFxFDAQMZe5bSla0jMamCNg=="], "interface-datastore": ["interface-datastore@8.3.2", "", { "dependencies": { "interface-store": "^6.0.0", "uint8arrays": "^5.1.0" } }, "sha512-R3NLts7pRbJKc3qFdQf+u40hK8XWc0w4Qkx3OFEstC80VoaDUABY/dXA2EJPhtNC+bsrf41Ehvqb6+pnIclyRA=="],
"interface-store": ["interface-store@7.0.1", "", {}, "sha512-OPRRUO3Cs6Jr/t98BrJLQp1jUTPgrRH0PqFfuNoPAqd+J7ABN1tjFVjQdaOBiybYJTS/AyBSZnZVWLPvp3dW3w=="], "interface-store": ["interface-store@6.0.3", "", {}, "sha512-+WvfEZnFUhRwFxgz+QCQi7UC6o9AM0EHM9bpIe2Nhqb100NHCsTvNAn4eJgvgV2/tmLo1MP9nGxQKEcZTAueLA=="],
"invariant": ["invariant@2.2.4", "", { "dependencies": { "loose-envify": "^1.0.0" } }, "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA=="], "invariant": ["invariant@2.2.4", "", { "dependencies": { "loose-envify": "^1.0.0" } }, "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA=="],
@@ -1994,6 +1983,8 @@
"it-all": ["it-all@3.0.9", "", {}, "sha512-fz1oJJ36ciGnu2LntAlE6SA97bFZpW7Rnt0uEc1yazzR2nKokZLr8lIRtgnpex4NsmaBcvHF+Z9krljWFy/mmg=="], "it-all": ["it-all@3.0.9", "", {}, "sha512-fz1oJJ36ciGnu2LntAlE6SA97bFZpW7Rnt0uEc1yazzR2nKokZLr8lIRtgnpex4NsmaBcvHF+Z9krljWFy/mmg=="],
"it-byte-stream": ["it-byte-stream@2.0.3", "", { "dependencies": { "abort-error": "^1.0.1", "it-queueless-pushable": "^2.0.0", "it-stream-types": "^2.0.2", "race-signal": "^1.1.3", "uint8arraylist": "^2.4.8" } }, "sha512-h7FFcn4DWiWsJw1dCJhuPdiY8cGi1z8g4aLAfFspTaJbwQxvEMlEBFG/f8lIVGwM8YK26ClM4/9lxLVhF33b8g=="],
"it-drain": ["it-drain@3.0.10", "", {}, "sha512-0w/bXzudlyKIyD1+rl0xUKTI7k4cshcS43LTlBiGFxI8K1eyLydNPxGcsVLsFVtKh1/ieS8AnVWt6KwmozxyEA=="], "it-drain": ["it-drain@3.0.10", "", {}, "sha512-0w/bXzudlyKIyD1+rl0xUKTI7k4cshcS43LTlBiGFxI8K1eyLydNPxGcsVLsFVtKh1/ieS8AnVWt6KwmozxyEA=="],
"it-filter": ["it-filter@3.1.4", "", { "dependencies": { "it-peekable": "^3.0.0" } }, "sha512-80kWEKgiFEa4fEYD3mwf2uygo1dTQ5Y5midKtL89iXyjinruA/sNXl6iFkTcdNedydjvIsFhWLiqRPQP4fAwWQ=="], "it-filter": ["it-filter@3.1.4", "", { "dependencies": { "it-peekable": "^3.0.0" } }, "sha512-80kWEKgiFEa4fEYD3mwf2uygo1dTQ5Y5midKtL89iXyjinruA/sNXl6iFkTcdNedydjvIsFhWLiqRPQP4fAwWQ=="],
@@ -2002,16 +1993,22 @@
"it-length-prefixed": ["it-length-prefixed@10.0.1", "", { "dependencies": { "it-reader": "^6.0.1", "it-stream-types": "^2.0.1", "uint8-varint": "^2.0.1", "uint8arraylist": "^2.0.0", "uint8arrays": "^5.0.1" } }, "sha512-BhyluvGps26u9a7eQIpOI1YN7mFgi8lFwmiPi07whewbBARKAG9LE09Odc8s1Wtbt2MB6rNUrl7j9vvfXTJwdQ=="], "it-length-prefixed": ["it-length-prefixed@10.0.1", "", { "dependencies": { "it-reader": "^6.0.1", "it-stream-types": "^2.0.1", "uint8-varint": "^2.0.1", "uint8arraylist": "^2.0.0", "uint8arrays": "^5.0.1" } }, "sha512-BhyluvGps26u9a7eQIpOI1YN7mFgi8lFwmiPi07whewbBARKAG9LE09Odc8s1Wtbt2MB6rNUrl7j9vvfXTJwdQ=="],
"it-length-prefixed-stream": ["it-length-prefixed-stream@2.0.3", "", { "dependencies": { "abort-error": "^1.0.1", "it-byte-stream": "^2.0.0", "it-stream-types": "^2.0.2", "uint8-varint": "^2.0.4", "uint8arraylist": "^2.4.8" } }, "sha512-Ns3jNFy2mcFnV59llCYitJnFHapg8wIcOsWkEaAwOkG9v4HBCk24nze/zGDQjiJdDTyFXTT5GOY3M/uaksot3w=="],
"it-map": ["it-map@3.1.4", "", { "dependencies": { "it-peekable": "^3.0.0" } }, "sha512-QB9PYQdE9fUfpVFYfSxBIyvKynUCgblb143c+ktTK6ZuKSKkp7iH58uYFzagqcJ5HcqIfn1xbfaralHWam+3fg=="], "it-map": ["it-map@3.1.4", "", { "dependencies": { "it-peekable": "^3.0.0" } }, "sha512-QB9PYQdE9fUfpVFYfSxBIyvKynUCgblb143c+ktTK6ZuKSKkp7iH58uYFzagqcJ5HcqIfn1xbfaralHWam+3fg=="],
"it-merge": ["it-merge@3.0.12", "", { "dependencies": { "it-queueless-pushable": "^2.0.0" } }, "sha512-nnnFSUxKlkZVZD7c0jYw6rDxCcAQYcMsFj27thf7KkDhpj0EA0g9KHPxbFzHuDoc6US2EPS/MtplkNj8sbCx4Q=="], "it-merge": ["it-merge@3.0.12", "", { "dependencies": { "it-queueless-pushable": "^2.0.0" } }, "sha512-nnnFSUxKlkZVZD7c0jYw6rDxCcAQYcMsFj27thf7KkDhpj0EA0g9KHPxbFzHuDoc6US2EPS/MtplkNj8sbCx4Q=="],
"it-pair": ["it-pair@2.0.6", "", { "dependencies": { "it-stream-types": "^2.0.1", "p-defer": "^4.0.0" } }, "sha512-5M0t5RAcYEQYNG5BV7d7cqbdwbCAp5yLdzvkxsZmkuZsLbTdZzah6MQySYfaAQjNDCq6PUnDt0hqBZ4NwMfW6g=="],
"it-parallel": ["it-parallel@3.0.13", "", { "dependencies": { "p-defer": "^4.0.1" } }, "sha512-85PPJ/O8q97Vj9wmDTSBBXEkattwfQGruXitIzrh0RLPso6RHfiVqkuTqBNufYYtB1x6PSkh0cwvjmMIkFEPHA=="], "it-parallel": ["it-parallel@3.0.13", "", { "dependencies": { "p-defer": "^4.0.1" } }, "sha512-85PPJ/O8q97Vj9wmDTSBBXEkattwfQGruXitIzrh0RLPso6RHfiVqkuTqBNufYYtB1x6PSkh0cwvjmMIkFEPHA=="],
"it-peekable": ["it-peekable@3.0.8", "", {}, "sha512-7IDBQKSp/dtBxXV3Fj0v3qM1jftJ9y9XrWLRIuU1X6RdKqWiN60syNwP0fiDxZD97b8SYM58dD3uklIk1TTQAw=="], "it-peekable": ["it-peekable@3.0.8", "", {}, "sha512-7IDBQKSp/dtBxXV3Fj0v3qM1jftJ9y9XrWLRIuU1X6RdKqWiN60syNwP0fiDxZD97b8SYM58dD3uklIk1TTQAw=="],
"it-pipe": ["it-pipe@3.0.1", "", { "dependencies": { "it-merge": "^3.0.0", "it-pushable": "^3.1.2", "it-stream-types": "^2.0.1" } }, "sha512-sIoNrQl1qSRg2seYSBH/3QxWhJFn9PKYvOf/bHdtCBF0bnghey44VyASsWzn5dAx0DCDDABq1hZIuzKmtBZmKA=="], "it-pipe": ["it-pipe@3.0.1", "", { "dependencies": { "it-merge": "^3.0.0", "it-pushable": "^3.1.2", "it-stream-types": "^2.0.1" } }, "sha512-sIoNrQl1qSRg2seYSBH/3QxWhJFn9PKYvOf/bHdtCBF0bnghey44VyASsWzn5dAx0DCDDABq1hZIuzKmtBZmKA=="],
"it-protobuf-stream": ["it-protobuf-stream@2.0.3", "", { "dependencies": { "abort-error": "^1.0.1", "it-length-prefixed-stream": "^2.0.0", "it-stream-types": "^2.0.2", "uint8arraylist": "^2.4.8" } }, "sha512-Dus9qyylOSnC7l75/3qs6j3Fe9MCM2K5luXi9o175DYijFRne5FPucdOGIYdwaDBDQ4Oy34dNCuFobOpcusvEQ=="],
"it-pushable": ["it-pushable@3.2.3", "", { "dependencies": { "p-defer": "^4.0.0" } }, "sha512-gzYnXYK8Y5t5b/BnJUr7glfQLO4U5vyb05gPx/TyTw+4Bv1zM9gFk4YsOrnulWefMewlphCjKkakFvj1y99Tcg=="], "it-pushable": ["it-pushable@3.2.3", "", { "dependencies": { "p-defer": "^4.0.0" } }, "sha512-gzYnXYK8Y5t5b/BnJUr7glfQLO4U5vyb05gPx/TyTw+4Bv1zM9gFk4YsOrnulWefMewlphCjKkakFvj1y99Tcg=="],
"it-queue": ["it-queue@1.1.0", "", { "dependencies": { "abort-error": "^1.0.1", "it-pushable": "^3.2.3", "main-event": "^1.0.0", "race-event": "^1.3.0", "race-signal": "^1.1.3" } }, "sha512-aK9unJRIaJc9qiv53LByhF7/I2AuD7Ro4oLfLieVLL9QXNvRx++ANMpv8yCp2UO0KAtBuf70GOxSYb6ElFVRpQ=="], "it-queue": ["it-queue@1.1.0", "", { "dependencies": { "abort-error": "^1.0.1", "it-pushable": "^3.2.3", "main-event": "^1.0.0", "race-event": "^1.3.0", "race-signal": "^1.1.3" } }, "sha512-aK9unJRIaJc9qiv53LByhF7/I2AuD7Ro4oLfLieVLL9QXNvRx++ANMpv8yCp2UO0KAtBuf70GOxSYb6ElFVRpQ=="],
@@ -2026,6 +2023,8 @@
"it-take": ["it-take@3.0.9", "", {}, "sha512-XMeUbnjOcgrhFXPUqa7H0VIjYSV/BvyxxjCp76QHVAFDJw2LmR1SHxUFiqyGeobgzJr7P2ZwSRRJQGn4D2BVlA=="], "it-take": ["it-take@3.0.9", "", {}, "sha512-XMeUbnjOcgrhFXPUqa7H0VIjYSV/BvyxxjCp76QHVAFDJw2LmR1SHxUFiqyGeobgzJr7P2ZwSRRJQGn4D2BVlA=="],
"it-ws": ["it-ws@6.1.5", "", { "dependencies": { "@types/ws": "^8.2.2", "event-iterator": "^2.0.0", "it-stream-types": "^2.0.1", "uint8arrays": "^5.0.0", "ws": "^8.4.0" } }, "sha512-uWjMtpy5HqhSd/LlrlP3fhYrr7rUfJFFMABv0F5d6n13Q+0glhZthwUKpEAVhDrXY95Tb1RB5lLqqef+QbVNaw=="],
"jackspeak": ["jackspeak@3.4.3", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" }, "optionalDependencies": { "@pkgjs/parseargs": "^0.11.0" } }, "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw=="], "jackspeak": ["jackspeak@3.4.3", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" }, "optionalDependencies": { "@pkgjs/parseargs": "^0.11.0" } }, "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw=="],
"javascript-stringify": ["javascript-stringify@2.1.0", "", {}, "sha512-JVAfqNPTvNq3sB/VHQJAFxN/sPgKnsKrCwyRt15zwNCdrMMJDdcEOdubuy+DuJYYdm0ox1J4uzEuYKkN+9yhVg=="], "javascript-stringify": ["javascript-stringify@2.1.0", "", {}, "sha512-JVAfqNPTvNq3sB/VHQJAFxN/sPgKnsKrCwyRt15zwNCdrMMJDdcEOdubuy+DuJYYdm0ox1J4uzEuYKkN+9yhVg=="],
@@ -2082,13 +2081,13 @@
"keyv": ["keyv@4.5.4", "", { "dependencies": { "json-buffer": "3.0.1" } }, "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw=="], "keyv": ["keyv@4.5.4", "", { "dependencies": { "json-buffer": "3.0.1" } }, "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw=="],
"kleur": ["kleur@3.0.3", "", {}, "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w=="], "kleur": ["kleur@4.1.5", "", {}, "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ=="],
"kvparser": ["kvparser@1.0.2", "", {}, "sha512-5P/5qpTAHjVYWqcI55B3yQwSY2FUrYYrJj5i65V1Wmg7/4W4OnBcaodaEvLyVuugeOnS+BAaKm9LbPazGJcRyA=="], "kvparser": ["kvparser@1.0.2", "", {}, "sha512-5P/5qpTAHjVYWqcI55B3yQwSY2FUrYYrJj5i65V1Wmg7/4W4OnBcaodaEvLyVuugeOnS+BAaKm9LbPazGJcRyA=="],
"leven": ["leven@2.1.0", "", {}, "sha512-nvVPLpIHUxCUoRLrFqTgSxXJ614d8AgQoWl7zPe/2VadE8+1dpU3LBhowRuBAcuwruWtOdD8oYC9jDNJjXDPyA=="], "leven": ["leven@2.1.0", "", {}, "sha512-nvVPLpIHUxCUoRLrFqTgSxXJ614d8AgQoWl7zPe/2VadE8+1dpU3LBhowRuBAcuwruWtOdD8oYC9jDNJjXDPyA=="],
"libp2p": ["libp2p@3.0.6", "", { "dependencies": { "@chainsafe/is-ip": "^2.1.0", "@chainsafe/netmask": "^2.0.0", "@libp2p/crypto": "^5.1.12", "@libp2p/interface": "^3.0.2", "@libp2p/interface-internal": "^3.0.5", "@libp2p/logger": "^6.0.5", "@libp2p/multistream-select": "^7.0.5", "@libp2p/peer-collections": "^7.0.5", "@libp2p/peer-id": "^6.0.3", "@libp2p/peer-store": "^12.0.5", "@libp2p/utils": "^7.0.5", "@multiformats/dns": "^1.0.6", "@multiformats/multiaddr": "^13.0.1", "@multiformats/multiaddr-matcher": "^3.0.1", "any-signal": "^4.1.1", "datastore-core": "^11.0.1", "interface-datastore": "^9.0.1", "it-merge": "^3.0.12", "it-parallel": "^3.0.13", "main-event": "^1.0.1", "multiformats": "^13.4.0", "p-defer": "^4.0.1", "p-event": "^7.0.0", "p-retry": "^7.0.0", "progress-events": "^1.0.1", "race-signal": "^2.0.0", "uint8arrays": "^5.1.0" } }, "sha512-QtEbPVTjsHNy0B503ZXRwhoMawEdy+HOHaywJHTB3yHduzgJq+dN7gJFChnyFE8t45UhGZK50bO/+Q0q+5xXhw=="], "libp2p": ["libp2p@2.8.12", "", { "dependencies": { "@chainsafe/is-ip": "^2.1.0", "@chainsafe/netmask": "^2.0.0", "@libp2p/crypto": "^5.1.7", "@libp2p/interface": "^2.10.5", "@libp2p/interface-internal": "^2.3.18", "@libp2p/logger": "^5.1.21", "@libp2p/multistream-select": "^6.0.28", "@libp2p/peer-collections": "^6.0.34", "@libp2p/peer-id": "^5.1.8", "@libp2p/peer-store": "^11.2.6", "@libp2p/utils": "^6.7.1", "@multiformats/dns": "^1.0.6", "@multiformats/multiaddr": "^12.4.4", "@multiformats/multiaddr-matcher": "^1.7.2", "any-signal": "^4.1.1", "datastore-core": "^10.0.2", "interface-datastore": "^8.3.1", "it-byte-stream": "^2.0.2", "it-merge": "^3.0.11", "it-parallel": "^3.0.11", "main-event": "^1.0.1", "multiformats": "^13.3.6", "p-defer": "^4.0.1", "p-retry": "^6.2.1", "progress-events": "^1.0.1", "race-event": "^1.3.0", "race-signal": "^1.1.3", "uint8arrays": "^5.1.0" } }, "sha512-wWknf2YsfHwnNK0XyFxCkVVNrckCrY+lwCdp4bpHScb5ALcWmzpgWP8+h/b66sEJ3IUJjhgjMkN1W9sS53KTPQ=="],
"light-my-request": ["light-my-request@6.6.0", "", { "dependencies": { "cookie": "^1.0.1", "process-warning": "^4.0.0", "set-cookie-parser": "^2.6.0" } }, "sha512-CHYbu8RtboSIoVsHZ6Ye4cj4Aw/yg2oAFimlF7mNvfDV192LR7nDiKtSIfCuLT7KokPSTn/9kfVLm5OGN0A28A=="], "light-my-request": ["light-my-request@6.6.0", "", { "dependencies": { "cookie": "^1.0.1", "process-warning": "^4.0.0", "set-cookie-parser": "^2.6.0" } }, "sha512-CHYbu8RtboSIoVsHZ6Ye4cj4Aw/yg2oAFimlF7mNvfDV192LR7nDiKtSIfCuLT7KokPSTn/9kfVLm5OGN0A28A=="],
@@ -2310,7 +2309,7 @@
"ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
"multiformats": ["multiformats@13.4.1", "", {}, "sha512-VqO6OSvLrFVAYYjgsr8tyv62/rCQhPgsZUXLTqoFLSgdkgiUYKYeArbt1uWLlEpkjxQe+P0+sHlbPEte1Bi06Q=="], "multiformats": ["multiformats@13.3.7", "", {}, "sha512-meL9DERHj+fFVWoOX9fXqfcYcSpUfSYJPcFvDPKrxitICbwAoWR+Ut4j5NO9zAT917HUHLQmqzQbAsGNHlDcxQ=="],
"nanoid": ["nanoid@5.1.3", "", { "bin": { "nanoid": "bin/nanoid.js" } }, "sha512-zAbEOEr7u2CbxwoMRlz/pNSpRP0FdAU4pRaYunCdEezWohXFs+a0Xw7RfkKaezMsmSM1vttcLthJtwRnVtOfHQ=="], "nanoid": ["nanoid@5.1.3", "", { "bin": { "nanoid": "bin/nanoid.js" } }, "sha512-zAbEOEr7u2CbxwoMRlz/pNSpRP0FdAU4pRaYunCdEezWohXFs+a0Xw7RfkKaezMsmSM1vttcLthJtwRnVtOfHQ=="],
@@ -2412,7 +2411,7 @@
"p-defer": ["p-defer@4.0.1", "", {}, "sha512-Mr5KC5efvAK5VUptYEIopP1bakB85k2IWXaRC0rsh1uwn1L6M0LVml8OIQ4Gudg4oyZakf7FmeRLkMMtZW1i5A=="], "p-defer": ["p-defer@4.0.1", "", {}, "sha512-Mr5KC5efvAK5VUptYEIopP1bakB85k2IWXaRC0rsh1uwn1L6M0LVml8OIQ4Gudg4oyZakf7FmeRLkMMtZW1i5A=="],
"p-event": ["p-event@7.0.0", "", { "dependencies": { "p-timeout": "^6.1.4" } }, "sha512-z4Xv/ieHhi6Dx3A5xbZI8WWTn+eSRo6buGTvA8Yv2iLyX+61SUIMKcBszZRHA6e2Apld6QEDSclAuha2iUntyA=="], "p-event": ["p-event@6.0.1", "", { "dependencies": { "p-timeout": "^6.1.2" } }, "sha512-Q6Bekk5wpzW5qIyUP4gdMEujObYstZl6DMMOSenwBvV0BlE5LkDwkjs5yHbZmdCEq2o4RJx4tE1vwxFVf2FG1w=="],
"p-limit": ["p-limit@6.2.0", "", { "dependencies": { "yocto-queue": "^1.1.1" } }, "sha512-kuUqqHNUqoIWp/c467RI4X6mmyuojY5jGutNU0wVTmEOOfcuwLqyMVoAi9MKi2Ak+5i9+nhmrK4ufZE8069kHA=="], "p-limit": ["p-limit@6.2.0", "", { "dependencies": { "yocto-queue": "^1.1.1" } }, "sha512-kuUqqHNUqoIWp/c467RI4X6mmyuojY5jGutNU0wVTmEOOfcuwLqyMVoAi9MKi2Ak+5i9+nhmrK4ufZE8069kHA=="],
@@ -2430,7 +2429,7 @@
"package-json-from-dist": ["package-json-from-dist@1.0.1", "", {}, "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw=="], "package-json-from-dist": ["package-json-from-dist@1.0.1", "", {}, "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw=="],
"package-manager-detector": ["package-manager-detector@1.4.1", "", {}, "sha512-dSMiVLBEA4XaNJ0PRb4N5cV/SEP4BWrWZKBmfF+OUm2pQTiZ6DDkKeWaltwu3JRhLoy59ayIkJ00cx9K9CaYTg=="], "package-manager-detector": ["package-manager-detector@1.1.0", "", {}, "sha512-Y8f9qUlBzW8qauJjd/eu6jlpJZsuPJm2ZAV0cDVd420o4EdpH5RPdoCv+60/TdJflGatr4sDfpAL6ArWZbM5tA=="],
"pacote": ["pacote@18.0.6", "", { "dependencies": { "@npmcli/git": "^5.0.0", "@npmcli/installed-package-contents": "^2.0.1", "@npmcli/package-json": "^5.1.0", "@npmcli/promise-spawn": "^7.0.0", "@npmcli/run-script": "^8.0.0", "cacache": "^18.0.0", "fs-minipass": "^3.0.0", "minipass": "^7.0.2", "npm-package-arg": "^11.0.0", "npm-packlist": "^8.0.0", "npm-pick-manifest": "^9.0.0", "npm-registry-fetch": "^17.0.0", "proc-log": "^4.0.0", "promise-retry": "^2.0.1", "sigstore": "^2.2.0", "ssri": "^10.0.0", "tar": "^6.1.11" }, "bin": { "pacote": "bin/index.js" } }, "sha512-+eK3G27SMwsB8kLIuj4h1FUhHtwiEUo21Tw8wNjmvdlpOEr613edv+8FUsTj/4F/VN5ywGE19X18N7CC2EJk6A=="], "pacote": ["pacote@18.0.6", "", { "dependencies": { "@npmcli/git": "^5.0.0", "@npmcli/installed-package-contents": "^2.0.1", "@npmcli/package-json": "^5.1.0", "@npmcli/promise-spawn": "^7.0.0", "@npmcli/run-script": "^8.0.0", "cacache": "^18.0.0", "fs-minipass": "^3.0.0", "minipass": "^7.0.2", "npm-package-arg": "^11.0.0", "npm-packlist": "^8.0.0", "npm-pick-manifest": "^9.0.0", "npm-registry-fetch": "^17.0.0", "proc-log": "^4.0.0", "promise-retry": "^2.0.1", "sigstore": "^2.2.0", "ssri": "^10.0.0", "tar": "^6.1.11" }, "bin": { "pacote": "bin/index.js" } }, "sha512-+eK3G27SMwsB8kLIuj4h1FUhHtwiEUo21Tw8wNjmvdlpOEr613edv+8FUsTj/4F/VN5ywGE19X18N7CC2EJk6A=="],
@@ -2734,7 +2733,7 @@
"shell-quote": ["shell-quote@1.8.2", "", {}, "sha512-AzqKpGKjrj7EM6rKVQEPpB288oCfnrEIuyoT9cyF4nmGa7V8Zk6f7RRqYisX8X9m+Q7bd632aZW4ky7EhbQztA=="], "shell-quote": ["shell-quote@1.8.2", "", {}, "sha512-AzqKpGKjrj7EM6rKVQEPpB288oCfnrEIuyoT9cyF4nmGa7V8Zk6f7RRqYisX8X9m+Q7bd632aZW4ky7EhbQztA=="],
"shiki": ["shiki@3.13.0", "", { "dependencies": { "@shikijs/core": "3.13.0", "@shikijs/engine-javascript": "3.13.0", "@shikijs/engine-oniguruma": "3.13.0", "@shikijs/langs": "3.13.0", "@shikijs/themes": "3.13.0", "@shikijs/types": "3.13.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-aZW4l8Og16CokuCLf8CF8kq+KK2yOygapU5m3+hoGw0Mdosc6fPitjM+ujYarppj5ZIKGyPDPP1vqmQhr+5/0g=="], "shiki": ["shiki@3.12.2", "", { "dependencies": { "@shikijs/core": "3.12.2", "@shikijs/engine-javascript": "3.12.2", "@shikijs/engine-oniguruma": "3.12.2", "@shikijs/langs": "3.12.2", "@shikijs/themes": "3.12.2", "@shikijs/types": "3.12.2", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-uIrKI+f9IPz1zDT+GMz+0RjzKJiijVr6WDWm9Pe3NNY6QigKCfifCEv9v9R2mDASKKjzjQ2QpFLcxaR3iHSnMA=="],
"shimmer": ["shimmer@1.2.1", "", {}, "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw=="], "shimmer": ["shimmer@1.2.1", "", {}, "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw=="],
@@ -2848,7 +2847,7 @@
"strnum": ["strnum@1.1.2", "", {}, "sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA=="], "strnum": ["strnum@1.1.2", "", {}, "sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA=="],
"supports-color": ["supports-color@10.2.2", "", {}, "sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g=="], "supports-color": ["supports-color@9.4.0", "", {}, "sha512-VL+lNrEoIXww1coLPOmiEmK/0sGigko5COxI09KzHc2VJXJsQ37UaQ+8quuxjDeA7+KnLGTWRyOXSLLR2Wb4jw=="],
"supports-preserve-symlinks-flag": ["supports-preserve-symlinks-flag@1.0.0", "", {}, "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="], "supports-preserve-symlinks-flag": ["supports-preserve-symlinks-flag@1.0.0", "", {}, "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="],
@@ -2870,7 +2869,7 @@
"tiny-typed-emitter": ["tiny-typed-emitter@2.1.0", "", {}, "sha512-qVtvMxeXbVej0cQWKqVSSAHmKZEHAvxdF8HEUBFWts8h+xEo5m/lEiPakuyZ3BnCBjOD8i24kzNOiOLLgsSxhA=="], "tiny-typed-emitter": ["tiny-typed-emitter@2.1.0", "", {}, "sha512-qVtvMxeXbVej0cQWKqVSSAHmKZEHAvxdF8HEUBFWts8h+xEo5m/lEiPakuyZ3BnCBjOD8i24kzNOiOLLgsSxhA=="],
"tinyexec": ["tinyexec@1.0.1", "", {}, "sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw=="], "tinyexec": ["tinyexec@0.3.2", "", {}, "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA=="],
"tinyglobby": ["tinyglobby@0.2.14", "", { "dependencies": { "fdir": "^6.4.4", "picomatch": "^4.0.2" } }, "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ=="], "tinyglobby": ["tinyglobby@0.2.14", "", { "dependencies": { "fdir": "^6.4.4", "picomatch": "^4.0.2" } }, "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ=="],
@@ -2892,7 +2891,7 @@
"ts-node": ["ts-node@10.9.2", "", { "dependencies": { "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", "@tsconfig/node12": "^1.0.7", "@tsconfig/node14": "^1.0.0", "@tsconfig/node16": "^1.0.2", "acorn": "^8.4.1", "acorn-walk": "^8.1.1", "arg": "^4.1.0", "create-require": "^1.1.0", "diff": "^4.0.1", "make-error": "^1.1.1", "v8-compile-cache-lib": "^3.0.1", "yn": "3.1.1" }, "peerDependencies": { "@swc/core": ">=1.2.50", "@swc/wasm": ">=1.2.50", "@types/node": "*", "typescript": ">=2.7" }, "optionalPeers": ["@swc/core", "@swc/wasm"], "bin": { "ts-node": "dist/bin.js", "ts-script": "dist/bin-script-deprecated.js", "ts-node-cwd": "dist/bin-cwd.js", "ts-node-esm": "dist/bin-esm.js", "ts-node-script": "dist/bin-script.js", "ts-node-transpile-only": "dist/bin-transpile.js" } }, "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ=="], "ts-node": ["ts-node@10.9.2", "", { "dependencies": { "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", "@tsconfig/node12": "^1.0.7", "@tsconfig/node14": "^1.0.0", "@tsconfig/node16": "^1.0.2", "acorn": "^8.4.1", "acorn-walk": "^8.1.1", "arg": "^4.1.0", "create-require": "^1.1.0", "diff": "^4.0.1", "make-error": "^1.1.1", "v8-compile-cache-lib": "^3.0.1", "yn": "3.1.1" }, "peerDependencies": { "@swc/core": ">=1.2.50", "@swc/wasm": ">=1.2.50", "@types/node": "*", "typescript": ">=2.7" }, "optionalPeers": ["@swc/core", "@swc/wasm"], "bin": { "ts-node": "dist/bin.js", "ts-script": "dist/bin-script-deprecated.js", "ts-node-cwd": "dist/bin-cwd.js", "ts-node-esm": "dist/bin-esm.js", "ts-node-script": "dist/bin-script.js", "ts-node-transpile-only": "dist/bin-transpile.js" } }, "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ=="],
"tsconfck": ["tsconfck@3.1.6", "", { "peerDependencies": { "typescript": "^5.0.0" }, "optionalPeers": ["typescript"], "bin": { "tsconfck": "bin/tsconfck.js" } }, "sha512-ks6Vjr/jEw0P1gmOVwutM3B7fWxoWBL2KRDb1JfqGVawBmO5UsvmWOQFGHBPl5yxYz4eERr19E6L7NMv+Fej4w=="], "tsconfck": ["tsconfck@3.1.5", "", { "peerDependencies": { "typescript": "^5.0.0" }, "optionalPeers": ["typescript"], "bin": { "tsconfck": "bin/tsconfck.js" } }, "sha512-CLDfGgUp7XPswWnezWwsCRxNmgQjhYq3VXHM0/XIRxhVrKw0M1if9agzryh1QS3nxjCROvV+xWxoJO1YctzzWg=="],
"tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
@@ -2942,7 +2941,7 @@
"unified": ["unified@11.0.5", "", { "dependencies": { "@types/unist": "^3.0.0", "bail": "^2.0.0", "devlop": "^1.0.0", "extend": "^3.0.0", "is-plain-obj": "^4.0.0", "trough": "^2.0.0", "vfile": "^6.0.0" } }, "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA=="], "unified": ["unified@11.0.5", "", { "dependencies": { "@types/unist": "^3.0.0", "bail": "^2.0.0", "devlop": "^1.0.0", "extend": "^3.0.0", "is-plain-obj": "^4.0.0", "trough": "^2.0.0", "vfile": "^6.0.0" } }, "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA=="],
"unifont": ["unifont@0.6.0", "", { "dependencies": { "css-tree": "^3.0.0", "ofetch": "^1.4.1", "ohash": "^2.0.0" } }, "sha512-5Fx50fFQMQL5aeHyWnZX9122sSLckcDvcfFiBf3QYeHa7a1MKJooUy52b67moi2MJYkrfo/TWY+CoLdr/w0tTA=="], "unifont": ["unifont@0.5.2", "", { "dependencies": { "css-tree": "^3.0.0", "ofetch": "^1.4.1", "ohash": "^2.0.0" } }, "sha512-LzR4WUqzH9ILFvjLAUU7dK3Lnou/qd5kD+IakBtBK4S15/+x2y9VX+DcWQv6s551R6W+vzwgVS6tFg3XggGBgg=="],
"unique-filename": ["unique-filename@3.0.0", "", { "dependencies": { "unique-slug": "^4.0.0" } }, "sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g=="], "unique-filename": ["unique-filename@3.0.0", "", { "dependencies": { "unique-slug": "^4.0.0" } }, "sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g=="],
@@ -3018,7 +3017,7 @@
"walk-up-path": ["walk-up-path@3.0.1", "", {}, "sha512-9YlCL/ynK3CTlrSRrDxZvUauLzAswPCrsaCgilqFevUYpeEW0/3ScEjaa3kbW/T0ghhkEr7mv+fpjqn1Y1YuTA=="], "walk-up-path": ["walk-up-path@3.0.1", "", {}, "sha512-9YlCL/ynK3CTlrSRrDxZvUauLzAswPCrsaCgilqFevUYpeEW0/3ScEjaa3kbW/T0ghhkEr7mv+fpjqn1Y1YuTA=="],
"weald": ["weald@1.0.6", "", { "dependencies": { "ms": "^3.0.0-canary.1", "supports-color": "^10.0.0" } }, "sha512-sX1PzkcMJZUJ848JbFzB6aKHHglTxqACEnq2KgI75b7vWYvfXFBNbOuDKqFKwCT44CrP6c5r+L4+5GmPnb5/SQ=="], "weald": ["weald@1.0.4", "", { "dependencies": { "ms": "^3.0.0-canary.1", "supports-color": "^9.4.0" } }, "sha512-+kYTuHonJBwmFhP1Z4YQK/dGi3jAnJGCYhyODFpHK73rbxnp9lnZQj7a2m+WVgn8fXr5bJaxUpF6l8qZpPeNWQ=="],
"web-namespaces": ["web-namespaces@2.0.1", "", {}, "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ=="], "web-namespaces": ["web-namespaces@2.0.1", "", {}, "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ=="],
@@ -3106,8 +3105,6 @@
"@astrojs/markdown-remark/js-yaml": ["js-yaml@4.1.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA=="], "@astrojs/markdown-remark/js-yaml": ["js-yaml@4.1.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA=="],
"@astrojs/telemetry/ci-info": ["ci-info@4.2.0", "", {}, "sha512-cYY9mypksY8NRqgDB1XD1RiJL338v/551niynFTGkZOO2LHuB2OmOYxDIe/ttN9AHwrqdum1360G3ald0W9kCg=="],
"@aws-crypto/crc32/@aws-sdk/types": ["@aws-sdk/types@3.804.0", "", { "dependencies": { "@smithy/types": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-A9qnsy9zQ8G89vrPPlNG9d1d8QcKRGqJKqwyGgS0dclJpwy6d1EWgQLIolKPl6vcFpLoe6avLOLxr+h8ur5wpg=="], "@aws-crypto/crc32/@aws-sdk/types": ["@aws-sdk/types@3.804.0", "", { "dependencies": { "@smithy/types": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-A9qnsy9zQ8G89vrPPlNG9d1d8QcKRGqJKqwyGgS0dclJpwy6d1EWgQLIolKPl6vcFpLoe6avLOLxr+h8ur5wpg=="],
"@aws-crypto/crc32c/@aws-sdk/types": ["@aws-sdk/types@3.804.0", "", { "dependencies": { "@smithy/types": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-A9qnsy9zQ8G89vrPPlNG9d1d8QcKRGqJKqwyGgS0dclJpwy6d1EWgQLIolKPl6vcFpLoe6avLOLxr+h8ur5wpg=="], "@aws-crypto/crc32c/@aws-sdk/types": ["@aws-sdk/types@3.804.0", "", { "dependencies": { "@smithy/types": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-A9qnsy9zQ8G89vrPPlNG9d1d8QcKRGqJKqwyGgS0dclJpwy6d1EWgQLIolKPl6vcFpLoe6avLOLxr+h8ur5wpg=="],
@@ -3468,20 +3465,10 @@
"@bufbuild/protoplugin/typescript": ["typescript@5.4.5", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ=="], "@bufbuild/protoplugin/typescript": ["typescript@5.4.5", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ=="],
"@chainsafe/libp2p-quic/@libp2p/interface": ["@libp2p/interface@2.11.0", "", { "dependencies": { "@multiformats/dns": "^1.0.6", "@multiformats/multiaddr": "^12.4.4", "it-pushable": "^3.2.3", "it-stream-types": "^2.0.2", "main-event": "^1.0.1", "multiformats": "^13.3.6", "progress-events": "^1.0.1", "uint8arraylist": "^2.4.8" } }, "sha512-0MUFKoXWHTQW3oWIgSHApmYMUKWO/Y02+7Hpyp+n3z+geD4Xo2Rku2gYWmxcq+Pyjkz6Q9YjDWz3Yb2SoV2E8Q=="],
"@chainsafe/libp2p-quic/@libp2p/utils": ["@libp2p/utils@6.7.2", "", { "dependencies": { "@chainsafe/is-ip": "^2.1.0", "@chainsafe/netmask": "^2.0.0", "@libp2p/crypto": "^5.1.8", "@libp2p/interface": "^2.11.0", "@libp2p/logger": "^5.2.0", "@multiformats/multiaddr": "^12.4.4", "@sindresorhus/fnv1a": "^3.1.0", "any-signal": "^4.1.1", "delay": "^6.0.0", "get-iterator": "^2.0.1", "is-loopback-addr": "^2.0.2", "is-plain-obj": "^4.1.0", "it-foreach": "^2.1.3", "it-pipe": "^3.0.1", "it-pushable": "^3.2.3", "it-stream-types": "^2.0.2", "main-event": "^1.0.1", "netmask": "^2.0.2", "p-defer": "^4.0.1", "race-event": "^1.3.0", "race-signal": "^1.1.3", "uint8arraylist": "^2.4.8", "uint8arrays": "^5.1.0" } }, "sha512-yglVPcYErb4al3MMTdedVLLsdUvr5KaqrrxohxTl/FXMFBvBs0o3w8lo29nfnTUpnNSHFhWZ9at0ZGNnpT/C/w=="],
"@chainsafe/libp2p-quic/@multiformats/multiaddr": ["@multiformats/multiaddr@12.5.1", "", { "dependencies": { "@chainsafe/is-ip": "^2.0.1", "@chainsafe/netmask": "^2.0.0", "@multiformats/dns": "^1.0.3", "abort-error": "^1.0.1", "multiformats": "^13.0.0", "uint8-varint": "^2.0.1", "uint8arrays": "^5.0.0" } }, "sha512-+DDlr9LIRUS8KncI1TX/FfUn8F2dl6BIxJgshS/yFQCNB5IAF0OGzcwB39g5NLE22s4qqDePv0Qof6HdpJ/4aQ=="],
"@chainsafe/libp2p-yamux/race-signal": ["race-signal@2.0.0", "", {}, "sha512-P31bLhE4ByBX/70QDXMutxnqgwrF1WUXea1O8DXuviAgkdbQ1iQMQotNgzJIBC9yUSn08u/acZrMUhgw7w6GpA=="],
"@dotenvx/dotenvx/commander": ["commander@11.1.0", "", {}, "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ=="], "@dotenvx/dotenvx/commander": ["commander@11.1.0", "", {}, "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ=="],
"@dotenvx/dotenvx/picomatch": ["picomatch@4.0.2", "", {}, "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg=="], "@dotenvx/dotenvx/picomatch": ["picomatch@4.0.2", "", {}, "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg=="],
"@ecies/ciphers/@noble/ciphers": ["@noble/ciphers@1.3.0", "", {}, "sha512-2I0gnIVPtfnMw9ee9h1dJG7tp81+8Ob3OJb3Mv37rx5L40/b0i7djjCVvGOVqc9AEIQyvyu1i6ypKdFw8R8gQw=="],
"@esbuild-kit/core-utils/esbuild": ["esbuild@0.18.20", "", { "optionalDependencies": { "@esbuild/android-arm": "0.18.20", "@esbuild/android-arm64": "0.18.20", "@esbuild/android-x64": "0.18.20", "@esbuild/darwin-arm64": "0.18.20", "@esbuild/darwin-x64": "0.18.20", "@esbuild/freebsd-arm64": "0.18.20", "@esbuild/freebsd-x64": "0.18.20", "@esbuild/linux-arm": "0.18.20", "@esbuild/linux-arm64": "0.18.20", "@esbuild/linux-ia32": "0.18.20", "@esbuild/linux-loong64": "0.18.20", "@esbuild/linux-mips64el": "0.18.20", "@esbuild/linux-ppc64": "0.18.20", "@esbuild/linux-riscv64": "0.18.20", "@esbuild/linux-s390x": "0.18.20", "@esbuild/linux-x64": "0.18.20", "@esbuild/netbsd-x64": "0.18.20", "@esbuild/openbsd-x64": "0.18.20", "@esbuild/sunos-x64": "0.18.20", "@esbuild/win32-arm64": "0.18.20", "@esbuild/win32-ia32": "0.18.20", "@esbuild/win32-x64": "0.18.20" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA=="], "@esbuild-kit/core-utils/esbuild": ["esbuild@0.18.20", "", { "optionalDependencies": { "@esbuild/android-arm": "0.18.20", "@esbuild/android-arm64": "0.18.20", "@esbuild/android-x64": "0.18.20", "@esbuild/darwin-arm64": "0.18.20", "@esbuild/darwin-x64": "0.18.20", "@esbuild/freebsd-arm64": "0.18.20", "@esbuild/freebsd-x64": "0.18.20", "@esbuild/linux-arm": "0.18.20", "@esbuild/linux-arm64": "0.18.20", "@esbuild/linux-ia32": "0.18.20", "@esbuild/linux-loong64": "0.18.20", "@esbuild/linux-mips64el": "0.18.20", "@esbuild/linux-ppc64": "0.18.20", "@esbuild/linux-riscv64": "0.18.20", "@esbuild/linux-s390x": "0.18.20", "@esbuild/linux-x64": "0.18.20", "@esbuild/netbsd-x64": "0.18.20", "@esbuild/openbsd-x64": "0.18.20", "@esbuild/sunos-x64": "0.18.20", "@esbuild/win32-arm64": "0.18.20", "@esbuild/win32-ia32": "0.18.20", "@esbuild/win32-x64": "0.18.20" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA=="],
"@fastify/ajv-compiler/ajv": ["ajv@8.17.1", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g=="], "@fastify/ajv-compiler/ajv": ["ajv@8.17.1", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g=="],
@@ -3518,31 +3505,9 @@
"@jridgewell/trace-mapping/@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.0", "", {}, "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ=="], "@jridgewell/trace-mapping/@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.0", "", {}, "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ=="],
"@libp2p/crypto/@libp2p/interface": ["@libp2p/interface@3.0.0", "", { "dependencies": { "@multiformats/dns": "^1.0.6", "@multiformats/multiaddr": "^13.0.1", "main-event": "^1.0.1", "multiformats": "^13.4.0", "progress-events": "^1.0.1", "uint8arraylist": "^2.4.8" } }, "sha512-fiHoXGUDiaZeksSm+Chf4/tuUynQuDWtadrbqDFxq0nJ5Q7aHPgsmJba7xSfELcqfQCTp00a31FQvXWSk7Oigg=="], "@libp2p/crypto/@noble/curves": ["@noble/curves@1.9.2", "", { "dependencies": { "@noble/hashes": "1.8.0" } }, "sha512-HxngEd2XUcg9xi20JkwlLCtYwfoFw4JGkuZpT+WlsPD4gB/cxkvTD8fSsoAnphGZhFdZYKeQIPCuFlWPm1uE0g=="],
"@libp2p/identify/@libp2p/crypto": ["@libp2p/crypto@5.1.12", "", { "dependencies": { "@libp2p/interface": "^3.0.2", "@noble/curves": "^2.0.1", "@noble/hashes": "^2.0.1", "multiformats": "^13.4.0", "protons-runtime": "^5.6.0", "uint8arraylist": "^2.4.8", "uint8arrays": "^5.1.0" } }, "sha512-1yJS0BZj+HF4M3Uv/92y3oIbMcCar218accFBcX+nKVhBlwDbx6fkUURhs5GilIhMgDtir+qQ8Un1hwF4CgGzw=="], "@libp2p/websockets/@types/ws": ["@types/ws@8.18.1", "", { "dependencies": { "@types/node": "*" } }, "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg=="],
"@libp2p/identify/@multiformats/multiaddr-matcher": ["@multiformats/multiaddr-matcher@3.0.1", "", { "dependencies": { "@multiformats/multiaddr": "^13.0.0" } }, "sha512-jvjwzCPysVTQ53F4KqwmcqZw73BqHMk0UUZrMP9P4OtJ/YHrfs122ikTqhVA2upe0P/Qz9l8HVlhEifVYB2q9A=="],
"@libp2p/peer-id/@libp2p/crypto": ["@libp2p/crypto@5.1.12", "", { "dependencies": { "@libp2p/interface": "^3.0.2", "@noble/curves": "^2.0.1", "@noble/hashes": "^2.0.1", "multiformats": "^13.4.0", "protons-runtime": "^5.6.0", "uint8arraylist": "^2.4.8", "uint8arrays": "^5.1.0" } }, "sha512-1yJS0BZj+HF4M3Uv/92y3oIbMcCar218accFBcX+nKVhBlwDbx6fkUURhs5GilIhMgDtir+qQ8Un1hwF4CgGzw=="],
"@libp2p/peer-record/@libp2p/crypto": ["@libp2p/crypto@5.1.12", "", { "dependencies": { "@libp2p/interface": "^3.0.2", "@noble/curves": "^2.0.1", "@noble/hashes": "^2.0.1", "multiformats": "^13.4.0", "protons-runtime": "^5.6.0", "uint8arraylist": "^2.4.8", "uint8arrays": "^5.1.0" } }, "sha512-1yJS0BZj+HF4M3Uv/92y3oIbMcCar218accFBcX+nKVhBlwDbx6fkUURhs5GilIhMgDtir+qQ8Un1hwF4CgGzw=="],
"@libp2p/peer-store/@libp2p/crypto": ["@libp2p/crypto@5.1.12", "", { "dependencies": { "@libp2p/interface": "^3.0.2", "@noble/curves": "^2.0.1", "@noble/hashes": "^2.0.1", "multiformats": "^13.4.0", "protons-runtime": "^5.6.0", "uint8arraylist": "^2.4.8", "uint8arrays": "^5.1.0" } }, "sha512-1yJS0BZj+HF4M3Uv/92y3oIbMcCar218accFBcX+nKVhBlwDbx6fkUURhs5GilIhMgDtir+qQ8Un1hwF4CgGzw=="],
"@libp2p/ping/@libp2p/crypto": ["@libp2p/crypto@5.1.12", "", { "dependencies": { "@libp2p/interface": "^3.0.2", "@noble/curves": "^2.0.1", "@noble/hashes": "^2.0.1", "multiformats": "^13.4.0", "protons-runtime": "^5.6.0", "uint8arraylist": "^2.4.8", "uint8arrays": "^5.1.0" } }, "sha512-1yJS0BZj+HF4M3Uv/92y3oIbMcCar218accFBcX+nKVhBlwDbx6fkUURhs5GilIhMgDtir+qQ8Un1hwF4CgGzw=="],
"@libp2p/ping/race-signal": ["race-signal@2.0.0", "", {}, "sha512-P31bLhE4ByBX/70QDXMutxnqgwrF1WUXea1O8DXuviAgkdbQ1iQMQotNgzJIBC9yUSn08u/acZrMUhgw7w6GpA=="],
"@libp2p/utils/@libp2p/crypto": ["@libp2p/crypto@5.1.12", "", { "dependencies": { "@libp2p/interface": "^3.0.2", "@noble/curves": "^2.0.1", "@noble/hashes": "^2.0.1", "multiformats": "^13.4.0", "protons-runtime": "^5.6.0", "uint8arraylist": "^2.4.8", "uint8arrays": "^5.1.0" } }, "sha512-1yJS0BZj+HF4M3Uv/92y3oIbMcCar218accFBcX+nKVhBlwDbx6fkUURhs5GilIhMgDtir+qQ8Un1hwF4CgGzw=="],
"@libp2p/utils/race-signal": ["race-signal@2.0.0", "", {}, "sha512-P31bLhE4ByBX/70QDXMutxnqgwrF1WUXea1O8DXuviAgkdbQ1iQMQotNgzJIBC9yUSn08u/acZrMUhgw7w6GpA=="],
"@libp2p/websockets/@multiformats/multiaddr-matcher": ["@multiformats/multiaddr-matcher@3.0.1", "", { "dependencies": { "@multiformats/multiaddr": "^13.0.0" } }, "sha512-jvjwzCPysVTQ53F4KqwmcqZw73BqHMk0UUZrMP9P4OtJ/YHrfs122ikTqhVA2upe0P/Qz9l8HVlhEifVYB2q9A=="],
"@libp2p/webtransport/@multiformats/multiaddr-matcher": ["@multiformats/multiaddr-matcher@3.0.1", "", { "dependencies": { "@multiformats/multiaddr": "^13.0.0" } }, "sha512-jvjwzCPysVTQ53F4KqwmcqZw73BqHMk0UUZrMP9P4OtJ/YHrfs122ikTqhVA2upe0P/Qz9l8HVlhEifVYB2q9A=="],
"@libp2p/webtransport/race-signal": ["race-signal@2.0.0", "", {}, "sha512-P31bLhE4ByBX/70QDXMutxnqgwrF1WUXea1O8DXuviAgkdbQ1iQMQotNgzJIBC9yUSn08u/acZrMUhgw7w6GpA=="],
"@macaron-css/babel/@emotion/hash": ["@emotion/hash@0.8.0", "", {}, "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow=="], "@macaron-css/babel/@emotion/hash": ["@emotion/hash@0.8.0", "", {}, "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow=="],
@@ -3560,10 +3525,6 @@
"@multiformats/dns/buffer": ["buffer@6.0.3", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.2.1" } }, "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA=="], "@multiformats/dns/buffer": ["buffer@6.0.3", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.2.1" } }, "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA=="],
"@multiformats/multiaddr/multiformats": ["multiformats@13.3.7", "", {}, "sha512-meL9DERHj+fFVWoOX9fXqfcYcSpUfSYJPcFvDPKrxitICbwAoWR+Ut4j5NO9zAT917HUHLQmqzQbAsGNHlDcxQ=="],
"@multiformats/multiaddr-matcher/@multiformats/multiaddr": ["@multiformats/multiaddr@12.5.1", "", { "dependencies": { "@chainsafe/is-ip": "^2.0.1", "@chainsafe/netmask": "^2.0.0", "@multiformats/dns": "^1.0.3", "abort-error": "^1.0.1", "multiformats": "^13.0.0", "uint8-varint": "^2.0.1", "uint8arrays": "^5.0.0" } }, "sha512-+DDlr9LIRUS8KncI1TX/FfUn8F2dl6BIxJgshS/yFQCNB5IAF0OGzcwB39g5NLE22s4qqDePv0Qof6HdpJ/4aQ=="],
"@neondatabase/serverless/@types/node": ["@types/node@22.18.6", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-r8uszLPpeIWbNKtvWRt/DbVi5zbqZyj1PTmhRMqBMvDnaz1QpmSKujUtJLrqGZeoM8v72MfYggDceY4K1itzWQ=="], "@neondatabase/serverless/@types/node": ["@types/node@22.18.6", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-r8uszLPpeIWbNKtvWRt/DbVi5zbqZyj1PTmhRMqBMvDnaz1QpmSKujUtJLrqGZeoM8v72MfYggDceY4K1itzWQ=="],
"@nestri/functions/@cloudflare/workers-types": ["@cloudflare/workers-types@4.20250522.0", "", {}, "sha512-9RIffHobc35JWeddzBguGgPa4wLDr5x5F94+0/qy7LiV6pTBQ/M5qGEN9VA16IDT3EUpYI0WKh6VpcmeVEtVtw=="], "@nestri/functions/@cloudflare/workers-types": ["@cloudflare/workers-types@4.20250522.0", "", {}, "sha512-9RIffHobc35JWeddzBguGgPa4wLDr5x5F94+0/qy7LiV6pTBQ/M5qGEN9VA16IDT3EUpYI0WKh6VpcmeVEtVtw=="],
@@ -3886,9 +3847,11 @@
"@rocicorp/zero/ws": ["ws@8.18.1", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w=="], "@rocicorp/zero/ws": ["ws@8.18.1", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w=="],
"@rollup/pluginutils/@types/estree": ["@types/estree@1.0.6", "", {}, "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw=="],
"@rollup/pluginutils/estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="], "@rollup/pluginutils/estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="],
"@rollup/pluginutils/picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="], "@rollup/pluginutils/picomatch": ["picomatch@4.0.2", "", {}, "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg=="],
"@smithy/eventstream-codec/@smithy/types": ["@smithy/types@4.3.1", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-UqKOQBL2x6+HWl3P+3QqFD4ncKq0I8Nuz9QItGv5WuKuMHuuwlhvqcZCoXGfc+P1QmfJE7VieykoYYmrOoFJxA=="], "@smithy/eventstream-codec/@smithy/types": ["@smithy/types@4.3.1", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-UqKOQBL2x6+HWl3P+3QqFD4ncKq0I8Nuz9QItGv5WuKuMHuuwlhvqcZCoXGfc+P1QmfJE7VieykoYYmrOoFJxA=="],
@@ -3906,7 +3869,7 @@
"@smithy/util-waiter/@smithy/types": ["@smithy/types@4.3.1", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-UqKOQBL2x6+HWl3P+3QqFD4ncKq0I8Nuz9QItGv5WuKuMHuuwlhvqcZCoXGfc+P1QmfJE7VieykoYYmrOoFJxA=="], "@smithy/util-waiter/@smithy/types": ["@smithy/types@4.3.1", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-UqKOQBL2x6+HWl3P+3QqFD4ncKq0I8Nuz9QItGv5WuKuMHuuwlhvqcZCoXGfc+P1QmfJE7VieykoYYmrOoFJxA=="],
"@types/bun/bun-types": ["bun-types@1.3.3", "", { "dependencies": { "@types/node": "*" } }, "sha512-z3Xwlg7j2l9JY27x5Qn3Wlyos8YAp0kKRlrePAOjgjMGS5IG6E7Jnlx736vH9UVI4wUICwwhC9anYL++XeOgTQ=="], "@types/bun/bun-types": ["bun-types@1.2.22", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-hwaAu8tct/Zn6Zft4U9BsZcXkYomzpHJX28ofvx7k0Zz2HNz54n1n+tDgxoWFGB4PcFvJXJQloPhaV2eP3Q6EA=="],
"@types/pg/@types/node": ["@types/node@22.18.6", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-r8uszLPpeIWbNKtvWRt/DbVi5zbqZyj1PTmhRMqBMvDnaz1QpmSKujUtJLrqGZeoM8v72MfYggDceY4K1itzWQ=="], "@types/pg/@types/node": ["@types/node@22.18.6", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-r8uszLPpeIWbNKtvWRt/DbVi5zbqZyj1PTmhRMqBMvDnaz1QpmSKujUtJLrqGZeoM8v72MfYggDceY4K1itzWQ=="],
@@ -3930,8 +3893,6 @@
"anymatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], "anymatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
"astro/debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
"astro/esbuild": ["esbuild@0.25.1", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.1", "@esbuild/android-arm": "0.25.1", "@esbuild/android-arm64": "0.25.1", "@esbuild/android-x64": "0.25.1", "@esbuild/darwin-arm64": "0.25.1", "@esbuild/darwin-x64": "0.25.1", "@esbuild/freebsd-arm64": "0.25.1", "@esbuild/freebsd-x64": "0.25.1", "@esbuild/linux-arm": "0.25.1", "@esbuild/linux-arm64": "0.25.1", "@esbuild/linux-ia32": "0.25.1", "@esbuild/linux-loong64": "0.25.1", "@esbuild/linux-mips64el": "0.25.1", "@esbuild/linux-ppc64": "0.25.1", "@esbuild/linux-riscv64": "0.25.1", "@esbuild/linux-s390x": "0.25.1", "@esbuild/linux-x64": "0.25.1", "@esbuild/netbsd-arm64": "0.25.1", "@esbuild/netbsd-x64": "0.25.1", "@esbuild/openbsd-arm64": "0.25.1", "@esbuild/openbsd-x64": "0.25.1", "@esbuild/sunos-x64": "0.25.1", "@esbuild/win32-arm64": "0.25.1", "@esbuild/win32-ia32": "0.25.1", "@esbuild/win32-x64": "0.25.1" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-BGO5LtrGC7vxnqucAe/rmvKdJllfGaYWdyABvyMoXQlfYMb2bbRuReWR5tEGE//4LcNJj9XrkovTqNYRFZHAMQ=="], "astro/esbuild": ["esbuild@0.25.1", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.1", "@esbuild/android-arm": "0.25.1", "@esbuild/android-arm64": "0.25.1", "@esbuild/android-x64": "0.25.1", "@esbuild/darwin-arm64": "0.25.1", "@esbuild/darwin-x64": "0.25.1", "@esbuild/freebsd-arm64": "0.25.1", "@esbuild/freebsd-x64": "0.25.1", "@esbuild/linux-arm": "0.25.1", "@esbuild/linux-arm64": "0.25.1", "@esbuild/linux-ia32": "0.25.1", "@esbuild/linux-loong64": "0.25.1", "@esbuild/linux-mips64el": "0.25.1", "@esbuild/linux-ppc64": "0.25.1", "@esbuild/linux-riscv64": "0.25.1", "@esbuild/linux-s390x": "0.25.1", "@esbuild/linux-x64": "0.25.1", "@esbuild/netbsd-arm64": "0.25.1", "@esbuild/netbsd-x64": "0.25.1", "@esbuild/openbsd-arm64": "0.25.1", "@esbuild/openbsd-x64": "0.25.1", "@esbuild/sunos-x64": "0.25.1", "@esbuild/win32-arm64": "0.25.1", "@esbuild/win32-ia32": "0.25.1", "@esbuild/win32-x64": "0.25.1" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-BGO5LtrGC7vxnqucAe/rmvKdJllfGaYWdyABvyMoXQlfYMb2bbRuReWR5tEGE//4LcNJj9XrkovTqNYRFZHAMQ=="],
"astro/js-yaml": ["js-yaml@4.1.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA=="], "astro/js-yaml": ["js-yaml@4.1.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA=="],
@@ -3940,9 +3901,9 @@
"astro/semver": ["semver@7.7.2", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="], "astro/semver": ["semver@7.7.2", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="],
"astro/vite": ["vite@6.4.0", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", "picomatch": "^4.0.2", "postcss": "^8.5.3", "rollup": "^4.34.9", "tinyglobby": "^0.2.13" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "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" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-oLnWs9Hak/LOlKjeSpOwD6JMks8BeICEdYMJBf6P4Lac/pO9tKiv/XhXnAM7nNfSkZahjlCZu9sS50zL8fSnsw=="], "astro/sharp": ["sharp@0.33.5", "", { "dependencies": { "color": "^4.2.3", "detect-libc": "^2.0.3", "semver": "^7.6.3" }, "optionalDependencies": { "@img/sharp-darwin-arm64": "0.33.5", "@img/sharp-darwin-x64": "0.33.5", "@img/sharp-libvips-darwin-arm64": "1.0.4", "@img/sharp-libvips-darwin-x64": "1.0.4", "@img/sharp-libvips-linux-arm": "1.0.5", "@img/sharp-libvips-linux-arm64": "1.0.4", "@img/sharp-libvips-linux-s390x": "1.0.4", "@img/sharp-libvips-linux-x64": "1.0.4", "@img/sharp-libvips-linuxmusl-arm64": "1.0.4", "@img/sharp-libvips-linuxmusl-x64": "1.0.4", "@img/sharp-linux-arm": "0.33.5", "@img/sharp-linux-arm64": "0.33.5", "@img/sharp-linux-s390x": "0.33.5", "@img/sharp-linux-x64": "0.33.5", "@img/sharp-linuxmusl-arm64": "0.33.5", "@img/sharp-linuxmusl-x64": "0.33.5", "@img/sharp-wasm32": "0.33.5", "@img/sharp-win32-ia32": "0.33.5", "@img/sharp-win32-x64": "0.33.5" } }, "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw=="],
"astro/vitefu": ["vitefu@1.1.1", "", { "peerDependencies": { "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0-beta.0" }, "optionalPeers": ["vite"] }, "sha512-B/Fegf3i8zh0yFbpzZ21amWzHmuNlLlmJT6n7bu5e+pCHUKQIfXSYokrqOBGEMMe9UG2sostKQF9mml/vYaWJQ=="], "astro/vite": ["vite@6.3.5", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", "picomatch": "^4.0.2", "postcss": "^8.5.3", "rollup": "^4.34.9", "tinyglobby": "^0.2.13" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "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" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ=="],
"aws-crt/buffer": ["buffer@6.0.3", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.2.1" } }, "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA=="], "aws-crt/buffer": ["buffer@6.0.3", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.2.1" } }, "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA=="],
@@ -3970,8 +3931,6 @@
"cacheable-request/get-stream": ["get-stream@5.2.0", "", { "dependencies": { "pump": "^3.0.0" } }, "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA=="], "cacheable-request/get-stream": ["get-stream@5.2.0", "", { "dependencies": { "pump": "^3.0.0" } }, "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA=="],
"cacheable-request/http-cache-semantics": ["http-cache-semantics@4.1.1", "", {}, "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ=="],
"cheerio/entities": ["entities@1.1.2", "", {}, "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w=="], "cheerio/entities": ["entities@1.1.2", "", {}, "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w=="],
"cheerio/htmlparser2": ["htmlparser2@3.10.1", "", { "dependencies": { "domelementtype": "^1.3.1", "domhandler": "^2.3.0", "domutils": "^1.5.1", "entities": "^1.1.1", "inherits": "^2.0.1", "readable-stream": "^3.1.1" } }, "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ=="], "cheerio/htmlparser2": ["htmlparser2@3.10.1", "", { "dependencies": { "domelementtype": "^1.3.1", "domhandler": "^2.3.0", "domutils": "^1.5.1", "entities": "^1.1.1", "inherits": "^2.0.1", "readable-stream": "^3.1.1" } }, "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ=="],
@@ -4002,12 +3961,6 @@
"ecc-jsbn/jsbn": ["jsbn@0.1.1", "", {}, "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg=="], "ecc-jsbn/jsbn": ["jsbn@0.1.1", "", {}, "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg=="],
"eciesjs/@noble/ciphers": ["@noble/ciphers@1.3.0", "", {}, "sha512-2I0gnIVPtfnMw9ee9h1dJG7tp81+8Ob3OJb3Mv37rx5L40/b0i7djjCVvGOVqc9AEIQyvyu1i6ypKdFw8R8gQw=="],
"eciesjs/@noble/curves": ["@noble/curves@1.9.0", "", { "dependencies": { "@noble/hashes": "1.8.0" } }, "sha512-7YDlXiNMdO1YZeH6t/kvopHHbIZzlxrCV9WLqCY6QhcXOoXiNCMDqJIglZ9Yjx5+w7Dz30TITFrlTjnRg7sKEg=="],
"eciesjs/@noble/hashes": ["@noble/hashes@1.8.0", "", {}, "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A=="],
"effect/@standard-schema/spec": ["@standard-schema/spec@1.0.0", "", {}, "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA=="], "effect/@standard-schema/spec": ["@standard-schema/spec@1.0.0", "", {}, "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA=="],
"estree-walker/@types/estree": ["@types/estree@1.0.6", "", {}, "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw=="], "estree-walker/@types/estree": ["@types/estree@1.0.6", "", {}, "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw=="],
@@ -4044,15 +3997,7 @@
"ip-address/sprintf-js": ["sprintf-js@1.1.3", "", {}, "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA=="], "ip-address/sprintf-js": ["sprintf-js@1.1.3", "", {}, "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA=="],
"libp2p/@libp2p/crypto": ["@libp2p/crypto@5.1.12", "", { "dependencies": { "@libp2p/interface": "^3.0.2", "@noble/curves": "^2.0.1", "@noble/hashes": "^2.0.1", "multiformats": "^13.4.0", "protons-runtime": "^5.6.0", "uint8arraylist": "^2.4.8", "uint8arrays": "^5.1.0" } }, "sha512-1yJS0BZj+HF4M3Uv/92y3oIbMcCar218accFBcX+nKVhBlwDbx6fkUURhs5GilIhMgDtir+qQ8Un1hwF4CgGzw=="], "it-ws/@types/ws": ["@types/ws@8.18.1", "", { "dependencies": { "@types/node": "*" } }, "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg=="],
"libp2p/@multiformats/multiaddr-matcher": ["@multiformats/multiaddr-matcher@3.0.1", "", { "dependencies": { "@multiformats/multiaddr": "^13.0.0" } }, "sha512-jvjwzCPysVTQ53F4KqwmcqZw73BqHMk0UUZrMP9P4OtJ/YHrfs122ikTqhVA2upe0P/Qz9l8HVlhEifVYB2q9A=="],
"libp2p/p-retry": ["p-retry@7.1.0", "", { "dependencies": { "is-network-error": "^1.1.0" } }, "sha512-xL4PiFRQa/f9L9ZvR4/gUCRNus4N8YX80ku8kv9Jqz+ZokkiZLM0bcvX0gm1F3PDi9SPRsww1BDsTWgE6Y1GLQ=="],
"libp2p/race-signal": ["race-signal@2.0.0", "", {}, "sha512-P31bLhE4ByBX/70QDXMutxnqgwrF1WUXea1O8DXuviAgkdbQ1iQMQotNgzJIBC9yUSn08u/acZrMUhgw7w6GpA=="],
"make-fetch-happen/http-cache-semantics": ["http-cache-semantics@4.1.1", "", {}, "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ=="],
"markdown-it/argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], "markdown-it/argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="],
@@ -4102,6 +4047,8 @@
"promise-retry/retry": ["retry@0.12.0", "", {}, "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow=="], "promise-retry/retry": ["retry@0.12.0", "", {}, "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow=="],
"prompts/kleur": ["kleur@3.0.3", "", {}, "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w=="],
"proxy-addr/ipaddr.js": ["ipaddr.js@1.9.1", "", {}, "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="], "proxy-addr/ipaddr.js": ["ipaddr.js@1.9.1", "", {}, "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="],
"psl/punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="], "psl/punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="],
@@ -4162,8 +4109,6 @@
"typedoc/yaml": ["yaml@2.7.1", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-10ULxpnOCQXxJvBgxsn9ptjq6uviG/htZKk9veJGhlqn3w/DxQ631zFF+nlQXLwmImeS5amR2dl2U8sg6U9jsQ=="], "typedoc/yaml": ["yaml@2.7.1", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-10ULxpnOCQXxJvBgxsn9ptjq6uviG/htZKk9veJGhlqn3w/DxQ631zFF+nlQXLwmImeS5amR2dl2U8sg6U9jsQ=="],
"uint8arrays/multiformats": ["multiformats@13.3.7", "", {}, "sha512-meL9DERHj+fFVWoOX9fXqfcYcSpUfSYJPcFvDPKrxitICbwAoWR+Ut4j5NO9zAT917HUHLQmqzQbAsGNHlDcxQ=="],
"unified/vfile": ["vfile@6.0.2", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-stringify-position": "^4.0.0", "vfile-message": "^4.0.0" } }, "sha512-zND7NlS8rJYb/sPqkb13ZvbbUoExdbi4w3SfRrMq6R3FvnLQmmfpajJNITuuYm6AZ5uao9vy4BAos3EXBPf2rg=="], "unified/vfile": ["vfile@6.0.2", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-stringify-position": "^4.0.0", "vfile-message": "^4.0.0" } }, "sha512-zND7NlS8rJYb/sPqkb13ZvbbUoExdbi4w3SfRrMq6R3FvnLQmmfpajJNITuuYm6AZ5uao9vy4BAos3EXBPf2rg=="],
"unstorage/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], "unstorage/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="],
@@ -4450,12 +4395,6 @@
"@babel/helper-compilation-targets/lru-cache/yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="], "@babel/helper-compilation-targets/lru-cache/yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="],
"@chainsafe/libp2p-quic/@libp2p/interface/multiformats": ["multiformats@13.3.7", "", {}, "sha512-meL9DERHj+fFVWoOX9fXqfcYcSpUfSYJPcFvDPKrxitICbwAoWR+Ut4j5NO9zAT917HUHLQmqzQbAsGNHlDcxQ=="],
"@chainsafe/libp2p-quic/@libp2p/utils/@libp2p/logger": ["@libp2p/logger@5.2.0", "", { "dependencies": { "@libp2p/interface": "^2.11.0", "@multiformats/multiaddr": "^12.4.4", "interface-datastore": "^8.3.1", "multiformats": "^13.3.6", "weald": "^1.0.4" } }, "sha512-OEFS529CnIKfbWEHmuCNESw9q0D0hL8cQ8klQfjIVPur15RcgAEgc1buQ7Y6l0B6tCYg120bp55+e9tGvn8c0g=="],
"@chainsafe/libp2p-quic/@multiformats/multiaddr/multiformats": ["multiformats@13.3.7", "", {}, "sha512-meL9DERHj+fFVWoOX9fXqfcYcSpUfSYJPcFvDPKrxitICbwAoWR+Ut4j5NO9zAT917HUHLQmqzQbAsGNHlDcxQ=="],
"@esbuild-kit/core-utils/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.18.20", "", { "os": "android", "cpu": "arm" }, "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw=="], "@esbuild-kit/core-utils/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.18.20", "", { "os": "android", "cpu": "arm" }, "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw=="],
"@esbuild-kit/core-utils/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.18.20", "", { "os": "android", "cpu": "arm64" }, "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ=="], "@esbuild-kit/core-utils/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.18.20", "", { "os": "android", "cpu": "arm64" }, "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ=="],
@@ -4520,8 +4459,6 @@
"@multiformats/dns/buffer/ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="], "@multiformats/dns/buffer/ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="],
"@multiformats/multiaddr-matcher/@multiformats/multiaddr/multiformats": ["multiformats@13.3.7", "", {}, "sha512-meL9DERHj+fFVWoOX9fXqfcYcSpUfSYJPcFvDPKrxitICbwAoWR+Ut4j5NO9zAT917HUHLQmqzQbAsGNHlDcxQ=="],
"@neondatabase/serverless/@types/node/undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="], "@neondatabase/serverless/@types/node/undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="],
"@nestri/functions/@openauthjs/openauth/jose": ["jose@5.9.6", "", {}, "sha512-AMlnetc9+CV9asI19zHmrgS/WYsWUwCn2R7RzlbJWD7F9eWYUTGyBmU9o6PxngtLGOiDGPRu+Uc4fhKzbpteZQ=="], "@nestri/functions/@openauthjs/openauth/jose": ["jose@5.9.6", "", {}, "sha512-AMlnetc9+CV9asI19zHmrgS/WYsWUwCn2R7RzlbJWD7F9eWYUTGyBmU9o6PxngtLGOiDGPRu+Uc4fhKzbpteZQ=="],
@@ -4616,8 +4553,6 @@
"@rocicorp/zero/@opentelemetry/sdk-trace-node/@opentelemetry/sdk-trace-base": ["@opentelemetry/sdk-trace-base@2.0.0", "", { "dependencies": { "@opentelemetry/core": "2.0.0", "@opentelemetry/resources": "2.0.0", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-qQnYdX+ZCkonM7tA5iU4fSRsVxbFGml8jbxOgipRGMFHKaXKHQ30js03rTobYjKjIfnOsZSbHKWF0/0v0OQGfw=="], "@rocicorp/zero/@opentelemetry/sdk-trace-node/@opentelemetry/sdk-trace-base": ["@opentelemetry/sdk-trace-base@2.0.0", "", { "dependencies": { "@opentelemetry/core": "2.0.0", "@opentelemetry/resources": "2.0.0", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-qQnYdX+ZCkonM7tA5iU4fSRsVxbFGml8jbxOgipRGMFHKaXKHQ30js03rTobYjKjIfnOsZSbHKWF0/0v0OQGfw=="],
"@types/bun/bun-types/@types/node": ["@types/node@22.18.6", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-r8uszLPpeIWbNKtvWRt/DbVi5zbqZyj1PTmhRMqBMvDnaz1QpmSKujUtJLrqGZeoM8v72MfYggDceY4K1itzWQ=="],
"@types/pg/@types/node/undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="], "@types/pg/@types/node/undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="],
"@vanilla-extract/integration/find-up/locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="], "@vanilla-extract/integration/find-up/locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="],
@@ -4686,6 +4621,46 @@
"astro/js-yaml/argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], "astro/js-yaml/argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="],
"astro/sharp/@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.0.4" }, "os": "darwin", "cpu": "arm64" }, "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ=="],
"astro/sharp/@img/sharp-darwin-x64": ["@img/sharp-darwin-x64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-x64": "1.0.4" }, "os": "darwin", "cpu": "x64" }, "sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q=="],
"astro/sharp/@img/sharp-libvips-darwin-arm64": ["@img/sharp-libvips-darwin-arm64@1.0.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg=="],
"astro/sharp/@img/sharp-libvips-darwin-x64": ["@img/sharp-libvips-darwin-x64@1.0.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ=="],
"astro/sharp/@img/sharp-libvips-linux-arm": ["@img/sharp-libvips-linux-arm@1.0.5", "", { "os": "linux", "cpu": "arm" }, "sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g=="],
"astro/sharp/@img/sharp-libvips-linux-arm64": ["@img/sharp-libvips-linux-arm64@1.0.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA=="],
"astro/sharp/@img/sharp-libvips-linux-s390x": ["@img/sharp-libvips-linux-s390x@1.0.4", "", { "os": "linux", "cpu": "s390x" }, "sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA=="],
"astro/sharp/@img/sharp-libvips-linux-x64": ["@img/sharp-libvips-linux-x64@1.0.4", "", { "os": "linux", "cpu": "x64" }, "sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw=="],
"astro/sharp/@img/sharp-libvips-linuxmusl-arm64": ["@img/sharp-libvips-linuxmusl-arm64@1.0.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA=="],
"astro/sharp/@img/sharp-libvips-linuxmusl-x64": ["@img/sharp-libvips-linuxmusl-x64@1.0.4", "", { "os": "linux", "cpu": "x64" }, "sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw=="],
"astro/sharp/@img/sharp-linux-arm": ["@img/sharp-linux-arm@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm": "1.0.5" }, "os": "linux", "cpu": "arm" }, "sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ=="],
"astro/sharp/@img/sharp-linux-arm64": ["@img/sharp-linux-arm64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm64": "1.0.4" }, "os": "linux", "cpu": "arm64" }, "sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA=="],
"astro/sharp/@img/sharp-linux-s390x": ["@img/sharp-linux-s390x@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-s390x": "1.0.4" }, "os": "linux", "cpu": "s390x" }, "sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q=="],
"astro/sharp/@img/sharp-linux-x64": ["@img/sharp-linux-x64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-x64": "1.0.4" }, "os": "linux", "cpu": "x64" }, "sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA=="],
"astro/sharp/@img/sharp-linuxmusl-arm64": ["@img/sharp-linuxmusl-arm64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-arm64": "1.0.4" }, "os": "linux", "cpu": "arm64" }, "sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g=="],
"astro/sharp/@img/sharp-linuxmusl-x64": ["@img/sharp-linuxmusl-x64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-x64": "1.0.4" }, "os": "linux", "cpu": "x64" }, "sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw=="],
"astro/sharp/@img/sharp-wasm32": ["@img/sharp-wasm32@0.33.5", "", { "dependencies": { "@emnapi/runtime": "^1.2.0" }, "cpu": "none" }, "sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg=="],
"astro/sharp/@img/sharp-win32-ia32": ["@img/sharp-win32-ia32@0.33.5", "", { "os": "win32", "cpu": "ia32" }, "sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ=="],
"astro/sharp/@img/sharp-win32-x64": ["@img/sharp-win32-x64@0.33.5", "", { "os": "win32", "cpu": "x64" }, "sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg=="],
"astro/sharp/semver": ["semver@7.7.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA=="],
"astro/vite/fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="], "astro/vite/fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="],
"aws-crt/buffer/ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="], "aws-crt/buffer/ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="],
@@ -4938,20 +4913,12 @@
"@aws-sdk/signature-v4-multi-region/@aws-sdk/middleware-sdk-s3/@smithy/util-stream/@smithy/node-http-handler": ["@smithy/node-http-handler@4.0.3", "", { "dependencies": { "@smithy/abort-controller": "^4.0.1", "@smithy/protocol-http": "^5.0.1", "@smithy/querystring-builder": "^4.0.1", "@smithy/types": "^4.1.0", "tslib": "^2.6.2" } }, "sha512-dYCLeINNbYdvmMLtW0VdhW1biXt+PPCGazzT5ZjKw46mOtdgToQEwjqZSS9/EN8+tNs/RO0cEWG044+YZs97aA=="], "@aws-sdk/signature-v4-multi-region/@aws-sdk/middleware-sdk-s3/@smithy/util-stream/@smithy/node-http-handler": ["@smithy/node-http-handler@4.0.3", "", { "dependencies": { "@smithy/abort-controller": "^4.0.1", "@smithy/protocol-http": "^5.0.1", "@smithy/querystring-builder": "^4.0.1", "@smithy/types": "^4.1.0", "tslib": "^2.6.2" } }, "sha512-dYCLeINNbYdvmMLtW0VdhW1biXt+PPCGazzT5ZjKw46mOtdgToQEwjqZSS9/EN8+tNs/RO0cEWG044+YZs97aA=="],
"@chainsafe/libp2p-quic/@libp2p/utils/@libp2p/logger/interface-datastore": ["interface-datastore@8.3.2", "", { "dependencies": { "interface-store": "^6.0.0", "uint8arrays": "^5.1.0" } }, "sha512-R3NLts7pRbJKc3qFdQf+u40hK8XWc0w4Qkx3OFEstC80VoaDUABY/dXA2EJPhtNC+bsrf41Ehvqb6+pnIclyRA=="],
"@chainsafe/libp2p-quic/@libp2p/utils/@libp2p/logger/multiformats": ["multiformats@13.3.7", "", {}, "sha512-meL9DERHj+fFVWoOX9fXqfcYcSpUfSYJPcFvDPKrxitICbwAoWR+Ut4j5NO9zAT917HUHLQmqzQbAsGNHlDcxQ=="],
"@chainsafe/libp2p-quic/@libp2p/utils/@libp2p/logger/weald": ["weald@1.0.4", "", { "dependencies": { "ms": "^3.0.0-canary.1", "supports-color": "^9.4.0" } }, "sha512-+kYTuHonJBwmFhP1Z4YQK/dGi3jAnJGCYhyODFpHK73rbxnp9lnZQj7a2m+WVgn8fXr5bJaxUpF6l8qZpPeNWQ=="],
"@grpc/proto-loader/yargs/cliui/wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="], "@grpc/proto-loader/yargs/cliui/wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="],
"@rocicorp/zero/@opentelemetry/sdk-trace-node/@opentelemetry/core/@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.33.0", "", {}, "sha512-TIpZvE8fiEILFfTlfPnltpBaD3d9/+uQHVCyC3vfdh6WfCXKhNFzoP5RyDDIndfvZC5GrA4pyEDNyjPloJud+w=="], "@rocicorp/zero/@opentelemetry/sdk-trace-node/@opentelemetry/core/@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.33.0", "", {}, "sha512-TIpZvE8fiEILFfTlfPnltpBaD3d9/+uQHVCyC3vfdh6WfCXKhNFzoP5RyDDIndfvZC5GrA4pyEDNyjPloJud+w=="],
"@rocicorp/zero/@opentelemetry/sdk-trace-node/@opentelemetry/sdk-trace-base/@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.33.0", "", {}, "sha512-TIpZvE8fiEILFfTlfPnltpBaD3d9/+uQHVCyC3vfdh6WfCXKhNFzoP5RyDDIndfvZC5GrA4pyEDNyjPloJud+w=="], "@rocicorp/zero/@opentelemetry/sdk-trace-node/@opentelemetry/sdk-trace-base/@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.33.0", "", {}, "sha512-TIpZvE8fiEILFfTlfPnltpBaD3d9/+uQHVCyC3vfdh6WfCXKhNFzoP5RyDDIndfvZC5GrA4pyEDNyjPloJud+w=="],
"@types/bun/bun-types/@types/node/undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="],
"@vanilla-extract/integration/find-up/locate-path/p-locate": ["p-locate@5.0.0", "", { "dependencies": { "p-limit": "^3.0.2" } }, "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw=="], "@vanilla-extract/integration/find-up/locate-path/p-locate": ["p-locate@5.0.0", "", { "dependencies": { "p-limit": "^3.0.2" } }, "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw=="],
"@vanilla-extract/integration/vite/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.21.5", "", { "os": "aix", "cpu": "ppc64" }, "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ=="], "@vanilla-extract/integration/vite/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.21.5", "", { "os": "aix", "cpu": "ppc64" }, "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ=="],
@@ -5086,6 +5053,8 @@
"@vanilla-extract/vite-plugin/vite/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.21.5", "", { "os": "win32", "cpu": "x64" }, "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw=="], "@vanilla-extract/vite-plugin/vite/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.21.5", "", { "os": "win32", "cpu": "x64" }, "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw=="],
"astro/sharp/@img/sharp-wasm32/@emnapi/runtime": ["@emnapi/runtime@1.3.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-kEBmG8KyqtxJZv+ygbEim+KCGtIq1fC22Ms3S4ziXmYKm8uyoLX0MHONVKwp+9opg390VaKRNt4a7A9NwmpNhw=="],
"aws-crt/mqtt/help-me/glob": ["glob@7.2.3", "", { "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" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="], "aws-crt/mqtt/help-me/glob": ["glob@7.2.3", "", { "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" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="],
"aws-crt/mqtt/mqtt-packet/bl": ["bl@4.1.0", "", { "dependencies": { "buffer": "^5.5.0", "inherits": "^2.0.4", "readable-stream": "^3.4.0" } }, "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w=="], "aws-crt/mqtt/mqtt-packet/bl": ["bl@4.1.0", "", { "dependencies": { "buffer": "^5.5.0", "inherits": "^2.0.4", "readable-stream": "^3.4.0" } }, "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w=="],
@@ -5210,12 +5179,6 @@
"@aws-sdk/signature-v4-multi-region/@aws-sdk/middleware-sdk-s3/@smithy/util-stream/@smithy/node-http-handler/@smithy/querystring-builder": ["@smithy/querystring-builder@4.0.1", "", { "dependencies": { "@smithy/types": "^4.1.0", "@smithy/util-uri-escape": "^4.0.0", "tslib": "^2.6.2" } }, "sha512-wU87iWZoCbcqrwszsOewEIuq+SU2mSoBE2CcsLwE0I19m0B2gOJr1MVjxWcDQYOzHbR1xCk7AcOBbGFUYOKvdg=="], "@aws-sdk/signature-v4-multi-region/@aws-sdk/middleware-sdk-s3/@smithy/util-stream/@smithy/node-http-handler/@smithy/querystring-builder": ["@smithy/querystring-builder@4.0.1", "", { "dependencies": { "@smithy/types": "^4.1.0", "@smithy/util-uri-escape": "^4.0.0", "tslib": "^2.6.2" } }, "sha512-wU87iWZoCbcqrwszsOewEIuq+SU2mSoBE2CcsLwE0I19m0B2gOJr1MVjxWcDQYOzHbR1xCk7AcOBbGFUYOKvdg=="],
"@chainsafe/libp2p-quic/@libp2p/utils/@libp2p/logger/interface-datastore/interface-store": ["interface-store@6.0.3", "", {}, "sha512-+WvfEZnFUhRwFxgz+QCQi7UC6o9AM0EHM9bpIe2Nhqb100NHCsTvNAn4eJgvgV2/tmLo1MP9nGxQKEcZTAueLA=="],
"@chainsafe/libp2p-quic/@libp2p/utils/@libp2p/logger/weald/ms": ["ms@3.0.0-canary.1", "", {}, "sha512-kh8ARjh8rMN7Du2igDRO9QJnqCb2xYTJxyQYK7vJJS4TvLLmsbyhiKpSW+t+y26gyOyMd0riphX0GeWKU3ky5g=="],
"@chainsafe/libp2p-quic/@libp2p/utils/@libp2p/logger/weald/supports-color": ["supports-color@9.4.0", "", {}, "sha512-VL+lNrEoIXww1coLPOmiEmK/0sGigko5COxI09KzHc2VJXJsQ37UaQ+8quuxjDeA7+KnLGTWRyOXSLLR2Wb4jw=="],
"@grpc/proto-loader/yargs/cliui/wrap-ansi/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], "@grpc/proto-loader/yargs/cliui/wrap-ansi/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
"@vanilla-extract/integration/find-up/locate-path/p-locate/p-limit": ["p-limit@3.1.0", "", { "dependencies": { "yocto-queue": "^0.1.0" } }, "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ=="], "@vanilla-extract/integration/find-up/locate-path/p-locate/p-limit": ["p-limit@3.1.0", "", { "dependencies": { "yocto-queue": "^0.1.0" } }, "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ=="],

View File

@@ -1,23 +0,0 @@
# Container build arguments #
ARG RUNNER_COMMON_IMAGE=runner-common:latest
#*********************#
# Final Runtime Stage #
#*********************#
FROM ${RUNNER_COMMON_IMAGE}
### FLAVOR/VARIANT CONFIGURATION ###
## HEROIC LAUNCHER ##
RUN --mount=type=cache,target=/var/cache/pacman/pkg \
pacman -S --noconfirm heroic-games-launcher-bin && \
# Cleanup
paccache -rk1 && \
rm -rf /usr/share/{info,man,doc}/*
## FLAVOR/VARIANT LAUNCH COMMAND ##
ENV NESTRI_LAUNCH_CMD="heroic"
### END OF FLAVOR/VARIANT CONFIGURATION ###
### REQUIRED DEFAULT ENTRYPOINT FOR FLAVOR/VARIANT ###
USER root
ENTRYPOINT ["supervisord", "-c", "/etc/nestri/supervisord.conf"]

View File

@@ -1,24 +0,0 @@
# Container build arguments #
ARG RUNNER_COMMON_IMAGE=runner-common:latest
#*********************#
# Final Runtime Stage #
#*********************#
FROM ${RUNNER_COMMON_IMAGE}
### FLAVOR/VARIANT CONFIGURATION ###
## MINECRAFT ##
RUN --mount=type=cache,target=/var/cache/pacman/pkg \
pacman -S --noconfirm paru && \
sudo -H -u ${NESTRI_USER} paru -S --noconfirm aur/minecraft-launcher && \
# Cleanup
paccache -rk1 && \
rm -rf /usr/share/{info,man,doc}/*
## FLAVOR/VARIANT LAUNCH COMMAND ##
ENV NESTRI_LAUNCH_CMD="minecraft-launcher"
### END OF FLAVOR/VARIANT CONFIGURATION ###
### REQUIRED DEFAULT ENTRYPOINT FOR FLAVOR/VARIANT ###
USER root
ENTRYPOINT ["supervisord", "-c", "/etc/nestri/supervisord.conf"]

View File

@@ -15,7 +15,7 @@ ENV CARGO_HOME=/usr/local/cargo \
# Install build essentials and caching tools # Install build essentials and caching tools
RUN --mount=type=cache,target=/var/cache/pacman/pkg \ RUN --mount=type=cache,target=/var/cache/pacman/pkg \
pacman -S --noconfirm rustup git base-devel mold \ pacman -Sy --noconfirm rustup git base-devel mold \
meson pkgconf cmake git gcc make meson pkgconf cmake git gcc make
# Override various linker with symlink so mold is forcefully used (ld, ld.lld, lld) # Override various linker with symlink so mold is forcefully used (ld, ld.lld, lld)
@@ -28,7 +28,7 @@ RUN rustup default stable
# Install cargo-chef with proper caching # Install cargo-chef with proper caching
RUN --mount=type=cache,target=${CARGO_HOME}/registry \ RUN --mount=type=cache,target=${CARGO_HOME}/registry \
cargo install cargo-chef --locked cargo install -j $(nproc) cargo-chef --locked
#*******************************# #*******************************#
# vimputti manager build stages # # vimputti manager build stages #
@@ -38,10 +38,10 @@ WORKDIR /builder
# Install build dependencies # Install build dependencies
RUN --mount=type=cache,target=/var/cache/pacman/pkg \ RUN --mount=type=cache,target=/var/cache/pacman/pkg \
pacman -S --noconfirm lib32-gcc-libs pacman -Sy --noconfirm lib32-gcc-libs
# Clone repository # Clone repository
RUN git clone --depth 1 --rev "2fde5376b6b9a38cdbd94ccc6a80c9d29a81a417" https://github.com/DatCaptainHorse/vimputti.git RUN git clone --depth 1 --rev "f2f21561ddcb814d74455311969d3e8934b052c6" https://github.com/DatCaptainHorse/vimputti.git
#-------------------------------------------------------------------- #--------------------------------------------------------------------
FROM vimputti-manager-deps AS vimputti-manager-planner FROM vimputti-manager-deps AS vimputti-manager-planner
@@ -83,7 +83,7 @@ WORKDIR /builder
# Install build dependencies # Install build dependencies
RUN --mount=type=cache,target=/var/cache/pacman/pkg \ RUN --mount=type=cache,target=/var/cache/pacman/pkg \
pacman -S --noconfirm gst-plugins-good gst-plugin-rswebrtc pacman -Sy --noconfirm gst-plugins-good gst-plugin-rswebrtc
#-------------------------------------------------------------------- #--------------------------------------------------------------------
FROM nestri-server-deps AS nestri-server-planner FROM nestri-server-deps AS nestri-server-planner
@@ -123,14 +123,14 @@ WORKDIR /builder
# Install build dependencies # Install build dependencies
RUN --mount=type=cache,target=/var/cache/pacman/pkg \ RUN --mount=type=cache,target=/var/cache/pacman/pkg \
pacman -S --noconfirm libxkbcommon wayland \ pacman -Sy --noconfirm libxkbcommon wayland \
gst-plugins-good gst-plugins-bad libinput gst-plugins-good gst-plugins-bad libinput
RUN --mount=type=cache,target=${CARGO_HOME}/registry \ RUN --mount=type=cache,target=${CARGO_HOME}/registry \
cargo install cargo-c cargo install cargo-c
# Clone repository # Clone repository
RUN git clone --depth 1 --rev "67b1183997fd7aaf57398e4b01bd64c4d2433c45" https://github.com/games-on-whales/gst-wayland-display.git RUN git clone --depth 1 --rev "a4abcfe2cffe2d33b564d1308b58504a5e3012b1" https://github.com/games-on-whales/gst-wayland-display.git
#-------------------------------------------------------------------- #--------------------------------------------------------------------
FROM gst-wayland-deps AS gst-wayland-planner FROM gst-wayland-deps AS gst-wayland-planner
@@ -148,7 +148,7 @@ COPY --from=gst-wayland-planner /builder/gst-wayland-display/recipe.json .
# Cache dependencies using cargo-chef # Cache dependencies using cargo-chef
RUN --mount=type=cache,target=${CARGO_HOME}/registry \ RUN --mount=type=cache,target=${CARGO_HOME}/registry \
cargo chef cook --release --recipe-path recipe.json --features cuda cargo chef cook --release --recipe-path recipe.json
ENV CARGO_TARGET_DIR=/builder/target ENV CARGO_TARGET_DIR=/builder/target
@@ -158,7 +158,7 @@ COPY --from=gst-wayland-planner /builder/gst-wayland-display/ .
# Build and install directly to artifacts # Build and install directly to artifacts
RUN --mount=type=cache,target=${CARGO_HOME}/registry \ RUN --mount=type=cache,target=${CARGO_HOME}/registry \
--mount=type=cache,target=/builder/target \ --mount=type=cache,target=/builder/target \
cargo cinstall --prefix=${ARTIFACTS} --release --features cuda cargo cinstall --prefix=${ARTIFACTS} --release
#*********************************# #*********************************#
# Patched bubblewrap build stages # # Patched bubblewrap build stages #
@@ -168,7 +168,7 @@ WORKDIR /builder
# Install build dependencies # Install build dependencies
RUN --mount=type=cache,target=/var/cache/pacman/pkg \ RUN --mount=type=cache,target=/var/cache/pacman/pkg \
pacman -S --noconfirm libtool libcap libselinux pacman -Sy --noconfirm libtool libcap libselinux
# Copy patch file from host # Copy patch file from host
COPY packages/patches/bubblewrap/ /builder/patches/ COPY packages/patches/bubblewrap/ /builder/patches/

View File

@@ -2,9 +2,9 @@
ARG RUNNER_BASE_IMAGE=runner-base:latest ARG RUNNER_BASE_IMAGE=runner-base:latest
ARG RUNNER_BUILDER_IMAGE=runner-builder:latest ARG RUNNER_BUILDER_IMAGE=runner-builder:latest
#**********************# #*********************#
# Runtime Common Stage # # Final Runtime Stage #
#**********************# #*********************#
FROM ${RUNNER_BASE_IMAGE} AS runtime FROM ${RUNNER_BASE_IMAGE} AS runtime
FROM ${RUNNER_BUILDER_IMAGE} AS builder FROM ${RUNNER_BUILDER_IMAGE} AS builder
FROM runtime FROM runtime
@@ -12,11 +12,11 @@ FROM runtime
### Package Installation ### ### Package Installation ###
# Core system components # Core system components
RUN --mount=type=cache,target=/var/cache/pacman/pkg \ RUN --mount=type=cache,target=/var/cache/pacman/pkg \
pacman -S --needed --noconfirm \ pacman -Sy --needed --noconfirm \
vulkan-intel lib32-vulkan-intel vpl-gpu-rt \ vulkan-intel lib32-vulkan-intel vpl-gpu-rt \
vulkan-radeon lib32-vulkan-radeon \ vulkan-radeon lib32-vulkan-radeon \
mesa lib32-mesa vulkan-mesa-layers lib32-vulkan-mesa-layers \ mesa lib32-mesa \
gtk3 lib32-gtk3 \ steam gtk3 lib32-gtk3 \
sudo xorg-xwayland seatd libinput gamescope mangohud wlr-randr \ sudo xorg-xwayland seatd libinput gamescope mangohud wlr-randr \
pipewire pipewire-pulse pipewire-alsa wireplumber \ pipewire pipewire-pulse pipewire-alsa wireplumber \
noto-fonts-cjk supervisor jq pacman-contrib \ noto-fonts-cjk supervisor jq pacman-contrib \
@@ -67,8 +67,10 @@ RUN mkdir -p /etc/pipewire/pipewire.conf.d && \
COPY packages/configs/wireplumber.conf.d/* /etc/wireplumber/wireplumber.conf.d/ COPY packages/configs/wireplumber.conf.d/* /etc/wireplumber/wireplumber.conf.d/
COPY packages/configs/pipewire.conf.d/* /etc/pipewire/pipewire.conf.d/ COPY packages/configs/pipewire.conf.d/* /etc/pipewire/pipewire.conf.d/
## MangoHud Config ## ## Steam Configs - Proton (Experimental flavor) ##
COPY packages/configs/MangoHud/MangoHud.conf /etc/nestri/configs/MangoHud/ RUN mkdir -p "${NESTRI_HOME}/.local/share/Steam/config"
COPY packages/configs/steam/config.vdf "${NESTRI_HOME}/.local/share/Steam/config/"
### Artifacts from Builder ### ### Artifacts from Builder ###
COPY --from=builder /artifacts/bin/nestri-server /usr/bin/ COPY --from=builder /artifacts/bin/nestri-server /usr/bin/
@@ -86,3 +88,7 @@ RUN chmod +x /etc/nestri/{envs.sh,entrypoint*.sh} && \
setcap cap_net_admin+ep /usr/bin/vimputti-manager && \ setcap cap_net_admin+ep /usr/bin/vimputti-manager && \
dbus-uuidgen > /etc/machine-id && \ dbus-uuidgen > /etc/machine-id && \
LANG=en_US.UTF-8 locale-gen LANG=en_US.UTF-8 locale-gen
# Root for most container engines, nestri-user compatible for apptainer without fakeroot
USER root
ENTRYPOINT ["supervisord", "-c", "/etc/nestri/supervisord.conf"]

View File

@@ -1,27 +0,0 @@
# Container build arguments #
ARG RUNNER_COMMON_IMAGE=runner-common:latest
#*********************#
# Final Runtime Stage #
#*********************#
FROM ${RUNNER_COMMON_IMAGE}
### FLAVOR/VARIANT CONFIGURATION ###
## STEAM ##
RUN --mount=type=cache,target=/var/cache/pacman/pkg \
pacman -S --noconfirm steam && \
# Cleanup
paccache -rk1 && \
rm -rf /usr/share/{info,man,doc}/*
## Steam Configs - Proton (Experimental flavor) ##
RUN mkdir -p "${NESTRI_HOME}/.local/share/Steam/config"
COPY packages/configs/steam/config.vdf "${NESTRI_HOME}/.local/share/Steam/config/"
## FLAVOR/VARIANT LAUNCH COMMAND ##
ENV NESTRI_LAUNCH_CMD="steam -tenfoot -cef-force-gpu"
### END OF FLAVOR/VARIANT CONFIGURATION ###
### REQUIRED DEFAULT ENTRYPOINT FOR FLAVOR/VARIANT ###
USER root
ENTRYPOINT ["supervisord", "-c", "/etc/nestri/supervisord.conf"]

View File

@@ -1,48 +0,0 @@
legacy_layout=false
# common
horizontal
horizontal_stretch
hud_no_margin
no_small_font
background_alpha=0.66
round_corners=0
background_color=000000
font_size=24
position=top-left
engine_short_names
# colors
text_color=DFDFDF
gpu_color=FF4E00
cpu_color=00AA00
engine_color=00AA00
vram_color=00AA00
ram_color=00AA00
frametime_color=FF4E00
# load colors
cpu_load_color=DFDFDF,DF964D,DF3D3D
gpu_load_color=DFDFDF,DF964D,DF3D3D
# GPU and VRAM
gpu_text=NESTRI
gpu_stats
gpu_load_change
gpu_load_value=70,90
vram
# CPU and RAM
cpu_text=CPU
cpu_stats
cpu_load_change
cpu_load_value=70,90
ram
# FPS and timing
fps
fps_metrics=0.01
frame_timing

View File

@@ -2,6 +2,6 @@ context.properties = {
default.clock.rate = 48000 default.clock.rate = 48000
default.clock.allowed-rates = [48000] default.clock.allowed-rates = [48000]
default.clock.min-quantum = 128 default.clock.min-quantum = 128
default.clock.max-quantum = 1024 default.clock.max-quantum = 256
default.clock.quantum = 512 default.clock.quantum = 128
} }

View File

@@ -22,7 +22,7 @@
], ],
"apply_properties": { "apply_properties": {
"pulse.min.req": 128, "pulse.min.req": 128,
"pulse.max.req": 1024, "pulse.max.req": 256,
"pulse.idle.timeout": 0 "pulse.idle.timeout": 0
} }
} }

View File

@@ -1,3 +0,0 @@
.idea/
dist/
node_modules/

View File

@@ -3,8 +3,10 @@ import { WebRTCStream } from "./webrtc-stream";
import { import {
ProtoControllerAttachSchema, ProtoControllerAttachSchema,
ProtoControllerDetachSchema, ProtoControllerDetachSchema,
ProtoControllerStateBatchSchema, ProtoControllerButtonSchema,
ProtoControllerStateBatch, ProtoControllerTriggerSchema,
ProtoControllerAxisSchema,
ProtoControllerStickSchema,
ProtoControllerRumble, ProtoControllerRumble,
} from "./proto/types_pb"; } from "./proto/types_pb";
import { create, toBinary, fromBinary } from "@bufbuild/protobuf"; import { create, toBinary, fromBinary } from "@bufbuild/protobuf";
@@ -17,7 +19,6 @@ interface Props {
} }
interface GamepadState { interface GamepadState {
previousButtonState: Map<number, boolean>;
buttonState: Map<number, boolean>; buttonState: Map<number, boolean>;
leftTrigger: number; leftTrigger: number;
rightTrigger: number; rightTrigger: number;
@@ -29,17 +30,11 @@ interface GamepadState {
dpadY: number; dpadY: number;
} }
enum PollState {
IDLE,
RUNNING,
}
export class Controller { export class Controller {
protected wrtc: WebRTCStream; protected wrtc: WebRTCStream;
protected connected: boolean = false; protected connected: boolean = false;
protected gamepad: Gamepad | null = null; protected gamepad: Gamepad | null = null;
protected state: GamepadState = { protected lastState: GamepadState = {
previousButtonState: new Map<number, boolean>(),
buttonState: new Map<number, boolean>(), buttonState: new Map<number, boolean>(),
leftTrigger: 0, leftTrigger: 0,
rightTrigger: 0, rightTrigger: 0,
@@ -53,34 +48,22 @@ export class Controller {
// TODO: As user configurable, set quite low now for decent controllers (not Nintendo ones :P) // TODO: As user configurable, set quite low now for decent controllers (not Nintendo ones :P)
protected stickDeadzone: number = 2048; // 2048 / 32768 = ~0.06 (6% of stick range) protected stickDeadzone: number = 2048; // 2048 / 32768 = ~0.06 (6% of stick range)
// Polling configuration private updateInterval = 10.0; // 100 updates per second
private readonly FULL_RATE_MS = 10; // 100 UPS private isIdle: boolean = true;
private readonly IDLE_THRESHOLD = 100; // ms before considering idle/hands off controller
private readonly FULL_INTERVAL = 250; // ms before sending full state occassionally, to verify inputs are synced
// Polling state
private pollingState: PollState = PollState.IDLE;
private lastInputTime: number = Date.now(); private lastInputTime: number = Date.now();
private lastFullTime: number = Date.now(); private idleUpdateInterval: number = 150.0; // ~6-7 updates per second for keep-alive packets
private pollInterval: any = null; private inputDetected: boolean = false;
private lastFullStateSend: number = Date.now();
// Controller batch vars private fullStateSendInterval: number = 500.0; // send full state every 0.5 seconds (helps packet loss)
private sequence: number = 0; private forceFullStateSend: boolean = false;
private readonly CHANGED_BUTTONS_STATE = 1 << 0;
private readonly CHANGED_LEFT_STICK_X = 1 << 1;
private readonly CHANGED_LEFT_STICK_Y = 1 << 2;
private readonly CHANGED_RIGHT_STICK_X = 1 << 3;
private readonly CHANGED_RIGHT_STICK_Y = 1 << 4;
private readonly CHANGED_LEFT_TRIGGER = 1 << 5;
private readonly CHANGED_RIGHT_TRIGGER = 1 << 6;
private readonly CHANGED_DPAD_X = 1 << 7;
private readonly CHANGED_DPAD_Y = 1 << 8;
private _dcHandler: ((data: ArrayBuffer) => void) | null = null; private _dcHandler: ((data: ArrayBuffer) => void) | null = null;
constructor({ webrtc, e }: Props) { constructor({ webrtc, e }: Props) {
this.wrtc = webrtc; this.wrtc = webrtc;
this.updateInterval = 1000 / webrtc.currentFrameRate;
// Get vendor of gamepad from id string (i.e. "... Vendor: 054c Product: 09cc") // Get vendor of gamepad from id string (i.e. "... Vendor: 054c Product: 09cc")
const vendorMatch = e.gamepad.id.match(/Vendor:\s?([0-9a-fA-F]{4})/); const vendorMatch = e.gamepad.id.match(/Vendor:\s?([0-9a-fA-F]{4})/);
const vendorId = vendorMatch ? vendorMatch[1].toLowerCase() : "unknown"; const vendorId = vendorMatch ? vendorMatch[1].toLowerCase() : "unknown";
@@ -106,7 +89,6 @@ export class Controller {
console.log( console.log(
`Gamepad connected: ${e.gamepad.id}, local slot ${e.gamepad.index}, msg: ${attachMsg.sessionSlot}`, `Gamepad connected: ${e.gamepad.id}, local slot ${e.gamepad.index}, msg: ${attachMsg.sessionSlot}`,
); );
this.run();
} }
} catch (err) { } catch (err) {
console.error("Error decoding datachannel message:", err); console.error("Error decoding datachannel message:", err);
@@ -180,70 +162,52 @@ export class Controller {
return ((value - fromMin) * (toMax - toMin)) / (fromMax - fromMin) + toMin; return ((value - fromMin) * (toMax - toMin)) / (fromMax - fromMin) + toMin;
} }
private restartPolling() {
// Clear existing interval
if (this.pollInterval) {
clearInterval(this.pollInterval);
this.pollInterval = null;
}
// Restart with active polling
this.pollingState = PollState.RUNNING;
this.lastInputTime = Date.now();
// Start interval
this.pollInterval = setInterval(
() => this.pollGamepad(),
this.FULL_RATE_MS,
);
}
private pollGamepad() { private pollGamepad() {
if (!this.connected || !this.gamepad) return; // Get updated gamepad state
const gamepads = navigator.getGamepads(); const gamepads = navigator.getGamepads();
if (!gamepads[this.gamepad.index]) return;
this.gamepad = gamepads[this.gamepad.index]; // Periodically force send full state to clear stuck inputs
if (Date.now() - this.lastFullStateSend > this.fullStateSendInterval) {
// Collect state changes this.forceFullStateSend = true;
const changedFields = this.collectStateChanges(); this.lastFullStateSend = Date.now();
// Send batched changes update if there's changes
if (changedFields > 0) {
let send_type = 1;
const timeSinceFull = Date.now() - this.lastFullTime;
if (timeSinceFull > this.FULL_INTERVAL) {
send_type = 0;
this.lastFullTime = Date.now();
} }
this.sendBatchedState(changedFields, send_type); if (this.gamepad) {
this.lastInputTime = Date.now(); if (gamepads[this.gamepad.index]) {
if (this.pollingState !== PollState.RUNNING) { this.gamepad = gamepads[this.gamepad!.index];
this.pollingState = PollState.RUNNING; /* Button handling */
} this.gamepad.buttons.forEach((button, index) => {
// Ignore d-pad buttons (12-15) as we handle those as axis
if (index >= 12 && index <= 15) return;
// ignore trigger buttons (6-7) as we handle those as axis
if (index === 6 || index === 7) return;
// If state differs, send
if (button.pressed !== this.lastState.buttonState.get(index) || this.forceFullStateSend) {
const linuxCode = this.controllerButtonToVirtualKeyCode(index);
if (linuxCode === undefined) {
// Skip unmapped button index
this.lastState.buttonState.set(index, button.pressed);
return;
} }
const timeSinceInput = Date.now() - this.lastInputTime; const buttonMessage = createMessage(
if (timeSinceInput > this.IDLE_THRESHOLD) { create(ProtoControllerButtonSchema, {
// Changing from running to idle.. sessionSlot: this.gamepad.index,
if (this.pollingState === PollState.RUNNING) { sessionId: this.wrtc.getSessionID(),
// Send full state on idle assumption button: linuxCode,
this.sendBatchedState(0xff, 0); pressed: button.pressed,
this.pollingState = PollState.IDLE; }),
} "controllerInput",
}
this.state.buttonState.forEach((b, i) =>
this.state.previousButtonState.set(i, b),
); );
this.wrtc.sendBinary(toBinary(ProtoMessageSchema, buttonMessage));
this.inputDetected = true;
// Store button state
this.lastState.buttonState.set(index, button.pressed);
} }
});
private collectStateChanges(): number { /* Trigger handling */
let changedFields = 0; // map trigger value from 0.0 to 1.0 to -32768 to 32767
// Collect analog values
const leftTrigger = Math.round( const leftTrigger = Math.round(
this.remapFromTo( this.remapFromTo(
this.gamepad.buttons[6]?.value ?? 0, this.gamepad.buttons[6]?.value ?? 0,
@@ -253,6 +217,21 @@ export class Controller {
32767, 32767,
), ),
); );
// If state differs, send
if (leftTrigger !== this.lastState.leftTrigger || this.forceFullStateSend) {
const triggerMessage = createMessage(
create(ProtoControllerTriggerSchema, {
sessionSlot: this.gamepad.index,
sessionId: this.wrtc.getSessionID(),
trigger: 0, // 0 = left, 1 = right
value: leftTrigger,
}),
"controllerInput",
);
this.wrtc.sendBinary(toBinary(ProtoMessageSchema, triggerMessage));
this.inputDetected = true;
this.lastState.leftTrigger = leftTrigger;
}
const rightTrigger = Math.round( const rightTrigger = Math.round(
this.remapFromTo( this.remapFromTo(
this.gamepad.buttons[7]?.value ?? 0, this.gamepad.buttons[7]?.value ?? 0,
@@ -262,7 +241,62 @@ export class Controller {
32767, 32767,
), ),
); );
// If state differs, send
if (rightTrigger !== this.lastState.rightTrigger || this.forceFullStateSend) {
const triggerMessage = createMessage(
create(ProtoControllerTriggerSchema, {
sessionSlot: this.gamepad.index,
sessionId: this.wrtc.getSessionID(),
trigger: 1, // 0 = left, 1 = right
value: rightTrigger,
}),
"controllerInput",
);
this.wrtc.sendBinary(toBinary(ProtoMessageSchema, triggerMessage));
this.inputDetected = true;
this.lastState.rightTrigger = rightTrigger;
}
/* DPad handling */
// We send dpad buttons as axis values -1 to 1 for left/up, right/down
const dpadLeft = this.gamepad.buttons[14]?.pressed ? 1 : 0;
const dpadRight = this.gamepad.buttons[15]?.pressed ? 1 : 0;
const dpadX = dpadLeft ? -1 : dpadRight ? 1 : 0;
if (dpadX !== this.lastState.dpadX || this.forceFullStateSend) {
const dpadMessage = createMessage(
create(ProtoControllerAxisSchema, {
sessionSlot: this.gamepad.index,
sessionId: this.wrtc.getSessionID(),
axis: 0, // 0 = dpadX, 1 = dpadY
value: dpadX,
}),
"controllerInput",
);
this.wrtc.sendBinary(toBinary(ProtoMessageSchema, dpadMessage));
this.inputDetected = true;
this.lastState.dpadX = dpadX;
}
const dpadUp = this.gamepad.buttons[12]?.pressed ? 1 : 0;
const dpadDown = this.gamepad.buttons[13]?.pressed ? 1 : 0;
const dpadY = dpadUp ? -1 : dpadDown ? 1 : 0;
if (dpadY !== this.lastState.dpadY || this.forceFullStateSend) {
const dpadMessage = createMessage(
create(ProtoControllerAxisSchema, {
sessionSlot: this.gamepad.index,
sessionId: this.wrtc.getSessionID(),
axis: 1, // 0 = dpadX, 1 = dpadY
value: dpadY,
}),
"controllerInput",
);
this.wrtc.sendBinary(toBinary(ProtoMessageSchema, dpadMessage));
this.inputDetected = true;
this.lastState.dpadY = dpadY;
}
/* Stick handling */
// stick values need to be mapped from -1.0 to 1.0 to -32768 to 32767
const leftX = this.remapFromTo( const leftX = this.remapFromTo(
this.gamepad.axes[0] ?? 0, this.gamepad.axes[0] ?? 0,
-1, -1,
@@ -277,10 +311,32 @@ export class Controller {
-32768, -32768,
32767, 32767,
); );
// Apply deadzone
const sendLeftX = const sendLeftX =
Math.abs(leftX) > this.stickDeadzone ? Math.round(leftX) : 0; Math.abs(leftX) > this.stickDeadzone ? Math.round(leftX) : 0;
const sendLeftY = const sendLeftY =
Math.abs(leftY) > this.stickDeadzone ? Math.round(leftY) : 0; Math.abs(leftY) > this.stickDeadzone ? Math.round(leftY) : 0;
// if outside deadzone, send normally if changed
// if moves inside deadzone, zero it if not inside deadzone last time
if (
sendLeftX !== this.lastState.leftX ||
sendLeftY !== this.lastState.leftY || this.forceFullStateSend
) {
const stickMessage = createMessage(
create(ProtoControllerStickSchema, {
sessionSlot: this.gamepad.index,
sessionId: this.wrtc.getSessionID(),
stick: 0, // 0 = left, 1 = right
x: sendLeftX,
y: sendLeftY,
}),
"controllerInput",
);
this.wrtc.sendBinary(toBinary(ProtoMessageSchema, stickMessage));
this.inputDetected = true;
this.lastState.leftX = sendLeftX;
this.lastState.leftY = sendLeftY;
}
const rightX = this.remapFromTo( const rightX = this.remapFromTo(
this.gamepad.axes[2] ?? 0, this.gamepad.axes[2] ?? 0,
@@ -296,173 +352,76 @@ export class Controller {
-32768, -32768,
32767, 32767,
); );
// Apply deadzone
const sendRightX = const sendRightX =
Math.abs(rightX) > this.stickDeadzone ? Math.round(rightX) : 0; Math.abs(rightX) > this.stickDeadzone ? Math.round(rightX) : 0;
const sendRightY = const sendRightY =
Math.abs(rightY) > this.stickDeadzone ? Math.round(rightY) : 0; Math.abs(rightY) > this.stickDeadzone ? Math.round(rightY) : 0;
if (
const dpadX = sendRightX !== this.lastState.rightX ||
(this.gamepad.buttons[14]?.pressed ? -1 : 0) + sendRightY !== this.lastState.rightY || this.forceFullStateSend
(this.gamepad.buttons[15]?.pressed ? 1 : 0); ) {
const dpadY = const stickMessage = createMessage(
(this.gamepad.buttons[12]?.pressed ? -1 : 0) + create(ProtoControllerStickSchema, {
(this.gamepad.buttons[13]?.pressed ? 1 : 0);
// Check what changed
for (let i = 0; i < this.gamepad.buttons.length; i++) {
if (i >= 6 && i <= 7) continue; // Skip triggers
if (i >= 12 && i <= 15) continue; // Skip d-pad
if (this.state.buttonState.get(i) !== this.gamepad.buttons[i].pressed) {
changedFields |= this.CHANGED_BUTTONS_STATE;
}
this.state.buttonState.set(i, this.gamepad.buttons[i].pressed);
}
if (leftTrigger !== this.state.leftTrigger) {
changedFields |= this.CHANGED_LEFT_TRIGGER;
}
this.state.leftTrigger = leftTrigger;
if (rightTrigger !== this.state.rightTrigger) {
changedFields |= this.CHANGED_RIGHT_TRIGGER;
}
this.state.rightTrigger = rightTrigger;
if (sendLeftX !== this.state.leftX) {
changedFields |= this.CHANGED_LEFT_STICK_X;
}
this.state.leftX = sendLeftX;
if (sendLeftY !== this.state.leftY) {
changedFields |= this.CHANGED_LEFT_STICK_Y;
}
this.state.leftY = sendLeftY;
if (sendRightX !== this.state.rightX) {
changedFields |= this.CHANGED_RIGHT_STICK_X;
}
this.state.rightX = sendRightX;
if (sendRightY !== this.state.rightY) {
changedFields |= this.CHANGED_RIGHT_STICK_Y;
}
this.state.rightY = sendRightY;
if (dpadX !== this.state.dpadX) {
changedFields |= this.CHANGED_DPAD_X;
}
this.state.dpadX = dpadX;
if (dpadY !== this.state.dpadY) {
changedFields |= this.CHANGED_DPAD_Y;
}
this.state.dpadY = dpadY;
return changedFields;
}
private sendBatchedState(changedFields: number, updateType: number) {
// @ts-ignore
let message: ProtoControllerStateBatch = {
sessionSlot: this.gamepad.index, sessionSlot: this.gamepad.index,
sessionId: this.wrtc.getSessionID(), sessionId: this.wrtc.getSessionID(),
updateType: updateType, stick: 1, // 0 = left, 1 = right
sequence: this.sequence++, x: sendRightX,
}; y: sendRightY,
}),
// For FULL_STATE, include everything
if (updateType === 0) {
message.changedFields = 0xff;
message.buttonChangedMask = Object.fromEntries(
Array.from(this.state.buttonState)
.map(
([key, value]) =>
[this.controllerButtonToVirtualKeyCode(key), value] as const,
)
.filter(([code]) => code !== undefined),
);
message.leftStickX = this.state.leftX;
message.leftStickY = this.state.leftY;
message.rightStickX = this.state.rightX;
message.rightStickY = this.state.rightY;
message.leftTrigger = this.state.leftTrigger;
message.rightTrigger = this.state.rightTrigger;
message.dpadX = this.state.dpadX;
message.dpadY = this.state.dpadY;
}
// For DELTA, only include changed fields
else {
message.changedFields = changedFields;
if (changedFields & this.CHANGED_BUTTONS_STATE) {
const currentStateMap = this.state.buttonState;
const previousStateMap = this.state.previousButtonState;
const allKeys = new Set([
// @ts-ignore
...currentStateMap.keys(),
// @ts-ignore
...previousStateMap.keys(),
]);
message.buttonChangedMask = Object.fromEntries(
Array.from(allKeys)
.filter((key) => {
const newState = currentStateMap.get(key);
const oldState = previousStateMap.get(key);
return newState !== oldState;
})
.map((key) => {
const newValue = currentStateMap.get(key) ?? false;
return [
this.controllerButtonToVirtualKeyCode(key),
newValue,
] as const;
})
.filter(([code]) => code !== undefined),
);
}
if (changedFields & this.CHANGED_LEFT_STICK_X) {
message.leftStickX = this.state.leftX;
}
if (changedFields & this.CHANGED_LEFT_STICK_Y) {
message.leftStickY = this.state.leftY;
}
if (changedFields & this.CHANGED_RIGHT_STICK_X) {
message.rightStickX = this.state.rightX;
}
if (changedFields & this.CHANGED_RIGHT_STICK_Y) {
message.rightStickY = this.state.rightY;
}
if (changedFields & this.CHANGED_LEFT_TRIGGER) {
message.leftTrigger = this.state.leftTrigger;
}
if (changedFields & this.CHANGED_RIGHT_TRIGGER) {
message.rightTrigger = this.state.rightTrigger;
}
if (changedFields & this.CHANGED_DPAD_X) {
message.dpadX = this.state.dpadX;
}
if (changedFields & this.CHANGED_DPAD_Y) {
message.dpadY = this.state.dpadY;
}
}
// Send message
const batchMessage = createMessage(
create(
ProtoControllerStateBatchSchema,
message as ProtoControllerStateBatch,
),
"controllerInput", "controllerInput",
); );
this.wrtc.sendBinary(toBinary(ProtoMessageSchema, batchMessage)); this.wrtc.sendBinary(toBinary(ProtoMessageSchema, stickMessage));
this.inputDetected = true;
this.lastState.rightX = sendRightX;
this.lastState.rightY = sendRightY;
} }
}
}
this.forceFullStateSend = false;
}
private loopInterval: any = null;
public run() { public run() {
if (this.connected) this.stop(); if (this.connected) this.stop();
this.connected = true; this.connected = true;
this.isIdle = true;
this.lastInputTime = Date.now();
// Start with active polling this.loopInterval = setInterval(() => {
this.restartPolling(); if (this.connected) {
this.inputDetected = false; // Reset before poll
this.pollGamepad();
// Switch polling rate based on input
if (this.inputDetected) {
this.lastInputTime = Date.now();
if (this.isIdle) {
this.isIdle = false;
clearInterval(this.loopInterval);
this.loopInterval = setInterval(() => {
if (this.connected) this.pollGamepad();
}, this.updateInterval);
}
} else if (!this.isIdle && Date.now() - this.lastInputTime > 200) {
// Switch to idle polling after 200ms of no input
this.isIdle = true;
clearInterval(this.loopInterval);
this.loopInterval = setInterval(() => {
if (this.connected) this.pollGamepad();
}, this.idleUpdateInterval);
}
}
}, this.isIdle ? this.idleUpdateInterval : this.updateInterval);
} }
public stop() { public stop() {
if (this.pollInterval) { if (this.loopInterval) {
clearInterval(this.pollInterval); clearInterval(this.loopInterval);
this.pollInterval = null; this.loopInterval = null;
} }
this.connected = false; this.connected = false;
} }
@@ -474,7 +433,6 @@ export class Controller {
this.wrtc.removeDataChannelCallback(this._dcHandler); this.wrtc.removeDataChannelCallback(this._dcHandler);
this._dcHandler = null; this._dcHandler = null;
} }
if (this.gamepad) {
// Gamepad disconnected // Gamepad disconnected
const detachMsg = createMessage( const detachMsg = createMessage(
create(ProtoControllerDetachSchema, { create(ProtoControllerDetachSchema, {
@@ -484,20 +442,18 @@ export class Controller {
); );
this.wrtc.sendBinary(toBinary(ProtoMessageSchema, detachMsg)); this.wrtc.sendBinary(toBinary(ProtoMessageSchema, detachMsg));
} }
}
private controllerButtonToVirtualKeyCode(code: number): number | undefined { private controllerButtonToVirtualKeyCode(code: number) {
return controllerButtonToLinuxEventCode[code] || undefined; return controllerButtonToLinuxEventCode[code] || undefined;
} }
private rumbleCallback(rumbleMsg: ProtoControllerRumble) { private rumbleCallback(rumbleMsg: ProtoControllerRumble) {
if (!this.connected || !this.gamepad) return; // If not connected, ignore
if (!this.connected) return;
// Check if this rumble is for us // Check if aimed at this controller slot
if ( if (rumbleMsg.sessionId !== this.wrtc.getSessionID() &&
rumbleMsg.sessionId !== this.wrtc.getSessionID() || rumbleMsg.sessionSlot !== this.gamepad.index)
rumbleMsg.sessionSlot !== this.gamepad.index
)
return; return;
// Trigger actual rumble // Trigger actual rumble

View File

@@ -36,8 +36,10 @@ export class Keyboard {
if (this.connected) this.stop(); if (this.connected) this.stop();
this.connected = true; this.connected = true;
document.addEventListener("keydown", this.keydownListener); document.addEventListener("keydown", this.keydownListener, {
document.addEventListener("keyup", this.keyupListener); passive: false,
});
document.addEventListener("keyup", this.keyupListener, { passive: false });
} }
private stop() { private stop() {
@@ -71,6 +73,6 @@ export class Keyboard {
private keyToVirtualKeyCode(code: string) { private keyToVirtualKeyCode(code: string) {
// Treat Home key as Escape - TODO: Make user-configurable // Treat Home key as Escape - TODO: Make user-configurable
if (code === "Home") return 1; if (code === "Home") return 1;
return keyCodeToLinuxEventCode[code] || 0; return keyCodeToLinuxEventCode[code] || undefined;
} }
} }

View File

@@ -35,6 +35,8 @@ export class Mouse {
this.wrtc = webrtc; this.wrtc = webrtc;
this.canvas = canvas; this.canvas = canvas;
this.sendInterval = 1000 / webrtc.currentFrameRate;
this.mousemoveListener = (e: MouseEvent) => { this.mousemoveListener = (e: MouseEvent) => {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
@@ -75,10 +77,18 @@ export class Mouse {
if (document.pointerLockElement == this.canvas) { if (document.pointerLockElement == this.canvas) {
this.connected = true; this.connected = true;
this.canvas.addEventListener("mousemove", this.mousemoveListener); this.canvas.addEventListener("mousemove", this.mousemoveListener, {
this.canvas.addEventListener("mousedown", this.mousedownListener); passive: false,
this.canvas.addEventListener("mouseup", this.mouseupListener); });
this.canvas.addEventListener("wheel", this.mousewheelListener); this.canvas.addEventListener("mousedown", this.mousedownListener, {
passive: false,
});
this.canvas.addEventListener("mouseup", this.mouseupListener, {
passive: false,
});
this.canvas.addEventListener("wheel", this.mousewheelListener, {
passive: false,
});
} else { } else {
if (this.connected) { if (this.connected) {
this.stop(); this.stop();
@@ -96,7 +106,7 @@ export class Mouse {
private startProcessing() { private startProcessing() {
setInterval(() => { setInterval(() => {
if (this.connected) { if (this.connected && (this.movementX !== 0 || this.movementY !== 0)) {
this.sendAggregatedMouseMove(); this.sendAggregatedMouseMove();
this.movementX = 0; this.movementX = 0;
this.movementY = 0; this.movementY = 0;

View File

@@ -1,4 +1,4 @@
// @generated by protoc-gen-es v2.10.1 with parameter "target=ts" // @generated by protoc-gen-es v2.10.0 with parameter "target=ts"
// @generated from file latency_tracker.proto (package proto, syntax proto3) // @generated from file latency_tracker.proto (package proto, syntax proto3)
/* eslint-disable */ /* eslint-disable */

View File

@@ -1,10 +1,10 @@
// @generated by protoc-gen-es v2.10.1 with parameter "target=ts" // @generated by protoc-gen-es v2.10.0 with parameter "target=ts"
// @generated from file messages.proto (package proto, syntax proto3) // @generated from file messages.proto (package proto, syntax proto3)
/* eslint-disable */ /* eslint-disable */
import type { GenFile, GenMessage } from "@bufbuild/protobuf/codegenv2"; import type { GenFile, GenMessage } from "@bufbuild/protobuf/codegenv2";
import { fileDesc, messageDesc } from "@bufbuild/protobuf/codegenv2"; import { fileDesc, messageDesc } from "@bufbuild/protobuf/codegenv2";
import type { ProtoClientDisconnected, ProtoClientRequestRoomStream, ProtoControllerAttach, ProtoControllerDetach, ProtoControllerRumble, ProtoControllerStateBatch, ProtoICE, ProtoKeyDown, ProtoKeyUp, ProtoMouseKeyDown, ProtoMouseKeyUp, ProtoMouseMove, ProtoMouseMoveAbs, ProtoMouseWheel, ProtoRaw, ProtoSDP, ProtoServerPushStream } from "./types_pb"; import type { ProtoClientDisconnected, ProtoClientRequestRoomStream, ProtoControllerAttach, ProtoControllerAxis, ProtoControllerButton, ProtoControllerDetach, ProtoControllerRumble, ProtoControllerStick, ProtoControllerTrigger, ProtoICE, ProtoKeyDown, ProtoKeyUp, ProtoMouseKeyDown, ProtoMouseKeyUp, ProtoMouseMove, ProtoMouseMoveAbs, ProtoMouseWheel, ProtoRaw, ProtoSDP, ProtoServerPushStream } from "./types_pb";
import { file_types } from "./types_pb"; import { file_types } from "./types_pb";
import type { ProtoLatencyTracker } from "./latency_tracker_pb"; import type { ProtoLatencyTracker } from "./latency_tracker_pb";
import { file_latency_tracker } from "./latency_tracker_pb"; import { file_latency_tracker } from "./latency_tracker_pb";
@@ -14,7 +14,7 @@ import type { Message } from "@bufbuild/protobuf";
* Describes the file messages.proto. * Describes the file messages.proto.
*/ */
export const file_messages: GenFile = /*@__PURE__*/ export const file_messages: GenFile = /*@__PURE__*/
fileDesc("Cg5tZXNzYWdlcy5wcm90bxIFcHJvdG8iVQoQUHJvdG9NZXNzYWdlQmFzZRIUCgxwYXlsb2FkX3R5cGUYASABKAkSKwoHbGF0ZW5jeRgCIAEoCzIaLnByb3RvLlByb3RvTGF0ZW5jeVRyYWNrZXIipQcKDFByb3RvTWVzc2FnZRItCgxtZXNzYWdlX2Jhc2UYASABKAsyFy5wcm90by5Qcm90b01lc3NhZ2VCYXNlEisKCm1vdXNlX21vdmUYAiABKAsyFS5wcm90by5Qcm90b01vdXNlTW92ZUgAEjIKDm1vdXNlX21vdmVfYWJzGAMgASgLMhgucHJvdG8uUHJvdG9Nb3VzZU1vdmVBYnNIABItCgttb3VzZV93aGVlbBgEIAEoCzIWLnByb3RvLlByb3RvTW91c2VXaGVlbEgAEjIKDm1vdXNlX2tleV9kb3duGAUgASgLMhgucHJvdG8uUHJvdG9Nb3VzZUtleURvd25IABIuCgxtb3VzZV9rZXlfdXAYBiABKAsyFi5wcm90by5Qcm90b01vdXNlS2V5VXBIABInCghrZXlfZG93bhgHIAEoCzITLnByb3RvLlByb3RvS2V5RG93bkgAEiMKBmtleV91cBgIIAEoCzIRLnByb3RvLlByb3RvS2V5VXBIABI5ChFjb250cm9sbGVyX2F0dGFjaBgJIAEoCzIcLnByb3RvLlByb3RvQ29udHJvbGxlckF0dGFjaEgAEjkKEWNvbnRyb2xsZXJfZGV0YWNoGAogASgLMhwucHJvdG8uUHJvdG9Db250cm9sbGVyRGV0YWNoSAASOQoRY29udHJvbGxlcl9ydW1ibGUYCyABKAsyHC5wcm90by5Qcm90b0NvbnRyb2xsZXJSdW1ibGVIABJCChZjb250cm9sbGVyX3N0YXRlX2JhdGNoGAwgASgLMiAucHJvdG8uUHJvdG9Db250cm9sbGVyU3RhdGVCYXRjaEgAEh4KA2ljZRgUIAEoCzIPLnByb3RvLlByb3RvSUNFSAASHgoDc2RwGBUgASgLMg8ucHJvdG8uUHJvdG9TRFBIABIeCgNyYXcYFiABKAsyDy5wcm90by5Qcm90b1Jhd0gAEkkKGmNsaWVudF9yZXF1ZXN0X3Jvb21fc3RyZWFtGBcgASgLMiMucHJvdG8uUHJvdG9DbGllbnRSZXF1ZXN0Um9vbVN0cmVhbUgAEj0KE2NsaWVudF9kaXNjb25uZWN0ZWQYGCABKAsyHi5wcm90by5Qcm90b0NsaWVudERpc2Nvbm5lY3RlZEgAEjoKEnNlcnZlcl9wdXNoX3N0cmVhbRgZIAEoCzIcLnByb3RvLlByb3RvU2VydmVyUHVzaFN0cmVhbUgAQgkKB3BheWxvYWRCFloUcmVsYXkvaW50ZXJuYWwvcHJvdG9iBnByb3RvMw", [file_types, file_latency_tracker]); fileDesc("Cg5tZXNzYWdlcy5wcm90bxIFcHJvdG8iVQoQUHJvdG9NZXNzYWdlQmFzZRIUCgxwYXlsb2FkX3R5cGUYASABKAkSKwoHbGF0ZW5jeRgCIAEoCzIaLnByb3RvLlByb3RvTGF0ZW5jeVRyYWNrZXIiyQgKDFByb3RvTWVzc2FnZRItCgxtZXNzYWdlX2Jhc2UYASABKAsyFy5wcm90by5Qcm90b01lc3NhZ2VCYXNlEisKCm1vdXNlX21vdmUYAiABKAsyFS5wcm90by5Qcm90b01vdXNlTW92ZUgAEjIKDm1vdXNlX21vdmVfYWJzGAMgASgLMhgucHJvdG8uUHJvdG9Nb3VzZU1vdmVBYnNIABItCgttb3VzZV93aGVlbBgEIAEoCzIWLnByb3RvLlByb3RvTW91c2VXaGVlbEgAEjIKDm1vdXNlX2tleV9kb3duGAUgASgLMhgucHJvdG8uUHJvdG9Nb3VzZUtleURvd25IABIuCgxtb3VzZV9rZXlfdXAYBiABKAsyFi5wcm90by5Qcm90b01vdXNlS2V5VXBIABInCghrZXlfZG93bhgHIAEoCzITLnByb3RvLlByb3RvS2V5RG93bkgAEiMKBmtleV91cBgIIAEoCzIRLnByb3RvLlByb3RvS2V5VXBIABI5ChFjb250cm9sbGVyX2F0dGFjaBgJIAEoCzIcLnByb3RvLlByb3RvQ29udHJvbGxlckF0dGFjaEgAEjkKEWNvbnRyb2xsZXJfZGV0YWNoGAogASgLMhwucHJvdG8uUHJvdG9Db250cm9sbGVyRGV0YWNoSAASOQoRY29udHJvbGxlcl9idXR0b24YCyABKAsyHC5wcm90by5Qcm90b0NvbnRyb2xsZXJCdXR0b25IABI7ChJjb250cm9sbGVyX3RyaWdnZXIYDCABKAsyHS5wcm90by5Qcm90b0NvbnRyb2xsZXJUcmlnZ2VySAASNwoQY29udHJvbGxlcl9zdGljaxgNIAEoCzIbLnByb3RvLlByb3RvQ29udHJvbGxlclN0aWNrSAASNQoPY29udHJvbGxlcl9heGlzGA4gASgLMhoucHJvdG8uUHJvdG9Db250cm9sbGVyQXhpc0gAEjkKEWNvbnRyb2xsZXJfcnVtYmxlGA8gASgLMhwucHJvdG8uUHJvdG9Db250cm9sbGVyUnVtYmxlSAASHgoDaWNlGBQgASgLMg8ucHJvdG8uUHJvdG9JQ0VIABIeCgNzZHAYFSABKAsyDy5wcm90by5Qcm90b1NEUEgAEh4KA3JhdxgWIAEoCzIPLnByb3RvLlByb3RvUmF3SAASSQoaY2xpZW50X3JlcXVlc3Rfcm9vbV9zdHJlYW0YFyABKAsyIy5wcm90by5Qcm90b0NsaWVudFJlcXVlc3RSb29tU3RyZWFtSAASPQoTY2xpZW50X2Rpc2Nvbm5lY3RlZBgYIAEoCzIeLnByb3RvLlByb3RvQ2xpZW50RGlzY29ubmVjdGVkSAASOgoSc2VydmVyX3B1c2hfc3RyZWFtGBkgASgLMhwucHJvdG8uUHJvdG9TZXJ2ZXJQdXNoU3RyZWFtSABCCQoHcGF5bG9hZEIWWhRyZWxheS9pbnRlcm5hbC9wcm90b2IGcHJvdG8z", [file_types, file_latency_tracker]);
/** /**
* @generated from message proto.ProtoMessageBase * @generated from message proto.ProtoMessageBase
@@ -90,16 +90,12 @@ export type ProtoMessage = Message<"proto.ProtoMessage"> & {
case: "keyDown"; case: "keyDown";
} | { } | {
/** /**
* ProtoClipboard clipboard = 9;
*
* @generated from field: proto.ProtoKeyUp key_up = 8; * @generated from field: proto.ProtoKeyUp key_up = 8;
*/ */
value: ProtoKeyUp; value: ProtoKeyUp;
case: "keyUp"; case: "keyUp";
} | { } | {
/** /**
* Controller input types
*
* @generated from field: proto.ProtoControllerAttach controller_attach = 9; * @generated from field: proto.ProtoControllerAttach controller_attach = 9;
*/ */
value: ProtoControllerAttach; value: ProtoControllerAttach;
@@ -112,16 +108,34 @@ export type ProtoMessage = Message<"proto.ProtoMessage"> & {
case: "controllerDetach"; case: "controllerDetach";
} | { } | {
/** /**
* @generated from field: proto.ProtoControllerRumble controller_rumble = 11; * @generated from field: proto.ProtoControllerButton controller_button = 11;
*/
value: ProtoControllerButton;
case: "controllerButton";
} | {
/**
* @generated from field: proto.ProtoControllerTrigger controller_trigger = 12;
*/
value: ProtoControllerTrigger;
case: "controllerTrigger";
} | {
/**
* @generated from field: proto.ProtoControllerStick controller_stick = 13;
*/
value: ProtoControllerStick;
case: "controllerStick";
} | {
/**
* @generated from field: proto.ProtoControllerAxis controller_axis = 14;
*/
value: ProtoControllerAxis;
case: "controllerAxis";
} | {
/**
* @generated from field: proto.ProtoControllerRumble controller_rumble = 15;
*/ */
value: ProtoControllerRumble; value: ProtoControllerRumble;
case: "controllerRumble"; case: "controllerRumble";
} | {
/**
* @generated from field: proto.ProtoControllerStateBatch controller_state_batch = 12;
*/
value: ProtoControllerStateBatch;
case: "controllerStateBatch";
} | { } | {
/** /**
* Signaling types * Signaling types

View File

@@ -1,16 +1,16 @@
// @generated by protoc-gen-es v2.10.1 with parameter "target=ts" // @generated by protoc-gen-es v2.10.0 with parameter "target=ts"
// @generated from file types.proto (package proto, syntax proto3) // @generated from file types.proto (package proto, syntax proto3)
/* eslint-disable */ /* eslint-disable */
import type { GenEnum, GenFile, GenMessage } from "@bufbuild/protobuf/codegenv2"; import type { GenFile, GenMessage } from "@bufbuild/protobuf/codegenv2";
import { enumDesc, fileDesc, messageDesc } from "@bufbuild/protobuf/codegenv2"; import { fileDesc, messageDesc } from "@bufbuild/protobuf/codegenv2";
import type { Message } from "@bufbuild/protobuf"; import type { Message } from "@bufbuild/protobuf";
/** /**
* Describes the file types.proto. * Describes the file types.proto.
*/ */
export const file_types: GenFile = /*@__PURE__*/ export const file_types: GenFile = /*@__PURE__*/
fileDesc("Cgt0eXBlcy5wcm90bxIFcHJvdG8iJgoOUHJvdG9Nb3VzZU1vdmUSCQoBeBgBIAEoBRIJCgF5GAIgASgFIikKEVByb3RvTW91c2VNb3ZlQWJzEgkKAXgYASABKAUSCQoBeRgCIAEoBSInCg9Qcm90b01vdXNlV2hlZWwSCQoBeBgBIAEoBRIJCgF5GAIgASgFIiAKEVByb3RvTW91c2VLZXlEb3duEgsKA2tleRgBIAEoBSIeCg9Qcm90b01vdXNlS2V5VXASCwoDa2V5GAEgASgFIhsKDFByb3RvS2V5RG93bhILCgNrZXkYASABKAUiGQoKUHJvdG9LZXlVcBILCgNrZXkYASABKAUiTQoVUHJvdG9Db250cm9sbGVyQXR0YWNoEgoKAmlkGAEgASgJEhQKDHNlc3Npb25fc2xvdBgCIAEoBRISCgpzZXNzaW9uX2lkGAMgASgJIkEKFVByb3RvQ29udHJvbGxlckRldGFjaBIUCgxzZXNzaW9uX3Nsb3QYASABKAUSEgoKc2Vzc2lvbl9pZBgCIAEoCSKCAQoVUHJvdG9Db250cm9sbGVyUnVtYmxlEhQKDHNlc3Npb25fc2xvdBgBIAEoBRISCgpzZXNzaW9uX2lkGAIgASgJEhUKDWxvd19mcmVxdWVuY3kYAyABKAUSFgoOaGlnaF9mcmVxdWVuY3kYBCABKAUSEAoIZHVyYXRpb24YBSABKAUi0AUKGVByb3RvQ29udHJvbGxlclN0YXRlQmF0Y2gSFAoMc2Vzc2lvbl9zbG90GAEgASgFEhIKCnNlc3Npb25faWQYAiABKAkSQAoLdXBkYXRlX3R5cGUYAyABKA4yKy5wcm90by5Qcm90b0NvbnRyb2xsZXJTdGF0ZUJhdGNoLlVwZGF0ZVR5cGUSEAoIc2VxdWVuY2UYBCABKA0SVAoTYnV0dG9uX2NoYW5nZWRfbWFzaxgFIAMoCzI3LnByb3RvLlByb3RvQ29udHJvbGxlclN0YXRlQmF0Y2guQnV0dG9uQ2hhbmdlZE1hc2tFbnRyeRIZCgxsZWZ0X3N0aWNrX3gYBiABKAVIAIgBARIZCgxsZWZ0X3N0aWNrX3kYByABKAVIAYgBARIaCg1yaWdodF9zdGlja194GAggASgFSAKIAQESGgoNcmlnaHRfc3RpY2tfeRgJIAEoBUgDiAEBEhkKDGxlZnRfdHJpZ2dlchgKIAEoBUgEiAEBEhoKDXJpZ2h0X3RyaWdnZXIYCyABKAVIBYgBARITCgZkcGFkX3gYDCABKAVIBogBARITCgZkcGFkX3kYDSABKAVIB4gBARIbCg5jaGFuZ2VkX2ZpZWxkcxgOIAEoDUgIiAEBGjgKFkJ1dHRvbkNoYW5nZWRNYXNrRW50cnkSCwoDa2V5GAEgASgFEg0KBXZhbHVlGAIgASgIOgI4ASInCgpVcGRhdGVUeXBlEg4KCkZVTExfU1RBVEUQABIJCgVERUxUQRABQg8KDV9sZWZ0X3N0aWNrX3hCDwoNX2xlZnRfc3RpY2tfeUIQCg5fcmlnaHRfc3RpY2tfeEIQCg5fcmlnaHRfc3RpY2tfeUIPCg1fbGVmdF90cmlnZ2VyQhAKDl9yaWdodF90cmlnZ2VyQgkKB19kcGFkX3hCCQoHX2RwYWRfeUIRCg9fY2hhbmdlZF9maWVsZHMiqgEKE1JUQ0ljZUNhbmRpZGF0ZUluaXQSEQoJY2FuZGlkYXRlGAEgASgJEhoKDXNkcE1MaW5lSW5kZXgYAiABKA1IAIgBARITCgZzZHBNaWQYAyABKAlIAYgBARIdChB1c2VybmFtZUZyYWdtZW50GAQgASgJSAKIAQFCEAoOX3NkcE1MaW5lSW5kZXhCCQoHX3NkcE1pZEITChFfdXNlcm5hbWVGcmFnbWVudCI2ChlSVENTZXNzaW9uRGVzY3JpcHRpb25Jbml0EgsKA3NkcBgBIAEoCRIMCgR0eXBlGAIgASgJIjkKCFByb3RvSUNFEi0KCWNhbmRpZGF0ZRgBIAEoCzIaLnByb3RvLlJUQ0ljZUNhbmRpZGF0ZUluaXQiOQoIUHJvdG9TRFASLQoDc2RwGAEgASgLMiAucHJvdG8uUlRDU2Vzc2lvbkRlc2NyaXB0aW9uSW5pdCIYCghQcm90b1JhdxIMCgRkYXRhGAEgASgJIkUKHFByb3RvQ2xpZW50UmVxdWVzdFJvb21TdHJlYW0SEQoJcm9vbV9uYW1lGAEgASgJEhIKCnNlc3Npb25faWQYAiABKAkiRwoXUHJvdG9DbGllbnREaXNjb25uZWN0ZWQSEgoKc2Vzc2lvbl9pZBgBIAEoCRIYChBjb250cm9sbGVyX3Nsb3RzGAIgAygFIioKFVByb3RvU2VydmVyUHVzaFN0cmVhbRIRCglyb29tX25hbWUYASABKAlCFloUcmVsYXkvaW50ZXJuYWwvcHJvdG9iBnByb3RvMw"); fileDesc("Cgt0eXBlcy5wcm90bxIFcHJvdG8iJgoOUHJvdG9Nb3VzZU1vdmUSCQoBeBgBIAEoBRIJCgF5GAIgASgFIikKEVByb3RvTW91c2VNb3ZlQWJzEgkKAXgYASABKAUSCQoBeRgCIAEoBSInCg9Qcm90b01vdXNlV2hlZWwSCQoBeBgBIAEoBRIJCgF5GAIgASgFIiAKEVByb3RvTW91c2VLZXlEb3duEgsKA2tleRgBIAEoBSIeCg9Qcm90b01vdXNlS2V5VXASCwoDa2V5GAEgASgFIhsKDFByb3RvS2V5RG93bhILCgNrZXkYASABKAUiGQoKUHJvdG9LZXlVcBILCgNrZXkYASABKAUiTQoVUHJvdG9Db250cm9sbGVyQXR0YWNoEgoKAmlkGAEgASgJEhQKDHNlc3Npb25fc2xvdBgCIAEoBRISCgpzZXNzaW9uX2lkGAMgASgJIkEKFVByb3RvQ29udHJvbGxlckRldGFjaBIUCgxzZXNzaW9uX3Nsb3QYASABKAUSEgoKc2Vzc2lvbl9pZBgCIAEoCSJiChVQcm90b0NvbnRyb2xsZXJCdXR0b24SFAoMc2Vzc2lvbl9zbG90GAEgASgFEhIKCnNlc3Npb25faWQYAiABKAkSDgoGYnV0dG9uGAMgASgFEg8KB3ByZXNzZWQYBCABKAgiYgoWUHJvdG9Db250cm9sbGVyVHJpZ2dlchIUCgxzZXNzaW9uX3Nsb3QYASABKAUSEgoKc2Vzc2lvbl9pZBgCIAEoCRIPCgd0cmlnZ2VyGAMgASgFEg0KBXZhbHVlGAQgASgFImUKFFByb3RvQ29udHJvbGxlclN0aWNrEhQKDHNlc3Npb25fc2xvdBgBIAEoBRISCgpzZXNzaW9uX2lkGAIgASgJEg0KBXN0aWNrGAMgASgFEgkKAXgYBCABKAUSCQoBeRgFIAEoBSJcChNQcm90b0NvbnRyb2xsZXJBeGlzEhQKDHNlc3Npb25fc2xvdBgBIAEoBRISCgpzZXNzaW9uX2lkGAIgASgJEgwKBGF4aXMYAyABKAUSDQoFdmFsdWUYBCABKAUiggEKFVByb3RvQ29udHJvbGxlclJ1bWJsZRIUCgxzZXNzaW9uX3Nsb3QYASABKAUSEgoKc2Vzc2lvbl9pZBgCIAEoCRIVCg1sb3dfZnJlcXVlbmN5GAMgASgFEhYKDmhpZ2hfZnJlcXVlbmN5GAQgASgFEhAKCGR1cmF0aW9uGAUgASgFIqoBChNSVENJY2VDYW5kaWRhdGVJbml0EhEKCWNhbmRpZGF0ZRgBIAEoCRIaCg1zZHBNTGluZUluZGV4GAIgASgNSACIAQESEwoGc2RwTWlkGAMgASgJSAGIAQESHQoQdXNlcm5hbWVGcmFnbWVudBgEIAEoCUgCiAEBQhAKDl9zZHBNTGluZUluZGV4QgkKB19zZHBNaWRCEwoRX3VzZXJuYW1lRnJhZ21lbnQiNgoZUlRDU2Vzc2lvbkRlc2NyaXB0aW9uSW5pdBILCgNzZHAYASABKAkSDAoEdHlwZRgCIAEoCSI5CghQcm90b0lDRRItCgljYW5kaWRhdGUYASABKAsyGi5wcm90by5SVENJY2VDYW5kaWRhdGVJbml0IjkKCFByb3RvU0RQEi0KA3NkcBgBIAEoCzIgLnByb3RvLlJUQ1Nlc3Npb25EZXNjcmlwdGlvbkluaXQiGAoIUHJvdG9SYXcSDAoEZGF0YRgBIAEoCSJFChxQcm90b0NsaWVudFJlcXVlc3RSb29tU3RyZWFtEhEKCXJvb21fbmFtZRgBIAEoCRISCgpzZXNzaW9uX2lkGAIgASgJIkcKF1Byb3RvQ2xpZW50RGlzY29ubmVjdGVkEhIKCnNlc3Npb25faWQYASABKAkSGAoQY29udHJvbGxlcl9zbG90cxgCIAMoBSIqChVQcm90b1NlcnZlclB1c2hTdHJlYW0SEQoJcm9vbV9uYW1lGAEgASgJQhZaFHJlbGF5L2ludGVybmFsL3Byb3RvYgZwcm90bzM");
/** /**
* MouseMove message * MouseMove message
@@ -223,6 +223,181 @@ export type ProtoControllerDetach = Message<"proto.ProtoControllerDetach"> & {
export const ProtoControllerDetachSchema: GenMessage<ProtoControllerDetach> = /*@__PURE__*/ export const ProtoControllerDetachSchema: GenMessage<ProtoControllerDetach> = /*@__PURE__*/
messageDesc(file_types, 8); messageDesc(file_types, 8);
/**
* ControllerButton message
*
* @generated from message proto.ProtoControllerButton
*/
export type ProtoControllerButton = Message<"proto.ProtoControllerButton"> & {
/**
* Session specific slot number (0-3)
*
* @generated from field: int32 session_slot = 1;
*/
sessionSlot: number;
/**
* Session ID of the client
*
* @generated from field: string session_id = 2;
*/
sessionId: string;
/**
* Button code (linux input event code)
*
* @generated from field: int32 button = 3;
*/
button: number;
/**
* true if pressed, false if released
*
* @generated from field: bool pressed = 4;
*/
pressed: boolean;
};
/**
* Describes the message proto.ProtoControllerButton.
* Use `create(ProtoControllerButtonSchema)` to create a new message.
*/
export const ProtoControllerButtonSchema: GenMessage<ProtoControllerButton> = /*@__PURE__*/
messageDesc(file_types, 9);
/**
* ControllerTriggers message
*
* @generated from message proto.ProtoControllerTrigger
*/
export type ProtoControllerTrigger = Message<"proto.ProtoControllerTrigger"> & {
/**
* Session specific slot number (0-3)
*
* @generated from field: int32 session_slot = 1;
*/
sessionSlot: number;
/**
* Session ID of the client
*
* @generated from field: string session_id = 2;
*/
sessionId: string;
/**
* Trigger number (0 for left, 1 for right)
*
* @generated from field: int32 trigger = 3;
*/
trigger: number;
/**
* trigger value (-32768 to 32767)
*
* @generated from field: int32 value = 4;
*/
value: number;
};
/**
* Describes the message proto.ProtoControllerTrigger.
* Use `create(ProtoControllerTriggerSchema)` to create a new message.
*/
export const ProtoControllerTriggerSchema: GenMessage<ProtoControllerTrigger> = /*@__PURE__*/
messageDesc(file_types, 10);
/**
* ControllerSticks message
*
* @generated from message proto.ProtoControllerStick
*/
export type ProtoControllerStick = Message<"proto.ProtoControllerStick"> & {
/**
* Session specific slot number (0-3)
*
* @generated from field: int32 session_slot = 1;
*/
sessionSlot: number;
/**
* Session ID of the client
*
* @generated from field: string session_id = 2;
*/
sessionId: string;
/**
* Stick number (0 for left, 1 for right)
*
* @generated from field: int32 stick = 3;
*/
stick: number;
/**
* X axis value (-32768 to 32767)
*
* @generated from field: int32 x = 4;
*/
x: number;
/**
* Y axis value (-32768 to 32767)
*
* @generated from field: int32 y = 5;
*/
y: number;
};
/**
* Describes the message proto.ProtoControllerStick.
* Use `create(ProtoControllerStickSchema)` to create a new message.
*/
export const ProtoControllerStickSchema: GenMessage<ProtoControllerStick> = /*@__PURE__*/
messageDesc(file_types, 11);
/**
* ControllerAxis message
*
* @generated from message proto.ProtoControllerAxis
*/
export type ProtoControllerAxis = Message<"proto.ProtoControllerAxis"> & {
/**
* Session specific slot number (0-3)
*
* @generated from field: int32 session_slot = 1;
*/
sessionSlot: number;
/**
* Session ID of the client
*
* @generated from field: string session_id = 2;
*/
sessionId: string;
/**
* Axis number (0 for d-pad horizontal, 1 for d-pad vertical)
*
* @generated from field: int32 axis = 3;
*/
axis: number;
/**
* axis value (-1 to 1)
*
* @generated from field: int32 value = 4;
*/
value: number;
};
/**
* Describes the message proto.ProtoControllerAxis.
* Use `create(ProtoControllerAxisSchema)` to create a new message.
*/
export const ProtoControllerAxisSchema: GenMessage<ProtoControllerAxis> = /*@__PURE__*/
messageDesc(file_types, 12);
/** /**
* ControllerRumble message * ControllerRumble message
* *
@@ -270,145 +445,7 @@ export type ProtoControllerRumble = Message<"proto.ProtoControllerRumble"> & {
* Use `create(ProtoControllerRumbleSchema)` to create a new message. * Use `create(ProtoControllerRumbleSchema)` to create a new message.
*/ */
export const ProtoControllerRumbleSchema: GenMessage<ProtoControllerRumble> = /*@__PURE__*/ export const ProtoControllerRumbleSchema: GenMessage<ProtoControllerRumble> = /*@__PURE__*/
messageDesc(file_types, 9); messageDesc(file_types, 13);
/**
* ControllerStateBatch - single message containing full or partial controller state
*
* @generated from message proto.ProtoControllerStateBatch
*/
export type ProtoControllerStateBatch = Message<"proto.ProtoControllerStateBatch"> & {
/**
* Session specific slot number (0-3)
*
* @generated from field: int32 session_slot = 1;
*/
sessionSlot: number;
/**
* Session ID of the client
*
* @generated from field: string session_id = 2;
*/
sessionId: string;
/**
* @generated from field: proto.ProtoControllerStateBatch.UpdateType update_type = 3;
*/
updateType: ProtoControllerStateBatch_UpdateType;
/**
* Sequence number for packet loss detection
*
* @generated from field: uint32 sequence = 4;
*/
sequence: number;
/**
* Button state map (Linux event codes)
*
* @generated from field: map<int32, bool> button_changed_mask = 5;
*/
buttonChangedMask: { [key: number]: boolean };
/**
* Analog inputs
*
* -32768 to 32767
*
* @generated from field: optional int32 left_stick_x = 6;
*/
leftStickX?: number;
/**
* -32768 to 32767
*
* @generated from field: optional int32 left_stick_y = 7;
*/
leftStickY?: number;
/**
* -32768 to 32767
*
* @generated from field: optional int32 right_stick_x = 8;
*/
rightStickX?: number;
/**
* -32768 to 32767
*
* @generated from field: optional int32 right_stick_y = 9;
*/
rightStickY?: number;
/**
* -32768 to 32767
*
* @generated from field: optional int32 left_trigger = 10;
*/
leftTrigger?: number;
/**
* -32768 to 32767
*
* @generated from field: optional int32 right_trigger = 11;
*/
rightTrigger?: number;
/**
* -1, 0, or 1
*
* @generated from field: optional int32 dpad_x = 12;
*/
dpadX?: number;
/**
* -1, 0, or 1
*
* @generated from field: optional int32 dpad_y = 13;
*/
dpadY?: number;
/**
* Bitmask indicating which fields have changed
* Bit 0: button_changed_mask, Bit 1: left_stick_x, Bit 2: left_stick_y, etc.
*
* @generated from field: optional uint32 changed_fields = 14;
*/
changedFields?: number;
};
/**
* Describes the message proto.ProtoControllerStateBatch.
* Use `create(ProtoControllerStateBatchSchema)` to create a new message.
*/
export const ProtoControllerStateBatchSchema: GenMessage<ProtoControllerStateBatch> = /*@__PURE__*/
messageDesc(file_types, 10);
/**
* @generated from enum proto.ProtoControllerStateBatch.UpdateType
*/
export enum ProtoControllerStateBatch_UpdateType {
/**
* Complete controller state
*
* @generated from enum value: FULL_STATE = 0;
*/
FULL_STATE = 0,
/**
* Only changed fields
*
* @generated from enum value: DELTA = 1;
*/
DELTA = 1,
}
/**
* Describes the enum proto.ProtoControllerStateBatch.UpdateType.
*/
export const ProtoControllerStateBatch_UpdateTypeSchema: GenEnum<ProtoControllerStateBatch_UpdateType> = /*@__PURE__*/
enumDesc(file_types, 10, 0);
/** /**
* @generated from message proto.RTCIceCandidateInit * @generated from message proto.RTCIceCandidateInit
@@ -440,7 +477,7 @@ export type RTCIceCandidateInit = Message<"proto.RTCIceCandidateInit"> & {
* Use `create(RTCIceCandidateInitSchema)` to create a new message. * Use `create(RTCIceCandidateInitSchema)` to create a new message.
*/ */
export const RTCIceCandidateInitSchema: GenMessage<RTCIceCandidateInit> = /*@__PURE__*/ export const RTCIceCandidateInitSchema: GenMessage<RTCIceCandidateInit> = /*@__PURE__*/
messageDesc(file_types, 11); messageDesc(file_types, 14);
/** /**
* @generated from message proto.RTCSessionDescriptionInit * @generated from message proto.RTCSessionDescriptionInit
@@ -462,7 +499,7 @@ export type RTCSessionDescriptionInit = Message<"proto.RTCSessionDescriptionInit
* Use `create(RTCSessionDescriptionInitSchema)` to create a new message. * Use `create(RTCSessionDescriptionInitSchema)` to create a new message.
*/ */
export const RTCSessionDescriptionInitSchema: GenMessage<RTCSessionDescriptionInit> = /*@__PURE__*/ export const RTCSessionDescriptionInitSchema: GenMessage<RTCSessionDescriptionInit> = /*@__PURE__*/
messageDesc(file_types, 12); messageDesc(file_types, 15);
/** /**
* ProtoICE message * ProtoICE message
@@ -481,7 +518,7 @@ export type ProtoICE = Message<"proto.ProtoICE"> & {
* Use `create(ProtoICESchema)` to create a new message. * Use `create(ProtoICESchema)` to create a new message.
*/ */
export const ProtoICESchema: GenMessage<ProtoICE> = /*@__PURE__*/ export const ProtoICESchema: GenMessage<ProtoICE> = /*@__PURE__*/
messageDesc(file_types, 13); messageDesc(file_types, 16);
/** /**
* ProtoSDP message * ProtoSDP message
@@ -500,7 +537,7 @@ export type ProtoSDP = Message<"proto.ProtoSDP"> & {
* Use `create(ProtoSDPSchema)` to create a new message. * Use `create(ProtoSDPSchema)` to create a new message.
*/ */
export const ProtoSDPSchema: GenMessage<ProtoSDP> = /*@__PURE__*/ export const ProtoSDPSchema: GenMessage<ProtoSDP> = /*@__PURE__*/
messageDesc(file_types, 14); messageDesc(file_types, 17);
/** /**
* ProtoRaw message * ProtoRaw message
@@ -519,7 +556,7 @@ export type ProtoRaw = Message<"proto.ProtoRaw"> & {
* Use `create(ProtoRawSchema)` to create a new message. * Use `create(ProtoRawSchema)` to create a new message.
*/ */
export const ProtoRawSchema: GenMessage<ProtoRaw> = /*@__PURE__*/ export const ProtoRawSchema: GenMessage<ProtoRaw> = /*@__PURE__*/
messageDesc(file_types, 15); messageDesc(file_types, 18);
/** /**
* ProtoClientRequestRoomStream message * ProtoClientRequestRoomStream message
@@ -543,7 +580,7 @@ export type ProtoClientRequestRoomStream = Message<"proto.ProtoClientRequestRoom
* Use `create(ProtoClientRequestRoomStreamSchema)` to create a new message. * Use `create(ProtoClientRequestRoomStreamSchema)` to create a new message.
*/ */
export const ProtoClientRequestRoomStreamSchema: GenMessage<ProtoClientRequestRoomStream> = /*@__PURE__*/ export const ProtoClientRequestRoomStreamSchema: GenMessage<ProtoClientRequestRoomStream> = /*@__PURE__*/
messageDesc(file_types, 16); messageDesc(file_types, 19);
/** /**
* ProtoClientDisconnected message * ProtoClientDisconnected message
@@ -567,7 +604,7 @@ export type ProtoClientDisconnected = Message<"proto.ProtoClientDisconnected"> &
* Use `create(ProtoClientDisconnectedSchema)` to create a new message. * Use `create(ProtoClientDisconnectedSchema)` to create a new message.
*/ */
export const ProtoClientDisconnectedSchema: GenMessage<ProtoClientDisconnected> = /*@__PURE__*/ export const ProtoClientDisconnectedSchema: GenMessage<ProtoClientDisconnected> = /*@__PURE__*/
messageDesc(file_types, 17); messageDesc(file_types, 20);
/** /**
* ProtoServerPushStream message * ProtoServerPushStream message
@@ -586,5 +623,5 @@ export type ProtoServerPushStream = Message<"proto.ProtoServerPushStream"> & {
* Use `create(ProtoServerPushStreamSchema)` to create a new message. * Use `create(ProtoServerPushStreamSchema)` to create a new message.
*/ */
export const ProtoServerPushStreamSchema: GenMessage<ProtoServerPushStream> = /*@__PURE__*/ export const ProtoServerPushStreamSchema: GenMessage<ProtoServerPushStream> = /*@__PURE__*/
messageDesc(file_types, 18); messageDesc(file_types, 21);

View File

@@ -13,10 +13,9 @@ import {
ProtoClientRequestRoomStream, ProtoClientRequestRoomStream,
ProtoClientRequestRoomStreamSchema, ProtoClientRequestRoomStreamSchema,
ProtoICE, ProtoICE,
ProtoICESchema, ProtoICESchema, ProtoRaw,
ProtoRaw,
ProtoSDP, ProtoSDP,
ProtoSDPSchema, ProtoSDPSchema
} from "./proto/types_pb"; } from "./proto/types_pb";
import { P2PMessageStream } from "./streamwrapper"; import { P2PMessageStream } from "./streamwrapper";
@@ -39,6 +38,7 @@ export class WebRTCStream {
private _roomName: string | undefined = undefined; private _roomName: string | undefined = undefined;
private _isConnected: boolean = false; private _isConnected: boolean = false;
private _dataChannelCallbacks: Array<(data: any) => void> = []; private _dataChannelCallbacks: Array<(data: any) => void> = [];
currentFrameRate: number = 100;
constructor( constructor(
serverURL: string, serverURL: string,
@@ -123,22 +123,16 @@ export class WebRTCStream {
} else { } else {
iceHolder.push(cand); iceHolder.push(cand);
} }
} else {
iceHolder.push(cand);
} }
}); });
this._msgStream.on( this._msgStream.on("session-assigned", (data: ProtoClientRequestRoomStream) => {
"session-assigned",
(data: ProtoClientRequestRoomStream) => {
this._sessionId = data.sessionId; this._sessionId = data.sessionId;
localStorage.setItem("nestri-session-id", this._sessionId); localStorage.setItem("nestri-session-id", this._sessionId);
console.log( console.log("Session ID assigned:", this._sessionId, "for room:", data.roomName);
"Session ID assigned:", });
this._sessionId,
"for room:",
data.roomName,
);
},
);
this._msgStream.on("offer", async (data: ProtoSDP) => { this._msgStream.on("offer", async (data: ProtoSDP) => {
if (!this._pc) { if (!this._pc) {
@@ -149,14 +143,6 @@ export class WebRTCStream {
sdp: data.sdp.sdp, sdp: data.sdp.sdp,
type: data.sdp.type as RTCSdpType, type: data.sdp.type as RTCSdpType,
}); });
// Add held candidates
iceHolder.forEach((candidate) => {
this._pc!.addIceCandidate(candidate).catch((err) => {
console.error("Error adding held ICE candidate:", err);
});
});
iceHolder = [];
// Create our answer // Create our answer
const answer = await this._pc!.createAnswer(); const answer = await this._pc!.createAnswer();
// Force stereo in Chromium browsers // Force stereo in Chromium browsers
@@ -186,7 +172,7 @@ export class WebRTCStream {
const requestMsg = createMessage( const requestMsg = createMessage(
create(ProtoClientRequestRoomStreamSchema, { create(ProtoClientRequestRoomStreamSchema, {
roomName: roomName, roomName: roomName,
sessionId: clientId ?? "", sessionId: clientId,
}), }),
"request-stream-room", "request-stream-room",
); );
@@ -301,8 +287,26 @@ export class WebRTCStream {
this._onConnected( this._onConnected(
new MediaStream([this._audioTrack, this._videoTrack]), new MediaStream([this._audioTrack, this._videoTrack]),
); );
// Continuously set low-latency target
this._pc.getReceivers().forEach((receiver: RTCRtpReceiver) => {
let intervalLoop = setInterval(async () => {
if (
receiver.track.readyState !== "live" ||
(receiver.transport && receiver.transport.state !== "connected")
) {
clearInterval(intervalLoop);
return;
} else {
// @ts-ignore
receiver.jitterBufferTarget = receiver.jitterBufferDelayHint = receiver.playoutDelayHint = 0;
}
}, 50);
});
} }
} }
this._gatherFrameRate();
} else if ( } else if (
this._pc.connectionState === "failed" || this._pc.connectionState === "failed" ||
this._pc.connectionState === "closed" || this._pc.connectionState === "closed" ||
@@ -402,16 +406,11 @@ export class WebRTCStream {
}; };
} }
private async _gatherStats(): Promise<any> { private _gatherFrameRate() {
if ( if (this._pc === undefined || this._videoTrack === undefined) return;
this._pc === undefined ||
this._videoTrack === undefined ||
!this._isConnected
)
return null;
return new Promise<any>((resolve) => { const videoInfoPromise = new Promise<{ fps: number }>((resolve) => {
// Keep trying to get stats until gotten // Keep trying to get fps until it's found
const interval = setInterval(async () => { const interval = setInterval(async () => {
if (this._pc === undefined) { if (this._pc === undefined) {
clearInterval(interval); clearInterval(interval);
@@ -423,11 +422,15 @@ export class WebRTCStream {
if (report.type === "inbound-rtp") { if (report.type === "inbound-rtp") {
clearInterval(interval); clearInterval(interval);
resolve({ pli: report.pliCount, nack: report.nackCount }); resolve({ fps: report.framesPerSecond });
} }
}); });
}, 250); }, 250);
}); });
videoInfoPromise.then((value) => {
this.currentFrameRate = value.fps;
});
} }
// Send binary message through the data channel // Send binary message through the data channel

View File

@@ -9,8 +9,8 @@
"astro": "astro" "astro": "astro"
}, },
"dependencies": { "dependencies": {
"@astrojs/node": "9.5.0", "@astrojs/node": "^9.4.2",
"@nestri/input": "*", "@nestri/input": "*",
"astro": "5.15.1" "astro": "5.14.5"
} }
} }

View File

@@ -99,6 +99,9 @@ if (envs_map.size > 0) {
}); });
window.addEventListener("gamepaddisconnected", (e) => { window.addEventListener("gamepaddisconnected", (e) => {
console.log("Gamepad disconnected:", e.gamepad); console.log("Gamepad disconnected:", e.gamepad);
if (e.gamepad.id.toLowerCase().includes("nestri"))
return;
let disconnected = nestriControllers.find((c) => c.getSlot() === e.gamepad.index); let disconnected = nestriControllers.find((c) => c.getSlot() === e.gamepad.index);
if (disconnected) { if (disconnected) {
disconnected.dispose(); disconnected.dispose();

View File

@@ -10,7 +10,7 @@ require (
github.com/oklog/ulid/v2 v2.1.1 github.com/oklog/ulid/v2 v2.1.1
github.com/pion/ice/v4 v4.0.10 github.com/pion/ice/v4 v4.0.10
github.com/pion/interceptor v0.1.41 github.com/pion/interceptor v0.1.41
github.com/pion/rtp v1.8.25 github.com/pion/rtp v1.8.24
github.com/pion/webrtc/v4 v4.1.6 github.com/pion/webrtc/v4 v4.1.6
github.com/prometheus/client_golang v1.23.2 github.com/prometheus/client_golang v1.23.2
google.golang.org/protobuf v1.36.10 google.golang.org/protobuf v1.36.10
@@ -30,7 +30,7 @@ require (
github.com/gorilla/websocket v1.5.3 // indirect github.com/gorilla/websocket v1.5.3 // indirect
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
github.com/huin/goupnp v1.3.0 // indirect github.com/huin/goupnp v1.3.0 // indirect
github.com/ipfs/go-cid v0.6.0 // indirect github.com/ipfs/go-cid v0.5.0 // indirect
github.com/jackpal/go-nat-pmp v1.0.2 // indirect github.com/jackpal/go-nat-pmp v1.0.2 // indirect
github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect
github.com/klauspost/compress v1.18.1 // indirect github.com/klauspost/compress v1.18.1 // indirect
@@ -40,7 +40,7 @@ require (
github.com/libp2p/go-flow-metrics v0.3.0 // indirect github.com/libp2p/go-flow-metrics v0.3.0 // indirect
github.com/libp2p/go-libp2p-asn-util v0.4.1 // indirect github.com/libp2p/go-libp2p-asn-util v0.4.1 // indirect
github.com/libp2p/go-msgio v0.3.0 // indirect github.com/libp2p/go-msgio v0.3.0 // indirect
github.com/libp2p/go-netroute v0.4.0 // indirect github.com/libp2p/go-netroute v0.3.0 // indirect
github.com/libp2p/go-yamux/v5 v5.1.0 // indirect github.com/libp2p/go-yamux/v5 v5.1.0 // indirect
github.com/libp2p/zeroconf/v2 v2.2.0 // indirect github.com/libp2p/zeroconf/v2 v2.2.0 // indirect
github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd // indirect github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd // indirect
@@ -71,13 +71,13 @@ require (
github.com/pion/sdp/v3 v3.0.16 // indirect github.com/pion/sdp/v3 v3.0.16 // indirect
github.com/pion/srtp/v3 v3.0.8 // indirect github.com/pion/srtp/v3 v3.0.8 // indirect
github.com/pion/stun v0.6.1 // indirect github.com/pion/stun v0.6.1 // indirect
github.com/pion/stun/v3 v3.0.1 // indirect github.com/pion/stun/v3 v3.0.0 // indirect
github.com/pion/transport/v2 v2.2.10 // indirect github.com/pion/transport/v2 v2.2.10 // indirect
github.com/pion/transport/v3 v3.0.8 // indirect github.com/pion/transport/v3 v3.0.8 // indirect
github.com/pion/turn/v4 v4.1.2 // indirect github.com/pion/turn/v4 v4.1.1 // indirect
github.com/prometheus/client_model v0.6.2 // indirect github.com/prometheus/client_model v0.6.2 // indirect
github.com/prometheus/common v0.67.2 // indirect github.com/prometheus/common v0.67.1 // indirect
github.com/prometheus/procfs v0.19.2 // indirect github.com/prometheus/procfs v0.17.0 // indirect
github.com/quic-go/qpack v0.5.1 // indirect github.com/quic-go/qpack v0.5.1 // indirect
github.com/quic-go/quic-go v0.55.0 // indirect github.com/quic-go/quic-go v0.55.0 // indirect
github.com/quic-go/webtransport-go v0.9.0 // indirect github.com/quic-go/webtransport-go v0.9.0 // indirect
@@ -91,12 +91,12 @@ require (
go.uber.org/zap v1.27.0 // indirect go.uber.org/zap v1.27.0 // indirect
go.yaml.in/yaml/v2 v2.4.3 // indirect go.yaml.in/yaml/v2 v2.4.3 // indirect
golang.org/x/crypto v0.43.0 // indirect golang.org/x/crypto v0.43.0 // indirect
golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 // indirect golang.org/x/exp v0.0.0-20251017212417-90e834f514db // indirect
golang.org/x/mod v0.29.0 // indirect golang.org/x/mod v0.29.0 // indirect
golang.org/x/net v0.46.0 // indirect golang.org/x/net v0.46.0 // indirect
golang.org/x/sync v0.17.0 // indirect golang.org/x/sync v0.17.0 // indirect
golang.org/x/sys v0.37.0 // indirect golang.org/x/sys v0.37.0 // indirect
golang.org/x/telemetry v0.0.0-20251028164327-d7a2859f34e8 // indirect golang.org/x/telemetry v0.0.0-20251014153721-24f779f6aaef // indirect
golang.org/x/text v0.30.0 // indirect golang.org/x/text v0.30.0 // indirect
golang.org/x/time v0.14.0 // indirect golang.org/x/time v0.14.0 // indirect
golang.org/x/tools v0.38.0 // indirect golang.org/x/tools v0.38.0 // indirect

View File

@@ -71,8 +71,8 @@ github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc= github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc=
github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8=
github.com/ipfs/go-cid v0.6.0 h1:DlOReBV1xhHBhhfy/gBNNTSyfOM6rLiIx9J7A4DGf30= github.com/ipfs/go-cid v0.5.0 h1:goEKKhaGm0ul11IHA7I6p1GmKz8kEYniqFopaB5Otwg=
github.com/ipfs/go-cid v0.6.0/go.mod h1:NC4kS1LZjzfhK40UGmpXv5/qD2kcMzACYJNntCUiDhQ= github.com/ipfs/go-cid v0.5.0/go.mod h1:0L7vmeNXpQpUS9vt+yEARkJ8rOg43DF3iPgn4GIN0mk=
github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus=
github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
github.com/jbenet/go-temp-err-catcher v0.1.0 h1:zpb3ZH6wIE8Shj2sKS+khgRvf7T7RABoLk/+KKHggpk= github.com/jbenet/go-temp-err-catcher v0.1.0 h1:zpb3ZH6wIE8Shj2sKS+khgRvf7T7RABoLk/+KKHggpk=
@@ -113,8 +113,8 @@ github.com/libp2p/go-libp2p-testing v0.12.0 h1:EPvBb4kKMWO29qP4mZGyhVzUyR25dvfUI
github.com/libp2p/go-libp2p-testing v0.12.0/go.mod h1:KcGDRXyN7sQCllucn1cOOS+Dmm7ujhfEyXQL5lvkcPg= github.com/libp2p/go-libp2p-testing v0.12.0/go.mod h1:KcGDRXyN7sQCllucn1cOOS+Dmm7ujhfEyXQL5lvkcPg=
github.com/libp2p/go-msgio v0.3.0 h1:mf3Z8B1xcFN314sWX+2vOTShIE0Mmn2TXn3YCUQGNj0= github.com/libp2p/go-msgio v0.3.0 h1:mf3Z8B1xcFN314sWX+2vOTShIE0Mmn2TXn3YCUQGNj0=
github.com/libp2p/go-msgio v0.3.0/go.mod h1:nyRM819GmVaF9LX3l03RMh10QdOroF++NBbxAb0mmDM= github.com/libp2p/go-msgio v0.3.0/go.mod h1:nyRM819GmVaF9LX3l03RMh10QdOroF++NBbxAb0mmDM=
github.com/libp2p/go-netroute v0.4.0 h1:sZZx9hyANYUx9PZyqcgE/E1GUG3iEtTZHUEvdtXT7/Q= github.com/libp2p/go-netroute v0.3.0 h1:nqPCXHmeNmgTJnktosJ/sIef9hvwYCrsLxXmfNks/oc=
github.com/libp2p/go-netroute v0.4.0/go.mod h1:Nkd5ShYgSMS5MUKy/MU2T57xFoOKvvLR92Lic48LEyA= github.com/libp2p/go-netroute v0.3.0/go.mod h1:Nkd5ShYgSMS5MUKy/MU2T57xFoOKvvLR92Lic48LEyA=
github.com/libp2p/go-reuseport v0.4.0 h1:nR5KU7hD0WxXCJbmw7r2rhRYruNRl2koHw8fQscQm2s= github.com/libp2p/go-reuseport v0.4.0 h1:nR5KU7hD0WxXCJbmw7r2rhRYruNRl2koHw8fQscQm2s=
github.com/libp2p/go-reuseport v0.4.0/go.mod h1:ZtI03j/wO5hZVDFo2jKywN6bYKWLOy8Se6DrI2E1cLU= github.com/libp2p/go-reuseport v0.4.0/go.mod h1:ZtI03j/wO5hZVDFo2jKywN6bYKWLOy8Se6DrI2E1cLU=
github.com/libp2p/go-yamux/v5 v5.1.0 h1:8Qlxj4E9JGJAQVW6+uj2o7mqkqsIVlSUGmTWhlXzoHE= github.com/libp2p/go-yamux/v5 v5.1.0 h1:8Qlxj4E9JGJAQVW6+uj2o7mqkqsIVlSUGmTWhlXzoHE=
@@ -199,8 +199,8 @@ github.com/pion/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA=
github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8= github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8=
github.com/pion/rtcp v1.2.16 h1:fk1B1dNW4hsI78XUCljZJlC4kZOPk67mNRuQ0fcEkSo= github.com/pion/rtcp v1.2.16 h1:fk1B1dNW4hsI78XUCljZJlC4kZOPk67mNRuQ0fcEkSo=
github.com/pion/rtcp v1.2.16/go.mod h1:/as7VKfYbs5NIb4h6muQ35kQF/J0ZVNz2Z3xKoCBYOo= github.com/pion/rtcp v1.2.16/go.mod h1:/as7VKfYbs5NIb4h6muQ35kQF/J0ZVNz2Z3xKoCBYOo=
github.com/pion/rtp v1.8.25 h1:b8+y44GNbwOJTYWuVan7SglX/hMlicVCAtL50ztyZHw= github.com/pion/rtp v1.8.24 h1:+ICyZXUQDv95EsHN70RrA4XKJf5MGWyC6QQc1u6/ynI=
github.com/pion/rtp v1.8.25/go.mod h1:rF5nS1GqbR7H/TCpKwylzeq6yDM+MM6k+On5EgeThEM= github.com/pion/rtp v1.8.24/go.mod h1:rF5nS1GqbR7H/TCpKwylzeq6yDM+MM6k+On5EgeThEM=
github.com/pion/sctp v1.8.40 h1:bqbgWYOrUhsYItEnRObUYZuzvOMsVplS3oNgzedBlG8= github.com/pion/sctp v1.8.40 h1:bqbgWYOrUhsYItEnRObUYZuzvOMsVplS3oNgzedBlG8=
github.com/pion/sctp v1.8.40/go.mod h1:SPBBUENXE6ThkEksN5ZavfAhFYll+h+66ZiG6IZQuzo= github.com/pion/sctp v1.8.40/go.mod h1:SPBBUENXE6ThkEksN5ZavfAhFYll+h+66ZiG6IZQuzo=
github.com/pion/sdp/v3 v3.0.16 h1:0dKzYO6gTAvuLaAKQkC02eCPjMIi4NuAr/ibAwrGDCo= github.com/pion/sdp/v3 v3.0.16 h1:0dKzYO6gTAvuLaAKQkC02eCPjMIi4NuAr/ibAwrGDCo=
@@ -209,16 +209,16 @@ github.com/pion/srtp/v3 v3.0.8 h1:RjRrjcIeQsilPzxvdaElN0CpuQZdMvcl9VZ5UY9suUM=
github.com/pion/srtp/v3 v3.0.8/go.mod h1:2Sq6YnDH7/UDCvkSoHSDNDeyBcFgWL0sAVycVbAsXFg= github.com/pion/srtp/v3 v3.0.8/go.mod h1:2Sq6YnDH7/UDCvkSoHSDNDeyBcFgWL0sAVycVbAsXFg=
github.com/pion/stun v0.6.1 h1:8lp6YejULeHBF8NmV8e2787BogQhduZugh5PdhDyyN4= github.com/pion/stun v0.6.1 h1:8lp6YejULeHBF8NmV8e2787BogQhduZugh5PdhDyyN4=
github.com/pion/stun v0.6.1/go.mod h1:/hO7APkX4hZKu/D0f2lHzNyvdkTGtIy3NDmLR7kSz/8= github.com/pion/stun v0.6.1/go.mod h1:/hO7APkX4hZKu/D0f2lHzNyvdkTGtIy3NDmLR7kSz/8=
github.com/pion/stun/v3 v3.0.1 h1:jx1uUq6BdPihF0yF33Jj2mh+C9p0atY94IkdnW174kA= github.com/pion/stun/v3 v3.0.0 h1:4h1gwhWLWuZWOJIJR9s2ferRO+W3zA/b6ijOI6mKzUw=
github.com/pion/stun/v3 v3.0.1/go.mod h1:RHnvlKFg+qHgoKIqtQWMOJF52wsImCAf/Jh5GjX+4Tw= github.com/pion/stun/v3 v3.0.0/go.mod h1:HvCN8txt8mwi4FBvS3EmDghW6aQJ24T+y+1TKjB5jyU=
github.com/pion/transport/v2 v2.2.1/go.mod h1:cXXWavvCnFF6McHTft3DWS9iic2Mftcz1Aq29pGcU5g= github.com/pion/transport/v2 v2.2.1/go.mod h1:cXXWavvCnFF6McHTft3DWS9iic2Mftcz1Aq29pGcU5g=
github.com/pion/transport/v2 v2.2.4/go.mod h1:q2U/tf9FEfnSBGSW6w5Qp5PFWRLRj3NjLhCCgpRK4p0= github.com/pion/transport/v2 v2.2.4/go.mod h1:q2U/tf9FEfnSBGSW6w5Qp5PFWRLRj3NjLhCCgpRK4p0=
github.com/pion/transport/v2 v2.2.10 h1:ucLBLE8nuxiHfvkFKnkDQRYWYfp8ejf4YBOPfaQpw6Q= github.com/pion/transport/v2 v2.2.10 h1:ucLBLE8nuxiHfvkFKnkDQRYWYfp8ejf4YBOPfaQpw6Q=
github.com/pion/transport/v2 v2.2.10/go.mod h1:sq1kSLWs+cHW9E+2fJP95QudkzbK7wscs8yYgQToO5E= github.com/pion/transport/v2 v2.2.10/go.mod h1:sq1kSLWs+cHW9E+2fJP95QudkzbK7wscs8yYgQToO5E=
github.com/pion/transport/v3 v3.0.8 h1:oI3myyYnTKUSTthu/NZZ8eu2I5sHbxbUNNFW62olaYc= github.com/pion/transport/v3 v3.0.8 h1:oI3myyYnTKUSTthu/NZZ8eu2I5sHbxbUNNFW62olaYc=
github.com/pion/transport/v3 v3.0.8/go.mod h1:+c2eewC5WJQHiAA46fkMMzoYZSuGzA/7E2FPrOYHctQ= github.com/pion/transport/v3 v3.0.8/go.mod h1:+c2eewC5WJQHiAA46fkMMzoYZSuGzA/7E2FPrOYHctQ=
github.com/pion/turn/v4 v4.1.2 h1:Em2svpl6aBFa88dLhxypMUzaLjC79kWZWx8FIov01cc= github.com/pion/turn/v4 v4.1.1 h1:9UnY2HB99tpDyz3cVVZguSxcqkJ1DsTSZ+8TGruh4fc=
github.com/pion/turn/v4 v4.1.2/go.mod h1:ISYWfZYy0Z3tXzRpyYZHTL+U23yFQIspfxogdQ8pn9Y= github.com/pion/turn/v4 v4.1.1/go.mod h1:2123tHk1O++vmjI5VSD0awT50NywDAq5A2NNNU4Jjs8=
github.com/pion/webrtc/v4 v4.1.6 h1:srHH2HwvCGwPba25EYJgUzgLqCQoXl1VCUnrGQMSzUw= github.com/pion/webrtc/v4 v4.1.6 h1:srHH2HwvCGwPba25EYJgUzgLqCQoXl1VCUnrGQMSzUw=
github.com/pion/webrtc/v4 v4.1.6/go.mod h1:wKecGRlkl3ox/As/MYghJL+b/cVXMEhoPMJWPuGQFhU= github.com/pion/webrtc/v4 v4.1.6/go.mod h1:wKecGRlkl3ox/As/MYghJL+b/cVXMEhoPMJWPuGQFhU=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@@ -231,11 +231,11 @@ github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk= github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.67.2 h1:PcBAckGFTIHt2+L3I33uNRTlKTplNzFctXcWhPyAEN8= github.com/prometheus/common v0.67.1 h1:OTSON1P4DNxzTg4hmKCc37o4ZAZDv0cfXLkOt0oEowI=
github.com/prometheus/common v0.67.2/go.mod h1:63W3KZb1JOKgcjlIr64WW/LvFGAqKPj0atm+knVGEko= github.com/prometheus/common v0.67.1/go.mod h1:RpmT9v35q2Y+lsieQsdOh5sXZ6ajUGC8NjZAmr8vb0Q=
github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.19.2 h1:zUMhqEW66Ex7OXIiDkll3tl9a1ZdilUOd/F6ZXw4Vws= github.com/prometheus/procfs v0.17.0 h1:FuLQ+05u4ZI+SS/w9+BWEM2TXiHKsUQ9TADiRH7DuK0=
github.com/prometheus/procfs v0.19.2/go.mod h1:M0aotyiemPhBCM0z5w87kL22CxfcH05ZpYlu+b4J7mw= github.com/prometheus/procfs v0.17.0/go.mod h1:oPQLaDAMRbA+u8H5Pbfq+dl3VDAvHxMUOVhe0wYB2zw=
github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI= github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI=
github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg= github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg=
github.com/quic-go/quic-go v0.55.0 h1:zccPQIqYCXDt5NmcEabyYvOnomjs8Tlwl7tISjJh9Mk= github.com/quic-go/quic-go v0.55.0 h1:zccPQIqYCXDt5NmcEabyYvOnomjs8Tlwl7tISjJh9Mk=
@@ -323,8 +323,8 @@ golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1m
golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04= golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04=
golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0= golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 h1:mgKeJMpvi0yx/sU5GsxQ7p6s2wtOnGAHZWCHUM4KGzY= golang.org/x/exp v0.0.0-20251017212417-90e834f514db h1:by6IehL4BH5k3e3SJmcoNbOobMey2SLpAF79iPOEBvw=
golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546/go.mod h1:j/pmGrbnkbPtQfxEe5D0VQhZC6qKbfKifgD0oM7sR70= golang.org/x/exp v0.0.0-20251017212417-90e834f514db/go.mod h1:j/pmGrbnkbPtQfxEe5D0VQhZC6qKbfKifgD0oM7sR70=
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
@@ -396,8 +396,8 @@ golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ= golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ=
golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/telemetry v0.0.0-20251028164327-d7a2859f34e8 h1:DwMAzqwLj2rVin75cRFh1kfhwQY3hyHrU1oCEDZXPmQ= golang.org/x/telemetry v0.0.0-20251014153721-24f779f6aaef h1:5xFtU4tmJMJSxSeDlr1dgBff2tDXrq0laLdS1EA3LYw=
golang.org/x/telemetry v0.0.0-20251028164327-d7a2859f34e8/go.mod h1:Pi4ztBfryZoJEkyFTI5/Ocsu2jXyDr6iSdgJiYE/uwE= golang.org/x/telemetry v0.0.0-20251014153721-24f779f6aaef/go.mod h1:Pi4ztBfryZoJEkyFTI5/Ocsu2jXyDr6iSdgJiYE/uwE=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=

View File

@@ -2,7 +2,6 @@ package common
import ( import (
"fmt" "fmt"
"github.com/pion/interceptor/pkg/nack"
"log/slog" "log/slog"
"strconv" "strconv"
@@ -31,121 +30,20 @@ func InitWebRTCAPI() error {
return fmt.Errorf("failed to register extensions: %w", err) return fmt.Errorf("failed to register extensions: %w", err)
} }
// Register codecs // Default codecs cover our needs
for _, codec := range []webrtc.RTPCodecParameters{ err = mediaEngine.RegisterDefaultCodecs()
{ if err != nil {
RTPCodecCapability: webrtc.RTPCodecCapability{MimeType: webrtc.MimeTypeOpus, ClockRate: 48000, Channels: 2, SDPFmtpLine: "minptime=10;useinbandfec=1"},
PayloadType: 111,
},
} {
if err = mediaEngine.RegisterCodec(codec, webrtc.RTPCodecTypeAudio); err != nil {
return err return err
} }
}
videoRTCPFeedback := []webrtc.RTCPFeedback{{"nack", ""}, {"nack", "pli"}}
for _, codec := range []webrtc.RTPCodecParameters{
{
RTPCodecCapability: webrtc.RTPCodecCapability{
MimeType: webrtc.MimeTypeH264, ClockRate: 90000,
SDPFmtpLine: "level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f",
RTCPFeedback: videoRTCPFeedback,
},
PayloadType: 102,
},
{
RTPCodecCapability: webrtc.RTPCodecCapability{
MimeType: webrtc.MimeTypeH264, ClockRate: 90000,
SDPFmtpLine: "level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=42001f",
RTCPFeedback: videoRTCPFeedback,
},
PayloadType: 104,
},
{
RTPCodecCapability: webrtc.RTPCodecCapability{
MimeType: webrtc.MimeTypeH264, ClockRate: 90000,
SDPFmtpLine: "level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f",
RTCPFeedback: videoRTCPFeedback,
},
PayloadType: 106,
},
{
RTPCodecCapability: webrtc.RTPCodecCapability{
MimeType: webrtc.MimeTypeH264, ClockRate: 90000,
SDPFmtpLine: "level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=42e01f",
RTCPFeedback: videoRTCPFeedback,
},
PayloadType: 108,
},
{
RTPCodecCapability: webrtc.RTPCodecCapability{
MimeType: webrtc.MimeTypeH264, ClockRate: 90000,
SDPFmtpLine: "level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=4d001f",
RTCPFeedback: videoRTCPFeedback,
},
PayloadType: 127,
},
{
RTPCodecCapability: webrtc.RTPCodecCapability{
MimeType: webrtc.MimeTypeH264,
ClockRate: 90000,
SDPFmtpLine: "level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=4d001f",
RTCPFeedback: videoRTCPFeedback,
},
PayloadType: 39,
},
{
RTPCodecCapability: webrtc.RTPCodecCapability{
MimeType: webrtc.MimeTypeH265,
ClockRate: 90000,
RTCPFeedback: videoRTCPFeedback,
},
PayloadType: 116,
},
{
RTPCodecCapability: webrtc.RTPCodecCapability{MimeType: webrtc.MimeTypeAV1, ClockRate: 90000, RTCPFeedback: videoRTCPFeedback},
PayloadType: 45,
},
{
RTPCodecCapability: webrtc.RTPCodecCapability{MimeType: webrtc.MimeTypeVP9, ClockRate: 90000, SDPFmtpLine: "profile-id=0", RTCPFeedback: videoRTCPFeedback},
PayloadType: 98,
},
{
RTPCodecCapability: webrtc.RTPCodecCapability{MimeType: webrtc.MimeTypeVP9, ClockRate: 90000, SDPFmtpLine: "profile-id=2", RTCPFeedback: videoRTCPFeedback},
PayloadType: 100,
},
{
RTPCodecCapability: webrtc.RTPCodecCapability{
MimeType: webrtc.MimeTypeH264, ClockRate: 90000,
SDPFmtpLine: "level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=64001f",
RTCPFeedback: videoRTCPFeedback,
},
PayloadType: 112,
},
} {
if err = mediaEngine.RegisterCodec(codec, webrtc.RTPCodecTypeVideo); err != nil {
return err
}
}
// Interceptor registry // Interceptor registry
interceptorRegistry := &interceptor.Registry{} interceptorRegistry := &interceptor.Registry{}
// Register our interceptors.. // Use default set
nackGenFactory, err := nack.NewGeneratorInterceptor() err = webrtc.RegisterDefaultInterceptors(mediaEngine, interceptorRegistry)
if err != nil { if err != nil {
return err return err
} }
interceptorRegistry.Add(nackGenFactory)
nackRespFactory, err := nack.NewResponderInterceptor()
if err != nil {
return err
}
interceptorRegistry.Add(nackRespFactory)
if err = webrtc.ConfigureRTCPReports(interceptorRegistry); err != nil {
return err
}
// Setting engine // Setting engine
settingEngine := webrtc.SettingEngine{} settingEngine := webrtc.SettingEngine{}
@@ -155,7 +53,7 @@ func InitWebRTCAPI() error {
nat11IP := GetFlags().NAT11IP nat11IP := GetFlags().NAT11IP
if len(nat11IP) > 0 { if len(nat11IP) > 0 {
settingEngine.SetNAT1To1IPs([]string{nat11IP}, webrtc.ICECandidateTypeHost) settingEngine.SetNAT1To1IPs([]string{nat11IP}, webrtc.ICECandidateTypeSrflx)
slog.Info("Using NAT 1:1 IP for WebRTC", "nat11_ip", nat11IP) slog.Info("Using NAT 1:1 IP for WebRTC", "nat11_ip", nat11IP)
} }

View File

@@ -125,7 +125,7 @@ func getLocalIP() string {
return "" return ""
} }
for _, address := range addrs { for _, address := range addrs {
if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() && !ipnet.IP.IsPrivate() && !ipnet.IP.IsUnspecified() { if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
if ipnet.IP.To4() != nil || ipnet.IP != nil { if ipnet.IP.To4() != nil || ipnet.IP != nil {
return ipnet.IP.String() return ipnet.IP.String()
} }

View File

@@ -1,53 +0,0 @@
package common
import (
"log/slog"
"github.com/pion/webrtc/v4"
)
// ICEHelper holds webrtc.ICECandidateInit(s) until remote candidate is set for given webrtc.PeerConnection
// Held candidates should be flushed at the end of negotiation to ensure all are available for connection
type ICEHelper struct {
candidates []webrtc.ICECandidateInit
pc *webrtc.PeerConnection
}
func NewICEHelper(pc *webrtc.PeerConnection) *ICEHelper {
return &ICEHelper{
pc: pc,
candidates: make([]webrtc.ICECandidateInit, 0),
}
}
func (ice *ICEHelper) SetPeerConnection(pc *webrtc.PeerConnection) {
ice.pc = pc
}
func (ice *ICEHelper) AddCandidate(c webrtc.ICECandidateInit) {
if ice.pc != nil {
if ice.pc.RemoteDescription() != nil {
// Add immediately if remote is set
if err := ice.pc.AddICECandidate(c); err != nil {
slog.Error("Failed to add ICE candidate", "err", err)
}
// Also flush held candidates automatically
ice.FlushHeldCandidates()
} else {
// Hold in slice until remote is set
ice.candidates = append(ice.candidates, c)
}
}
}
func (ice *ICEHelper) FlushHeldCandidates() {
if ice.pc != nil && len(ice.candidates) > 0 {
for _, heldCandidate := range ice.candidates {
if err := ice.pc.AddICECandidate(heldCandidate); err != nil {
slog.Error("Failed to add held ICE candidate", "err", err)
}
}
// Clear the held candidates
ice.candidates = make([]webrtc.ICECandidateInit, 0)
}
}

View File

@@ -10,6 +10,7 @@ import (
"os" "os"
"relay/internal/common" "relay/internal/common"
"relay/internal/shared" "relay/internal/shared"
"time"
"github.com/libp2p/go-libp2p" "github.com/libp2p/go-libp2p"
pubsub "github.com/libp2p/go-libp2p-pubsub" pubsub "github.com/libp2p/go-libp2p-pubsub"
@@ -20,9 +21,9 @@ import (
rcmgr "github.com/libp2p/go-libp2p/p2p/host/resource-manager" rcmgr "github.com/libp2p/go-libp2p/p2p/host/resource-manager"
"github.com/libp2p/go-libp2p/p2p/protocol/ping" "github.com/libp2p/go-libp2p/p2p/protocol/ping"
"github.com/libp2p/go-libp2p/p2p/security/noise" "github.com/libp2p/go-libp2p/p2p/security/noise"
p2pquic "github.com/libp2p/go-libp2p/p2p/transport/quic"
"github.com/libp2p/go-libp2p/p2p/transport/quicreuse" "github.com/libp2p/go-libp2p/p2p/transport/quicreuse"
"github.com/libp2p/go-libp2p/p2p/transport/tcp" "github.com/libp2p/go-libp2p/p2p/transport/tcp"
ws "github.com/libp2p/go-libp2p/p2p/transport/websocket"
webtransport "github.com/libp2p/go-libp2p/p2p/transport/webtransport" webtransport "github.com/libp2p/go-libp2p/p2p/transport/webtransport"
"github.com/multiformats/go-multiaddr" "github.com/multiformats/go-multiaddr"
"github.com/oklog/ulid/v2" "github.com/oklog/ulid/v2"
@@ -37,6 +38,16 @@ var globalRelay *Relay
// -- Structs -- // -- Structs --
// ClientSession tracks browser client connections
type ClientSession struct {
PeerID peer.ID
SessionID string
RoomName string
ConnectedAt time.Time
LastActivity time.Time
ControllerSlots []int32 // Track which controller slots this client owns
}
// Relay structure enhanced with metrics and state // Relay structure enhanced with metrics and state
type Relay struct { type Relay struct {
*PeerInfo *PeerInfo
@@ -48,6 +59,7 @@ type Relay struct {
// Local // Local
LocalRooms *common.SafeMap[ulid.ULID, *shared.Room] // room ID -> local Room struct (hosted by this relay) LocalRooms *common.SafeMap[ulid.ULID, *shared.Room] // room ID -> local Room struct (hosted by this relay)
LocalMeshConnections *common.SafeMap[peer.ID, *webrtc.PeerConnection] // peer ID -> PeerConnection (connected to this relay) LocalMeshConnections *common.SafeMap[peer.ID, *webrtc.PeerConnection] // peer ID -> PeerConnection (connected to this relay)
ClientSessions *common.SafeMap[peer.ID, *ClientSession] // peer ID -> ClientSession
// Protocols // Protocols
ProtocolRegistry ProtocolRegistry
@@ -91,10 +103,10 @@ func NewRelay(ctx context.Context, port int, identityKey crypto.PrivKey) (*Relay
listenAddrs := []string{ listenAddrs := []string{
fmt.Sprintf("/ip4/0.0.0.0/tcp/%d", port), // IPv4 - Raw TCP fmt.Sprintf("/ip4/0.0.0.0/tcp/%d", port), // IPv4 - Raw TCP
fmt.Sprintf("/ip6/::/tcp/%d", port), // IPv6 - Raw TCP fmt.Sprintf("/ip6/::/tcp/%d", port), // IPv6 - Raw TCP
fmt.Sprintf("/ip4/0.0.0.0/tcp/%d/ws", port), // IPv4 - TCP WebSocket
fmt.Sprintf("/ip6/::/tcp/%d/ws", port), // IPv6 - TCP WebSocket
fmt.Sprintf("/ip4/0.0.0.0/udp/%d/quic-v1/webtransport", port), // IPv4 - UDP QUIC WebTransport fmt.Sprintf("/ip4/0.0.0.0/udp/%d/quic-v1/webtransport", port), // IPv4 - UDP QUIC WebTransport
fmt.Sprintf("/ip6/::/udp/%d/quic-v1/webtransport", port), // IPv6 - UDP QUIC WebTransport fmt.Sprintf("/ip6/::/udp/%d/quic-v1/webtransport", port), // IPv6 - UDP QUIC WebTransport
fmt.Sprintf("/ip4/0.0.0.0/udp/%d/quic-v1", port), // IPv4 - UDP Raw QUIC
fmt.Sprintf("/ip6/::/udp/%d/quic-v1", port), // IPv6 - UDP Raw QUIC
} }
var muAddrs []multiaddr.Multiaddr var muAddrs []multiaddr.Multiaddr
@@ -112,8 +124,8 @@ func NewRelay(ctx context.Context, port int, identityKey crypto.PrivKey) (*Relay
libp2p.Identity(identityKey), libp2p.Identity(identityKey),
// Enable required transports // Enable required transports
libp2p.Transport(tcp.NewTCPTransport), libp2p.Transport(tcp.NewTCPTransport),
libp2p.Transport(ws.New),
libp2p.Transport(webtransport.New), libp2p.Transport(webtransport.New),
libp2p.Transport(p2pquic.NewTransport),
// Other options // Other options
libp2p.ListenAddrs(muAddrs...), libp2p.ListenAddrs(muAddrs...),
libp2p.Security(noise.ID, noise.New), libp2p.Security(noise.ID, noise.New),
@@ -144,6 +156,7 @@ func NewRelay(ctx context.Context, port int, identityKey crypto.PrivKey) (*Relay
PingService: pingSvc, PingService: pingSvc,
LocalRooms: common.NewSafeMap[ulid.ULID, *shared.Room](), LocalRooms: common.NewSafeMap[ulid.ULID, *shared.Room](),
LocalMeshConnections: common.NewSafeMap[peer.ID, *webrtc.PeerConnection](), LocalMeshConnections: common.NewSafeMap[peer.ID, *webrtc.PeerConnection](),
ClientSessions: common.NewSafeMap[peer.ID, *ClientSession](),
} }
// Add network notifier after relay is initialized // Add network notifier after relay is initialized

View File

@@ -7,9 +7,11 @@ import (
"fmt" "fmt"
"io" "io"
"log/slog" "log/slog"
"math"
"relay/internal/common" "relay/internal/common"
"relay/internal/connections" "relay/internal/connections"
"relay/internal/shared" "relay/internal/shared"
"time"
gen "relay/internal/proto" gen "relay/internal/proto"
@@ -70,7 +72,7 @@ func (sp *StreamProtocol) handleStreamRequest(stream network.Stream) {
safeBRW := common.NewSafeBufioRW(brw) safeBRW := common.NewSafeBufioRW(brw)
var currentRoomName string // Track the current room for this stream var currentRoomName string // Track the current room for this stream
iceHelper := common.NewICEHelper(nil) iceHolder := make([]webrtc.ICECandidateInit, 0)
for { for {
var msgWrapper gen.ProtoMessage var msgWrapper gen.ProtoMessage
err := safeBRW.ReceiveProto(&msgWrapper) err := safeBRW.ReceiveProto(&msgWrapper)
@@ -109,7 +111,16 @@ func (sp *StreamProtocol) handleStreamRequest(stream network.Stream) {
sessionID = ulid.String() sessionID = ulid.String()
} }
slog.Info("Client session requested room stream", "session", sessionID, "room", reqMsg.RoomName) session := &ClientSession{
PeerID: stream.Conn().RemotePeer(),
SessionID: sessionID,
RoomName: reqMsg.RoomName,
ConnectedAt: time.Now(),
LastActivity: time.Now(),
}
sp.relay.ClientSessions.Set(stream.Conn().RemotePeer(), session)
slog.Info("Client session established", "peer", session.PeerID, "session", sessionID, "room", reqMsg.RoomName)
// Send session ID back to client // Send session ID back to client
sesMsg, err := common.CreateMessage( sesMsg, err := common.CreateMessage(
@@ -166,7 +177,7 @@ func (sp *StreamProtocol) handleStreamRequest(stream network.Stream) {
// Create participant for this viewer // Create participant for this viewer
participant, err := shared.NewParticipant( participant, err := shared.NewParticipant(
sessionID, "",
stream.Conn().RemotePeer(), stream.Conn().RemotePeer(),
) )
if err != nil { if err != nil {
@@ -174,9 +185,13 @@ func (sp *StreamProtocol) handleStreamRequest(stream network.Stream) {
continue continue
} }
// If this is a client session, link it
if session, ok := sp.relay.ClientSessions.Get(stream.Conn().RemotePeer()); ok {
participant.SessionID = session.SessionID
}
// Assign peer connection // Assign peer connection
participant.PeerConnection = pc participant.PeerConnection = pc
iceHelper.SetPeerConnection(pc)
// Add audio/video tracks // Add audio/video tracks
{ {
@@ -250,9 +265,57 @@ func (sp *StreamProtocol) handleStreamRequest(stream network.Stream) {
// Track controller input separately // Track controller input separately
ndc.RegisterMessageCallback("controllerInput", func(data []byte) { ndc.RegisterMessageCallback("controllerInput", func(data []byte) {
// Parse the message to track controller slots for client sessions // Parse the message to track controller slots for client sessions
var controllerMsgWrapper gen.ProtoMessage var msgWrapper gen.ProtoMessage
if err = proto.Unmarshal(data, &controllerMsgWrapper); err != nil { if err = proto.Unmarshal(data, &msgWrapper); err != nil {
slog.Error("Failed to unmarshal controller input", "err", err) slog.Error("Failed to unmarshal controller input", "err", err)
} else if msgWrapper.Payload != nil {
// Get the peer ID for this connection
peerID := stream.Conn().RemotePeer()
// Check if it's a controller attach with assigned slot
if attach := msgWrapper.GetControllerAttach(); attach != nil && attach.SessionSlot >= 0 {
if session, ok := sp.relay.ClientSessions.Get(peerID); ok {
// Check if slot already tracked
hasSlot := false
for _, slot := range session.ControllerSlots {
if slot == attach.SessionSlot {
hasSlot = true
break
}
}
if !hasSlot {
session.ControllerSlots = append(session.ControllerSlots, attach.SessionSlot)
session.LastActivity = time.Now()
slog.Info("Controller slot assigned to client session",
"session", session.SessionID,
"slot", attach.SessionSlot,
"total_slots", len(session.ControllerSlots))
}
}
}
// Check if it's a controller detach
if detach := msgWrapper.GetControllerDetach(); detach != nil && detach.SessionSlot >= 0 {
if session, ok := sp.relay.ClientSessions.Get(peerID); ok {
newSlots := make([]int32, 0, len(session.ControllerSlots))
for _, slot := range session.ControllerSlots {
if slot != detach.SessionSlot {
newSlots = append(newSlots, slot)
}
}
session.ControllerSlots = newSlots
session.LastActivity = time.Now()
slog.Info("Controller slot removed from client session",
"session", session.SessionID,
"slot", detach.SessionSlot,
"remaining_slots", len(session.ControllerSlots))
}
}
// Update last activity on any controller input
if session, ok := sp.relay.ClientSessions.Get(peerID); ok {
session.LastActivity = time.Now()
}
} }
// Forward to upstream room // Forward to upstream room
@@ -270,16 +333,12 @@ func (sp *StreamProtocol) handleStreamRequest(stream network.Stream) {
} }
candInit := candidate.ToJSON() candInit := candidate.ToJSON()
var sdpMLineIndex *uint32 biggified := uint32(*candInit.SDPMLineIndex)
if candInit.SDPMLineIndex != nil {
idx := uint32(*candInit.SDPMLineIndex)
sdpMLineIndex = &idx
}
iceMsg, err := common.CreateMessage( iceMsg, err := common.CreateMessage(
&gen.ProtoICE{ &gen.ProtoICE{
Candidate: &gen.RTCIceCandidateInit{ Candidate: &gen.RTCIceCandidateInit{
Candidate: candInit.Candidate, Candidate: candInit.Candidate,
SdpMLineIndex: sdpMLineIndex, SdpMLineIndex: &biggified,
SdpMid: candInit.SDPMid, SdpMid: candInit.SDPMid,
}, },
}, },
@@ -341,16 +400,36 @@ func (sp *StreamProtocol) handleStreamRequest(stream network.Stream) {
case "ice-candidate": case "ice-candidate":
iceMsg := msgWrapper.GetIce() iceMsg := msgWrapper.GetIce()
if iceMsg != nil { if iceMsg != nil {
smollified := uint16(*iceMsg.Candidate.SdpMLineIndex)
cand := webrtc.ICECandidateInit{ cand := webrtc.ICECandidateInit{
Candidate: iceMsg.Candidate.Candidate, Candidate: iceMsg.Candidate.Candidate,
SDPMid: iceMsg.Candidate.SdpMid, SDPMid: iceMsg.Candidate.SdpMid,
SDPMLineIndex: &smollified,
UsernameFragment: iceMsg.Candidate.UsernameFragment, UsernameFragment: iceMsg.Candidate.UsernameFragment,
} }
if iceMsg.Candidate.SdpMLineIndex != nil { // Use currentRoomName to get the connection from nested map
smollified := uint16(*iceMsg.Candidate.SdpMLineIndex) if len(currentRoomName) > 0 {
cand.SDPMLineIndex = &smollified if roomMap, ok := sp.servedConns.Get(currentRoomName); ok {
if conn, ok := roomMap.Get(stream.Conn().RemotePeer()); ok && conn.pc.RemoteDescription() != nil {
if err = conn.pc.AddICECandidate(cand); err != nil {
slog.Error("Failed to add ICE candidate", "err", err)
}
for _, heldIce := range iceHolder {
if err := conn.pc.AddICECandidate(heldIce); err != nil {
slog.Error("Failed to add held ICE candidate", "err", err)
}
}
// Clear the held candidates
iceHolder = make([]webrtc.ICECandidateInit, 0)
} else {
// Hold the candidate until remote description is set
iceHolder = append(iceHolder, cand)
}
}
} else {
// Hold the candidate until remote description is set
iceHolder = append(iceHolder, cand)
} }
iceHelper.AddCandidate(cand)
} else { } else {
slog.Error("Could not GetIce from ice-candidate") slog.Error("Could not GetIce from ice-candidate")
} }
@@ -370,8 +449,6 @@ func (sp *StreamProtocol) handleStreamRequest(stream network.Stream) {
continue continue
} }
slog.Debug("Set remote description for answer") slog.Debug("Set remote description for answer")
// Flush held candidates now if missed before (race-condition)
iceHelper.FlushHeldCandidates()
} else { } else {
slog.Warn("Received answer without active PeerConnection") slog.Warn("Received answer without active PeerConnection")
} }
@@ -392,7 +469,7 @@ func (sp *StreamProtocol) handleStreamPush(stream network.Stream) {
safeBRW := common.NewSafeBufioRW(brw) safeBRW := common.NewSafeBufioRW(brw)
var room *shared.Room var room *shared.Room
iceHelper := common.NewICEHelper(nil) iceHolder := make([]webrtc.ICECandidateInit, 0)
for { for {
var msgWrapper gen.ProtoMessage var msgWrapper gen.ProtoMessage
err := safeBRW.ReceiveProto(&msgWrapper) err := safeBRW.ReceiveProto(&msgWrapper)
@@ -401,7 +478,7 @@ func (sp *StreamProtocol) handleStreamPush(stream network.Stream) {
slog.Debug("Stream push connection closed by peer", "peer", stream.Conn().RemotePeer(), "error", err) slog.Debug("Stream push connection closed by peer", "peer", stream.Conn().RemotePeer(), "error", err)
if room != nil { if room != nil {
room.Close() room.Close()
sp.incomingConns.Delete(room.Name) sp.incomingConns.Set(room.Name, nil)
} }
return return
} }
@@ -410,7 +487,7 @@ func (sp *StreamProtocol) handleStreamPush(stream network.Stream) {
_ = stream.Reset() _ = stream.Reset()
if room != nil { if room != nil {
room.Close() room.Close()
sp.incomingConns.Delete(room.Name) sp.incomingConns.Set(room.Name, nil)
} }
return return
} }
@@ -469,7 +546,21 @@ func (sp *StreamProtocol) handleStreamPush(stream network.Stream) {
SDPMLineIndex: &smollified, SDPMLineIndex: &smollified,
UsernameFragment: iceMsg.Candidate.UsernameFragment, UsernameFragment: iceMsg.Candidate.UsernameFragment,
} }
iceHelper.AddCandidate(cand) if conn, ok := sp.incomingConns.Get(room.Name); ok && conn.pc.RemoteDescription() != nil {
if err = conn.pc.AddICECandidate(cand); err != nil {
slog.Error("Failed to add ICE candidate for pushed stream", "err", err)
}
for _, heldIce := range iceHolder {
if err = conn.pc.AddICECandidate(heldIce); err != nil {
slog.Error("Failed to add held ICE candidate for pushed stream", "err", err)
}
}
// Clear the held candidates
iceHolder = make([]webrtc.ICECandidateInit, 0)
} else {
// Hold the candidate until remote description is set
iceHolder = append(iceHolder, cand)
}
} else { } else {
slog.Error("Failed to GetIce in pushed stream ice-candidate") slog.Error("Failed to GetIce in pushed stream ice-candidate")
} }
@@ -501,7 +592,6 @@ func (sp *StreamProtocol) handleStreamPush(stream network.Stream) {
// Assign room peer connection // Assign room peer connection
room.PeerConnection = pc room.PeerConnection = pc
iceHelper.SetPeerConnection(pc)
pc.OnDataChannel(func(dc *webrtc.DataChannel) { pc.OnDataChannel(func(dc *webrtc.DataChannel) {
// TODO: Is this the best way to handle DataChannel? Should we just use the map directly? // TODO: Is this the best way to handle DataChannel? Should we just use the map directly?
@@ -519,14 +609,9 @@ func (sp *StreamProtocol) handleStreamPush(stream network.Stream) {
roomMap.Range(func(peerID peer.ID, conn *StreamConnection) bool { roomMap.Range(func(peerID peer.ID, conn *StreamConnection) bool {
if conn.ndc != nil { if conn.ndc != nil {
if err = conn.ndc.SendBinary(data); err != nil { if err = conn.ndc.SendBinary(data); err != nil {
if errors.Is(err, io.ErrClosedPipe) {
slog.Warn("Failed to forward controller input to viewer, treating as disconnected", "err", err)
sp.relay.onPeerDisconnected(peerID)
} else {
slog.Error("Failed to forward controller input from pushed stream to viewer", "room", room.Name, "peer", peerID, "err", err) slog.Error("Failed to forward controller input from pushed stream to viewer", "room", room.Name, "peer", peerID, "err", err)
} }
} }
}
return true return true
}) })
} }
@@ -605,8 +690,52 @@ func (sp *StreamProtocol) handleStreamPush(stream network.Stream) {
} }
} }
// Broadcast // Calculate differences
room.BroadcastPacket(remoteTrack.Kind(), rtpPacket) var timeDiff int64
var sequenceDiff int
if remoteTrack.Kind() == webrtc.RTPCodecTypeVideo {
timeDiff = int64(rtpPacket.Timestamp) - int64(room.LastVideoTimestamp)
if !room.VideoTimestampSet {
timeDiff = 0
room.VideoTimestampSet = true
} else if timeDiff < -(math.MaxUint32 / 10) {
timeDiff += math.MaxUint32 + 1
}
sequenceDiff = int(rtpPacket.SequenceNumber) - int(room.LastVideoSequenceNumber)
if !room.VideoSequenceSet {
sequenceDiff = 0
room.VideoSequenceSet = true
} else if sequenceDiff < -(math.MaxUint16 / 10) {
sequenceDiff += math.MaxUint16 + 1
}
room.LastVideoTimestamp = rtpPacket.Timestamp
room.LastVideoSequenceNumber = rtpPacket.SequenceNumber
} else { // Audio
timeDiff = int64(rtpPacket.Timestamp) - int64(room.LastAudioTimestamp)
if !room.AudioTimestampSet {
timeDiff = 0
room.AudioTimestampSet = true
} else if timeDiff < -(math.MaxUint32 / 10) {
timeDiff += math.MaxUint32 + 1
}
sequenceDiff = int(rtpPacket.SequenceNumber) - int(room.LastAudioSequenceNumber)
if !room.AudioSequenceSet {
sequenceDiff = 0
room.AudioSequenceSet = true
} else if sequenceDiff < -(math.MaxUint16 / 10) {
sequenceDiff += math.MaxUint16 + 1
}
room.LastAudioTimestamp = rtpPacket.Timestamp
room.LastAudioSequenceNumber = rtpPacket.SequenceNumber
}
// Broadcast with differences
room.BroadcastPacketRetimed(remoteTrack.Kind(), rtpPacket, timeDiff, sequenceDiff)
} }
slog.Debug("Track closed for room", "room", room.Name, "track_kind", remoteTrack.Kind().String()) slog.Debug("Track closed for room", "room", room.Name, "track_kind", remoteTrack.Kind().String())
@@ -618,8 +747,6 @@ func (sp *StreamProtocol) handleStreamPush(stream network.Stream) {
continue continue
} }
slog.Debug("Set remote description for pushed stream", "room", room.Name) slog.Debug("Set remote description for pushed stream", "room", room.Name)
// Flush candidates now if they weren't before (race-condition)
iceHelper.FlushHeldCandidates()
// Create an answer // Create an answer
answer, err := pc.CreateAnswer(nil) answer, err := pc.CreateAnswer(nil)

View File

@@ -5,9 +5,14 @@ import (
"encoding/json" "encoding/json"
"errors" "errors"
"log/slog" "log/slog"
"relay/internal/common"
"relay/internal/shared" "relay/internal/shared"
"time" "time"
gen "relay/internal/proto"
"google.golang.org/protobuf/proto"
pubsub "github.com/libp2p/go-libp2p-pubsub" pubsub "github.com/libp2p/go-libp2p-pubsub"
"github.com/libp2p/go-libp2p/core/network" "github.com/libp2p/go-libp2p/core/network"
"github.com/libp2p/go-libp2p/core/peer" "github.com/libp2p/go-libp2p/core/peer"
@@ -129,6 +134,46 @@ func (r *Relay) onPeerConnected(peerID peer.ID) {
// onPeerDisconnected marks a peer as disconnected in our status view and removes latency info // onPeerDisconnected marks a peer as disconnected in our status view and removes latency info
func (r *Relay) onPeerDisconnected(peerID peer.ID) { func (r *Relay) onPeerDisconnected(peerID peer.ID) {
// Check if this was a client session disconnect
if session, ok := r.ClientSessions.Get(peerID); ok {
slog.Info("Client session disconnected",
"peer", peerID,
"session", session.SessionID,
"room", session.RoomName,
"controller_slots", session.ControllerSlots)
// Send cleanup message to nestri-server if client had active controllers
if len(session.ControllerSlots) > 0 {
room := r.GetRoomByName(session.RoomName)
if room != nil && room.DataChannel != nil {
// Create disconnect notification
disconnectMsg, err := common.CreateMessage(&gen.ProtoClientDisconnected{
SessionId: session.SessionID,
ControllerSlots: session.ControllerSlots,
}, "client-disconnected", nil)
if err != nil {
slog.Error("Failed to create client disconnect message", "err", err)
}
disMarshal, err := proto.Marshal(disconnectMsg)
if err != nil {
slog.Error("Failed to marshal client disconnect message", "err", err)
} else {
if err = room.DataChannel.SendBinary(disMarshal); err != nil {
slog.Error("Failed to send client disconnect notification", "err", err)
} else {
slog.Info("Sent controller cleanup notification to nestri-server",
"session", session.SessionID,
"slots", session.ControllerSlots)
}
}
}
}
r.ClientSessions.Delete(peerID)
return
}
// Relay peer disconnect handling // Relay peer disconnect handling
slog.Info("Mesh peer disconnected, deleting from local peer map", "peer", peerID) slog.Info("Mesh peer disconnected, deleting from local peer map", "peer", peerID)
if r.Peers.Has(peerID) { if r.Peers.Has(peerID) {

View File

@@ -87,8 +87,11 @@ type ProtoMessage struct {
// *ProtoMessage_KeyUp // *ProtoMessage_KeyUp
// *ProtoMessage_ControllerAttach // *ProtoMessage_ControllerAttach
// *ProtoMessage_ControllerDetach // *ProtoMessage_ControllerDetach
// *ProtoMessage_ControllerButton
// *ProtoMessage_ControllerTrigger
// *ProtoMessage_ControllerStick
// *ProtoMessage_ControllerAxis
// *ProtoMessage_ControllerRumble // *ProtoMessage_ControllerRumble
// *ProtoMessage_ControllerStateBatch
// *ProtoMessage_Ice // *ProtoMessage_Ice
// *ProtoMessage_Sdp // *ProtoMessage_Sdp
// *ProtoMessage_Raw // *ProtoMessage_Raw
@@ -225,19 +228,46 @@ func (x *ProtoMessage) GetControllerDetach() *ProtoControllerDetach {
return nil return nil
} }
func (x *ProtoMessage) GetControllerRumble() *ProtoControllerRumble { func (x *ProtoMessage) GetControllerButton() *ProtoControllerButton {
if x != nil { if x != nil {
if x, ok := x.Payload.(*ProtoMessage_ControllerRumble); ok { if x, ok := x.Payload.(*ProtoMessage_ControllerButton); ok {
return x.ControllerRumble return x.ControllerButton
} }
} }
return nil return nil
} }
func (x *ProtoMessage) GetControllerStateBatch() *ProtoControllerStateBatch { func (x *ProtoMessage) GetControllerTrigger() *ProtoControllerTrigger {
if x != nil { if x != nil {
if x, ok := x.Payload.(*ProtoMessage_ControllerStateBatch); ok { if x, ok := x.Payload.(*ProtoMessage_ControllerTrigger); ok {
return x.ControllerStateBatch return x.ControllerTrigger
}
}
return nil
}
func (x *ProtoMessage) GetControllerStick() *ProtoControllerStick {
if x != nil {
if x, ok := x.Payload.(*ProtoMessage_ControllerStick); ok {
return x.ControllerStick
}
}
return nil
}
func (x *ProtoMessage) GetControllerAxis() *ProtoControllerAxis {
if x != nil {
if x, ok := x.Payload.(*ProtoMessage_ControllerAxis); ok {
return x.ControllerAxis
}
}
return nil
}
func (x *ProtoMessage) GetControllerRumble() *ProtoControllerRumble {
if x != nil {
if x, ok := x.Payload.(*ProtoMessage_ControllerRumble); ok {
return x.ControllerRumble
} }
} }
return nil return nil
@@ -331,7 +361,6 @@ type ProtoMessage_KeyUp struct {
} }
type ProtoMessage_ControllerAttach struct { type ProtoMessage_ControllerAttach struct {
// Controller input types
ControllerAttach *ProtoControllerAttach `protobuf:"bytes,9,opt,name=controller_attach,json=controllerAttach,proto3,oneof"` ControllerAttach *ProtoControllerAttach `protobuf:"bytes,9,opt,name=controller_attach,json=controllerAttach,proto3,oneof"`
} }
@@ -339,12 +368,24 @@ type ProtoMessage_ControllerDetach struct {
ControllerDetach *ProtoControllerDetach `protobuf:"bytes,10,opt,name=controller_detach,json=controllerDetach,proto3,oneof"` ControllerDetach *ProtoControllerDetach `protobuf:"bytes,10,opt,name=controller_detach,json=controllerDetach,proto3,oneof"`
} }
type ProtoMessage_ControllerRumble struct { type ProtoMessage_ControllerButton struct {
ControllerRumble *ProtoControllerRumble `protobuf:"bytes,11,opt,name=controller_rumble,json=controllerRumble,proto3,oneof"` ControllerButton *ProtoControllerButton `protobuf:"bytes,11,opt,name=controller_button,json=controllerButton,proto3,oneof"`
} }
type ProtoMessage_ControllerStateBatch struct { type ProtoMessage_ControllerTrigger struct {
ControllerStateBatch *ProtoControllerStateBatch `protobuf:"bytes,12,opt,name=controller_state_batch,json=controllerStateBatch,proto3,oneof"` ControllerTrigger *ProtoControllerTrigger `protobuf:"bytes,12,opt,name=controller_trigger,json=controllerTrigger,proto3,oneof"`
}
type ProtoMessage_ControllerStick struct {
ControllerStick *ProtoControllerStick `protobuf:"bytes,13,opt,name=controller_stick,json=controllerStick,proto3,oneof"`
}
type ProtoMessage_ControllerAxis struct {
ControllerAxis *ProtoControllerAxis `protobuf:"bytes,14,opt,name=controller_axis,json=controllerAxis,proto3,oneof"`
}
type ProtoMessage_ControllerRumble struct {
ControllerRumble *ProtoControllerRumble `protobuf:"bytes,15,opt,name=controller_rumble,json=controllerRumble,proto3,oneof"`
} }
type ProtoMessage_Ice struct { type ProtoMessage_Ice struct {
@@ -390,9 +431,15 @@ func (*ProtoMessage_ControllerAttach) isProtoMessage_Payload() {}
func (*ProtoMessage_ControllerDetach) isProtoMessage_Payload() {} func (*ProtoMessage_ControllerDetach) isProtoMessage_Payload() {}
func (*ProtoMessage_ControllerRumble) isProtoMessage_Payload() {} func (*ProtoMessage_ControllerButton) isProtoMessage_Payload() {}
func (*ProtoMessage_ControllerStateBatch) isProtoMessage_Payload() {} func (*ProtoMessage_ControllerTrigger) isProtoMessage_Payload() {}
func (*ProtoMessage_ControllerStick) isProtoMessage_Payload() {}
func (*ProtoMessage_ControllerAxis) isProtoMessage_Payload() {}
func (*ProtoMessage_ControllerRumble) isProtoMessage_Payload() {}
func (*ProtoMessage_Ice) isProtoMessage_Payload() {} func (*ProtoMessage_Ice) isProtoMessage_Payload() {}
@@ -413,7 +460,8 @@ const file_messages_proto_rawDesc = "" +
"\x0emessages.proto\x12\x05proto\x1a\vtypes.proto\x1a\x15latency_tracker.proto\"k\n" + "\x0emessages.proto\x12\x05proto\x1a\vtypes.proto\x1a\x15latency_tracker.proto\"k\n" +
"\x10ProtoMessageBase\x12!\n" + "\x10ProtoMessageBase\x12!\n" +
"\fpayload_type\x18\x01 \x01(\tR\vpayloadType\x124\n" + "\fpayload_type\x18\x01 \x01(\tR\vpayloadType\x124\n" +
"\alatency\x18\x02 \x01(\v2\x1a.proto.ProtoLatencyTrackerR\alatency\"\x9b\t\n" + "\alatency\x18\x02 \x01(\v2\x1a.proto.ProtoLatencyTrackerR\alatency\"\xef\n" +
"\n" +
"\fProtoMessage\x12:\n" + "\fProtoMessage\x12:\n" +
"\fmessage_base\x18\x01 \x01(\v2\x17.proto.ProtoMessageBaseR\vmessageBase\x126\n" + "\fmessage_base\x18\x01 \x01(\v2\x17.proto.ProtoMessageBaseR\vmessageBase\x126\n" +
"\n" + "\n" +
@@ -429,8 +477,11 @@ const file_messages_proto_rawDesc = "" +
"\x11controller_attach\x18\t \x01(\v2\x1c.proto.ProtoControllerAttachH\x00R\x10controllerAttach\x12K\n" + "\x11controller_attach\x18\t \x01(\v2\x1c.proto.ProtoControllerAttachH\x00R\x10controllerAttach\x12K\n" +
"\x11controller_detach\x18\n" + "\x11controller_detach\x18\n" +
" \x01(\v2\x1c.proto.ProtoControllerDetachH\x00R\x10controllerDetach\x12K\n" + " \x01(\v2\x1c.proto.ProtoControllerDetachH\x00R\x10controllerDetach\x12K\n" +
"\x11controller_rumble\x18\v \x01(\v2\x1c.proto.ProtoControllerRumbleH\x00R\x10controllerRumble\x12X\n" + "\x11controller_button\x18\v \x01(\v2\x1c.proto.ProtoControllerButtonH\x00R\x10controllerButton\x12N\n" +
"\x16controller_state_batch\x18\f \x01(\v2 .proto.ProtoControllerStateBatchH\x00R\x14controllerStateBatch\x12#\n" + "\x12controller_trigger\x18\f \x01(\v2\x1d.proto.ProtoControllerTriggerH\x00R\x11controllerTrigger\x12H\n" +
"\x10controller_stick\x18\r \x01(\v2\x1b.proto.ProtoControllerStickH\x00R\x0fcontrollerStick\x12E\n" +
"\x0fcontroller_axis\x18\x0e \x01(\v2\x1a.proto.ProtoControllerAxisH\x00R\x0econtrollerAxis\x12K\n" +
"\x11controller_rumble\x18\x0f \x01(\v2\x1c.proto.ProtoControllerRumbleH\x00R\x10controllerRumble\x12#\n" +
"\x03ice\x18\x14 \x01(\v2\x0f.proto.ProtoICEH\x00R\x03ice\x12#\n" + "\x03ice\x18\x14 \x01(\v2\x0f.proto.ProtoICEH\x00R\x03ice\x12#\n" +
"\x03sdp\x18\x15 \x01(\v2\x0f.proto.ProtoSDPH\x00R\x03sdp\x12#\n" + "\x03sdp\x18\x15 \x01(\v2\x0f.proto.ProtoSDPH\x00R\x03sdp\x12#\n" +
"\x03raw\x18\x16 \x01(\v2\x0f.proto.ProtoRawH\x00R\x03raw\x12b\n" + "\x03raw\x18\x16 \x01(\v2\x0f.proto.ProtoRawH\x00R\x03raw\x12b\n" +
@@ -465,14 +516,17 @@ var file_messages_proto_goTypes = []any{
(*ProtoKeyUp)(nil), // 9: proto.ProtoKeyUp (*ProtoKeyUp)(nil), // 9: proto.ProtoKeyUp
(*ProtoControllerAttach)(nil), // 10: proto.ProtoControllerAttach (*ProtoControllerAttach)(nil), // 10: proto.ProtoControllerAttach
(*ProtoControllerDetach)(nil), // 11: proto.ProtoControllerDetach (*ProtoControllerDetach)(nil), // 11: proto.ProtoControllerDetach
(*ProtoControllerRumble)(nil), // 12: proto.ProtoControllerRumble (*ProtoControllerButton)(nil), // 12: proto.ProtoControllerButton
(*ProtoControllerStateBatch)(nil), // 13: proto.ProtoControllerStateBatch (*ProtoControllerTrigger)(nil), // 13: proto.ProtoControllerTrigger
(*ProtoICE)(nil), // 14: proto.ProtoICE (*ProtoControllerStick)(nil), // 14: proto.ProtoControllerStick
(*ProtoSDP)(nil), // 15: proto.ProtoSDP (*ProtoControllerAxis)(nil), // 15: proto.ProtoControllerAxis
(*ProtoRaw)(nil), // 16: proto.ProtoRaw (*ProtoControllerRumble)(nil), // 16: proto.ProtoControllerRumble
(*ProtoClientRequestRoomStream)(nil), // 17: proto.ProtoClientRequestRoomStream (*ProtoICE)(nil), // 17: proto.ProtoICE
(*ProtoClientDisconnected)(nil), // 18: proto.ProtoClientDisconnected (*ProtoSDP)(nil), // 18: proto.ProtoSDP
(*ProtoServerPushStream)(nil), // 19: proto.ProtoServerPushStream (*ProtoRaw)(nil), // 19: proto.ProtoRaw
(*ProtoClientRequestRoomStream)(nil), // 20: proto.ProtoClientRequestRoomStream
(*ProtoClientDisconnected)(nil), // 21: proto.ProtoClientDisconnected
(*ProtoServerPushStream)(nil), // 22: proto.ProtoServerPushStream
} }
var file_messages_proto_depIdxs = []int32{ var file_messages_proto_depIdxs = []int32{
2, // 0: proto.ProtoMessageBase.latency:type_name -> proto.ProtoLatencyTracker 2, // 0: proto.ProtoMessageBase.latency:type_name -> proto.ProtoLatencyTracker
@@ -486,19 +540,22 @@ var file_messages_proto_depIdxs = []int32{
9, // 8: proto.ProtoMessage.key_up:type_name -> proto.ProtoKeyUp 9, // 8: proto.ProtoMessage.key_up:type_name -> proto.ProtoKeyUp
10, // 9: proto.ProtoMessage.controller_attach:type_name -> proto.ProtoControllerAttach 10, // 9: proto.ProtoMessage.controller_attach:type_name -> proto.ProtoControllerAttach
11, // 10: proto.ProtoMessage.controller_detach:type_name -> proto.ProtoControllerDetach 11, // 10: proto.ProtoMessage.controller_detach:type_name -> proto.ProtoControllerDetach
12, // 11: proto.ProtoMessage.controller_rumble:type_name -> proto.ProtoControllerRumble 12, // 11: proto.ProtoMessage.controller_button:type_name -> proto.ProtoControllerButton
13, // 12: proto.ProtoMessage.controller_state_batch:type_name -> proto.ProtoControllerStateBatch 13, // 12: proto.ProtoMessage.controller_trigger:type_name -> proto.ProtoControllerTrigger
14, // 13: proto.ProtoMessage.ice:type_name -> proto.ProtoICE 14, // 13: proto.ProtoMessage.controller_stick:type_name -> proto.ProtoControllerStick
15, // 14: proto.ProtoMessage.sdp:type_name -> proto.ProtoSDP 15, // 14: proto.ProtoMessage.controller_axis:type_name -> proto.ProtoControllerAxis
16, // 15: proto.ProtoMessage.raw:type_name -> proto.ProtoRaw 16, // 15: proto.ProtoMessage.controller_rumble:type_name -> proto.ProtoControllerRumble
17, // 16: proto.ProtoMessage.client_request_room_stream:type_name -> proto.ProtoClientRequestRoomStream 17, // 16: proto.ProtoMessage.ice:type_name -> proto.ProtoICE
18, // 17: proto.ProtoMessage.client_disconnected:type_name -> proto.ProtoClientDisconnected 18, // 17: proto.ProtoMessage.sdp:type_name -> proto.ProtoSDP
19, // 18: proto.ProtoMessage.server_push_stream:type_name -> proto.ProtoServerPushStream 19, // 18: proto.ProtoMessage.raw:type_name -> proto.ProtoRaw
19, // [19:19] is the sub-list for method output_type 20, // 19: proto.ProtoMessage.client_request_room_stream:type_name -> proto.ProtoClientRequestRoomStream
19, // [19:19] is the sub-list for method input_type 21, // 20: proto.ProtoMessage.client_disconnected:type_name -> proto.ProtoClientDisconnected
19, // [19:19] is the sub-list for extension type_name 22, // 21: proto.ProtoMessage.server_push_stream:type_name -> proto.ProtoServerPushStream
19, // [19:19] is the sub-list for extension extendee 22, // [22:22] is the sub-list for method output_type
0, // [0:19] is the sub-list for field type_name 22, // [22:22] is the sub-list for method input_type
22, // [22:22] is the sub-list for extension type_name
22, // [22:22] is the sub-list for extension extendee
0, // [0:22] is the sub-list for field type_name
} }
func init() { file_messages_proto_init() } func init() { file_messages_proto_init() }
@@ -518,8 +575,11 @@ func file_messages_proto_init() {
(*ProtoMessage_KeyUp)(nil), (*ProtoMessage_KeyUp)(nil),
(*ProtoMessage_ControllerAttach)(nil), (*ProtoMessage_ControllerAttach)(nil),
(*ProtoMessage_ControllerDetach)(nil), (*ProtoMessage_ControllerDetach)(nil),
(*ProtoMessage_ControllerButton)(nil),
(*ProtoMessage_ControllerTrigger)(nil),
(*ProtoMessage_ControllerStick)(nil),
(*ProtoMessage_ControllerAxis)(nil),
(*ProtoMessage_ControllerRumble)(nil), (*ProtoMessage_ControllerRumble)(nil),
(*ProtoMessage_ControllerStateBatch)(nil),
(*ProtoMessage_Ice)(nil), (*ProtoMessage_Ice)(nil),
(*ProtoMessage_Sdp)(nil), (*ProtoMessage_Sdp)(nil),
(*ProtoMessage_Raw)(nil), (*ProtoMessage_Raw)(nil),

View File

@@ -21,52 +21,6 @@ const (
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
) )
type ProtoControllerStateBatch_UpdateType int32
const (
ProtoControllerStateBatch_FULL_STATE ProtoControllerStateBatch_UpdateType = 0 // Complete controller state
ProtoControllerStateBatch_DELTA ProtoControllerStateBatch_UpdateType = 1 // Only changed fields
)
// Enum value maps for ProtoControllerStateBatch_UpdateType.
var (
ProtoControllerStateBatch_UpdateType_name = map[int32]string{
0: "FULL_STATE",
1: "DELTA",
}
ProtoControllerStateBatch_UpdateType_value = map[string]int32{
"FULL_STATE": 0,
"DELTA": 1,
}
)
func (x ProtoControllerStateBatch_UpdateType) Enum() *ProtoControllerStateBatch_UpdateType {
p := new(ProtoControllerStateBatch_UpdateType)
*p = x
return p
}
func (x ProtoControllerStateBatch_UpdateType) String() string {
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
}
func (ProtoControllerStateBatch_UpdateType) Descriptor() protoreflect.EnumDescriptor {
return file_types_proto_enumTypes[0].Descriptor()
}
func (ProtoControllerStateBatch_UpdateType) Type() protoreflect.EnumType {
return &file_types_proto_enumTypes[0]
}
func (x ProtoControllerStateBatch_UpdateType) Number() protoreflect.EnumNumber {
return protoreflect.EnumNumber(x)
}
// Deprecated: Use ProtoControllerStateBatch_UpdateType.Descriptor instead.
func (ProtoControllerStateBatch_UpdateType) EnumDescriptor() ([]byte, []int) {
return file_types_proto_rawDescGZIP(), []int{10, 0}
}
// MouseMove message // MouseMove message
type ProtoMouseMove struct { type ProtoMouseMove struct {
state protoimpl.MessageState `protogen:"open.v1"` state protoimpl.MessageState `protogen:"open.v1"`
@@ -520,6 +474,290 @@ func (x *ProtoControllerDetach) GetSessionId() string {
return "" return ""
} }
// ControllerButton message
type ProtoControllerButton struct {
state protoimpl.MessageState `protogen:"open.v1"`
SessionSlot int32 `protobuf:"varint,1,opt,name=session_slot,json=sessionSlot,proto3" json:"session_slot,omitempty"` // Session specific slot number (0-3)
SessionId string `protobuf:"bytes,2,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"` // Session ID of the client
Button int32 `protobuf:"varint,3,opt,name=button,proto3" json:"button,omitempty"` // Button code (linux input event code)
Pressed bool `protobuf:"varint,4,opt,name=pressed,proto3" json:"pressed,omitempty"` // true if pressed, false if released
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *ProtoControllerButton) Reset() {
*x = ProtoControllerButton{}
mi := &file_types_proto_msgTypes[9]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ProtoControllerButton) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ProtoControllerButton) ProtoMessage() {}
func (x *ProtoControllerButton) ProtoReflect() protoreflect.Message {
mi := &file_types_proto_msgTypes[9]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ProtoControllerButton.ProtoReflect.Descriptor instead.
func (*ProtoControllerButton) Descriptor() ([]byte, []int) {
return file_types_proto_rawDescGZIP(), []int{9}
}
func (x *ProtoControllerButton) GetSessionSlot() int32 {
if x != nil {
return x.SessionSlot
}
return 0
}
func (x *ProtoControllerButton) GetSessionId() string {
if x != nil {
return x.SessionId
}
return ""
}
func (x *ProtoControllerButton) GetButton() int32 {
if x != nil {
return x.Button
}
return 0
}
func (x *ProtoControllerButton) GetPressed() bool {
if x != nil {
return x.Pressed
}
return false
}
// ControllerTriggers message
type ProtoControllerTrigger struct {
state protoimpl.MessageState `protogen:"open.v1"`
SessionSlot int32 `protobuf:"varint,1,opt,name=session_slot,json=sessionSlot,proto3" json:"session_slot,omitempty"` // Session specific slot number (0-3)
SessionId string `protobuf:"bytes,2,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"` // Session ID of the client
Trigger int32 `protobuf:"varint,3,opt,name=trigger,proto3" json:"trigger,omitempty"` // Trigger number (0 for left, 1 for right)
Value int32 `protobuf:"varint,4,opt,name=value,proto3" json:"value,omitempty"` // trigger value (-32768 to 32767)
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *ProtoControllerTrigger) Reset() {
*x = ProtoControllerTrigger{}
mi := &file_types_proto_msgTypes[10]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ProtoControllerTrigger) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ProtoControllerTrigger) ProtoMessage() {}
func (x *ProtoControllerTrigger) ProtoReflect() protoreflect.Message {
mi := &file_types_proto_msgTypes[10]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ProtoControllerTrigger.ProtoReflect.Descriptor instead.
func (*ProtoControllerTrigger) Descriptor() ([]byte, []int) {
return file_types_proto_rawDescGZIP(), []int{10}
}
func (x *ProtoControllerTrigger) GetSessionSlot() int32 {
if x != nil {
return x.SessionSlot
}
return 0
}
func (x *ProtoControllerTrigger) GetSessionId() string {
if x != nil {
return x.SessionId
}
return ""
}
func (x *ProtoControllerTrigger) GetTrigger() int32 {
if x != nil {
return x.Trigger
}
return 0
}
func (x *ProtoControllerTrigger) GetValue() int32 {
if x != nil {
return x.Value
}
return 0
}
// ControllerSticks message
type ProtoControllerStick struct {
state protoimpl.MessageState `protogen:"open.v1"`
SessionSlot int32 `protobuf:"varint,1,opt,name=session_slot,json=sessionSlot,proto3" json:"session_slot,omitempty"` // Session specific slot number (0-3)
SessionId string `protobuf:"bytes,2,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"` // Session ID of the client
Stick int32 `protobuf:"varint,3,opt,name=stick,proto3" json:"stick,omitempty"` // Stick number (0 for left, 1 for right)
X int32 `protobuf:"varint,4,opt,name=x,proto3" json:"x,omitempty"` // X axis value (-32768 to 32767)
Y int32 `protobuf:"varint,5,opt,name=y,proto3" json:"y,omitempty"` // Y axis value (-32768 to 32767)
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *ProtoControllerStick) Reset() {
*x = ProtoControllerStick{}
mi := &file_types_proto_msgTypes[11]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ProtoControllerStick) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ProtoControllerStick) ProtoMessage() {}
func (x *ProtoControllerStick) ProtoReflect() protoreflect.Message {
mi := &file_types_proto_msgTypes[11]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ProtoControllerStick.ProtoReflect.Descriptor instead.
func (*ProtoControllerStick) Descriptor() ([]byte, []int) {
return file_types_proto_rawDescGZIP(), []int{11}
}
func (x *ProtoControllerStick) GetSessionSlot() int32 {
if x != nil {
return x.SessionSlot
}
return 0
}
func (x *ProtoControllerStick) GetSessionId() string {
if x != nil {
return x.SessionId
}
return ""
}
func (x *ProtoControllerStick) GetStick() int32 {
if x != nil {
return x.Stick
}
return 0
}
func (x *ProtoControllerStick) GetX() int32 {
if x != nil {
return x.X
}
return 0
}
func (x *ProtoControllerStick) GetY() int32 {
if x != nil {
return x.Y
}
return 0
}
// ControllerAxis message
type ProtoControllerAxis struct {
state protoimpl.MessageState `protogen:"open.v1"`
SessionSlot int32 `protobuf:"varint,1,opt,name=session_slot,json=sessionSlot,proto3" json:"session_slot,omitempty"` // Session specific slot number (0-3)
SessionId string `protobuf:"bytes,2,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"` // Session ID of the client
Axis int32 `protobuf:"varint,3,opt,name=axis,proto3" json:"axis,omitempty"` // Axis number (0 for d-pad horizontal, 1 for d-pad vertical)
Value int32 `protobuf:"varint,4,opt,name=value,proto3" json:"value,omitempty"` // axis value (-1 to 1)
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *ProtoControllerAxis) Reset() {
*x = ProtoControllerAxis{}
mi := &file_types_proto_msgTypes[12]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ProtoControllerAxis) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ProtoControllerAxis) ProtoMessage() {}
func (x *ProtoControllerAxis) ProtoReflect() protoreflect.Message {
mi := &file_types_proto_msgTypes[12]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ProtoControllerAxis.ProtoReflect.Descriptor instead.
func (*ProtoControllerAxis) Descriptor() ([]byte, []int) {
return file_types_proto_rawDescGZIP(), []int{12}
}
func (x *ProtoControllerAxis) GetSessionSlot() int32 {
if x != nil {
return x.SessionSlot
}
return 0
}
func (x *ProtoControllerAxis) GetSessionId() string {
if x != nil {
return x.SessionId
}
return ""
}
func (x *ProtoControllerAxis) GetAxis() int32 {
if x != nil {
return x.Axis
}
return 0
}
func (x *ProtoControllerAxis) GetValue() int32 {
if x != nil {
return x.Value
}
return 0
}
// ControllerRumble message // ControllerRumble message
type ProtoControllerRumble struct { type ProtoControllerRumble struct {
state protoimpl.MessageState `protogen:"open.v1"` state protoimpl.MessageState `protogen:"open.v1"`
@@ -534,7 +772,7 @@ type ProtoControllerRumble struct {
func (x *ProtoControllerRumble) Reset() { func (x *ProtoControllerRumble) Reset() {
*x = ProtoControllerRumble{} *x = ProtoControllerRumble{}
mi := &file_types_proto_msgTypes[9] mi := &file_types_proto_msgTypes[13]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -546,7 +784,7 @@ func (x *ProtoControllerRumble) String() string {
func (*ProtoControllerRumble) ProtoMessage() {} func (*ProtoControllerRumble) ProtoMessage() {}
func (x *ProtoControllerRumble) ProtoReflect() protoreflect.Message { func (x *ProtoControllerRumble) ProtoReflect() protoreflect.Message {
mi := &file_types_proto_msgTypes[9] mi := &file_types_proto_msgTypes[13]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -559,7 +797,7 @@ func (x *ProtoControllerRumble) ProtoReflect() protoreflect.Message {
// Deprecated: Use ProtoControllerRumble.ProtoReflect.Descriptor instead. // Deprecated: Use ProtoControllerRumble.ProtoReflect.Descriptor instead.
func (*ProtoControllerRumble) Descriptor() ([]byte, []int) { func (*ProtoControllerRumble) Descriptor() ([]byte, []int) {
return file_types_proto_rawDescGZIP(), []int{9} return file_types_proto_rawDescGZIP(), []int{13}
} }
func (x *ProtoControllerRumble) GetSessionSlot() int32 { func (x *ProtoControllerRumble) GetSessionSlot() int32 {
@@ -597,160 +835,6 @@ func (x *ProtoControllerRumble) GetDuration() int32 {
return 0 return 0
} }
// ControllerStateBatch - single message containing full or partial controller state
type ProtoControllerStateBatch struct {
state protoimpl.MessageState `protogen:"open.v1"`
SessionSlot int32 `protobuf:"varint,1,opt,name=session_slot,json=sessionSlot,proto3" json:"session_slot,omitempty"` // Session specific slot number (0-3)
SessionId string `protobuf:"bytes,2,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"` // Session ID of the client
UpdateType ProtoControllerStateBatch_UpdateType `protobuf:"varint,3,opt,name=update_type,json=updateType,proto3,enum=proto.ProtoControllerStateBatch_UpdateType" json:"update_type,omitempty"`
// Sequence number for packet loss detection
Sequence uint32 `protobuf:"varint,4,opt,name=sequence,proto3" json:"sequence,omitempty"`
// Button state map (Linux event codes)
ButtonChangedMask map[int32]bool `protobuf:"bytes,5,rep,name=button_changed_mask,json=buttonChangedMask,proto3" json:"button_changed_mask,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"varint,2,opt,name=value"`
// Analog inputs
LeftStickX *int32 `protobuf:"varint,6,opt,name=left_stick_x,json=leftStickX,proto3,oneof" json:"left_stick_x,omitempty"` // -32768 to 32767
LeftStickY *int32 `protobuf:"varint,7,opt,name=left_stick_y,json=leftStickY,proto3,oneof" json:"left_stick_y,omitempty"` // -32768 to 32767
RightStickX *int32 `protobuf:"varint,8,opt,name=right_stick_x,json=rightStickX,proto3,oneof" json:"right_stick_x,omitempty"` // -32768 to 32767
RightStickY *int32 `protobuf:"varint,9,opt,name=right_stick_y,json=rightStickY,proto3,oneof" json:"right_stick_y,omitempty"` // -32768 to 32767
LeftTrigger *int32 `protobuf:"varint,10,opt,name=left_trigger,json=leftTrigger,proto3,oneof" json:"left_trigger,omitempty"` // -32768 to 32767
RightTrigger *int32 `protobuf:"varint,11,opt,name=right_trigger,json=rightTrigger,proto3,oneof" json:"right_trigger,omitempty"` // -32768 to 32767
DpadX *int32 `protobuf:"varint,12,opt,name=dpad_x,json=dpadX,proto3,oneof" json:"dpad_x,omitempty"` // -1, 0, or 1
DpadY *int32 `protobuf:"varint,13,opt,name=dpad_y,json=dpadY,proto3,oneof" json:"dpad_y,omitempty"` // -1, 0, or 1
// Bitmask indicating which fields have changed
// Bit 0: button_changed_mask, Bit 1: left_stick_x, Bit 2: left_stick_y, etc.
ChangedFields *uint32 `protobuf:"varint,14,opt,name=changed_fields,json=changedFields,proto3,oneof" json:"changed_fields,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *ProtoControllerStateBatch) Reset() {
*x = ProtoControllerStateBatch{}
mi := &file_types_proto_msgTypes[10]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ProtoControllerStateBatch) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ProtoControllerStateBatch) ProtoMessage() {}
func (x *ProtoControllerStateBatch) ProtoReflect() protoreflect.Message {
mi := &file_types_proto_msgTypes[10]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ProtoControllerStateBatch.ProtoReflect.Descriptor instead.
func (*ProtoControllerStateBatch) Descriptor() ([]byte, []int) {
return file_types_proto_rawDescGZIP(), []int{10}
}
func (x *ProtoControllerStateBatch) GetSessionSlot() int32 {
if x != nil {
return x.SessionSlot
}
return 0
}
func (x *ProtoControllerStateBatch) GetSessionId() string {
if x != nil {
return x.SessionId
}
return ""
}
func (x *ProtoControllerStateBatch) GetUpdateType() ProtoControllerStateBatch_UpdateType {
if x != nil {
return x.UpdateType
}
return ProtoControllerStateBatch_FULL_STATE
}
func (x *ProtoControllerStateBatch) GetSequence() uint32 {
if x != nil {
return x.Sequence
}
return 0
}
func (x *ProtoControllerStateBatch) GetButtonChangedMask() map[int32]bool {
if x != nil {
return x.ButtonChangedMask
}
return nil
}
func (x *ProtoControllerStateBatch) GetLeftStickX() int32 {
if x != nil && x.LeftStickX != nil {
return *x.LeftStickX
}
return 0
}
func (x *ProtoControllerStateBatch) GetLeftStickY() int32 {
if x != nil && x.LeftStickY != nil {
return *x.LeftStickY
}
return 0
}
func (x *ProtoControllerStateBatch) GetRightStickX() int32 {
if x != nil && x.RightStickX != nil {
return *x.RightStickX
}
return 0
}
func (x *ProtoControllerStateBatch) GetRightStickY() int32 {
if x != nil && x.RightStickY != nil {
return *x.RightStickY
}
return 0
}
func (x *ProtoControllerStateBatch) GetLeftTrigger() int32 {
if x != nil && x.LeftTrigger != nil {
return *x.LeftTrigger
}
return 0
}
func (x *ProtoControllerStateBatch) GetRightTrigger() int32 {
if x != nil && x.RightTrigger != nil {
return *x.RightTrigger
}
return 0
}
func (x *ProtoControllerStateBatch) GetDpadX() int32 {
if x != nil && x.DpadX != nil {
return *x.DpadX
}
return 0
}
func (x *ProtoControllerStateBatch) GetDpadY() int32 {
if x != nil && x.DpadY != nil {
return *x.DpadY
}
return 0
}
func (x *ProtoControllerStateBatch) GetChangedFields() uint32 {
if x != nil && x.ChangedFields != nil {
return *x.ChangedFields
}
return 0
}
type RTCIceCandidateInit struct { type RTCIceCandidateInit struct {
state protoimpl.MessageState `protogen:"open.v1"` state protoimpl.MessageState `protogen:"open.v1"`
Candidate string `protobuf:"bytes,1,opt,name=candidate,proto3" json:"candidate,omitempty"` Candidate string `protobuf:"bytes,1,opt,name=candidate,proto3" json:"candidate,omitempty"`
@@ -763,7 +847,7 @@ type RTCIceCandidateInit struct {
func (x *RTCIceCandidateInit) Reset() { func (x *RTCIceCandidateInit) Reset() {
*x = RTCIceCandidateInit{} *x = RTCIceCandidateInit{}
mi := &file_types_proto_msgTypes[11] mi := &file_types_proto_msgTypes[14]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -775,7 +859,7 @@ func (x *RTCIceCandidateInit) String() string {
func (*RTCIceCandidateInit) ProtoMessage() {} func (*RTCIceCandidateInit) ProtoMessage() {}
func (x *RTCIceCandidateInit) ProtoReflect() protoreflect.Message { func (x *RTCIceCandidateInit) ProtoReflect() protoreflect.Message {
mi := &file_types_proto_msgTypes[11] mi := &file_types_proto_msgTypes[14]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -788,7 +872,7 @@ func (x *RTCIceCandidateInit) ProtoReflect() protoreflect.Message {
// Deprecated: Use RTCIceCandidateInit.ProtoReflect.Descriptor instead. // Deprecated: Use RTCIceCandidateInit.ProtoReflect.Descriptor instead.
func (*RTCIceCandidateInit) Descriptor() ([]byte, []int) { func (*RTCIceCandidateInit) Descriptor() ([]byte, []int) {
return file_types_proto_rawDescGZIP(), []int{11} return file_types_proto_rawDescGZIP(), []int{14}
} }
func (x *RTCIceCandidateInit) GetCandidate() string { func (x *RTCIceCandidateInit) GetCandidate() string {
@@ -829,7 +913,7 @@ type RTCSessionDescriptionInit struct {
func (x *RTCSessionDescriptionInit) Reset() { func (x *RTCSessionDescriptionInit) Reset() {
*x = RTCSessionDescriptionInit{} *x = RTCSessionDescriptionInit{}
mi := &file_types_proto_msgTypes[12] mi := &file_types_proto_msgTypes[15]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -841,7 +925,7 @@ func (x *RTCSessionDescriptionInit) String() string {
func (*RTCSessionDescriptionInit) ProtoMessage() {} func (*RTCSessionDescriptionInit) ProtoMessage() {}
func (x *RTCSessionDescriptionInit) ProtoReflect() protoreflect.Message { func (x *RTCSessionDescriptionInit) ProtoReflect() protoreflect.Message {
mi := &file_types_proto_msgTypes[12] mi := &file_types_proto_msgTypes[15]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -854,7 +938,7 @@ func (x *RTCSessionDescriptionInit) ProtoReflect() protoreflect.Message {
// Deprecated: Use RTCSessionDescriptionInit.ProtoReflect.Descriptor instead. // Deprecated: Use RTCSessionDescriptionInit.ProtoReflect.Descriptor instead.
func (*RTCSessionDescriptionInit) Descriptor() ([]byte, []int) { func (*RTCSessionDescriptionInit) Descriptor() ([]byte, []int) {
return file_types_proto_rawDescGZIP(), []int{12} return file_types_proto_rawDescGZIP(), []int{15}
} }
func (x *RTCSessionDescriptionInit) GetSdp() string { func (x *RTCSessionDescriptionInit) GetSdp() string {
@@ -881,7 +965,7 @@ type ProtoICE struct {
func (x *ProtoICE) Reset() { func (x *ProtoICE) Reset() {
*x = ProtoICE{} *x = ProtoICE{}
mi := &file_types_proto_msgTypes[13] mi := &file_types_proto_msgTypes[16]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -893,7 +977,7 @@ func (x *ProtoICE) String() string {
func (*ProtoICE) ProtoMessage() {} func (*ProtoICE) ProtoMessage() {}
func (x *ProtoICE) ProtoReflect() protoreflect.Message { func (x *ProtoICE) ProtoReflect() protoreflect.Message {
mi := &file_types_proto_msgTypes[13] mi := &file_types_proto_msgTypes[16]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -906,7 +990,7 @@ func (x *ProtoICE) ProtoReflect() protoreflect.Message {
// Deprecated: Use ProtoICE.ProtoReflect.Descriptor instead. // Deprecated: Use ProtoICE.ProtoReflect.Descriptor instead.
func (*ProtoICE) Descriptor() ([]byte, []int) { func (*ProtoICE) Descriptor() ([]byte, []int) {
return file_types_proto_rawDescGZIP(), []int{13} return file_types_proto_rawDescGZIP(), []int{16}
} }
func (x *ProtoICE) GetCandidate() *RTCIceCandidateInit { func (x *ProtoICE) GetCandidate() *RTCIceCandidateInit {
@@ -926,7 +1010,7 @@ type ProtoSDP struct {
func (x *ProtoSDP) Reset() { func (x *ProtoSDP) Reset() {
*x = ProtoSDP{} *x = ProtoSDP{}
mi := &file_types_proto_msgTypes[14] mi := &file_types_proto_msgTypes[17]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -938,7 +1022,7 @@ func (x *ProtoSDP) String() string {
func (*ProtoSDP) ProtoMessage() {} func (*ProtoSDP) ProtoMessage() {}
func (x *ProtoSDP) ProtoReflect() protoreflect.Message { func (x *ProtoSDP) ProtoReflect() protoreflect.Message {
mi := &file_types_proto_msgTypes[14] mi := &file_types_proto_msgTypes[17]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -951,7 +1035,7 @@ func (x *ProtoSDP) ProtoReflect() protoreflect.Message {
// Deprecated: Use ProtoSDP.ProtoReflect.Descriptor instead. // Deprecated: Use ProtoSDP.ProtoReflect.Descriptor instead.
func (*ProtoSDP) Descriptor() ([]byte, []int) { func (*ProtoSDP) Descriptor() ([]byte, []int) {
return file_types_proto_rawDescGZIP(), []int{14} return file_types_proto_rawDescGZIP(), []int{17}
} }
func (x *ProtoSDP) GetSdp() *RTCSessionDescriptionInit { func (x *ProtoSDP) GetSdp() *RTCSessionDescriptionInit {
@@ -971,7 +1055,7 @@ type ProtoRaw struct {
func (x *ProtoRaw) Reset() { func (x *ProtoRaw) Reset() {
*x = ProtoRaw{} *x = ProtoRaw{}
mi := &file_types_proto_msgTypes[15] mi := &file_types_proto_msgTypes[18]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -983,7 +1067,7 @@ func (x *ProtoRaw) String() string {
func (*ProtoRaw) ProtoMessage() {} func (*ProtoRaw) ProtoMessage() {}
func (x *ProtoRaw) ProtoReflect() protoreflect.Message { func (x *ProtoRaw) ProtoReflect() protoreflect.Message {
mi := &file_types_proto_msgTypes[15] mi := &file_types_proto_msgTypes[18]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -996,7 +1080,7 @@ func (x *ProtoRaw) ProtoReflect() protoreflect.Message {
// Deprecated: Use ProtoRaw.ProtoReflect.Descriptor instead. // Deprecated: Use ProtoRaw.ProtoReflect.Descriptor instead.
func (*ProtoRaw) Descriptor() ([]byte, []int) { func (*ProtoRaw) Descriptor() ([]byte, []int) {
return file_types_proto_rawDescGZIP(), []int{15} return file_types_proto_rawDescGZIP(), []int{18}
} }
func (x *ProtoRaw) GetData() string { func (x *ProtoRaw) GetData() string {
@@ -1017,7 +1101,7 @@ type ProtoClientRequestRoomStream struct {
func (x *ProtoClientRequestRoomStream) Reset() { func (x *ProtoClientRequestRoomStream) Reset() {
*x = ProtoClientRequestRoomStream{} *x = ProtoClientRequestRoomStream{}
mi := &file_types_proto_msgTypes[16] mi := &file_types_proto_msgTypes[19]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -1029,7 +1113,7 @@ func (x *ProtoClientRequestRoomStream) String() string {
func (*ProtoClientRequestRoomStream) ProtoMessage() {} func (*ProtoClientRequestRoomStream) ProtoMessage() {}
func (x *ProtoClientRequestRoomStream) ProtoReflect() protoreflect.Message { func (x *ProtoClientRequestRoomStream) ProtoReflect() protoreflect.Message {
mi := &file_types_proto_msgTypes[16] mi := &file_types_proto_msgTypes[19]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -1042,7 +1126,7 @@ func (x *ProtoClientRequestRoomStream) ProtoReflect() protoreflect.Message {
// Deprecated: Use ProtoClientRequestRoomStream.ProtoReflect.Descriptor instead. // Deprecated: Use ProtoClientRequestRoomStream.ProtoReflect.Descriptor instead.
func (*ProtoClientRequestRoomStream) Descriptor() ([]byte, []int) { func (*ProtoClientRequestRoomStream) Descriptor() ([]byte, []int) {
return file_types_proto_rawDescGZIP(), []int{16} return file_types_proto_rawDescGZIP(), []int{19}
} }
func (x *ProtoClientRequestRoomStream) GetRoomName() string { func (x *ProtoClientRequestRoomStream) GetRoomName() string {
@@ -1070,7 +1154,7 @@ type ProtoClientDisconnected struct {
func (x *ProtoClientDisconnected) Reset() { func (x *ProtoClientDisconnected) Reset() {
*x = ProtoClientDisconnected{} *x = ProtoClientDisconnected{}
mi := &file_types_proto_msgTypes[17] mi := &file_types_proto_msgTypes[20]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -1082,7 +1166,7 @@ func (x *ProtoClientDisconnected) String() string {
func (*ProtoClientDisconnected) ProtoMessage() {} func (*ProtoClientDisconnected) ProtoMessage() {}
func (x *ProtoClientDisconnected) ProtoReflect() protoreflect.Message { func (x *ProtoClientDisconnected) ProtoReflect() protoreflect.Message {
mi := &file_types_proto_msgTypes[17] mi := &file_types_proto_msgTypes[20]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -1095,7 +1179,7 @@ func (x *ProtoClientDisconnected) ProtoReflect() protoreflect.Message {
// Deprecated: Use ProtoClientDisconnected.ProtoReflect.Descriptor instead. // Deprecated: Use ProtoClientDisconnected.ProtoReflect.Descriptor instead.
func (*ProtoClientDisconnected) Descriptor() ([]byte, []int) { func (*ProtoClientDisconnected) Descriptor() ([]byte, []int) {
return file_types_proto_rawDescGZIP(), []int{17} return file_types_proto_rawDescGZIP(), []int{20}
} }
func (x *ProtoClientDisconnected) GetSessionId() string { func (x *ProtoClientDisconnected) GetSessionId() string {
@@ -1122,7 +1206,7 @@ type ProtoServerPushStream struct {
func (x *ProtoServerPushStream) Reset() { func (x *ProtoServerPushStream) Reset() {
*x = ProtoServerPushStream{} *x = ProtoServerPushStream{}
mi := &file_types_proto_msgTypes[18] mi := &file_types_proto_msgTypes[21]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -1134,7 +1218,7 @@ func (x *ProtoServerPushStream) String() string {
func (*ProtoServerPushStream) ProtoMessage() {} func (*ProtoServerPushStream) ProtoMessage() {}
func (x *ProtoServerPushStream) ProtoReflect() protoreflect.Message { func (x *ProtoServerPushStream) ProtoReflect() protoreflect.Message {
mi := &file_types_proto_msgTypes[18] mi := &file_types_proto_msgTypes[21]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -1147,7 +1231,7 @@ func (x *ProtoServerPushStream) ProtoReflect() protoreflect.Message {
// Deprecated: Use ProtoServerPushStream.ProtoReflect.Descriptor instead. // Deprecated: Use ProtoServerPushStream.ProtoReflect.Descriptor instead.
func (*ProtoServerPushStream) Descriptor() ([]byte, []int) { func (*ProtoServerPushStream) Descriptor() ([]byte, []int) {
return file_types_proto_rawDescGZIP(), []int{18} return file_types_proto_rawDescGZIP(), []int{21}
} }
func (x *ProtoServerPushStream) GetRoomName() string { func (x *ProtoServerPushStream) GetRoomName() string {
@@ -1188,51 +1272,39 @@ const file_types_proto_rawDesc = "" +
"\x15ProtoControllerDetach\x12!\n" + "\x15ProtoControllerDetach\x12!\n" +
"\fsession_slot\x18\x01 \x01(\x05R\vsessionSlot\x12\x1d\n" + "\fsession_slot\x18\x01 \x01(\x05R\vsessionSlot\x12\x1d\n" +
"\n" + "\n" +
"session_id\x18\x02 \x01(\tR\tsessionId\"\xc1\x01\n" + "session_id\x18\x02 \x01(\tR\tsessionId\"\x8b\x01\n" +
"\x15ProtoControllerButton\x12!\n" +
"\fsession_slot\x18\x01 \x01(\x05R\vsessionSlot\x12\x1d\n" +
"\n" +
"session_id\x18\x02 \x01(\tR\tsessionId\x12\x16\n" +
"\x06button\x18\x03 \x01(\x05R\x06button\x12\x18\n" +
"\apressed\x18\x04 \x01(\bR\apressed\"\x8a\x01\n" +
"\x16ProtoControllerTrigger\x12!\n" +
"\fsession_slot\x18\x01 \x01(\x05R\vsessionSlot\x12\x1d\n" +
"\n" +
"session_id\x18\x02 \x01(\tR\tsessionId\x12\x18\n" +
"\atrigger\x18\x03 \x01(\x05R\atrigger\x12\x14\n" +
"\x05value\x18\x04 \x01(\x05R\x05value\"\x8a\x01\n" +
"\x14ProtoControllerStick\x12!\n" +
"\fsession_slot\x18\x01 \x01(\x05R\vsessionSlot\x12\x1d\n" +
"\n" +
"session_id\x18\x02 \x01(\tR\tsessionId\x12\x14\n" +
"\x05stick\x18\x03 \x01(\x05R\x05stick\x12\f\n" +
"\x01x\x18\x04 \x01(\x05R\x01x\x12\f\n" +
"\x01y\x18\x05 \x01(\x05R\x01y\"\x81\x01\n" +
"\x13ProtoControllerAxis\x12!\n" +
"\fsession_slot\x18\x01 \x01(\x05R\vsessionSlot\x12\x1d\n" +
"\n" +
"session_id\x18\x02 \x01(\tR\tsessionId\x12\x12\n" +
"\x04axis\x18\x03 \x01(\x05R\x04axis\x12\x14\n" +
"\x05value\x18\x04 \x01(\x05R\x05value\"\xc1\x01\n" +
"\x15ProtoControllerRumble\x12!\n" + "\x15ProtoControllerRumble\x12!\n" +
"\fsession_slot\x18\x01 \x01(\x05R\vsessionSlot\x12\x1d\n" + "\fsession_slot\x18\x01 \x01(\x05R\vsessionSlot\x12\x1d\n" +
"\n" + "\n" +
"session_id\x18\x02 \x01(\tR\tsessionId\x12#\n" + "session_id\x18\x02 \x01(\tR\tsessionId\x12#\n" +
"\rlow_frequency\x18\x03 \x01(\x05R\flowFrequency\x12%\n" + "\rlow_frequency\x18\x03 \x01(\x05R\flowFrequency\x12%\n" +
"\x0ehigh_frequency\x18\x04 \x01(\x05R\rhighFrequency\x12\x1a\n" + "\x0ehigh_frequency\x18\x04 \x01(\x05R\rhighFrequency\x12\x1a\n" +
"\bduration\x18\x05 \x01(\x05R\bduration\"\x87\a\n" + "\bduration\x18\x05 \x01(\x05R\bduration\"\xde\x01\n" +
"\x19ProtoControllerStateBatch\x12!\n" +
"\fsession_slot\x18\x01 \x01(\x05R\vsessionSlot\x12\x1d\n" +
"\n" +
"session_id\x18\x02 \x01(\tR\tsessionId\x12L\n" +
"\vupdate_type\x18\x03 \x01(\x0e2+.proto.ProtoControllerStateBatch.UpdateTypeR\n" +
"updateType\x12\x1a\n" +
"\bsequence\x18\x04 \x01(\rR\bsequence\x12g\n" +
"\x13button_changed_mask\x18\x05 \x03(\v27.proto.ProtoControllerStateBatch.ButtonChangedMaskEntryR\x11buttonChangedMask\x12%\n" +
"\fleft_stick_x\x18\x06 \x01(\x05H\x00R\n" +
"leftStickX\x88\x01\x01\x12%\n" +
"\fleft_stick_y\x18\a \x01(\x05H\x01R\n" +
"leftStickY\x88\x01\x01\x12'\n" +
"\rright_stick_x\x18\b \x01(\x05H\x02R\vrightStickX\x88\x01\x01\x12'\n" +
"\rright_stick_y\x18\t \x01(\x05H\x03R\vrightStickY\x88\x01\x01\x12&\n" +
"\fleft_trigger\x18\n" +
" \x01(\x05H\x04R\vleftTrigger\x88\x01\x01\x12(\n" +
"\rright_trigger\x18\v \x01(\x05H\x05R\frightTrigger\x88\x01\x01\x12\x1a\n" +
"\x06dpad_x\x18\f \x01(\x05H\x06R\x05dpadX\x88\x01\x01\x12\x1a\n" +
"\x06dpad_y\x18\r \x01(\x05H\aR\x05dpadY\x88\x01\x01\x12*\n" +
"\x0echanged_fields\x18\x0e \x01(\rH\bR\rchangedFields\x88\x01\x01\x1aD\n" +
"\x16ButtonChangedMaskEntry\x12\x10\n" +
"\x03key\x18\x01 \x01(\x05R\x03key\x12\x14\n" +
"\x05value\x18\x02 \x01(\bR\x05value:\x028\x01\"'\n" +
"\n" +
"UpdateType\x12\x0e\n" +
"\n" +
"FULL_STATE\x10\x00\x12\t\n" +
"\x05DELTA\x10\x01B\x0f\n" +
"\r_left_stick_xB\x0f\n" +
"\r_left_stick_yB\x10\n" +
"\x0e_right_stick_xB\x10\n" +
"\x0e_right_stick_yB\x0f\n" +
"\r_left_triggerB\x10\n" +
"\x0e_right_triggerB\t\n" +
"\a_dpad_xB\t\n" +
"\a_dpad_yB\x11\n" +
"\x0f_changed_fields\"\xde\x01\n" +
"\x13RTCIceCandidateInit\x12\x1c\n" + "\x13RTCIceCandidateInit\x12\x1c\n" +
"\tcandidate\x18\x01 \x01(\tR\tcandidate\x12)\n" + "\tcandidate\x18\x01 \x01(\tR\tcandidate\x12)\n" +
"\rsdpMLineIndex\x18\x02 \x01(\rH\x00R\rsdpMLineIndex\x88\x01\x01\x12\x1b\n" + "\rsdpMLineIndex\x18\x02 \x01(\rH\x00R\rsdpMLineIndex\x88\x01\x01\x12\x1b\n" +
@@ -1273,41 +1345,39 @@ func file_types_proto_rawDescGZIP() []byte {
return file_types_proto_rawDescData return file_types_proto_rawDescData
} }
var file_types_proto_enumTypes = make([]protoimpl.EnumInfo, 1) var file_types_proto_msgTypes = make([]protoimpl.MessageInfo, 22)
var file_types_proto_msgTypes = make([]protoimpl.MessageInfo, 20)
var file_types_proto_goTypes = []any{ var file_types_proto_goTypes = []any{
(ProtoControllerStateBatch_UpdateType)(0), // 0: proto.ProtoControllerStateBatch.UpdateType (*ProtoMouseMove)(nil), // 0: proto.ProtoMouseMove
(*ProtoMouseMove)(nil), // 1: proto.ProtoMouseMove (*ProtoMouseMoveAbs)(nil), // 1: proto.ProtoMouseMoveAbs
(*ProtoMouseMoveAbs)(nil), // 2: proto.ProtoMouseMoveAbs (*ProtoMouseWheel)(nil), // 2: proto.ProtoMouseWheel
(*ProtoMouseWheel)(nil), // 3: proto.ProtoMouseWheel (*ProtoMouseKeyDown)(nil), // 3: proto.ProtoMouseKeyDown
(*ProtoMouseKeyDown)(nil), // 4: proto.ProtoMouseKeyDown (*ProtoMouseKeyUp)(nil), // 4: proto.ProtoMouseKeyUp
(*ProtoMouseKeyUp)(nil), // 5: proto.ProtoMouseKeyUp (*ProtoKeyDown)(nil), // 5: proto.ProtoKeyDown
(*ProtoKeyDown)(nil), // 6: proto.ProtoKeyDown (*ProtoKeyUp)(nil), // 6: proto.ProtoKeyUp
(*ProtoKeyUp)(nil), // 7: proto.ProtoKeyUp (*ProtoControllerAttach)(nil), // 7: proto.ProtoControllerAttach
(*ProtoControllerAttach)(nil), // 8: proto.ProtoControllerAttach (*ProtoControllerDetach)(nil), // 8: proto.ProtoControllerDetach
(*ProtoControllerDetach)(nil), // 9: proto.ProtoControllerDetach (*ProtoControllerButton)(nil), // 9: proto.ProtoControllerButton
(*ProtoControllerRumble)(nil), // 10: proto.ProtoControllerRumble (*ProtoControllerTrigger)(nil), // 10: proto.ProtoControllerTrigger
(*ProtoControllerStateBatch)(nil), // 11: proto.ProtoControllerStateBatch (*ProtoControllerStick)(nil), // 11: proto.ProtoControllerStick
(*RTCIceCandidateInit)(nil), // 12: proto.RTCIceCandidateInit (*ProtoControllerAxis)(nil), // 12: proto.ProtoControllerAxis
(*RTCSessionDescriptionInit)(nil), // 13: proto.RTCSessionDescriptionInit (*ProtoControllerRumble)(nil), // 13: proto.ProtoControllerRumble
(*ProtoICE)(nil), // 14: proto.ProtoICE (*RTCIceCandidateInit)(nil), // 14: proto.RTCIceCandidateInit
(*ProtoSDP)(nil), // 15: proto.ProtoSDP (*RTCSessionDescriptionInit)(nil), // 15: proto.RTCSessionDescriptionInit
(*ProtoRaw)(nil), // 16: proto.ProtoRaw (*ProtoICE)(nil), // 16: proto.ProtoICE
(*ProtoClientRequestRoomStream)(nil), // 17: proto.ProtoClientRequestRoomStream (*ProtoSDP)(nil), // 17: proto.ProtoSDP
(*ProtoClientDisconnected)(nil), // 18: proto.ProtoClientDisconnected (*ProtoRaw)(nil), // 18: proto.ProtoRaw
(*ProtoServerPushStream)(nil), // 19: proto.ProtoServerPushStream (*ProtoClientRequestRoomStream)(nil), // 19: proto.ProtoClientRequestRoomStream
nil, // 20: proto.ProtoControllerStateBatch.ButtonChangedMaskEntry (*ProtoClientDisconnected)(nil), // 20: proto.ProtoClientDisconnected
(*ProtoServerPushStream)(nil), // 21: proto.ProtoServerPushStream
} }
var file_types_proto_depIdxs = []int32{ var file_types_proto_depIdxs = []int32{
0, // 0: proto.ProtoControllerStateBatch.update_type:type_name -> proto.ProtoControllerStateBatch.UpdateType 14, // 0: proto.ProtoICE.candidate:type_name -> proto.RTCIceCandidateInit
20, // 1: proto.ProtoControllerStateBatch.button_changed_mask:type_name -> proto.ProtoControllerStateBatch.ButtonChangedMaskEntry 15, // 1: proto.ProtoSDP.sdp:type_name -> proto.RTCSessionDescriptionInit
12, // 2: proto.ProtoICE.candidate:type_name -> proto.RTCIceCandidateInit 2, // [2:2] is the sub-list for method output_type
13, // 3: proto.ProtoSDP.sdp:type_name -> proto.RTCSessionDescriptionInit 2, // [2:2] is the sub-list for method input_type
4, // [4:4] is the sub-list for method output_type 2, // [2:2] is the sub-list for extension type_name
4, // [4:4] is the sub-list for method input_type 2, // [2:2] is the sub-list for extension extendee
4, // [4:4] is the sub-list for extension type_name 0, // [0:2] is the sub-list for field type_name
4, // [4:4] is the sub-list for extension extendee
0, // [0:4] is the sub-list for field type_name
} }
func init() { file_types_proto_init() } func init() { file_types_proto_init() }
@@ -1315,21 +1385,19 @@ func file_types_proto_init() {
if File_types_proto != nil { if File_types_proto != nil {
return return
} }
file_types_proto_msgTypes[10].OneofWrappers = []any{} file_types_proto_msgTypes[14].OneofWrappers = []any{}
file_types_proto_msgTypes[11].OneofWrappers = []any{}
type x struct{} type x struct{}
out := protoimpl.TypeBuilder{ out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{ File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(), GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_types_proto_rawDesc), len(file_types_proto_rawDesc)), RawDescriptor: unsafe.Slice(unsafe.StringData(file_types_proto_rawDesc), len(file_types_proto_rawDesc)),
NumEnums: 1, NumEnums: 0,
NumMessages: 20, NumMessages: 22,
NumExtensions: 0, NumExtensions: 0,
NumServices: 0, NumServices: 0,
}, },
GoTypes: file_types_proto_goTypes, GoTypes: file_types_proto_goTypes,
DependencyIndexes: file_types_proto_depIdxs, DependencyIndexes: file_types_proto_depIdxs,
EnumInfos: file_types_proto_enumTypes,
MessageInfos: file_types_proto_msgTypes, MessageInfos: file_types_proto_msgTypes,
}.Build() }.Build()
File_types_proto = out.File File_types_proto = out.File

View File

@@ -63,13 +63,13 @@ func (p *Participant) SetTrack(trackType webrtc.RTPCodecType, track *webrtc.Trac
p.AudioTrack = track p.AudioTrack = track
_, err := p.PeerConnection.AddTrack(track) _, err := p.PeerConnection.AddTrack(track)
if err != nil { if err != nil {
slog.Error("Failed to add audio track", "participant", p.ID, "err", err) slog.Error("Failed to add Participant audio track", err)
} }
case webrtc.RTPCodecTypeVideo: case webrtc.RTPCodecTypeVideo:
p.VideoTrack = track p.VideoTrack = track
_, err := p.PeerConnection.AddTrack(track) _, err := p.PeerConnection.AddTrack(track)
if err != nil { if err != nil {
slog.Error("Failed to add video track", "participant", p.ID, "err", err) slog.Error("Failed to add Participant video track", err)
} }
default: default:
slog.Warn("Unknown track type", "participant", p.ID, "trackType", trackType) slog.Warn("Unknown track type", "participant", p.ID, "trackType", trackType)
@@ -78,20 +78,17 @@ func (p *Participant) SetTrack(trackType webrtc.RTPCodecType, track *webrtc.Trac
// Close cleans up participant resources // Close cleans up participant resources
func (p *Participant) Close() { func (p *Participant) Close() {
p.closeOnce.Do(func() {
close(p.packetQueue)
})
if p.DataChannel != nil { if p.DataChannel != nil {
err := p.DataChannel.Close() err := p.DataChannel.Close()
if err != nil { if err != nil {
slog.Error("Failed to close DataChannel", "participant", p.ID, "err", err) slog.Error("Failed to close Participant DataChannel", err)
} }
p.DataChannel = nil p.DataChannel = nil
} }
if p.PeerConnection != nil { if p.PeerConnection != nil {
err := p.PeerConnection.Close() err := p.PeerConnection.Close()
if err != nil { if err != nil {
slog.Error("Failed to close PeerConnection", "participant", p.ID, "err", err) slog.Error("Failed to close Participant PeerConnection", err)
} }
p.PeerConnection = nil p.PeerConnection = nil
} }
@@ -106,15 +103,28 @@ func (p *Participant) Close() {
func (p *Participant) packetWriter() { func (p *Participant) packetWriter() {
for pkt := range p.packetQueue { for pkt := range p.packetQueue {
var track *webrtc.TrackLocalStaticRTP var track *webrtc.TrackLocalStaticRTP
var sequenceNumber uint16
var timestamp uint32
// No mutex needed - only this goroutine modifies these // No mutex needed - only this goroutine modifies these
if pkt.kind == webrtc.RTPCodecTypeAudio { if pkt.kind == webrtc.RTPCodecTypeAudio {
track = p.AudioTrack track = p.AudioTrack
p.AudioSequenceNumber = uint16(int(p.AudioSequenceNumber) + pkt.sequenceDiff)
p.AudioTimestamp = uint32(int64(p.AudioTimestamp) + pkt.timeDiff)
sequenceNumber = p.AudioSequenceNumber
timestamp = p.AudioTimestamp
} else { } else {
track = p.VideoTrack track = p.VideoTrack
p.VideoSequenceNumber = uint16(int(p.VideoSequenceNumber) + pkt.sequenceDiff)
p.VideoTimestamp = uint32(int64(p.VideoTimestamp) + pkt.timeDiff)
sequenceNumber = p.VideoSequenceNumber
timestamp = p.VideoTimestamp
} }
if track != nil { if track != nil {
pkt.packet.SequenceNumber = sequenceNumber
pkt.packet.Timestamp = timestamp
if err := track.WriteRTP(pkt.packet); err != nil && !errors.Is(err, io.ErrClosedPipe) { if err := track.WriteRTP(pkt.packet); err != nil && !errors.Is(err, io.ErrClosedPipe) {
slog.Error("WriteRTP failed", "participant", p.ID, "kind", pkt.kind, "err", err) slog.Error("WriteRTP failed", "participant", p.ID, "kind", pkt.kind, "err", err)
} }

View File

@@ -21,6 +21,8 @@ var participantPacketPool = sync.Pool{
type participantPacket struct { type participantPacket struct {
kind webrtc.RTPCodecType kind webrtc.RTPCodecType
packet *rtp.Packet packet *rtp.Packet
timeDiff int64
sequenceDiff int
} }
type RoomInfo struct { type RoomInfo struct {
@@ -139,7 +141,7 @@ func (r *Room) IsOnline() bool {
return r.PeerConnection != nil return r.PeerConnection != nil
} }
func (r *Room) BroadcastPacket(kind webrtc.RTPCodecType, pkt *rtp.Packet) { func (r *Room) BroadcastPacketRetimed(kind webrtc.RTPCodecType, pkt *rtp.Packet, timeDiff int64, sequenceDiff int) {
// Lock-free load of channel slice // Lock-free load of channel slice
channels := r.participantChannels.Load() channels := r.participantChannels.Load()
@@ -153,7 +155,9 @@ func (r *Room) BroadcastPacket(kind webrtc.RTPCodecType, pkt *rtp.Packet) {
// Get packet struct from pool // Get packet struct from pool
pp := participantPacketPool.Get().(*participantPacket) pp := participantPacketPool.Get().(*participantPacket)
pp.kind = kind pp.kind = kind
pp.packet = pkt pp.packet = pkt.Clone()
pp.timeDiff = timeDiff
pp.sequenceDiff = sequenceDiff
select { select {
case ch <- pp: case ch <- pp:

View File

@@ -348,8 +348,18 @@ main() {
setup_namespaceless setup_namespaceless
fi fi
# Wait for vimputti socket before switching to application startup # Make sure /run/udev/ directory exists with /run/udev/control, needed for virtual controller support
wait_for_socket "/tmp/vimputti-0" "vimputti" || exit 1 if [[ ! -d "/run/udev" || ! -e "/run/udev/control" ]]; then
log "Creating /run/udev directory and control file.."
$ENTCMD_PREFIX mkdir -p /run/udev || {
log "Error: Failed to create /run/udev directory"
exit 1
}
$ENTCMD_PREFIX touch /run/udev/control || {
log "Error: Failed to create /run/udev/control file"
exit 1
}
fi
# Switch to nestri runner entrypoint # Switch to nestri runner entrypoint
log "Switching to application startup entrypoint..." log "Switching to application startup entrypoint..."

View File

@@ -106,9 +106,12 @@ start_compositor() {
kill_if_running "${COMPOSITOR_PID:-}" "compositor" kill_if_running "${COMPOSITOR_PID:-}" "compositor"
kill_if_running "${APP_PID:-}" "application" kill_if_running "${APP_PID:-}" "application"
# Set default compositor if unset # Set default values only if variables are unset (not empty)
if [[ -z "${NESTRI_LAUNCH_CMD+x}" ]]; then
NESTRI_LAUNCH_CMD="dbus-launch steam -tenfoot -cef-force-gpu"
fi
if [[ -z "${NESTRI_LAUNCH_COMPOSITOR+x}" ]]; then if [[ -z "${NESTRI_LAUNCH_COMPOSITOR+x}" ]]; then
NESTRI_LAUNCH_COMPOSITOR="gamescope --backend wayland -g -f --rt -W ${WIDTH} -H ${HEIGHT} -r ${FRAMERATE:-60}" NESTRI_LAUNCH_COMPOSITOR="gamescope --backend wayland --force-grab-cursor -g -f --rt --mangoapp -W ${WIDTH} -H ${HEIGHT} -r ${FRAMERATE:-60}"
fi fi
# If PRELOAD_SHIM_arch's are set and exist, set LD_PRELOAD for 32/64-bit apps # If PRELOAD_SHIM_arch's are set and exist, set LD_PRELOAD for 32/64-bit apps
@@ -118,16 +121,6 @@ start_compositor() {
log "Using LD_PRELOAD shim(s)" log "Using LD_PRELOAD shim(s)"
fi fi
# Configure launch cmd with dbus if set
local launch_cmd=""
if [[ -n "${NESTRI_LAUNCH_CMD+x}" ]]; then
if $do_ld_preload; then
launch_cmd="LD_PRELOAD='/usr/\$LIB/libvimputti_shim.so' dbus-launch $NESTRI_LAUNCH_CMD"
else
launch_cmd="dbus-launch $NESTRI_LAUNCH_CMD"
fi
fi
# Launch compositor if configured # Launch compositor if configured
if [[ -n "${NESTRI_LAUNCH_COMPOSITOR}" ]]; then if [[ -n "${NESTRI_LAUNCH_COMPOSITOR}" ]]; then
local compositor_cmd="$NESTRI_LAUNCH_COMPOSITOR" local compositor_cmd="$NESTRI_LAUNCH_COMPOSITOR"
@@ -136,12 +129,17 @@ start_compositor() {
# Check if this is a gamescope command # Check if this is a gamescope command
if [[ "$compositor_cmd" == *"gamescope"* ]]; then if [[ "$compositor_cmd" == *"gamescope"* ]]; then
is_gamescope=true is_gamescope=true
if [[ -n "$launch_cmd" ]] && [[ "$compositor_cmd" != *" -- "* ]]; then if [[ -n "$NESTRI_LAUNCH_CMD" ]] && [[ "$compositor_cmd" != *" -- "* ]]; then
# If steam in launch command, enable gamescope integration via -e and enable mangohud # If steam in launch command, enable gamescope integration via -e
if [[ "$launch_cmd" == *"steam"* ]]; then if [[ "$NESTRI_LAUNCH_CMD" == *"steam"* ]]; then
compositor_cmd+=" --mangoapp -e" compositor_cmd+=" -e"
fi
# If ld_preload is true, add env with LD_PRELOAD
if $do_ld_preload; then
compositor_cmd+=" -- env LD_PRELOAD='/usr/\$LIB/libvimputti_shim.so' bash -c $(printf %q "$NESTRI_LAUNCH_CMD")"
else
compositor_cmd+=" -- bash -c $(printf %q "$NESTRI_LAUNCH_CMD")"
fi fi
compositor_cmd+=" -- bash -c $(printf %q "$launch_cmd")"
fi fi
fi fi
@@ -187,9 +185,9 @@ start_compositor() {
WAYLAND_DISPLAY=wayland-0 wlr-randr --output "$OUTPUT_NAME" --custom-mode "$WIDTH"x"$HEIGHT" WAYLAND_DISPLAY=wayland-0 wlr-randr --output "$OUTPUT_NAME" --custom-mode "$WIDTH"x"$HEIGHT"
log "Patched resolution with wlr-randr" log "Patched resolution with wlr-randr"
if [[ -n "$launch_cmd" ]]; then if [[ -n "${NESTRI_LAUNCH_CMD}" ]]; then
log "Starting application: $launch_cmd" log "Starting application: $NESTRI_LAUNCH_CMD"
WAYLAND_DISPLAY="$COMPOSITOR_SOCKET" bash -c "$launch_cmd" & WAYLAND_DISPLAY="$COMPOSITOR_SOCKET" /bin/bash -c "$NESTRI_LAUNCH_CMD" &
APP_PID=$! APP_PID=$!
fi fi
else else
@@ -202,9 +200,9 @@ start_compositor() {
log "Warning: Compositor socket not found after 15 seconds ($COMPOSITOR_SOCKET)" log "Warning: Compositor socket not found after 15 seconds ($COMPOSITOR_SOCKET)"
else else
# Launch standalone application if no compositor # Launch standalone application if no compositor
if [[ -n "$launch_cmd" ]]; then if [[ -n "${NESTRI_LAUNCH_CMD}" ]]; then
log "Starting standalone application: $launch_cmd" log "Starting application: $NESTRI_LAUNCH_CMD"
WAYLAND_DISPLAY=wayland-1 bash -c "$launch_cmd" & WAYLAND_DISPLAY=wayland-1 /bin/bash -c "$NESTRI_LAUNCH_CMD" &
APP_PID=$! APP_PID=$!
else else
log "No compositor or application configured" log "No compositor or application configured"

View File

@@ -4,13 +4,15 @@ export USER=${NESTRI_USER}
export LANG=${NESTRI_LANG} export LANG=${NESTRI_LANG}
export HOME=${NESTRI_HOME} export HOME=${NESTRI_HOME}
export XDG_RUNTIME_DIR=${NESTRI_XDG_RUNTIME_DIR} export XDG_RUNTIME_DIR=${NESTRI_XDG_RUNTIME_DIR}
export XDG_SESSION_TYPE=x11
export DISPLAY=:0
# Causes some setups to break # Causes some setups to break
export PROTON_NO_FSYNC=1 export PROTON_NO_FSYNC=1
# Sleeker Mangohud preset :)
export MANGOHUD_CONFIG=preset=2
# Make gstreamer GL elements work without display output (NVIDIA issue..) # Make gstreamer GL elements work without display output (NVIDIA issue..)
export GST_GL_API=gles2 export GST_GL_API=gles2
export GST_GL_WINDOW=surfaceless export GST_GL_WINDOW=surfaceless
# Gamescope does not respect MangoHud default config location
export MANGOHUD_CONFIGFILE=/etc/nestri/configs/MangoHud/MangoHud.conf

View File

@@ -18,7 +18,7 @@ autorestart=true
autostart=true autostart=true
startretries=3 startretries=3
priority=3 priority=3
nice=-2 nice=-10
environment=HOME=%(ENV_NESTRI_HOME)s,XDG_RUNTIME_DIR=%(ENV_NESTRI_XDG_RUNTIME_DIR)s environment=HOME=%(ENV_NESTRI_HOME)s,XDG_RUNTIME_DIR=%(ENV_NESTRI_XDG_RUNTIME_DIR)s
[program:pipewire-pulse] [program:pipewire-pulse]
@@ -28,7 +28,7 @@ autorestart=true
autostart=true autostart=true
startretries=3 startretries=3
priority=4 priority=4
nice=-2 nice=-10
environment=HOME=%(ENV_NESTRI_HOME)s,XDG_RUNTIME_DIR=%(ENV_NESTRI_XDG_RUNTIME_DIR)s environment=HOME=%(ENV_NESTRI_HOME)s,XDG_RUNTIME_DIR=%(ENV_NESTRI_XDG_RUNTIME_DIR)s
[program:wireplumber] [program:wireplumber]
@@ -38,7 +38,7 @@ autorestart=true
autostart=true autostart=true
startretries=3 startretries=3
priority=5 priority=5
nice=-2 nice=-10
environment=HOME=%(ENV_NESTRI_HOME)s,XDG_RUNTIME_DIR=%(ENV_NESTRI_XDG_RUNTIME_DIR)s environment=HOME=%(ENV_NESTRI_HOME)s,XDG_RUNTIME_DIR=%(ENV_NESTRI_XDG_RUNTIME_DIR)s
[program:vimputti-manager] [program:vimputti-manager]

File diff suppressed because it is too large Load Diff

View File

@@ -22,13 +22,13 @@ rand = "0.9"
rustls = { version = "0.23", features = ["ring"] } rustls = { version = "0.23", features = ["ring"] }
tracing = "0.1" tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter"] } tracing-subscriber = { version = "0.3", features = ["env-filter"] }
vimputti = "0.1.7" vimputti = "0.1.4"
chrono = "0.4" chrono = "0.4"
prost = "0.14" prost = "0.14"
prost-types = "0.14" prost-types = "0.14"
parking_lot = "0.12" parking_lot = "0.12"
byteorder = "1.5" byteorder = "1.5"
libp2p = { version = "0.56", features = ["identify", "dns", "tcp", "noise", "ping", "tokio", "serde", "yamux", "macros", "autonat", "quic"] } libp2p = { version = "0.56", features = ["identify", "dns", "tcp", "noise", "ping", "tokio", "serde", "yamux", "macros", "websocket", "autonat"] }
libp2p-identify = "0.47" libp2p-identify = "0.47"
libp2p-ping = "0.47" libp2p-ping = "0.47"
libp2p-autonat = { version = "0.15", features = ["v2"] } libp2p-autonat = { version = "0.15", features = ["v2"] }
@@ -37,7 +37,7 @@ libp2p-yamux = "0.47"
libp2p-noise = "0.46" libp2p-noise = "0.46"
libp2p-dns = { version = "0.44", features = ["tokio"] } libp2p-dns = { version = "0.44", features = ["tokio"] }
libp2p-tcp = { version = "0.44", features = ["tokio"] } libp2p-tcp = { version = "0.44", features = ["tokio"] }
libp2p-quic = { version = "0.13", features = ["tokio"] } libp2p-websocket = "0.45"
dashmap = "6.1" dashmap = "6.1"
anyhow = "1.0" anyhow = "1.0"
unsigned-varint = "0.8" unsigned-varint = "0.8"

View File

@@ -1,2 +1,2 @@
[toolchain] [toolchain]
channel = "1.91" channel = "1.90"

View File

@@ -122,14 +122,6 @@ impl Args {
.value_parser(value_parser!(encoding_args::RateControlMethod)) .value_parser(value_parser!(encoding_args::RateControlMethod))
.default_value("cbr"), .default_value("cbr"),
) )
.arg(
Arg::new("video-latency-control")
.long("video-latency-control")
.env("VIDEO_LATENCY_CONTROL")
.help("Video latency control")
.value_parser(value_parser!(encoding_args::LatencyControl))
.default_value("lowest-latency"),
)
.arg( .arg(
Arg::new("video-cqp") Arg::new("video-cqp")
.long("video-cqp") .long("video-cqp")
@@ -173,14 +165,6 @@ impl Args {
) )
.default_value("8"), .default_value("8"),
) )
.arg(
Arg::new("keyframe-dist-secs")
.long("keyframe-dist-secs")
.env("KEYFRAME_DIST_SECS")
.help("Distance between keyframes in seconds")
.value_parser(value_parser!(u32).range(1..))
.default_value("1"),
)
.arg( .arg(
Arg::new("audio-capture-method") Arg::new("audio-capture-method")
.long("audio-capture-method") .long("audio-capture-method")
@@ -211,14 +195,6 @@ impl Args {
.value_parser(value_parser!(encoding_args::RateControlMethod)) .value_parser(value_parser!(encoding_args::RateControlMethod))
.default_value("cbr"), .default_value("cbr"),
) )
.arg(
Arg::new("audio-latency-control")
.long("audio-latency-control")
.env("AUDIO_LATENCY_CONTROL")
.help("Audio latency control")
.value_parser(value_parser!(encoding_args::LatencyControl))
.default_value("lowest-latency"),
)
.arg( .arg(
Arg::new("audio-bitrate") Arg::new("audio-bitrate")
.long("audio-bitrate") .long("audio-bitrate")

View File

@@ -60,12 +60,6 @@ pub enum RateControl {
CBR(RateControlCBR), CBR(RateControlCBR),
} }
#[derive(Debug, PartialEq, Eq, Clone, ValueEnum)]
pub enum LatencyControl {
LowestLatency,
HighestQuality,
}
pub struct EncodingOptionsBase { pub struct EncodingOptionsBase {
/// Codec (e.g. "h264", "opus" etc.) /// Codec (e.g. "h264", "opus" etc.)
pub codec: Codec, pub codec: Codec,
@@ -73,8 +67,6 @@ pub struct EncodingOptionsBase {
pub encoder: Option<String>, pub encoder: Option<String>,
/// Rate control method (e.g. "cqp", "vbr", "cbr") /// Rate control method (e.g. "cqp", "vbr", "cbr")
pub rate_control: RateControl, pub rate_control: RateControl,
/// Latency control option, what to tweak settings towards (latency or quality)
pub latency_control: LatencyControl,
} }
impl EncodingOptionsBase { impl EncodingOptionsBase {
pub fn debug_print(&self) { pub fn debug_print(&self) {
@@ -95,14 +87,6 @@ impl EncodingOptionsBase {
tracing::info!("-> Target Bitrate: {}", cbr.target_bitrate); tracing::info!("-> Target Bitrate: {}", cbr.target_bitrate);
} }
} }
match &self.latency_control {
LatencyControl::LowestLatency => {
tracing::info!("> Latency Control: Priorizing lowest latency");
}
LatencyControl::HighestQuality => {
tracing::info!("> Latency Control: Priorizing quality at the cost of latency");
}
}
} }
} }
@@ -110,7 +94,6 @@ pub struct VideoEncodingOptions {
pub base: EncodingOptionsBase, pub base: EncodingOptionsBase,
pub encoder_type: EncoderType, pub encoder_type: EncoderType,
pub bit_depth: u32, pub bit_depth: u32,
pub keyframe_dist_secs: u32,
} }
impl VideoEncodingOptions { impl VideoEncodingOptions {
pub fn from_matches(matches: &clap::ArgMatches) -> Self { pub fn from_matches(matches: &clap::ArgMatches) -> Self {
@@ -142,10 +125,6 @@ impl VideoEncodingOptions {
max_bitrate: matches.get_one::<u32>("video-bitrate-max").unwrap().clone(), max_bitrate: matches.get_one::<u32>("video-bitrate-max").unwrap().clone(),
}), }),
}, },
latency_control: matches
.get_one::<LatencyControl>("video-latency-control")
.unwrap_or(&LatencyControl::LowestLatency)
.clone(),
}, },
encoder_type: matches encoder_type: matches
.get_one::<EncoderType>("video-encoder-type") .get_one::<EncoderType>("video-encoder-type")
@@ -155,10 +134,6 @@ impl VideoEncodingOptions {
.get_one::<u32>("video-bit-depth") .get_one::<u32>("video-bit-depth")
.copied() .copied()
.unwrap_or(8), .unwrap_or(8),
keyframe_dist_secs: matches
.get_one::<u32>("keyframe-dist-secs")
.copied()
.unwrap_or(1),
} }
} }
@@ -167,7 +142,6 @@ impl VideoEncodingOptions {
self.base.debug_print(); self.base.debug_print();
tracing::info!("> Encoder Type: {}", self.encoder_type.as_str()); tracing::info!("> Encoder Type: {}", self.encoder_type.as_str());
tracing::info!("> Bit Depth: {}", self.bit_depth); tracing::info!("> Bit Depth: {}", self.bit_depth);
tracing::info!("> Keyframe Distance Seconds: {}", self.keyframe_dist_secs);
} }
} }
impl Deref for VideoEncodingOptions { impl Deref for VideoEncodingOptions {
@@ -234,10 +208,6 @@ impl AudioEncodingOptions {
}), }),
wot => panic!("Invalid rate control method for audio: {}", wot.as_str()), wot => panic!("Invalid rate control method for audio: {}", wot.as_str()),
}, },
latency_control: matches
.get_one::<LatencyControl>("audio-latency-control")
.unwrap_or(&LatencyControl::LowestLatency)
.clone(),
}, },
capture_method: matches capture_method: matches
.get_one::<AudioCaptureMethod>("audio-capture-method") .get_one::<AudioCaptureMethod>("audio-capture-method")

View File

@@ -74,6 +74,7 @@ pub enum EncoderAPI {
QSV, QSV,
VAAPI, VAAPI,
NVENC, NVENC,
AMF,
SOFTWARE, SOFTWARE,
UNKNOWN, UNKNOWN,
} }
@@ -84,6 +85,7 @@ impl EncoderAPI {
Self::QSV => "Intel QuickSync Video", Self::QSV => "Intel QuickSync Video",
Self::VAAPI => "Video Acceleration API", Self::VAAPI => "Video Acceleration API",
Self::NVENC => "NVIDIA NVENC", Self::NVENC => "NVIDIA NVENC",
Self::AMF => "AMD Media Framework",
Self::SOFTWARE => "Software", Self::SOFTWARE => "Software",
Self::UNKNOWN => "Unknown", Self::UNKNOWN => "Unknown",
} }
@@ -165,6 +167,8 @@ fn get_encoder_api(encoder: &str, encoder_type: &EncoderType) -> EncoderAPI {
EncoderAPI::VAAPI EncoderAPI::VAAPI
} else if encoder.starts_with("nv") { } else if encoder.starts_with("nv") {
EncoderAPI::NVENC EncoderAPI::NVENC
} else if encoder.starts_with("amf") {
EncoderAPI::AMF
} else { } else {
EncoderAPI::UNKNOWN EncoderAPI::UNKNOWN
} }
@@ -271,9 +275,9 @@ pub fn encoder_low_latency_params(
encoder: &VideoEncoderInfo, encoder: &VideoEncoderInfo,
_rate_control: &RateControl, _rate_control: &RateControl,
framerate: u32, framerate: u32,
keyframe_dist_secs: u32,
) -> VideoEncoderInfo { ) -> VideoEncoderInfo {
let mut encoder_optz = encoder_gop_params(encoder, framerate * keyframe_dist_secs); // 1 second keyframe interval for fast recovery, is this too taxing?
let mut encoder_optz = encoder_gop_params(encoder, framerate);
match encoder_optz.encoder_api { match encoder_optz.encoder_api {
EncoderAPI::QSV => { EncoderAPI::QSV => {
@@ -289,6 +293,16 @@ pub fn encoder_low_latency_params(
encoder_optz.set_parameter("tune", "ultra-low-latency"); encoder_optz.set_parameter("tune", "ultra-low-latency");
encoder_optz.set_parameter("zerolatency", "true"); encoder_optz.set_parameter("zerolatency", "true");
} }
EncoderAPI::AMF => {
encoder_optz.set_parameter("preset", "speed");
let usage = match encoder_optz.codec {
VideoCodec::H264 | VideoCodec::H265 => "ultra-low-latency",
VideoCodec::AV1 => "low-latency",
};
if !usage.is_empty() {
encoder_optz.set_parameter("usage", usage);
}
}
EncoderAPI::SOFTWARE => match encoder_optz.name.as_str() { EncoderAPI::SOFTWARE => match encoder_optz.name.as_str() {
"openh264enc" => { "openh264enc" => {
encoder_optz.set_parameter("complexity", "low"); encoder_optz.set_parameter("complexity", "low");
@@ -316,56 +330,6 @@ pub fn encoder_low_latency_params(
encoder_optz encoder_optz
} }
pub fn encoder_high_quality_params(
encoder: &VideoEncoderInfo,
_rate_control: &RateControl,
framerate: u32,
keyframe_dist_secs: u32,
) -> VideoEncoderInfo {
let mut encoder_optz = encoder_gop_params(encoder, framerate * keyframe_dist_secs);
match encoder_optz.encoder_api {
EncoderAPI::QSV => {
encoder_optz.set_parameter("low-latency", "false");
encoder_optz.set_parameter("target-usage", "1");
}
EncoderAPI::VAAPI => {
encoder_optz.set_parameter("target-usage", "1");
}
EncoderAPI::NVENC => {
encoder_optz.set_parameter("multi-pass", "two-pass");
encoder_optz.set_parameter("preset", "p7");
encoder_optz.set_parameter("tune", "high-quality");
encoder_optz.set_parameter("zerolatency", "false");
encoder_optz.set_parameter("spatial-aq", "true");
encoder_optz.set_parameter("rc-lookahead", "3");
}
EncoderAPI::SOFTWARE => match encoder_optz.name.as_str() {
"openh264enc" => {
encoder_optz.set_parameter("complexity", "high");
encoder_optz.set_parameter("usage-type", "screen");
}
"x264enc" => {
encoder_optz.set_parameter("rc-lookahead", "3");
encoder_optz.set_parameter("speed-preset", "medium");
}
"svtav1enc" => {
encoder_optz.set_parameter("preset", "8");
encoder_optz.set_parameter("parameters-string", "lookahead=3");
}
"av1enc" => {
encoder_optz.set_parameter("usage-profile", "realtime");
encoder_optz.set_parameter("cpu-used", "8");
encoder_optz.set_parameter("lag-in-frames", "3");
}
_ => {}
},
_ => {}
}
encoder_optz
}
pub fn get_compatible_encoders(gpus: &Vec<GPUInfo>) -> Vec<VideoEncoderInfo> { pub fn get_compatible_encoders(gpus: &Vec<GPUInfo>) -> Vec<VideoEncoderInfo> {
let mut encoders = Vec::new(); let mut encoders = Vec::new();
let registry = gstreamer::Registry::get(); let registry = gstreamer::Registry::get();
@@ -463,6 +427,16 @@ pub fn get_compatible_encoders(gpus: &Vec<GPUInfo>) -> Vec<VideoEncoderInfo> {
None None
} }
} }
EncoderAPI::AMF if element.has_property("device") => {
let device_id = match element.property_value("device").get::<u32>() {
Ok(v) => Some(v as usize),
Err(_) => None,
};
device_id.and_then(|id| {
get_gpus_by_vendor(&gpus, GPUVendor::AMD).get(id).cloned()
})
}
_ => None, _ => None,
} }
}) })
@@ -575,6 +549,7 @@ pub fn get_best_compatible_encoder(
score += match encoder.encoder_api { score += match encoder.encoder_api {
EncoderAPI::NVENC => 3, EncoderAPI::NVENC => 3,
EncoderAPI::QSV => 3, EncoderAPI::QSV => 3,
EncoderAPI::AMF => 3,
EncoderAPI::VAAPI => 2, EncoderAPI::VAAPI => 2,
EncoderAPI::SOFTWARE => 1, EncoderAPI::SOFTWARE => 1,
EncoderAPI::UNKNOWN => 0, EncoderAPI::UNKNOWN => 0,

View File

@@ -29,8 +29,10 @@ impl ControllerInput {
client: &vimputti::client::VimputtiClient, client: &vimputti::client::VimputtiClient,
) -> Result<Self> { ) -> Result<Self> {
let config = controller_string_to_type(&controller_type)?; let config = controller_string_to_type(&controller_type)?;
let device = client.create_device(config.clone()).await?; Ok(Self {
Ok(Self { config, device }) config: config.clone(),
device: client.create_device(config).await?,
})
} }
pub fn device_mut(&mut self) -> &mut vimputti::client::VirtualController { pub fn device_mut(&mut self) -> &mut vimputti::client::VirtualController {
@@ -119,60 +121,9 @@ async fn command_loop(
slot.session_id == session_id && slot.session_slot == session_slot as u32 slot.session_id == session_id && slot.session_slot == session_slot as u32
}) })
.map(|(slot_num, _)| *slot_num); .map(|(slot_num, _)| *slot_num);
let slot = existing_slot.or_else(|| get_free_slot(&controllers));
if let Some(existing_slot) = existing_slot { if let Some(slot) = slot {
if let Some(controller_slot) = controllers.get_mut(&existing_slot) {
let rumble_tx = rumble_tx.clone();
let attach_tx = attach_tx.clone();
controller_slot
.controller
.device_mut()
.on_rumble(move |strong, weak, duration_ms| {
let _ = rumble_tx.try_send((
existing_slot,
strong,
weak,
duration_ms,
data.session_id.clone(),
));
})
.await
.map_err(|e| {
tracing::warn!(
"Failed to register rumble callback for slot {}: {}",
existing_slot,
e
);
})
.ok();
// Return to attach_tx what slot was assigned
let attach_info = ProtoControllerAttach {
id: data.id.clone(),
session_slot: existing_slot as i32,
session_id: session_id.clone(),
};
match attach_tx.send(attach_info).await {
Ok(_) => {
tracing::info!(
"Controller {} re-attached to slot {} (session: {})",
data.id,
existing_slot,
session_id
);
}
Err(e) => {
tracing::error!(
"Failed to send re-attach info for slot {}: {}",
existing_slot,
e
);
}
}
}
} else if let Some(slot) = get_free_slot(&controllers) {
if let Ok(mut controller) = if let Ok(mut controller) =
ControllerInput::new(data.id.clone(), &vimputti_client).await ControllerInput::new(data.id.clone(), &vimputti_client).await
{ {
@@ -182,13 +133,7 @@ async fn command_loop(
controller controller
.device_mut() .device_mut()
.on_rumble(move |strong, weak, duration_ms| { .on_rumble(move |strong, weak, duration_ms| {
let _ = rumble_tx.try_send(( let _ = rumble_tx.try_send((slot, strong, weak, duration_ms, data.session_id.clone()));
slot,
strong,
weak,
duration_ms,
data.session_id.clone(),
));
}) })
.await .await
.map_err(|e| { .map_err(|e| {
@@ -245,10 +190,65 @@ async fn command_loop(
if controllers.remove(&(data.session_slot as u32)).is_some() { if controllers.remove(&(data.session_slot as u32)).is_some() {
tracing::info!("Controller detached from slot {}", data.session_slot); tracing::info!("Controller detached from slot {}", data.session_slot);
} else { } else {
tracing::warn!( tracing::warn!("No controller found in slot {} to detach", data.session_slot);
"No controller found in slot {} to detach", }
data.session_slot }
); Payload::ControllerButton(data) => {
if let Some(controller) = controllers.get(&(data.session_slot as u32)) {
if let Some(button) = vimputti::Button::from_ev_code(data.button as u16) {
let device = controller.controller.device();
device.button(button, data.pressed);
device.sync();
}
} else {
tracing::warn!("Controller slot {} not found for button event", data.session_slot);
}
}
Payload::ControllerStick(data) => {
if let Some(controller) = controllers.get(&(data.session_slot as u32)) {
let device = controller.controller.device();
if data.stick == 0 {
// Left stick
device.axis(vimputti::Axis::LeftStickX, data.x);
device.sync();
device.axis(vimputti::Axis::LeftStickY, data.y);
} else if data.stick == 1 {
// Right stick
device.axis(vimputti::Axis::RightStickX, data.x);
device.sync();
device.axis(vimputti::Axis::RightStickY, data.y);
}
device.sync();
} else {
tracing::warn!("Controller slot {} not found for stick event", data.session_slot);
}
}
Payload::ControllerTrigger(data) => {
if let Some(controller) = controllers.get(&(data.session_slot as u32)) {
let device = controller.controller.device();
if data.trigger == 0 {
// Left trigger
device.axis(vimputti::Axis::LowerLeftTrigger, data.value);
} else if data.trigger == 1 {
// Right trigger
device.axis(vimputti::Axis::LowerRightTrigger, data.value);
}
device.sync();
} else {
tracing::warn!("Controller slot {} not found for trigger event", data.session_slot);
}
}
Payload::ControllerAxis(data) => {
if let Some(controller) = controllers.get(&(data.session_slot as u32)) {
let device = controller.controller.device();
if data.axis == 0 {
// dpad x
device.axis(vimputti::Axis::DPadX, data.value);
} else if data.axis == 1 {
// dpad y
device.axis(vimputti::Axis::DPadY, data.value);
}
device.sync();
} }
} }
Payload::ClientDisconnected(data) => { Payload::ClientDisconnected(data) => {
@@ -274,125 +274,6 @@ async fn command_loop(
} }
} }
} }
Payload::ControllerStateBatch(data) => {
if let Some(controller) = controllers.get(&(data.session_slot as u32)) {
let device = controller.controller.device();
// Handle inputs based on update type
if data.update_type == 0 {
// FULL_STATE: Update all values
let _ = device.sync().await;
for (btn_code, pressed) in data.button_changed_mask {
if let Some(button) = vimputti::Button::from_ev_code(btn_code as u16) {
let _ = device.button(button, pressed).await;
let _ = device.sync().await;
}
}
if let Some(x) = data.left_stick_x {
let _ = device.axis(vimputti::Axis::LeftStickX, x).await;
let _ = device.sync().await;
}
if let Some(y) = data.left_stick_y {
let _ = device.axis(vimputti::Axis::LeftStickY, y).await;
let _ = device.sync().await;
}
if let Some(x) = data.right_stick_x {
let _ = device.axis(vimputti::Axis::RightStickX, x).await;
let _ = device.sync().await;
}
if let Some(y) = data.right_stick_y {
let _ = device.axis(vimputti::Axis::RightStickY, y).await;
let _ = device.sync().await;
}
if let Some(value) = data.left_trigger {
let _ = device.axis(vimputti::Axis::LowerLeftTrigger, value).await;
let _ = device.sync().await;
}
if let Some(value) = data.right_trigger {
let _ = device.axis(vimputti::Axis::LowerRightTrigger, value).await;
let _ = device.sync().await;
}
if let Some(x) = data.dpad_x {
let _ = device.axis(vimputti::Axis::DPadX, x).await;
let _ = device.sync().await;
}
if let Some(y) = data.dpad_y {
let _ = device.axis(vimputti::Axis::DPadY, y).await;
let _ = device.sync().await;
}
} else {
// DELTA: Only update changed values
if let Some(changed_fields) = data.changed_fields {
let _ = device.sync().await;
if (changed_fields & (1 << 0)) != 0 {
for (btn_code, pressed) in data.button_changed_mask {
if let Some(button) =
vimputti::Button::from_ev_code(btn_code as u16)
{
let _ = device.button(button, pressed).await;
let _ = device.sync().await;
}
}
}
if (changed_fields & (1 << 1)) != 0 {
if let Some(x) = data.left_stick_x {
let _ = device.axis(vimputti::Axis::LeftStickX, x).await;
let _ = device.sync().await;
}
}
if (changed_fields & (1 << 2)) != 0 {
if let Some(y) = data.left_stick_y {
let _ = device.axis(vimputti::Axis::LeftStickY, y).await;
let _ = device.sync().await;
}
}
if (changed_fields & (1 << 3)) != 0 {
if let Some(x) = data.right_stick_x {
let _ = device.axis(vimputti::Axis::RightStickX, x).await;
let _ = device.sync().await;
}
}
if (changed_fields & (1 << 4)) != 0 {
if let Some(y) = data.right_stick_y {
let _ = device.axis(vimputti::Axis::RightStickY, y).await;
let _ = device.sync().await;
}
}
if (changed_fields & (1 << 5)) != 0 {
if let Some(value) = data.left_trigger {
let _ =
device.axis(vimputti::Axis::LowerLeftTrigger, value).await;
let _ = device.sync().await;
}
}
if (changed_fields & (1 << 6)) != 0 {
if let Some(value) = data.right_trigger {
let _ =
device.axis(vimputti::Axis::LowerRightTrigger, value).await;
let _ = device.sync().await;
}
}
if (changed_fields & (1 << 7)) != 0 {
if let Some(x) = data.dpad_x {
let _ = device.axis(vimputti::Axis::DPadX, x).await;
let _ = device.sync().await;
}
}
if (changed_fields & (1 << 8)) != 0 {
if let Some(y) = data.dpad_y {
let _ = device.axis(vimputti::Axis::DPadY, y).await;
let _ = device.sync().await;
}
}
}
}
} else {
tracing::warn!(
"Controller slot {} not found for state batch event",
data.session_slot
);
}
}
_ => { _ => {
//no-op //no-op
} }

View File

@@ -8,7 +8,6 @@ mod p2p;
mod proto; mod proto;
use crate::args::encoding_args; use crate::args::encoding_args;
use crate::args::encoding_args::LatencyControl;
use crate::enc_helper::{EncoderAPI, EncoderType}; use crate::enc_helper::{EncoderAPI, EncoderType};
use crate::gpu::{GPUInfo, GPUVendor}; use crate::gpu::{GPUInfo, GPUVendor};
use crate::input::controller::ControllerManager; use crate::input::controller::ControllerManager;
@@ -131,20 +130,11 @@ fn handle_encoder_video_settings(
args: &args::Args, args: &args::Args,
video_encoder: &enc_helper::VideoEncoderInfo, video_encoder: &enc_helper::VideoEncoderInfo,
) -> enc_helper::VideoEncoderInfo { ) -> enc_helper::VideoEncoderInfo {
let mut optimized_encoder = match args.encoding.video.latency_control { let mut optimized_encoder = enc_helper::encoder_low_latency_params(
LatencyControl::LowestLatency => enc_helper::encoder_low_latency_params(
&video_encoder, &video_encoder,
&args.encoding.video.rate_control, &args.encoding.video.rate_control,
args.app.framerate, args.app.framerate,
args.encoding.video.keyframe_dist_secs, );
),
LatencyControl::HighestQuality => enc_helper::encoder_high_quality_params(
&video_encoder,
&args.encoding.video.rate_control,
args.app.framerate,
args.encoding.video.keyframe_dist_secs,
),
};
// Handle rate-control method // Handle rate-control method
match &args.encoding.video.rate_control { match &args.encoding.video.rate_control {
encoding_args::RateControl::CQP(cqp) => { encoding_args::RateControl::CQP(cqp) => {
@@ -439,34 +429,39 @@ async fn main() -> Result<(), Box<dyn Error>> {
webrtcsink.set_property("do-retransmission", false); webrtcsink.set_property("do-retransmission", false);
/* Queues */ /* Queues */
// Sink queues let video_queue = gstreamer::ElementFactory::make("queue")
let video_sink_queue = gstreamer::ElementFactory::make("queue").build()?;
let audio_sink_queue = gstreamer::ElementFactory::make("queue").build()?;
// Source queues
let video_source_queue = gstreamer::ElementFactory::make("queue")
.property("max-size-buffers", 2u32) .property("max-size-buffers", 2u32)
.property("max-size-time", 0u64) .property("max-size-time", 0u64)
.property("max-size-bytes", 0u32) .property("max-size-bytes", 0u32)
.build()?; .build()?;
let audio_source_queue = gstreamer::ElementFactory::make("queue")
let audio_queue = gstreamer::ElementFactory::make("queue")
.property("max-size-buffers", 2u32) .property("max-size-buffers", 2u32)
.property("max-size-time", 0u64) .property("max-size-time", 0u64)
.property("max-size-bytes", 0u32) .property("max-size-bytes", 0u32)
.build()?; .build()?;
/* Clock Sync */
let video_clocksync = gstreamer::ElementFactory::make("clocksync")
.property("sync-to-first", true)
.build()?;
let audio_clocksync = gstreamer::ElementFactory::make("clocksync")
.property("sync-to-first", true)
.build()?;
// Add elements to the pipeline // Add elements to the pipeline
pipeline.add_many(&[ pipeline.add_many(&[
webrtcsink.upcast_ref(), webrtcsink.upcast_ref(),
&video_sink_queue,
&audio_sink_queue,
&video_encoder, &video_encoder,
&caps_filter, &caps_filter,
&video_source_queue, &video_queue,
&video_clocksync,
&video_source, &video_source,
&audio_encoder, &audio_encoder,
&audio_capsfilter, &audio_capsfilter,
&audio_source_queue, &audio_queue,
&audio_clocksync,
&audio_rate, &audio_rate,
&audio_converter, &audio_converter,
&audio_source, &audio_source,
@@ -498,24 +493,16 @@ async fn main() -> Result<(), Box<dyn Error>> {
&audio_converter, &audio_converter,
&audio_rate, &audio_rate,
&audio_capsfilter, &audio_capsfilter,
&audio_source_queue, &audio_queue,
&audio_clocksync,
&audio_encoder, &audio_encoder,
])?; ])?;
// Link audio parser to audio encoder if present, otherwise just webrtcsink // Link audio parser to audio encoder if present, otherwise just webrtcsink
if let Some(parser) = &audio_parser { if let Some(parser) = &audio_parser {
gstreamer::Element::link_many(&[ gstreamer::Element::link_many(&[&audio_encoder, parser, webrtcsink.upcast_ref()])?;
&audio_encoder,
parser,
&audio_sink_queue,
webrtcsink.upcast_ref(),
])?;
} else { } else {
gstreamer::Element::link_many(&[ gstreamer::Element::link_many(&[&audio_encoder, webrtcsink.upcast_ref()])?;
&audio_encoder,
&audio_sink_queue,
webrtcsink.upcast_ref(),
])?;
} }
// With zero-copy.. // With zero-copy..
@@ -525,20 +512,26 @@ async fn main() -> Result<(), Box<dyn Error>> {
gstreamer::Element::link_many(&[ gstreamer::Element::link_many(&[
&video_source, &video_source,
&caps_filter, &caps_filter,
&video_source_queue, &video_queue,
&video_clocksync,
&vapostproc, &vapostproc,
&va_caps_filter, &va_caps_filter,
&video_encoder, &video_encoder,
])?; ])?;
} else if video_encoder_info.encoder_api == EncoderAPI::NVENC { } else if video_encoder_info.encoder_api == EncoderAPI::NVENC {
// NVENC pipeline // NVENC pipeline
gstreamer::Element::link_many(&[&video_source, &caps_filter, &video_encoder])?; gstreamer::Element::link_many(&[
&video_source,
&caps_filter,
&video_encoder,
])?;
} }
} else { } else {
gstreamer::Element::link_many(&[ gstreamer::Element::link_many(&[
&video_source, &video_source,
&caps_filter, &caps_filter,
&video_source_queue, &video_queue,
&video_clocksync,
&video_converter.unwrap(), &video_converter.unwrap(),
&video_encoder, &video_encoder,
])?; ])?;
@@ -546,24 +539,21 @@ async fn main() -> Result<(), Box<dyn Error>> {
// Link video parser if present with webrtcsink, otherwise just link webrtc sink // Link video parser if present with webrtcsink, otherwise just link webrtc sink
if let Some(parser) = &video_parser { if let Some(parser) = &video_parser {
gstreamer::Element::link_many(&[ gstreamer::Element::link_many(&[&video_encoder, parser, webrtcsink.upcast_ref()])?;
&video_encoder,
parser,
&video_sink_queue,
webrtcsink.upcast_ref(),
])?;
} else { } else {
gstreamer::Element::link_many(&[ gstreamer::Element::link_many(&[&video_encoder, webrtcsink.upcast_ref()])?;
&video_encoder,
&video_sink_queue,
webrtcsink.upcast_ref(),
])?;
} }
video_source.set_property("do-timestamp", &false); // Make sure QOS is disabled to avoid latency
audio_source.set_property("do-timestamp", &false); video_encoder.set_property("qos", true);
// Optimize latency of pipeline // Optimize latency of pipeline
video_source
.sync_state_with_parent()
.expect("failed to sync with parent");
video_source.set_property("do-timestamp", &true);
audio_source.set_property("do-timestamp", &true);
pipeline.set_property("latency", &0u64); pipeline.set_property("latency", &0u64);
pipeline.set_property("async-handling", true); pipeline.set_property("async-handling", true);
pipeline.set_property("message-forward", true); pipeline.set_property("message-forward", true);

View File

@@ -55,8 +55,9 @@ impl NestriP2P {
noise::Config::new, noise::Config::new,
yamux::Config::default, yamux::Config::default,
)? )?
.with_quic()
.with_dns()? .with_dns()?
.with_websocket(noise::Config::new, yamux::Config::default)
.await?
.with_behaviour(|key| NestriBehaviour::new(key.public()))? .with_behaviour(|key| NestriBehaviour::new(key.public()))?
.build(), .build(),
)); ));

View File

@@ -1,12 +1,14 @@
// @generated // @generated
// This file is @generated by prost-build. // This file is @generated by prost-build.
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] #[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct ProtoTimestampEntry { pub struct ProtoTimestampEntry {
#[prost(string, tag="1")] #[prost(string, tag="1")]
pub stage: ::prost::alloc::string::String, pub stage: ::prost::alloc::string::String,
#[prost(message, optional, tag="2")] #[prost(message, optional, tag="2")]
pub time: ::core::option::Option<::prost_types::Timestamp>, pub time: ::core::option::Option<::prost_types::Timestamp>,
} }
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)] #[derive(Clone, PartialEq, ::prost::Message)]
pub struct ProtoLatencyTracker { pub struct ProtoLatencyTracker {
#[prost(string, tag="1")] #[prost(string, tag="1")]
@@ -17,7 +19,8 @@ pub struct ProtoLatencyTracker {
// Mouse messages // Mouse messages
/// MouseMove message /// MouseMove message
#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] #[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, Copy, PartialEq, ::prost::Message)]
pub struct ProtoMouseMove { pub struct ProtoMouseMove {
#[prost(int32, tag="1")] #[prost(int32, tag="1")]
pub x: i32, pub x: i32,
@@ -25,7 +28,8 @@ pub struct ProtoMouseMove {
pub y: i32, pub y: i32,
} }
/// MouseMoveAbs message /// MouseMoveAbs message
#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] #[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, Copy, PartialEq, ::prost::Message)]
pub struct ProtoMouseMoveAbs { pub struct ProtoMouseMoveAbs {
#[prost(int32, tag="1")] #[prost(int32, tag="1")]
pub x: i32, pub x: i32,
@@ -33,7 +37,8 @@ pub struct ProtoMouseMoveAbs {
pub y: i32, pub y: i32,
} }
/// MouseWheel message /// MouseWheel message
#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] #[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, Copy, PartialEq, ::prost::Message)]
pub struct ProtoMouseWheel { pub struct ProtoMouseWheel {
#[prost(int32, tag="1")] #[prost(int32, tag="1")]
pub x: i32, pub x: i32,
@@ -41,13 +46,15 @@ pub struct ProtoMouseWheel {
pub y: i32, pub y: i32,
} }
/// MouseKeyDown message /// MouseKeyDown message
#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] #[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, Copy, PartialEq, ::prost::Message)]
pub struct ProtoMouseKeyDown { pub struct ProtoMouseKeyDown {
#[prost(int32, tag="1")] #[prost(int32, tag="1")]
pub key: i32, pub key: i32,
} }
/// MouseKeyUp message /// MouseKeyUp message
#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] #[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, Copy, PartialEq, ::prost::Message)]
pub struct ProtoMouseKeyUp { pub struct ProtoMouseKeyUp {
#[prost(int32, tag="1")] #[prost(int32, tag="1")]
pub key: i32, pub key: i32,
@@ -55,26 +62,24 @@ pub struct ProtoMouseKeyUp {
// Keyboard messages // Keyboard messages
/// KeyDown message /// KeyDown message
#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] #[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, Copy, PartialEq, ::prost::Message)]
pub struct ProtoKeyDown { pub struct ProtoKeyDown {
#[prost(int32, tag="1")] #[prost(int32, tag="1")]
pub key: i32, pub key: i32,
} }
/// KeyUp message /// KeyUp message
#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] #[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, Copy, PartialEq, ::prost::Message)]
pub struct ProtoKeyUp { pub struct ProtoKeyUp {
#[prost(int32, tag="1")] #[prost(int32, tag="1")]
pub key: i32, pub key: i32,
} }
// Clipboard message
// message ProtoClipboard {
// string content = 1; // Clipboard content
// }
// Controller messages // Controller messages
/// ControllerAttach message /// ControllerAttach message
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] #[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct ProtoControllerAttach { pub struct ProtoControllerAttach {
/// One of the following enums: "ps", "xbox" or "switch" /// One of the following enums: "ps", "xbox" or "switch"
#[prost(string, tag="1")] #[prost(string, tag="1")]
@@ -87,7 +92,8 @@ pub struct ProtoControllerAttach {
pub session_id: ::prost::alloc::string::String, pub session_id: ::prost::alloc::string::String,
} }
/// ControllerDetach message /// ControllerDetach message
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] #[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct ProtoControllerDetach { pub struct ProtoControllerDetach {
/// Session specific slot number (0-3) /// Session specific slot number (0-3)
#[prost(int32, tag="1")] #[prost(int32, tag="1")]
@@ -96,8 +102,80 @@ pub struct ProtoControllerDetach {
#[prost(string, tag="2")] #[prost(string, tag="2")]
pub session_id: ::prost::alloc::string::String, pub session_id: ::prost::alloc::string::String,
} }
/// ControllerButton message
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct ProtoControllerButton {
/// Session specific slot number (0-3)
#[prost(int32, tag="1")]
pub session_slot: i32,
/// Session ID of the client
#[prost(string, tag="2")]
pub session_id: ::prost::alloc::string::String,
/// Button code (linux input event code)
#[prost(int32, tag="3")]
pub button: i32,
/// true if pressed, false if released
#[prost(bool, tag="4")]
pub pressed: bool,
}
/// ControllerTriggers message
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct ProtoControllerTrigger {
/// Session specific slot number (0-3)
#[prost(int32, tag="1")]
pub session_slot: i32,
/// Session ID of the client
#[prost(string, tag="2")]
pub session_id: ::prost::alloc::string::String,
/// Trigger number (0 for left, 1 for right)
#[prost(int32, tag="3")]
pub trigger: i32,
/// trigger value (-32768 to 32767)
#[prost(int32, tag="4")]
pub value: i32,
}
/// ControllerSticks message
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct ProtoControllerStick {
/// Session specific slot number (0-3)
#[prost(int32, tag="1")]
pub session_slot: i32,
/// Session ID of the client
#[prost(string, tag="2")]
pub session_id: ::prost::alloc::string::String,
/// Stick number (0 for left, 1 for right)
#[prost(int32, tag="3")]
pub stick: i32,
/// X axis value (-32768 to 32767)
#[prost(int32, tag="4")]
pub x: i32,
/// Y axis value (-32768 to 32767)
#[prost(int32, tag="5")]
pub y: i32,
}
/// ControllerAxis message
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct ProtoControllerAxis {
/// Session specific slot number (0-3)
#[prost(int32, tag="1")]
pub session_slot: i32,
/// Session ID of the client
#[prost(string, tag="2")]
pub session_id: ::prost::alloc::string::String,
/// Axis number (0 for d-pad horizontal, 1 for d-pad vertical)
#[prost(int32, tag="3")]
pub axis: i32,
/// axis value (-1 to 1)
#[prost(int32, tag="4")]
pub value: i32,
}
/// ControllerRumble message /// ControllerRumble message
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] #[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct ProtoControllerRumble { pub struct ProtoControllerRumble {
/// Session specific slot number (0-3) /// Session specific slot number (0-3)
#[prost(int32, tag="1")] #[prost(int32, tag="1")]
@@ -115,88 +193,10 @@ pub struct ProtoControllerRumble {
#[prost(int32, tag="5")] #[prost(int32, tag="5")]
pub duration: i32, pub duration: i32,
} }
/// ControllerStateBatch - single message containing full or partial controller state
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct ProtoControllerStateBatch {
/// Session specific slot number (0-3)
#[prost(int32, tag="1")]
pub session_slot: i32,
/// Session ID of the client
#[prost(string, tag="2")]
pub session_id: ::prost::alloc::string::String,
#[prost(enumeration="proto_controller_state_batch::UpdateType", tag="3")]
pub update_type: i32,
/// Sequence number for packet loss detection
#[prost(uint32, tag="4")]
pub sequence: u32,
/// Button state map (Linux event codes)
#[prost(map="int32, bool", tag="5")]
pub button_changed_mask: ::std::collections::HashMap<i32, bool>,
/// Analog inputs
///
/// -32768 to 32767
#[prost(int32, optional, tag="6")]
pub left_stick_x: ::core::option::Option<i32>,
/// -32768 to 32767
#[prost(int32, optional, tag="7")]
pub left_stick_y: ::core::option::Option<i32>,
/// -32768 to 32767
#[prost(int32, optional, tag="8")]
pub right_stick_x: ::core::option::Option<i32>,
/// -32768 to 32767
#[prost(int32, optional, tag="9")]
pub right_stick_y: ::core::option::Option<i32>,
/// -32768 to 32767
#[prost(int32, optional, tag="10")]
pub left_trigger: ::core::option::Option<i32>,
/// -32768 to 32767
#[prost(int32, optional, tag="11")]
pub right_trigger: ::core::option::Option<i32>,
/// -1, 0, or 1
#[prost(int32, optional, tag="12")]
pub dpad_x: ::core::option::Option<i32>,
/// -1, 0, or 1
#[prost(int32, optional, tag="13")]
pub dpad_y: ::core::option::Option<i32>,
/// Bitmask indicating which fields have changed
/// Bit 0: button_changed_mask, Bit 1: left_stick_x, Bit 2: left_stick_y, etc.
#[prost(uint32, optional, tag="14")]
pub changed_fields: ::core::option::Option<u32>,
}
/// Nested message and enum types in `ProtoControllerStateBatch`.
pub mod proto_controller_state_batch {
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
#[repr(i32)]
pub enum UpdateType {
/// Complete controller state
FullState = 0,
/// Only changed fields
Delta = 1,
}
impl UpdateType {
/// String value of the enum field names used in the ProtoBuf definition.
///
/// The values are not transformed in any way and thus are considered stable
/// (if the ProtoBuf definition does not change) and safe for programmatic use.
pub fn as_str_name(&self) -> &'static str {
match self {
Self::FullState => "FULL_STATE",
Self::Delta => "DELTA",
}
}
/// Creates an enum from field names used in the ProtoBuf definition.
pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
match value {
"FULL_STATE" => Some(Self::FullState),
"DELTA" => Some(Self::Delta),
_ => None,
}
}
}
}
// WebRTC + signaling // WebRTC + signaling
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] #[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct RtcIceCandidateInit { pub struct RtcIceCandidateInit {
#[prost(string, tag="1")] #[prost(string, tag="1")]
pub candidate: ::prost::alloc::string::String, pub candidate: ::prost::alloc::string::String,
@@ -207,7 +207,8 @@ pub struct RtcIceCandidateInit {
#[prost(string, optional, tag="4")] #[prost(string, optional, tag="4")]
pub username_fragment: ::core::option::Option<::prost::alloc::string::String>, pub username_fragment: ::core::option::Option<::prost::alloc::string::String>,
} }
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] #[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct RtcSessionDescriptionInit { pub struct RtcSessionDescriptionInit {
#[prost(string, tag="1")] #[prost(string, tag="1")]
pub sdp: ::prost::alloc::string::String, pub sdp: ::prost::alloc::string::String,
@@ -215,25 +216,29 @@ pub struct RtcSessionDescriptionInit {
pub r#type: ::prost::alloc::string::String, pub r#type: ::prost::alloc::string::String,
} }
/// ProtoICE message /// ProtoICE message
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] #[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct ProtoIce { pub struct ProtoIce {
#[prost(message, optional, tag="1")] #[prost(message, optional, tag="1")]
pub candidate: ::core::option::Option<RtcIceCandidateInit>, pub candidate: ::core::option::Option<RtcIceCandidateInit>,
} }
/// ProtoSDP message /// ProtoSDP message
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] #[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct ProtoSdp { pub struct ProtoSdp {
#[prost(message, optional, tag="1")] #[prost(message, optional, tag="1")]
pub sdp: ::core::option::Option<RtcSessionDescriptionInit>, pub sdp: ::core::option::Option<RtcSessionDescriptionInit>,
} }
/// ProtoRaw message /// ProtoRaw message
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] #[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct ProtoRaw { pub struct ProtoRaw {
#[prost(string, tag="1")] #[prost(string, tag="1")]
pub data: ::prost::alloc::string::String, pub data: ::prost::alloc::string::String,
} }
/// ProtoClientRequestRoomStream message /// ProtoClientRequestRoomStream message
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] #[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct ProtoClientRequestRoomStream { pub struct ProtoClientRequestRoomStream {
#[prost(string, tag="1")] #[prost(string, tag="1")]
pub room_name: ::prost::alloc::string::String, pub room_name: ::prost::alloc::string::String,
@@ -241,7 +246,8 @@ pub struct ProtoClientRequestRoomStream {
pub session_id: ::prost::alloc::string::String, pub session_id: ::prost::alloc::string::String,
} }
/// ProtoClientDisconnected message /// ProtoClientDisconnected message
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] #[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct ProtoClientDisconnected { pub struct ProtoClientDisconnected {
#[prost(string, tag="1")] #[prost(string, tag="1")]
pub session_id: ::prost::alloc::string::String, pub session_id: ::prost::alloc::string::String,
@@ -249,11 +255,13 @@ pub struct ProtoClientDisconnected {
pub controller_slots: ::prost::alloc::vec::Vec<i32>, pub controller_slots: ::prost::alloc::vec::Vec<i32>,
} }
/// ProtoServerPushStream message /// ProtoServerPushStream message
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] #[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct ProtoServerPushStream { pub struct ProtoServerPushStream {
#[prost(string, tag="1")] #[prost(string, tag="1")]
pub room_name: ::prost::alloc::string::String, pub room_name: ::prost::alloc::string::String,
} }
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)] #[derive(Clone, PartialEq, ::prost::Message)]
pub struct ProtoMessageBase { pub struct ProtoMessageBase {
#[prost(string, tag="1")] #[prost(string, tag="1")]
@@ -261,16 +269,18 @@ pub struct ProtoMessageBase {
#[prost(message, optional, tag="2")] #[prost(message, optional, tag="2")]
pub latency: ::core::option::Option<ProtoLatencyTracker>, pub latency: ::core::option::Option<ProtoLatencyTracker>,
} }
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)] #[derive(Clone, PartialEq, ::prost::Message)]
pub struct ProtoMessage { pub struct ProtoMessage {
#[prost(message, optional, tag="1")] #[prost(message, optional, tag="1")]
pub message_base: ::core::option::Option<ProtoMessageBase>, pub message_base: ::core::option::Option<ProtoMessageBase>,
#[prost(oneof="proto_message::Payload", tags="2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 20, 21, 22, 23, 24, 25")] #[prost(oneof="proto_message::Payload", tags="2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 20, 21, 22, 23, 24, 25")]
pub payload: ::core::option::Option<proto_message::Payload>, pub payload: ::core::option::Option<proto_message::Payload>,
} }
/// Nested message and enum types in `ProtoMessage`. /// Nested message and enum types in `ProtoMessage`.
pub mod proto_message { pub mod proto_message {
#[derive(Clone, PartialEq, ::prost::Oneof)] #[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Oneof)]
pub enum Payload { pub enum Payload {
/// Input types /// Input types
#[prost(message, tag="2")] #[prost(message, tag="2")]
@@ -285,18 +295,22 @@ pub mod proto_message {
MouseKeyUp(super::ProtoMouseKeyUp), MouseKeyUp(super::ProtoMouseKeyUp),
#[prost(message, tag="7")] #[prost(message, tag="7")]
KeyDown(super::ProtoKeyDown), KeyDown(super::ProtoKeyDown),
/// ProtoClipboard clipboard = 9;
#[prost(message, tag="8")] #[prost(message, tag="8")]
KeyUp(super::ProtoKeyUp), KeyUp(super::ProtoKeyUp),
/// Controller input types
#[prost(message, tag="9")] #[prost(message, tag="9")]
ControllerAttach(super::ProtoControllerAttach), ControllerAttach(super::ProtoControllerAttach),
#[prost(message, tag="10")] #[prost(message, tag="10")]
ControllerDetach(super::ProtoControllerDetach), ControllerDetach(super::ProtoControllerDetach),
#[prost(message, tag="11")] #[prost(message, tag="11")]
ControllerRumble(super::ProtoControllerRumble), ControllerButton(super::ProtoControllerButton),
#[prost(message, tag="12")] #[prost(message, tag="12")]
ControllerStateBatch(super::ProtoControllerStateBatch), ControllerTrigger(super::ProtoControllerTrigger),
#[prost(message, tag="13")]
ControllerStick(super::ProtoControllerStick),
#[prost(message, tag="14")]
ControllerAxis(super::ProtoControllerAxis),
#[prost(message, tag="15")]
ControllerRumble(super::ProtoControllerRumble),
/// Signaling types /// Signaling types
#[prost(message, tag="20")] #[prost(message, tag="20")]
Ice(super::ProtoIce), Ice(super::ProtoIce),

View File

@@ -23,12 +23,13 @@ message ProtoMessage {
ProtoMouseKeyUp mouse_key_up = 6; ProtoMouseKeyUp mouse_key_up = 6;
ProtoKeyDown key_down = 7; ProtoKeyDown key_down = 7;
ProtoKeyUp key_up = 8; ProtoKeyUp key_up = 8;
// Controller input types
ProtoControllerAttach controller_attach = 9; ProtoControllerAttach controller_attach = 9;
ProtoControllerDetach controller_detach = 10; ProtoControllerDetach controller_detach = 10;
ProtoControllerRumble controller_rumble = 11; ProtoControllerButton controller_button = 11;
ProtoControllerStateBatch controller_state_batch = 12; ProtoControllerTrigger controller_trigger = 12;
ProtoControllerStick controller_stick = 13;
ProtoControllerAxis controller_axis = 14;
ProtoControllerRumble controller_rumble = 15;
// Signaling types // Signaling types
ProtoICE ice = 20; ProtoICE ice = 20;

View File

@@ -61,6 +61,39 @@ message ProtoControllerDetach {
string session_id = 2; // Session ID of the client string session_id = 2; // Session ID of the client
} }
// ControllerButton message
message ProtoControllerButton {
int32 session_slot = 1; // Session specific slot number (0-3)
string session_id = 2; // Session ID of the client
int32 button = 3; // Button code (linux input event code)
bool pressed = 4; // true if pressed, false if released
}
// ControllerTriggers message
message ProtoControllerTrigger {
int32 session_slot = 1; // Session specific slot number (0-3)
string session_id = 2; // Session ID of the client
int32 trigger = 3; // Trigger number (0 for left, 1 for right)
int32 value = 4; // trigger value (-32768 to 32767)
}
// ControllerSticks message
message ProtoControllerStick {
int32 session_slot = 1; // Session specific slot number (0-3)
string session_id = 2; // Session ID of the client
int32 stick = 3; // Stick number (0 for left, 1 for right)
int32 x = 4; // X axis value (-32768 to 32767)
int32 y = 5; // Y axis value (-32768 to 32767)
}
// ControllerAxis message
message ProtoControllerAxis {
int32 session_slot = 1; // Session specific slot number (0-3)
string session_id = 2; // Session ID of the client
int32 axis = 3; // Axis number (0 for d-pad horizontal, 1 for d-pad vertical)
int32 value = 4; // axis value (-1 to 1)
}
// ControllerRumble message // ControllerRumble message
message ProtoControllerRumble { message ProtoControllerRumble {
int32 session_slot = 1; // Session specific slot number (0-3) int32 session_slot = 1; // Session specific slot number (0-3)
@@ -70,38 +103,6 @@ message ProtoControllerRumble {
int32 duration = 5; // Duration in milliseconds int32 duration = 5; // Duration in milliseconds
} }
// ControllerStateBatch - single message containing full or partial controller state
message ProtoControllerStateBatch {
int32 session_slot = 1; // Session specific slot number (0-3)
string session_id = 2; // Session ID of the client
enum UpdateType {
FULL_STATE = 0; // Complete controller state
DELTA = 1; // Only changed fields
}
UpdateType update_type = 3;
// Sequence number for packet loss detection
uint32 sequence = 4;
// Button state map (Linux event codes)
map<int32, bool> button_changed_mask = 5;
// Analog inputs
optional int32 left_stick_x = 6; // -32768 to 32767
optional int32 left_stick_y = 7; // -32768 to 32767
optional int32 right_stick_x = 8; // -32768 to 32767
optional int32 right_stick_y = 9; // -32768 to 32767
optional int32 left_trigger = 10; // -32768 to 32767
optional int32 right_trigger = 11; // -32768 to 32767
optional int32 dpad_x = 12; // -1, 0, or 1
optional int32 dpad_y = 13; // -1, 0, or 1
// Bitmask indicating which fields have changed
// Bit 0: button_changed_mask, Bit 1: left_stick_x, Bit 2: left_stick_y, etc.
optional uint32 changed_fields = 14;
}
/* WebRTC + signaling */ /* WebRTC + signaling */
message RTCIceCandidateInit { message RTCIceCandidateInit {