From 6a78fdd0d197c6a171a444fc93513830461e1d7a Mon Sep 17 00:00:00 2001 From: Endel Dreyer Date: Wed, 11 Mar 2026 16:29:52 -0300 Subject: [PATCH 1/9] make NativeWebSocket 'universal' across Unity, Godot, MonoGame, and .NET --- .github/workflows/unity-upm-release.yml | 228 +++ .github/workflows/upmsemver.yml | 98 -- .gitignore | 8 + Media/header.png | Bin 14504 -> 19910 bytes NativeWebSocket.sln | 31 + .../Samples~/WebSocketExample/Connection.cs | 69 - .../WebSocketExample/Connection.cs.meta | 11 - .../WebSocketExampleScene.unity | 326 ---- .../WebSocketExampleScene.unity.meta | 7 - NativeWebSocket/Assets/WebSocket.meta | 8 - NativeWebSocket/Assets/WebSocket/WebSocket.cs | 848 ---------- .../Assets/WebSocket/WebSocket.cs.meta | 11 - .../Assets/WebSocket/WebSocket.jslib.meta | 32 - .../Assets/WebSocket/WebSocket.jspre.meta | 2 - .../endel.nativewebsocket.asmdef.meta | 7 - NativeWebSocket/Assets/WebSocketExample.meta | 8 - NativeWebSocket/Assets/package.json.meta | 7 - NativeWebSocket/Packages/manifest.json | 48 - .../ProjectSettings/AudioManager.asset | 19 - .../ProjectSettings/ClusterInputManager.asset | 6 - .../ProjectSettings/DynamicsManager.asset | 34 - .../ProjectSettings/EditorBuildSettings.asset | 8 - .../ProjectSettings/EditorSettings.asset | 39 - .../ProjectSettings/GraphicsSettings.asset | 64 - .../ProjectSettings/InputManager.asset | 295 ---- .../ProjectSettings/NavMeshAreas.asset | 93 -- .../ProjectSettings/Physics2DSettings.asset | 56 - .../ProjectSettings/PresetManager.asset | 7 - .../ProjectSettings/ProjectSettings.asset | 650 -------- .../ProjectSettings/ProjectVersion.txt | 2 - .../ProjectSettings/QualitySettings.asset | 231 --- .../ProjectSettings/TagManager.asset | 43 - .../ProjectSettings/TimeManager.asset | 9 - .../UnityConnectSettings.asset | 34 - .../ProjectSettings/VFXManager.asset | 14 - .../ProjectSettings/XRSettings.asset | 10 - NodeServer/index.js | 10 +- NodeServer/package-lock.json | 1480 +++++++++++------ NodeServer/package.json | 8 +- README.md | 279 +++- examples/Godot/GodotExample.csproj.old | 10 + examples/Godot/Main.tscn | 6 + examples/Godot/WebSocketExample.cs | 65 + examples/Godot/WebSocketExample.cs.uid | 1 + examples/Godot/project.godot | 23 + examples/MonoGame/Game1.cs | 92 + examples/MonoGame/Program.cs | 2 + examples/Unity/Connection.cs | 73 + integrations/Godot/Example.cs | 45 + .../MonoGame/NativeWebSocket.MonoGame.csproj | 21 + .../MonoGame/WebSocketGameComponent.cs | 61 + .../Samples~/WebSocketExample/Connection.cs | 61 + integrations/Unity/WebSocket.cs | 357 ++++ .../Unity}/WebSocket.jslib | 0 .../Unity}/WebSocket.jspre | 0 integrations/Unity/WebSocketFactoryWebGL.cs | 133 ++ integrations/Unity/WebSocketWebGL.cs | 191 +++ .../Unity}/endel.nativewebsocket.asmdef | 6 +- .../Unity}/package.json | 11 +- src/NativeWebSocket/IWebSocket.cs | 51 + src/NativeWebSocket/NativeWebSocket.csproj | 14 + src/NativeWebSocket/WebSocket.cs | 352 ++++ src/NativeWebSocket/WebSocketTypes.cs | 70 + 63 files changed, 3097 insertions(+), 3688 deletions(-) create mode 100644 .github/workflows/unity-upm-release.yml delete mode 100644 .github/workflows/upmsemver.yml create mode 100644 NativeWebSocket.sln delete mode 100644 NativeWebSocket/Assets/Samples~/WebSocketExample/Connection.cs delete mode 100644 NativeWebSocket/Assets/Samples~/WebSocketExample/Connection.cs.meta delete mode 100644 NativeWebSocket/Assets/Samples~/WebSocketExample/WebSocketExampleScene.unity delete mode 100644 NativeWebSocket/Assets/Samples~/WebSocketExample/WebSocketExampleScene.unity.meta delete mode 100644 NativeWebSocket/Assets/WebSocket.meta delete mode 100644 NativeWebSocket/Assets/WebSocket/WebSocket.cs delete mode 100644 NativeWebSocket/Assets/WebSocket/WebSocket.cs.meta delete mode 100644 NativeWebSocket/Assets/WebSocket/WebSocket.jslib.meta delete mode 100644 NativeWebSocket/Assets/WebSocket/WebSocket.jspre.meta delete mode 100644 NativeWebSocket/Assets/WebSocket/endel.nativewebsocket.asmdef.meta delete mode 100644 NativeWebSocket/Assets/WebSocketExample.meta delete mode 100644 NativeWebSocket/Assets/package.json.meta delete mode 100644 NativeWebSocket/Packages/manifest.json delete mode 100644 NativeWebSocket/ProjectSettings/AudioManager.asset delete mode 100644 NativeWebSocket/ProjectSettings/ClusterInputManager.asset delete mode 100644 NativeWebSocket/ProjectSettings/DynamicsManager.asset delete mode 100644 NativeWebSocket/ProjectSettings/EditorBuildSettings.asset delete mode 100644 NativeWebSocket/ProjectSettings/EditorSettings.asset delete mode 100644 NativeWebSocket/ProjectSettings/GraphicsSettings.asset delete mode 100644 NativeWebSocket/ProjectSettings/InputManager.asset delete mode 100644 NativeWebSocket/ProjectSettings/NavMeshAreas.asset delete mode 100644 NativeWebSocket/ProjectSettings/Physics2DSettings.asset delete mode 100644 NativeWebSocket/ProjectSettings/PresetManager.asset delete mode 100644 NativeWebSocket/ProjectSettings/ProjectSettings.asset delete mode 100644 NativeWebSocket/ProjectSettings/ProjectVersion.txt delete mode 100644 NativeWebSocket/ProjectSettings/QualitySettings.asset delete mode 100644 NativeWebSocket/ProjectSettings/TagManager.asset delete mode 100644 NativeWebSocket/ProjectSettings/TimeManager.asset delete mode 100644 NativeWebSocket/ProjectSettings/UnityConnectSettings.asset delete mode 100644 NativeWebSocket/ProjectSettings/VFXManager.asset delete mode 100644 NativeWebSocket/ProjectSettings/XRSettings.asset create mode 100644 examples/Godot/GodotExample.csproj.old create mode 100644 examples/Godot/Main.tscn create mode 100644 examples/Godot/WebSocketExample.cs create mode 100644 examples/Godot/WebSocketExample.cs.uid create mode 100644 examples/Godot/project.godot create mode 100644 examples/MonoGame/Game1.cs create mode 100644 examples/MonoGame/Program.cs create mode 100644 examples/Unity/Connection.cs create mode 100644 integrations/Godot/Example.cs create mode 100644 integrations/MonoGame/NativeWebSocket.MonoGame.csproj create mode 100644 integrations/MonoGame/WebSocketGameComponent.cs create mode 100644 integrations/Unity/Samples~/WebSocketExample/Connection.cs create mode 100644 integrations/Unity/WebSocket.cs rename {NativeWebSocket/Assets/WebSocket => integrations/Unity}/WebSocket.jslib (100%) rename {NativeWebSocket/Assets/WebSocket => integrations/Unity}/WebSocket.jspre (100%) create mode 100644 integrations/Unity/WebSocketFactoryWebGL.cs create mode 100644 integrations/Unity/WebSocketWebGL.cs rename {NativeWebSocket/Assets/WebSocket => integrations/Unity}/endel.nativewebsocket.asmdef (81%) rename {NativeWebSocket/Assets => integrations/Unity}/package.json (78%) create mode 100644 src/NativeWebSocket/IWebSocket.cs create mode 100644 src/NativeWebSocket/NativeWebSocket.csproj create mode 100644 src/NativeWebSocket/WebSocket.cs create mode 100644 src/NativeWebSocket/WebSocketTypes.cs diff --git a/.github/workflows/unity-upm-release.yml b/.github/workflows/unity-upm-release.yml new file mode 100644 index 0000000..ef46208 --- /dev/null +++ b/.github/workflows/unity-upm-release.yml @@ -0,0 +1,228 @@ +name: Unity UPM Release + +on: + push: + branches: + - master + pull_request: + branches: + - master + +jobs: + checkSemver: + name: Check for Semver Change + runs-on: ubuntu-latest + outputs: + semver-updated: ${{ steps.check.outputs.changed }} + steps: + - name: Checkout Code + uses: actions/checkout@v4 + - uses: EndBug/version-check@v1 + id: check + with: + file-name: integrations/Unity/package.json + diff-search: true + token: ${{ secrets.GITHUB_TOKEN }} + - name: Log when changed + if: steps.check.outputs.changed == 'true' + run: 'echo "Version change found in commit ${{ steps.check.outputs.commit }}! New version: ${{ steps.check.outputs.version }} (${{ steps.check.outputs.type }})"' + + updateUPM: + name: Update UPM branch + runs-on: ubuntu-latest + needs: [checkSemver] + if: needs.checkSemver.outputs.semver-updated == 'true' + steps: + - uses: actions/checkout@v4 + + - name: Assemble UPM package + run: | + mkdir -p upm-package/WebSocket + + # Core library files (single source of truth) + cp src/NativeWebSocket/IWebSocket.cs upm-package/WebSocket/ + cp src/NativeWebSocket/WebSocketTypes.cs upm-package/WebSocket/ + + # Unity-specific files (WebSocket.cs has #if !UNITY_WEBGL guard, + # WebSocketWebGL.cs + WebSocketFactoryWebGL.cs have #if UNITY_WEBGL guard) + cp integrations/Unity/WebSocket.cs upm-package/WebSocket/ + cp integrations/Unity/WebSocketWebGL.cs upm-package/WebSocket/ + cp integrations/Unity/WebSocketFactoryWebGL.cs upm-package/WebSocket/ + cp integrations/Unity/WebSocket.jslib upm-package/WebSocket/ + cp integrations/Unity/WebSocket.jspre upm-package/WebSocket/ + cp integrations/Unity/endel.nativewebsocket.asmdef upm-package/WebSocket/ + + # Package metadata and samples + cp integrations/Unity/package.json upm-package/ + cp -r integrations/Unity/Samples~ upm-package/ + + - name: Push package directory to subtree + uses: s0/git-publish-subdir-action@develop + env: + REPO: self + BRANCH: upm-2.0 + FOLDER: upm-package/ + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + createPackage: + name: Create Unity Package and Release + runs-on: ubuntu-latest + needs: [checkSemver] + if: needs.checkSemver.outputs.semver-updated == 'true' + steps: + - name: Checkout Code + uses: actions/checkout@v4 + + - name: Assemble package directory + run: | + mkdir -p upm-package/WebSocket + + # Core library files + cp src/NativeWebSocket/IWebSocket.cs upm-package/WebSocket/ + cp src/NativeWebSocket/WebSocketTypes.cs upm-package/WebSocket/ + + # Unity-specific files + cp integrations/Unity/WebSocket.cs upm-package/WebSocket/ + cp integrations/Unity/WebSocketWebGL.cs upm-package/WebSocket/ + cp integrations/Unity/WebSocketFactoryWebGL.cs upm-package/WebSocket/ + cp integrations/Unity/WebSocket.jslib upm-package/WebSocket/ + cp integrations/Unity/WebSocket.jspre upm-package/WebSocket/ + cp integrations/Unity/endel.nativewebsocket.asmdef upm-package/WebSocket/ + + # Package metadata + cp integrations/Unity/package.json upm-package/ + + - name: Generate .meta files + run: | + generate_meta() { + local file="$1" + local guid + guid=$(echo -n "$file" | md5sum | cut -c1-32) + local ext="${file##*.}" + local meta="${file}.meta" + + case "$ext" in + cs) + cat > "$meta" < "$meta" < "$meta" < upm-package/WebSocket.meta < metaList + cat metaList + + - name: Extract Version + id: version + uses: notiz-dev/github-action-json-property@release + with: + path: 'integrations/Unity/package.json' + prop_path: 'version' + - run: echo ${{steps.version.outputs.prop}} + + - name: Generate Unity Package + id: build-package + uses: pCYSl5EDgo/create-unitypackage@master + with: + package-path: 'NativeWebSocket.unitypackage' + include-files: metaList + project-folder: upm-package + + - name: Upload Package + uses: actions/upload-artifact@v4 + with: + path: ./NativeWebSocket.unitypackage + name: NativeWebSocket + + - name: Changelog + uses: scottbrenner/generate-changelog-action@master + id: Changelog + + - name: Create Release + id: create_release + uses: actions/create-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: ${{ steps.version.outputs.prop }} + release_name: ${{ steps.version.outputs.prop }} + body: | + ${{ steps.Changelog.outputs.changelog }} + draft: false + prerelease: true + + - name: Upload Release Asset + id: upload-release-asset + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: ./NativeWebSocket.unitypackage + asset_name: NativeWebSocket.unitypackage + asset_content_type: application/x-gzip diff --git a/.github/workflows/upmsemver.yml b/.github/workflows/upmsemver.yml deleted file mode 100644 index 57b149e..0000000 --- a/.github/workflows/upmsemver.yml +++ /dev/null @@ -1,98 +0,0 @@ -name: Update Unity UPM semantic versioning - -on: - push: - branches: - - master - -jobs: - checkSemver: - name: Check for Semver Change - runs-on: ubuntu-latest - outputs: - semver-updated: ${{ steps.check.outputs.changed }} - steps: - - name: Checkout Code - uses: actions/checkout@v2 - - uses: EndBug/version-check@v1 - id: check - with: - file-name: NativeWebSocket/Assets/package.json - diff-search: true - token: ${{ secrets.GITHUB_TOKEN }} - - name: Log when changed - if: steps.check.outputs.changed == 'true' - run: 'echo "Version change found in commit ${{ steps.check.outputs.commit }}! New version: ${{ steps.check.outputs.version }} (${{ steps.check.outputs.type }})"' - updateUPM: - name: Update UPM branch - runs-on: ubuntu-latest - needs: [checkSemver] - if: needs.checkSemver.outputs.semver-updated == 'true' - steps: - # Copy correct directory into upm branch - - uses: actions/checkout@v2 - - - name: Push package directory to subtree - uses: s0/git-publish-subdir-action@develop - env: - REPO: self - BRANCH: upm - FOLDER: NativeWebSocket/Assets/ - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - createPackage: - name: Create Unity Package and Release - runs-on: ubuntu-latest - needs: [checkSemver] - if: needs.checkSemver.outputs.semver-updated == 'true' - steps: - - name: Checkout Code - uses: actions/checkout@v2 - - name: Gather files - run: | - echo "NativeWebSocket/Assets/WebSocket.meta" > metaList - find NativeWebSocket/Assets/WebSocket/ -name \*.meta >> metaList - - name: Extract Version - id: version - uses: notiz-dev/github-action-json-property@release - with: - path: 'NativeWebSocket/Assets/package.json' - prop_path: 'version' - - run: echo ${{steps.version.outputs.prop}} - - name: Create Directory - run: mkdir Release - - name: Generate Unity Package - id: build-package - uses: pCYSl5EDgo/create-unitypackage@master - with: - package-path: 'NativeWebSocket.unitypackage' - include-files: metaList - - name: Upload Package - uses: actions/upload-artifact@master - with: - path: ./NativeWebSocket.unitypackage - name: NativeWebSocket - - name: Changelog - uses: scottbrenner/generate-changelog-action@master - id: Changelog - - name: Create Release - id: create_release - uses: actions/create-release@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - tag_name: ${{ steps.version.outputs.prop }} - release_name: ${{ steps.version.outputs.prop }} - body: | - ${{ steps.Changelog.outputs.changelog }} - draft: false - prerelease: true - - name: Upload Release Asset - id: upload-release-asset - uses: actions/upload-release-asset@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps - asset_path: ./NativeWebSocket.unitypackage - asset_name: NativeWebSocket.unitypackage - asset_content_type: application/x-gzip diff --git a/.gitignore b/.gitignore index 1fbd435..d48e0ad 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,7 @@ .DS_Store node_modules +bin/ +obj/ # This .gitignore file should be placed at the root of your Unity project directory # @@ -34,6 +36,11 @@ ExportedObj/ *.csproj *.unityproj *.sln + +# Don't ignore project files for the core library and integrations +!src/**/*.csproj +!integrations/**/*.csproj +!NativeWebSocket.sln *.suo *.tmp *.user @@ -60,3 +67,4 @@ sysinfo.txt # Crashlytics generated file crashlytics-build.properties +.godot diff --git a/Media/header.png b/Media/header.png index 7352b48d2fc7cceeab66edefe314eb51be3c8b12..d60f01f8b055bcd0c76b0d971c7ab92707742f10 100644 GIT binary patch literal 19910 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 acOY>w55*NfWRindg2+fJNaTyZ^8a5m5N@OZ diff --git a/NativeWebSocket.sln b/NativeWebSocket.sln new file mode 100644 index 0000000..25e22b7 --- /dev/null +++ b/NativeWebSocket.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31903.59 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NativeWebSocket", "src\NativeWebSocket\NativeWebSocket.csproj", "{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NativeWebSocket.MonoGame", "integrations\MonoGame\NativeWebSocket.MonoGame.csproj", "{B2C3D4E5-F6A7-8901-BCDE-F12345678901}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MonoGameExample", "examples\MonoGame\MonoGameExample.csproj", "{C3D4E5F6-A7B8-9012-CDEF-123456789012}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {A1B2C3D4-E5F6-7890-ABCD-EF1234567890}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A1B2C3D4-E5F6-7890-ABCD-EF1234567890}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A1B2C3D4-E5F6-7890-ABCD-EF1234567890}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A1B2C3D4-E5F6-7890-ABCD-EF1234567890}.Release|Any CPU.Build.0 = Release|Any CPU + {B2C3D4E5-F6A7-8901-BCDE-F12345678901}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B2C3D4E5-F6A7-8901-BCDE-F12345678901}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B2C3D4E5-F6A7-8901-BCDE-F12345678901}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B2C3D4E5-F6A7-8901-BCDE-F12345678901}.Release|Any CPU.Build.0 = Release|Any CPU + {C3D4E5F6-A7B8-9012-CDEF-123456789012}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C3D4E5F6-A7B8-9012-CDEF-123456789012}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C3D4E5F6-A7B8-9012-CDEF-123456789012}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C3D4E5F6-A7B8-9012-CDEF-123456789012}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/NativeWebSocket/Assets/Samples~/WebSocketExample/Connection.cs b/NativeWebSocket/Assets/Samples~/WebSocketExample/Connection.cs deleted file mode 100644 index 32acbd8..0000000 --- a/NativeWebSocket/Assets/Samples~/WebSocketExample/Connection.cs +++ /dev/null @@ -1,69 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using UnityEngine; - -using NativeWebSocket; - -public class Connection : MonoBehaviour -{ - WebSocket websocket; - - // Start is called before the first frame update - async void Start() - { - // websocket = new WebSocket("ws://echo.websocket.org"); - websocket = new WebSocket("ws://localhost:3000"); - - websocket.OnOpen += () => - { - Debug.Log("Connection open!"); - }; - - websocket.OnError += (e) => - { - Debug.Log("Error! " + e); - }; - - websocket.OnClose += (e) => - { - Debug.Log("Connection closed!"); - }; - - websocket.OnMessage += (bytes) => - { - // Reading a plain text message - var message = System.Text.Encoding.UTF8.GetString(bytes); - Debug.Log("Received OnMessage! (" + bytes.Length + " bytes) " + message); - }; - - // Keep sending messages at every 0.3s - InvokeRepeating("SendWebSocketMessage", 0.0f, 0.3f); - - await websocket.Connect(); - } - - void Update() - { - #if !UNITY_WEBGL || UNITY_EDITOR - websocket.DispatchMessageQueue(); - #endif - } - - async void SendWebSocketMessage() - { - if (websocket.State == WebSocketState.Open) - { - // Sending bytes - await websocket.Send(new byte[] { 10, 20, 30 }); - - // Sending plain text - await websocket.SendText("plain text message"); - } - } - - private async void OnApplicationQuit() - { - await websocket.Close(); - } -} diff --git a/NativeWebSocket/Assets/Samples~/WebSocketExample/Connection.cs.meta b/NativeWebSocket/Assets/Samples~/WebSocketExample/Connection.cs.meta deleted file mode 100644 index 6ad36a6..0000000 --- a/NativeWebSocket/Assets/Samples~/WebSocketExample/Connection.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 0f451fab1e6d94aea8fb73803e281bb3 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/NativeWebSocket/Assets/Samples~/WebSocketExample/WebSocketExampleScene.unity b/NativeWebSocket/Assets/Samples~/WebSocketExample/WebSocketExampleScene.unity deleted file mode 100644 index c47fb7f..0000000 --- a/NativeWebSocket/Assets/Samples~/WebSocketExample/WebSocketExampleScene.unity +++ /dev/null @@ -1,326 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!29 &1 -OcclusionCullingSettings: - m_ObjectHideFlags: 0 - serializedVersion: 2 - m_OcclusionBakeSettings: - smallestOccluder: 5 - smallestHole: 0.25 - backfaceThreshold: 100 - m_SceneGUID: 00000000000000000000000000000000 - m_OcclusionCullingData: {fileID: 0} ---- !u!104 &2 -RenderSettings: - m_ObjectHideFlags: 0 - serializedVersion: 9 - m_Fog: 0 - m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} - m_FogMode: 3 - m_FogDensity: 0.01 - m_LinearFogStart: 0 - m_LinearFogEnd: 300 - m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} - m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} - m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} - m_AmbientIntensity: 1 - m_AmbientMode: 0 - m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} - m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0} - m_HaloStrength: 0.5 - m_FlareStrength: 1 - m_FlareFadeSpeed: 3 - m_HaloTexture: {fileID: 0} - m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} - m_DefaultReflectionMode: 0 - m_DefaultReflectionResolution: 128 - m_ReflectionBounces: 1 - m_ReflectionIntensity: 1 - m_CustomReflection: {fileID: 0} - m_Sun: {fileID: 705507994} - m_IndirectSpecularColor: {r: 0.44657868, g: 0.49641263, b: 0.57481706, a: 1} - m_UseRadianceAmbientProbe: 0 ---- !u!157 &3 -LightmapSettings: - m_ObjectHideFlags: 0 - serializedVersion: 11 - m_GIWorkflowMode: 0 - m_GISettings: - serializedVersion: 2 - m_BounceScale: 1 - m_IndirectOutputScale: 1 - m_AlbedoBoost: 1 - m_EnvironmentLightingMode: 0 - m_EnableBakedLightmaps: 1 - m_EnableRealtimeLightmaps: 1 - m_LightmapEditorSettings: - serializedVersion: 12 - m_Resolution: 2 - m_BakeResolution: 40 - m_AtlasSize: 1024 - m_AO: 0 - m_AOMaxDistance: 1 - m_CompAOExponent: 1 - m_CompAOExponentDirect: 0 - m_ExtractAmbientOcclusion: 0 - m_Padding: 2 - m_LightmapParameters: {fileID: 0} - m_LightmapsBakeMode: 1 - m_TextureCompression: 1 - m_FinalGather: 0 - m_FinalGatherFiltering: 1 - m_FinalGatherRayCount: 256 - m_ReflectionCompression: 2 - m_MixedBakeMode: 2 - m_BakeBackend: 1 - m_PVRSampling: 1 - m_PVRDirectSampleCount: 32 - m_PVRSampleCount: 500 - m_PVRBounces: 2 - m_PVREnvironmentSampleCount: 500 - m_PVREnvironmentReferencePointCount: 2048 - m_PVRFilteringMode: 2 - m_PVRDenoiserTypeDirect: 0 - m_PVRDenoiserTypeIndirect: 0 - m_PVRDenoiserTypeAO: 0 - m_PVRFilterTypeDirect: 0 - m_PVRFilterTypeIndirect: 0 - m_PVRFilterTypeAO: 0 - m_PVREnvironmentMIS: 0 - m_PVRCulling: 1 - m_PVRFilteringGaussRadiusDirect: 1 - m_PVRFilteringGaussRadiusIndirect: 5 - m_PVRFilteringGaussRadiusAO: 2 - m_PVRFilteringAtrousPositionSigmaDirect: 0.5 - m_PVRFilteringAtrousPositionSigmaIndirect: 2 - m_PVRFilteringAtrousPositionSigmaAO: 1 - m_ExportTrainingData: 0 - m_TrainingDataDestination: TrainingData - m_LightingDataAsset: {fileID: 0} - m_UseShadowmask: 1 ---- !u!196 &4 -NavMeshSettings: - serializedVersion: 2 - m_ObjectHideFlags: 0 - m_BuildSettings: - serializedVersion: 2 - agentTypeID: 0 - agentRadius: 0.5 - agentHeight: 2 - agentSlope: 45 - agentClimb: 0.4 - ledgeDropHeight: 0 - maxJumpAcrossDistance: 0 - minRegionArea: 2 - manualCellSize: 0 - cellSize: 0.16666667 - manualTileSize: 0 - tileSize: 256 - accuratePlacement: 0 - debug: - m_Flags: 0 - m_NavMeshData: {fileID: 0} ---- !u!1 &705507993 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 705507995} - - component: {fileID: 705507994} - m_Layer: 0 - m_Name: Directional Light - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!108 &705507994 -Light: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 705507993} - m_Enabled: 1 - serializedVersion: 9 - m_Type: 1 - m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1} - m_Intensity: 1 - m_Range: 10 - m_SpotAngle: 30 - m_InnerSpotAngle: 21.802082 - m_CookieSize: 10 - m_Shadows: - m_Type: 2 - m_Resolution: -1 - m_CustomResolution: -1 - m_Strength: 1 - m_Bias: 0.05 - m_NormalBias: 0.4 - m_NearPlane: 0.2 - m_CullingMatrixOverride: - e00: 1 - e01: 0 - e02: 0 - e03: 0 - e10: 0 - e11: 1 - e12: 0 - e13: 0 - e20: 0 - e21: 0 - e22: 1 - e23: 0 - e30: 0 - e31: 0 - e32: 0 - e33: 1 - m_UseCullingMatrixOverride: 0 - m_Cookie: {fileID: 0} - m_DrawHalo: 0 - m_Flare: {fileID: 0} - m_RenderMode: 0 - m_CullingMask: - serializedVersion: 2 - m_Bits: 4294967295 - m_RenderingLayerMask: 1 - m_Lightmapping: 1 - m_LightShadowCasterMode: 0 - m_AreaSize: {x: 1, y: 1} - m_BounceIntensity: 1 - m_ColorTemperature: 6570 - m_UseColorTemperature: 0 - m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0} - m_UseBoundingSphereOverride: 0 - m_ShadowRadius: 0 - m_ShadowAngle: 0 ---- !u!4 &705507995 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 705507993} - m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261} - m_LocalPosition: {x: 0, y: 3, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: [] - m_Father: {fileID: 0} - m_RootOrder: 1 - m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0} ---- !u!1 &963194225 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 963194228} - - component: {fileID: 963194227} - - component: {fileID: 963194226} - - component: {fileID: 963194230} - - component: {fileID: 963194229} - m_Layer: 0 - m_Name: Main Camera - m_TagString: MainCamera - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!81 &963194226 -AudioListener: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 963194225} - m_Enabled: 1 ---- !u!20 &963194227 -Camera: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 963194225} - m_Enabled: 1 - serializedVersion: 2 - m_ClearFlags: 1 - m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0} - m_projectionMatrixMode: 1 - m_GateFitMode: 2 - m_FOVAxisMode: 0 - m_SensorSize: {x: 36, y: 24} - m_LensShift: {x: 0, y: 0} - m_FocalLength: 50 - m_NormalizedViewPortRect: - serializedVersion: 2 - x: 0 - y: 0 - width: 1 - height: 1 - near clip plane: 0.3 - far clip plane: 1000 - field of view: 60 - orthographic: 0 - orthographic size: 5 - m_Depth: -1 - m_CullingMask: - serializedVersion: 2 - m_Bits: 4294967295 - m_RenderingPath: -1 - m_TargetTexture: {fileID: 0} - m_TargetDisplay: 0 - m_TargetEye: 3 - m_HDR: 1 - m_AllowMSAA: 1 - m_AllowDynamicResolution: 0 - m_ForceIntoRT: 0 - m_OcclusionCulling: 1 - m_StereoConvergence: 10 - m_StereoSeparation: 0.022 ---- !u!4 &963194228 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 963194225} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 1, z: -10} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: [] - m_Father: {fileID: 0} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!114 &963194229 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 963194225} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 0f451fab1e6d94aea8fb73803e281bb3, type: 3} - m_Name: - m_EditorClassIdentifier: ---- !u!54 &963194230 -Rigidbody: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 963194225} - serializedVersion: 2 - m_Mass: 1 - m_Drag: 0 - m_AngularDrag: 0.05 - m_UseGravity: 1 - m_IsKinematic: 0 - m_Interpolate: 0 - m_Constraints: 0 - m_CollisionDetection: 0 diff --git a/NativeWebSocket/Assets/Samples~/WebSocketExample/WebSocketExampleScene.unity.meta b/NativeWebSocket/Assets/Samples~/WebSocketExample/WebSocketExampleScene.unity.meta deleted file mode 100644 index 952bd1e..0000000 --- a/NativeWebSocket/Assets/Samples~/WebSocketExample/WebSocketExampleScene.unity.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 9fc0d4010bbf28b4594072e72b8655ab -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/NativeWebSocket/Assets/WebSocket.meta b/NativeWebSocket/Assets/WebSocket.meta deleted file mode 100644 index 5b5dd00..0000000 --- a/NativeWebSocket/Assets/WebSocket.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 1b0aac75ea12c4d6d8aaf04e069a69a7 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/NativeWebSocket/Assets/WebSocket/WebSocket.cs b/NativeWebSocket/Assets/WebSocket/WebSocket.cs deleted file mode 100644 index 956fa21..0000000 --- a/NativeWebSocket/Assets/WebSocket/WebSocket.cs +++ /dev/null @@ -1,848 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Net.WebSockets; -using System.Runtime.CompilerServices; -using System.Text; -using System.Threading; -using System.Threading.Tasks; - -using AOT; -using System.Runtime.InteropServices; -using UnityEngine; -using System.Collections; - -public class MainThreadUtil : MonoBehaviour -{ - public static MainThreadUtil Instance { get; private set; } - public static SynchronizationContext synchronizationContext { get; private set; } - - [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] - public static void Setup() - { - Instance = new GameObject("MainThreadUtil") - .AddComponent(); - synchronizationContext = SynchronizationContext.Current; - } - - public static void Run(IEnumerator waitForUpdate) - { - synchronizationContext.Post(_ => Instance.StartCoroutine( - waitForUpdate), null); - } - - void Awake() - { - gameObject.hideFlags = HideFlags.HideAndDontSave; - DontDestroyOnLoad(gameObject); - } -} - -public class WaitForUpdate : CustomYieldInstruction -{ - public override bool keepWaiting - { - get { return false; } - } - - public MainThreadAwaiter GetAwaiter() - { - var awaiter = new MainThreadAwaiter(); - MainThreadUtil.Run(CoroutineWrapper(this, awaiter)); - return awaiter; - } - - public class MainThreadAwaiter : INotifyCompletion - { - Action continuation; - - public bool IsCompleted { get; set; } - - public void GetResult() { } - - public void Complete() - { - IsCompleted = true; - continuation?.Invoke(); - } - - void INotifyCompletion.OnCompleted(Action continuation) - { - this.continuation = continuation; - } - } - - public static IEnumerator CoroutineWrapper(IEnumerator theWorker, MainThreadAwaiter awaiter) - { - yield return theWorker; - awaiter.Complete(); - } -} - -namespace NativeWebSocket -{ - public delegate void WebSocketOpenEventHandler(); - public delegate void WebSocketMessageEventHandler(byte[] data); - public delegate void WebSocketErrorEventHandler(string errorMsg); - public delegate void WebSocketCloseEventHandler(WebSocketCloseCode closeCode); - - public enum WebSocketCloseCode - { - /* Do NOT use NotSet - it's only purpose is to indicate that the close code cannot be parsed. */ - NotSet = 0, - Normal = 1000, - Away = 1001, - ProtocolError = 1002, - UnsupportedData = 1003, - Undefined = 1004, - NoStatus = 1005, - Abnormal = 1006, - InvalidData = 1007, - PolicyViolation = 1008, - TooBig = 1009, - MandatoryExtension = 1010, - ServerError = 1011, - TlsHandshakeFailure = 1015 - } - - public enum WebSocketState - { - Connecting, - Open, - Closing, - Closed - } - - public interface IWebSocket - { - event WebSocketOpenEventHandler OnOpen; - event WebSocketMessageEventHandler OnMessage; - event WebSocketErrorEventHandler OnError; - event WebSocketCloseEventHandler OnClose; - - WebSocketState State { get; } - } - - public static class WebSocketHelpers - { - public static WebSocketCloseCode ParseCloseCodeEnum(int closeCode) - { - - if (WebSocketCloseCode.IsDefined(typeof(WebSocketCloseCode), closeCode)) - { - return (WebSocketCloseCode)closeCode; - } - else - { - return WebSocketCloseCode.Undefined; - } - - } - - public static WebSocketException GetErrorMessageFromCode(int errorCode, Exception inner) - { - switch (errorCode) - { - case -1: - return new WebSocketUnexpectedException("WebSocket instance not found.", inner); - case -2: - return new WebSocketInvalidStateException("WebSocket is already connected or in connecting state.", inner); - case -3: - return new WebSocketInvalidStateException("WebSocket is not connected.", inner); - case -4: - return new WebSocketInvalidStateException("WebSocket is already closing.", inner); - case -5: - return new WebSocketInvalidStateException("WebSocket is already closed.", inner); - case -6: - return new WebSocketInvalidStateException("WebSocket is not in open state.", inner); - case -7: - return new WebSocketInvalidArgumentException("Cannot close WebSocket. An invalid code was specified or reason is too long.", inner); - default: - return new WebSocketUnexpectedException("Unknown error.", inner); - } - } - } - - public class WebSocketException : Exception - { - public WebSocketException() { } - public WebSocketException(string message) : base(message) { } - public WebSocketException(string message, Exception inner) : base(message, inner) { } - } - - public class WebSocketUnexpectedException : WebSocketException - { - public WebSocketUnexpectedException() { } - public WebSocketUnexpectedException(string message) : base(message) { } - public WebSocketUnexpectedException(string message, Exception inner) : base(message, inner) { } - } - - public class WebSocketInvalidArgumentException : WebSocketException - { - public WebSocketInvalidArgumentException() { } - public WebSocketInvalidArgumentException(string message) : base(message) { } - public WebSocketInvalidArgumentException(string message, Exception inner) : base(message, inner) { } - } - - public class WebSocketInvalidStateException : WebSocketException - { - public WebSocketInvalidStateException() { } - public WebSocketInvalidStateException(string message) : base(message) { } - public WebSocketInvalidStateException(string message, Exception inner) : base(message, inner) { } - } - - public class WaitForBackgroundThread - { - public ConfiguredTaskAwaitable.ConfiguredTaskAwaiter GetAwaiter() - { - return Task.Run(() => { }).ConfigureAwait(false).GetAwaiter(); - } - } - -#if UNITY_WEBGL && !UNITY_EDITOR - - /// - /// WebSocket class bound to JSLIB. - /// - public class WebSocket : IWebSocket { - - /* WebSocket JSLIB functions */ - [DllImport ("__Internal")] - public static extern int WebSocketConnect (int instanceId); - - [DllImport ("__Internal")] - public static extern int WebSocketClose (int instanceId, int code, string reason); - - [DllImport ("__Internal")] - public static extern int WebSocketSend (int instanceId, byte[] dataPtr, int dataLength); - - [DllImport ("__Internal")] - public static extern int WebSocketSendText (int instanceId, string message); - - [DllImport ("__Internal")] - public static extern int WebSocketGetState (int instanceId); - - protected int instanceId; - - public event WebSocketOpenEventHandler OnOpen; - public event WebSocketMessageEventHandler OnMessage; - public event WebSocketErrorEventHandler OnError; - public event WebSocketCloseEventHandler OnClose; - - public WebSocket (string url, Dictionary headers = null) { - if (!WebSocketFactory.isInitialized) { - WebSocketFactory.Initialize (); - } - - int instanceId = WebSocketFactory.WebSocketAllocate (url); - WebSocketFactory.instances.Add (instanceId, this); - - this.instanceId = instanceId; - } - - public WebSocket (string url, string subprotocol, Dictionary headers = null) { - if (!WebSocketFactory.isInitialized) { - WebSocketFactory.Initialize (); - } - - int instanceId = WebSocketFactory.WebSocketAllocate (url); - WebSocketFactory.instances.Add (instanceId, this); - - WebSocketFactory.WebSocketAddSubProtocol(instanceId, subprotocol); - - this.instanceId = instanceId; - } - - public WebSocket (string url, List subprotocols, Dictionary headers = null) { - if (!WebSocketFactory.isInitialized) { - WebSocketFactory.Initialize (); - } - - int instanceId = WebSocketFactory.WebSocketAllocate (url); - WebSocketFactory.instances.Add (instanceId, this); - - foreach (string subprotocol in subprotocols) { - WebSocketFactory.WebSocketAddSubProtocol(instanceId, subprotocol); - } - - this.instanceId = instanceId; - } - - ~WebSocket () { - WebSocketFactory.HandleInstanceDestroy (this.instanceId); - } - - public int GetInstanceId () { - return this.instanceId; - } - - public Task Connect () { - int ret = WebSocketConnect (this.instanceId); - - if (ret < 0) - throw WebSocketHelpers.GetErrorMessageFromCode (ret, null); - - return Task.CompletedTask; - } - - public void CancelConnection () { - if (State == WebSocketState.Open) - Close (WebSocketCloseCode.Abnormal); - } - - public Task Close (WebSocketCloseCode code = WebSocketCloseCode.Normal, string reason = null) { - int ret = WebSocketClose (this.instanceId, (int) code, reason); - - if (ret < 0) - throw WebSocketHelpers.GetErrorMessageFromCode (ret, null); - - return Task.CompletedTask; - } - - public Task Send (byte[] data) { - int ret = WebSocketSend (this.instanceId, data, data.Length); - - if (ret < 0) - throw WebSocketHelpers.GetErrorMessageFromCode (ret, null); - - return Task.CompletedTask; - } - - public Task SendText (string message) { - int ret = WebSocketSendText (this.instanceId, message); - - if (ret < 0) - throw WebSocketHelpers.GetErrorMessageFromCode (ret, null); - - return Task.CompletedTask; - } - - public WebSocketState State { - get { - int state = WebSocketGetState (this.instanceId); - - if (state < 0) - throw WebSocketHelpers.GetErrorMessageFromCode (state, null); - - switch (state) { - case 0: - return WebSocketState.Connecting; - - case 1: - return WebSocketState.Open; - - case 2: - return WebSocketState.Closing; - - case 3: - return WebSocketState.Closed; - - default: - return WebSocketState.Closed; - } - } - } - - public void DelegateOnOpenEvent () { - this.OnOpen?.Invoke (); - } - - public void DelegateOnMessageEvent (byte[] data) { - this.OnMessage?.Invoke (data); - } - - public void DelegateOnErrorEvent (string errorMsg) { - this.OnError?.Invoke (errorMsg); - } - - public void DelegateOnCloseEvent (int closeCode) { - this.OnClose?.Invoke (WebSocketHelpers.ParseCloseCodeEnum (closeCode)); - } - - } - -#else - - public class WebSocket : IWebSocket - { - public event WebSocketOpenEventHandler OnOpen; - public event WebSocketMessageEventHandler OnMessage; - public event WebSocketErrorEventHandler OnError; - public event WebSocketCloseEventHandler OnClose; - - private Uri uri; - private Dictionary headers; - private List subprotocols; - private ClientWebSocket m_Socket = new ClientWebSocket(); - - private CancellationTokenSource m_TokenSource; - private CancellationToken m_CancellationToken; - - private readonly object OutgoingMessageLock = new object(); - private readonly object IncomingMessageLock = new object(); - - private bool isSending = false; - private List> sendBytesQueue = new List>(); - private List> sendTextQueue = new List>(); - - public WebSocket(string url, Dictionary headers = null) - { - uri = new Uri(url); - - if (headers == null) - { - this.headers = new Dictionary(); - } - else - { - this.headers = headers; - } - - subprotocols = new List(); - - string protocol = uri.Scheme; - if (!protocol.Equals("ws") && !protocol.Equals("wss")) - throw new ArgumentException("Unsupported protocol: " + protocol); - } - - public WebSocket(string url, string subprotocol, Dictionary headers = null) - { - uri = new Uri(url); - - if (headers == null) - { - this.headers = new Dictionary(); - } - else - { - this.headers = headers; - } - - subprotocols = new List {subprotocol}; - - string protocol = uri.Scheme; - if (!protocol.Equals("ws") && !protocol.Equals("wss")) - throw new ArgumentException("Unsupported protocol: " + protocol); - } - - public WebSocket(string url, List subprotocols, Dictionary headers = null) - { - uri = new Uri(url); - - if (headers == null) - { - this.headers = new Dictionary(); - } - else - { - this.headers = headers; - } - - this.subprotocols = subprotocols; - - string protocol = uri.Scheme; - if (!protocol.Equals("ws") && !protocol.Equals("wss")) - throw new ArgumentException("Unsupported protocol: " + protocol); - } - - public void CancelConnection() - { - m_TokenSource?.Cancel(); - } - - public async Task Connect() - { - try - { - m_TokenSource = new CancellationTokenSource(); - m_CancellationToken = m_TokenSource.Token; - - m_Socket = new ClientWebSocket(); - - foreach (var header in headers) - { - m_Socket.Options.SetRequestHeader(header.Key, header.Value); - } - - foreach (string subprotocol in subprotocols) { - m_Socket.Options.AddSubProtocol(subprotocol); - } - - await m_Socket.ConnectAsync(uri, m_CancellationToken); - OnOpen?.Invoke(); - - await Receive(); - } - catch (Exception ex) - { - OnError?.Invoke(ex.Message); - OnClose?.Invoke(WebSocketCloseCode.Abnormal); - } - finally - { - if (m_Socket != null) - { - m_TokenSource.Cancel(); - m_Socket.Dispose(); - } - } - } - - public WebSocketState State - { - get - { - switch (m_Socket.State) - { - case System.Net.WebSockets.WebSocketState.Connecting: - return WebSocketState.Connecting; - - case System.Net.WebSockets.WebSocketState.Open: - return WebSocketState.Open; - - case System.Net.WebSockets.WebSocketState.CloseSent: - case System.Net.WebSockets.WebSocketState.CloseReceived: - return WebSocketState.Closing; - - case System.Net.WebSockets.WebSocketState.Closed: - return WebSocketState.Closed; - - default: - return WebSocketState.Closed; - } - } - } - - public Task Send(byte[] bytes) - { - // return m_Socket.SendAsync(buffer, WebSocketMessageType.Binary, true, CancellationToken.None); - return SendMessage(sendBytesQueue, WebSocketMessageType.Binary, new ArraySegment(bytes)); - } - - public Task SendText(string message) - { - var encoded = Encoding.UTF8.GetBytes(message); - - // m_Socket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None); - return SendMessage(sendTextQueue, WebSocketMessageType.Text, new ArraySegment(encoded, 0, encoded.Length)); - } - - private async Task SendMessage(List> queue, WebSocketMessageType messageType, ArraySegment buffer) - { - // Return control to the calling method immediately. - // await Task.Yield (); - - // Make sure we have data. - if (buffer.Count == 0) - { - return; - } - - // The state of the connection is contained in the context Items dictionary. - bool sending; - - lock (OutgoingMessageLock) - { - sending = isSending; - - // If not, we are now. - if (!isSending) - { - isSending = true; - } - } - - if (!sending) - { - // Lock with a timeout, just in case. - if (!Monitor.TryEnter(m_Socket, 1000)) - { - // If we couldn't obtain exclusive access to the socket in one second, something is wrong. - await m_Socket.CloseAsync(WebSocketCloseStatus.InternalServerError, string.Empty, m_CancellationToken); - return; - } - - try - { - // Send the message synchronously. - var t = m_Socket.SendAsync(buffer, messageType, true, m_CancellationToken); - t.Wait(m_CancellationToken); - } - finally - { - Monitor.Exit(m_Socket); - - // Note that we've finished sending. - lock (OutgoingMessageLock) - { - isSending = false; - } - } - - // Handle any queued messages. - await HandleQueue(queue, messageType); - } - else - { - // Add the message to the queue. - lock (OutgoingMessageLock) - { - queue.Add(buffer); - } - } - } - - private async Task HandleQueue(List> queue, WebSocketMessageType messageType) - { - var buffer = new ArraySegment(); - lock (OutgoingMessageLock) - { - // Check for an item in the queue. - if (queue.Count > 0) - { - // Pull it off the top. - buffer = queue[0]; - queue.RemoveAt(0); - } - } - - // Send that message. - if (buffer.Count > 0) - { - await SendMessage(queue, messageType, buffer); - } - } - - private List m_MessageList = new List(); - - // simple dispatcher for queued messages. - public void DispatchMessageQueue() - { - if (m_MessageList.Count == 0) - { - return; - } - - List messageListCopy; - - lock (IncomingMessageLock) - { - messageListCopy = new List(m_MessageList); - m_MessageList.Clear(); - } - - var len = messageListCopy.Count; - for (int i = 0; i < len; i++) - { - OnMessage?.Invoke(messageListCopy[i]); - } - } - - public async Task Receive() - { - WebSocketCloseCode closeCode = WebSocketCloseCode.Abnormal; - await new WaitForBackgroundThread(); - - ArraySegment buffer = new ArraySegment(new byte[8192]); - try - { - while (m_Socket.State == System.Net.WebSockets.WebSocketState.Open) - { - WebSocketReceiveResult result = null; - - using (var ms = new MemoryStream()) - { - do - { - result = await m_Socket.ReceiveAsync(buffer, m_CancellationToken); - ms.Write(buffer.Array, buffer.Offset, result.Count); - } - while (!result.EndOfMessage); - - ms.Seek(0, SeekOrigin.Begin); - - if (result.MessageType == WebSocketMessageType.Text) - { - lock (IncomingMessageLock) - { - m_MessageList.Add(ms.ToArray()); - } - - //using (var reader = new StreamReader(ms, Encoding.UTF8)) - //{ - // string message = reader.ReadToEnd(); - // OnMessage?.Invoke(this, new MessageEventArgs(message)); - //} - } - else if (result.MessageType == WebSocketMessageType.Binary) - { - lock (IncomingMessageLock) - { - m_MessageList.Add(ms.ToArray()); - } - } - else if (result.MessageType == WebSocketMessageType.Close) - { - await Close(); - closeCode = WebSocketHelpers.ParseCloseCodeEnum((int)result.CloseStatus); - break; - } - } - } - } - catch (Exception) - { - m_TokenSource.Cancel(); - } - finally - { - await new WaitForUpdate(); - OnClose?.Invoke(closeCode); - } - } - - public async Task Close() - { - if (State == WebSocketState.Open) - { - await m_Socket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, m_CancellationToken); - } - } - } -#endif - - /// - /// Factory - /// - - /// - /// Class providing static access methods to work with JSLIB WebSocket or WebSocketSharp interface - /// - public static class WebSocketFactory - { - -#if UNITY_WEBGL && !UNITY_EDITOR - /* Map of websocket instances */ - public static Dictionary instances = new Dictionary (); - - /* Delegates */ - public delegate void OnOpenCallback (int instanceId); - public delegate void OnMessageCallback (int instanceId, System.IntPtr msgPtr, int msgSize); - public delegate void OnErrorCallback (int instanceId, System.IntPtr errorPtr); - public delegate void OnCloseCallback (int instanceId, int closeCode); - - /* WebSocket JSLIB callback setters and other functions */ - [DllImport ("__Internal")] - public static extern int WebSocketAllocate (string url); - - [DllImport ("__Internal")] - public static extern int WebSocketAddSubProtocol (int instanceId, string subprotocol); - - [DllImport ("__Internal")] - public static extern void WebSocketFree (int instanceId); - - [DllImport ("__Internal")] - public static extern void WebSocketSetOnOpen (OnOpenCallback callback); - - [DllImport ("__Internal")] - public static extern void WebSocketSetOnMessage (OnMessageCallback callback); - - [DllImport ("__Internal")] - public static extern void WebSocketSetOnError (OnErrorCallback callback); - - [DllImport ("__Internal")] - public static extern void WebSocketSetOnClose (OnCloseCallback callback); - - /* If callbacks was initialized and set */ - public static bool isInitialized = false; - - /* - * Initialize WebSocket callbacks to JSLIB - */ - public static void Initialize () { - - WebSocketSetOnOpen (DelegateOnOpenEvent); - WebSocketSetOnMessage (DelegateOnMessageEvent); - WebSocketSetOnError (DelegateOnErrorEvent); - WebSocketSetOnClose (DelegateOnCloseEvent); - - isInitialized = true; - - } - - /// - /// Called when instance is destroyed (by destructor) - /// Method removes instance from map and free it in JSLIB implementation - /// - /// Instance identifier. - public static void HandleInstanceDestroy (int instanceId) { - - instances.Remove (instanceId); - WebSocketFree (instanceId); - - } - - [MonoPInvokeCallback (typeof (OnOpenCallback))] - public static void DelegateOnOpenEvent (int instanceId) { - - WebSocket instanceRef; - - if (instances.TryGetValue (instanceId, out instanceRef)) { - instanceRef.DelegateOnOpenEvent (); - } - - } - - [MonoPInvokeCallback (typeof (OnMessageCallback))] - public static void DelegateOnMessageEvent (int instanceId, System.IntPtr msgPtr, int msgSize) { - - WebSocket instanceRef; - - if (instances.TryGetValue (instanceId, out instanceRef)) { - byte[] msg = new byte[msgSize]; - Marshal.Copy (msgPtr, msg, 0, msgSize); - - instanceRef.DelegateOnMessageEvent (msg); - } - - } - - [MonoPInvokeCallback (typeof (OnErrorCallback))] - public static void DelegateOnErrorEvent (int instanceId, System.IntPtr errorPtr) { - - WebSocket instanceRef; - - if (instances.TryGetValue (instanceId, out instanceRef)) { - - string errorMsg = Marshal.PtrToStringAuto (errorPtr); - instanceRef.DelegateOnErrorEvent (errorMsg); - - } - - } - - [MonoPInvokeCallback (typeof (OnCloseCallback))] - public static void DelegateOnCloseEvent (int instanceId, int closeCode) { - - WebSocket instanceRef; - - if (instances.TryGetValue (instanceId, out instanceRef)) { - instanceRef.DelegateOnCloseEvent (closeCode); - } - - } -#endif - - /// - /// Create WebSocket client instance - /// - /// The WebSocket instance. - /// WebSocket valid URL. - public static WebSocket CreateInstance(string url) - { - return new WebSocket(url); - } - - } - -} diff --git a/NativeWebSocket/Assets/WebSocket/WebSocket.cs.meta b/NativeWebSocket/Assets/WebSocket/WebSocket.cs.meta deleted file mode 100644 index 708e6f1..0000000 --- a/NativeWebSocket/Assets/WebSocket/WebSocket.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: df0e653fbf9005342904aa0f14d46088 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/NativeWebSocket/Assets/WebSocket/WebSocket.jslib.meta b/NativeWebSocket/Assets/WebSocket/WebSocket.jslib.meta deleted file mode 100644 index a4f0052..0000000 --- a/NativeWebSocket/Assets/WebSocket/WebSocket.jslib.meta +++ /dev/null @@ -1,32 +0,0 @@ -fileFormatVersion: 2 -guid: 3b767cc116f846f4b813fe00142b8736 -PluginImporter: - externalObjects: {} - serializedVersion: 2 - iconMap: {} - executionOrder: {} - defineConstraints: [] - isPreloaded: 0 - isOverridable: 0 - isExplicitlyReferenced: 0 - validateReferences: 1 - platformData: - - first: - Any: - second: - enabled: 0 - settings: {} - - first: - Editor: Editor - second: - enabled: 0 - settings: - DefaultValueInitialized: true - - first: - WebGL: WebGL - second: - enabled: 1 - settings: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/NativeWebSocket/Assets/WebSocket/WebSocket.jspre.meta b/NativeWebSocket/Assets/WebSocket/WebSocket.jspre.meta deleted file mode 100644 index fb05d9b..0000000 --- a/NativeWebSocket/Assets/WebSocket/WebSocket.jspre.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: 267dd868ba98c4220b28f212fc144f59 \ No newline at end of file diff --git a/NativeWebSocket/Assets/WebSocket/endel.nativewebsocket.asmdef.meta b/NativeWebSocket/Assets/WebSocket/endel.nativewebsocket.asmdef.meta deleted file mode 100644 index 01d2d89..0000000 --- a/NativeWebSocket/Assets/WebSocket/endel.nativewebsocket.asmdef.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 04376767bc1f3b428aefa3d20743e819 -AssemblyDefinitionImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/NativeWebSocket/Assets/WebSocketExample.meta b/NativeWebSocket/Assets/WebSocketExample.meta deleted file mode 100644 index fecdc8e..0000000 --- a/NativeWebSocket/Assets/WebSocketExample.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: e7a91621cd77941248ad2d795977b3c7 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/NativeWebSocket/Assets/package.json.meta b/NativeWebSocket/Assets/package.json.meta deleted file mode 100644 index 401838d..0000000 --- a/NativeWebSocket/Assets/package.json.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: a9f6363663f95e3499b2616618078182 -TextScriptImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/NativeWebSocket/Packages/manifest.json b/NativeWebSocket/Packages/manifest.json deleted file mode 100644 index 781bbaa..0000000 --- a/NativeWebSocket/Packages/manifest.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "dependencies": { - "com.unity.ai.navigation": "2.0.9", - "com.unity.collab-proxy": "2.11.2", - "com.unity.ext.nunit": "2.0.5", - "com.unity.ide.rider": "3.0.38", - "com.unity.ide.visualstudio": "2.0.26", - "com.unity.ide.vscode": "1.2.4", - "com.unity.multiplayer.center": "1.0.1", - "com.unity.test-framework": "1.6.0", - "com.unity.timeline": "1.8.10", - "com.unity.ugui": "2.0.0", - "com.unity.modules.accessibility": "1.0.0", - "com.unity.modules.adaptiveperformance": "1.0.0", - "com.unity.modules.ai": "1.0.0", - "com.unity.modules.androidjni": "1.0.0", - "com.unity.modules.animation": "1.0.0", - "com.unity.modules.assetbundle": "1.0.0", - "com.unity.modules.audio": "1.0.0", - "com.unity.modules.cloth": "1.0.0", - "com.unity.modules.director": "1.0.0", - "com.unity.modules.imageconversion": "1.0.0", - "com.unity.modules.imgui": "1.0.0", - "com.unity.modules.jsonserialize": "1.0.0", - "com.unity.modules.particlesystem": "1.0.0", - "com.unity.modules.physics": "1.0.0", - "com.unity.modules.physics2d": "1.0.0", - "com.unity.modules.screencapture": "1.0.0", - "com.unity.modules.terrain": "1.0.0", - "com.unity.modules.terrainphysics": "1.0.0", - "com.unity.modules.tilemap": "1.0.0", - "com.unity.modules.ui": "1.0.0", - "com.unity.modules.uielements": "1.0.0", - "com.unity.modules.umbra": "1.0.0", - "com.unity.modules.unityanalytics": "1.0.0", - "com.unity.modules.unitywebrequest": "1.0.0", - "com.unity.modules.unitywebrequestassetbundle": "1.0.0", - "com.unity.modules.unitywebrequestaudio": "1.0.0", - "com.unity.modules.unitywebrequesttexture": "1.0.0", - "com.unity.modules.unitywebrequestwww": "1.0.0", - "com.unity.modules.vectorgraphics": "1.0.0", - "com.unity.modules.vehicles": "1.0.0", - "com.unity.modules.video": "1.0.0", - "com.unity.modules.vr": "1.0.0", - "com.unity.modules.wind": "1.0.0", - "com.unity.modules.xr": "1.0.0" - } -} diff --git a/NativeWebSocket/ProjectSettings/AudioManager.asset b/NativeWebSocket/ProjectSettings/AudioManager.asset deleted file mode 100644 index 07ebfb0..0000000 --- a/NativeWebSocket/ProjectSettings/AudioManager.asset +++ /dev/null @@ -1,19 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!11 &1 -AudioManager: - m_ObjectHideFlags: 0 - serializedVersion: 2 - m_Volume: 1 - Rolloff Scale: 1 - Doppler Factor: 1 - Default Speaker Mode: 2 - m_SampleRate: 0 - m_DSPBufferSize: 1024 - m_VirtualVoiceCount: 512 - m_RealVoiceCount: 32 - m_SpatializerPlugin: - m_AmbisonicDecoderPlugin: - m_DisableAudio: 0 - m_VirtualizeEffects: 1 - m_RequestedDSPBufferSize: 1024 diff --git a/NativeWebSocket/ProjectSettings/ClusterInputManager.asset b/NativeWebSocket/ProjectSettings/ClusterInputManager.asset deleted file mode 100644 index e7886b2..0000000 --- a/NativeWebSocket/ProjectSettings/ClusterInputManager.asset +++ /dev/null @@ -1,6 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!236 &1 -ClusterInputManager: - m_ObjectHideFlags: 0 - m_Inputs: [] diff --git a/NativeWebSocket/ProjectSettings/DynamicsManager.asset b/NativeWebSocket/ProjectSettings/DynamicsManager.asset deleted file mode 100644 index cdc1f3e..0000000 --- a/NativeWebSocket/ProjectSettings/DynamicsManager.asset +++ /dev/null @@ -1,34 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!55 &1 -PhysicsManager: - m_ObjectHideFlags: 0 - serializedVersion: 11 - m_Gravity: {x: 0, y: -9.81, z: 0} - m_DefaultMaterial: {fileID: 0} - m_BounceThreshold: 2 - m_SleepThreshold: 0.005 - m_DefaultContactOffset: 0.01 - m_DefaultSolverIterations: 6 - m_DefaultSolverVelocityIterations: 1 - m_QueriesHitBackfaces: 0 - m_QueriesHitTriggers: 1 - m_EnableAdaptiveForce: 0 - m_ClothInterCollisionDistance: 0 - m_ClothInterCollisionStiffness: 0 - m_ContactsGeneration: 1 - m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - m_AutoSimulation: 1 - m_AutoSyncTransforms: 0 - m_ReuseCollisionCallbacks: 1 - m_ClothInterCollisionSettingsToggle: 0 - m_ContactPairsMode: 0 - m_BroadphaseType: 0 - m_WorldBounds: - m_Center: {x: 0, y: 0, z: 0} - m_Extent: {x: 250, y: 250, z: 250} - m_WorldSubdivisions: 8 - m_FrictionType: 0 - m_EnableEnhancedDeterminism: 0 - m_EnableUnifiedHeightmaps: 1 - m_DefaultMaxAngluarSpeed: 7 diff --git a/NativeWebSocket/ProjectSettings/EditorBuildSettings.asset b/NativeWebSocket/ProjectSettings/EditorBuildSettings.asset deleted file mode 100644 index 0147887..0000000 --- a/NativeWebSocket/ProjectSettings/EditorBuildSettings.asset +++ /dev/null @@ -1,8 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!1045 &1 -EditorBuildSettings: - m_ObjectHideFlags: 0 - serializedVersion: 2 - m_Scenes: [] - m_configObjects: {} diff --git a/NativeWebSocket/ProjectSettings/EditorSettings.asset b/NativeWebSocket/ProjectSettings/EditorSettings.asset deleted file mode 100644 index e4a3012..0000000 --- a/NativeWebSocket/ProjectSettings/EditorSettings.asset +++ /dev/null @@ -1,39 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!159 &1 -EditorSettings: - m_ObjectHideFlags: 0 - serializedVersion: 11 - m_SerializationMode: 2 - m_LineEndingsForNewScripts: 2 - m_DefaultBehaviorMode: 0 - m_PrefabRegularEnvironment: {fileID: 0} - m_PrefabUIEnvironment: {fileID: 0} - m_SpritePackerMode: 0 - m_SpritePackerPaddingPower: 1 - m_EtcTextureCompressorBehavior: 1 - m_EtcTextureFastCompressor: 1 - m_EtcTextureNormalCompressor: 2 - m_EtcTextureBestCompressor: 4 - m_ProjectGenerationIncludedExtensions: txt;xml;fnt;cd;asmdef;rsp;asmref - m_ProjectGenerationRootNamespace: - m_EnableTextureStreamingInEditMode: 1 - m_EnableTextureStreamingInPlayMode: 1 - m_AsyncShaderCompilation: 1 - m_CachingShaderPreprocessor: 0 - m_EnterPlayModeOptionsEnabled: 0 - m_EnterPlayModeOptions: 3 - m_GameObjectNamingDigits: 1 - m_GameObjectNamingScheme: 0 - m_AssetNamingUsesSpace: 1 - m_UseLegacyProbeSampleCount: 1 - m_SerializeInlineMappingsOnOneLine: 0 - m_DisableCookiesInLightmapper: 1 - m_AssetPipelineMode: 1 - m_CacheServerMode: 0 - m_CacheServerEndpoint: - m_CacheServerNamespacePrefix: default - m_CacheServerEnableDownload: 1 - m_CacheServerEnableUpload: 1 - m_CacheServerEnableAuth: 0 - m_CacheServerEnableTls: 0 diff --git a/NativeWebSocket/ProjectSettings/GraphicsSettings.asset b/NativeWebSocket/ProjectSettings/GraphicsSettings.asset deleted file mode 100644 index f3874f6..0000000 --- a/NativeWebSocket/ProjectSettings/GraphicsSettings.asset +++ /dev/null @@ -1,64 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!30 &1 -GraphicsSettings: - m_ObjectHideFlags: 0 - serializedVersion: 12 - m_Deferred: - m_Mode: 1 - m_Shader: {fileID: 69, guid: 0000000000000000f000000000000000, type: 0} - m_DeferredReflections: - m_Mode: 1 - m_Shader: {fileID: 74, guid: 0000000000000000f000000000000000, type: 0} - m_ScreenSpaceShadows: - m_Mode: 1 - m_Shader: {fileID: 64, guid: 0000000000000000f000000000000000, type: 0} - m_LegacyDeferred: - m_Mode: 1 - m_Shader: {fileID: 63, guid: 0000000000000000f000000000000000, type: 0} - m_DepthNormals: - m_Mode: 1 - m_Shader: {fileID: 62, guid: 0000000000000000f000000000000000, type: 0} - m_MotionVectors: - m_Mode: 1 - m_Shader: {fileID: 75, guid: 0000000000000000f000000000000000, type: 0} - m_LightHalo: - m_Mode: 1 - m_Shader: {fileID: 105, guid: 0000000000000000f000000000000000, type: 0} - m_LensFlare: - m_Mode: 1 - m_Shader: {fileID: 102, guid: 0000000000000000f000000000000000, type: 0} - m_AlwaysIncludedShaders: - - {fileID: 7, guid: 0000000000000000f000000000000000, type: 0} - - {fileID: 15104, guid: 0000000000000000f000000000000000, type: 0} - - {fileID: 15105, guid: 0000000000000000f000000000000000, type: 0} - - {fileID: 15106, guid: 0000000000000000f000000000000000, type: 0} - - {fileID: 10753, guid: 0000000000000000f000000000000000, type: 0} - - {fileID: 10770, guid: 0000000000000000f000000000000000, type: 0} - - {fileID: 16000, guid: 0000000000000000f000000000000000, type: 0} - - {fileID: 16001, guid: 0000000000000000f000000000000000, type: 0} - - {fileID: 17000, guid: 0000000000000000f000000000000000, type: 0} - m_PreloadedShaders: [] - m_SpritesDefaultMaterial: {fileID: 10754, guid: 0000000000000000f000000000000000, - type: 0} - m_CustomRenderPipeline: {fileID: 0} - m_TransparencySortMode: 0 - m_TransparencySortAxis: {x: 0, y: 0, z: 1} - m_DefaultRenderingPath: 1 - m_DefaultMobileRenderingPath: 1 - m_TierSettings: [] - m_LightmapStripping: 0 - m_FogStripping: 0 - m_InstancingStripping: 0 - m_LightmapKeepPlain: 1 - m_LightmapKeepDirCombined: 1 - m_LightmapKeepDynamicPlain: 1 - m_LightmapKeepDynamicDirCombined: 1 - m_LightmapKeepShadowMask: 1 - m_LightmapKeepSubtractive: 1 - m_FogKeepLinear: 1 - m_FogKeepExp: 1 - m_FogKeepExp2: 1 - m_AlbedoSwatchInfos: [] - m_LightsUseLinearIntensity: 0 - m_LightsUseColorTemperature: 0 diff --git a/NativeWebSocket/ProjectSettings/InputManager.asset b/NativeWebSocket/ProjectSettings/InputManager.asset deleted file mode 100644 index 17c8f53..0000000 --- a/NativeWebSocket/ProjectSettings/InputManager.asset +++ /dev/null @@ -1,295 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!13 &1 -InputManager: - m_ObjectHideFlags: 0 - serializedVersion: 2 - m_Axes: - - serializedVersion: 3 - m_Name: Horizontal - descriptiveName: - descriptiveNegativeName: - negativeButton: left - positiveButton: right - altNegativeButton: a - altPositiveButton: d - gravity: 3 - dead: 0.001 - sensitivity: 3 - snap: 1 - invert: 0 - type: 0 - axis: 0 - joyNum: 0 - - serializedVersion: 3 - m_Name: Vertical - descriptiveName: - descriptiveNegativeName: - negativeButton: down - positiveButton: up - altNegativeButton: s - altPositiveButton: w - gravity: 3 - dead: 0.001 - sensitivity: 3 - snap: 1 - invert: 0 - type: 0 - axis: 0 - joyNum: 0 - - serializedVersion: 3 - m_Name: Fire1 - descriptiveName: - descriptiveNegativeName: - negativeButton: - positiveButton: left ctrl - altNegativeButton: - altPositiveButton: mouse 0 - gravity: 1000 - dead: 0.001 - sensitivity: 1000 - snap: 0 - invert: 0 - type: 0 - axis: 0 - joyNum: 0 - - serializedVersion: 3 - m_Name: Fire2 - descriptiveName: - descriptiveNegativeName: - negativeButton: - positiveButton: left alt - altNegativeButton: - altPositiveButton: mouse 1 - gravity: 1000 - dead: 0.001 - sensitivity: 1000 - snap: 0 - invert: 0 - type: 0 - axis: 0 - joyNum: 0 - - serializedVersion: 3 - m_Name: Fire3 - descriptiveName: - descriptiveNegativeName: - negativeButton: - positiveButton: left shift - altNegativeButton: - altPositiveButton: mouse 2 - gravity: 1000 - dead: 0.001 - sensitivity: 1000 - snap: 0 - invert: 0 - type: 0 - axis: 0 - joyNum: 0 - - serializedVersion: 3 - m_Name: Jump - descriptiveName: - descriptiveNegativeName: - negativeButton: - positiveButton: space - altNegativeButton: - altPositiveButton: - gravity: 1000 - dead: 0.001 - sensitivity: 1000 - snap: 0 - invert: 0 - type: 0 - axis: 0 - joyNum: 0 - - serializedVersion: 3 - m_Name: Mouse X - descriptiveName: - descriptiveNegativeName: - negativeButton: - positiveButton: - altNegativeButton: - altPositiveButton: - gravity: 0 - dead: 0 - sensitivity: 0.1 - snap: 0 - invert: 0 - type: 1 - axis: 0 - joyNum: 0 - - serializedVersion: 3 - m_Name: Mouse Y - descriptiveName: - descriptiveNegativeName: - negativeButton: - positiveButton: - altNegativeButton: - altPositiveButton: - gravity: 0 - dead: 0 - sensitivity: 0.1 - snap: 0 - invert: 0 - type: 1 - axis: 1 - joyNum: 0 - - serializedVersion: 3 - m_Name: Mouse ScrollWheel - descriptiveName: - descriptiveNegativeName: - negativeButton: - positiveButton: - altNegativeButton: - altPositiveButton: - gravity: 0 - dead: 0 - sensitivity: 0.1 - snap: 0 - invert: 0 - type: 1 - axis: 2 - joyNum: 0 - - serializedVersion: 3 - m_Name: Horizontal - descriptiveName: - descriptiveNegativeName: - negativeButton: - positiveButton: - altNegativeButton: - altPositiveButton: - gravity: 0 - dead: 0.19 - sensitivity: 1 - snap: 0 - invert: 0 - type: 2 - axis: 0 - joyNum: 0 - - serializedVersion: 3 - m_Name: Vertical - descriptiveName: - descriptiveNegativeName: - negativeButton: - positiveButton: - altNegativeButton: - altPositiveButton: - gravity: 0 - dead: 0.19 - sensitivity: 1 - snap: 0 - invert: 1 - type: 2 - axis: 1 - joyNum: 0 - - serializedVersion: 3 - m_Name: Fire1 - descriptiveName: - descriptiveNegativeName: - negativeButton: - positiveButton: joystick button 0 - altNegativeButton: - altPositiveButton: - gravity: 1000 - dead: 0.001 - sensitivity: 1000 - snap: 0 - invert: 0 - type: 0 - axis: 0 - joyNum: 0 - - serializedVersion: 3 - m_Name: Fire2 - descriptiveName: - descriptiveNegativeName: - negativeButton: - positiveButton: joystick button 1 - altNegativeButton: - altPositiveButton: - gravity: 1000 - dead: 0.001 - sensitivity: 1000 - snap: 0 - invert: 0 - type: 0 - axis: 0 - joyNum: 0 - - serializedVersion: 3 - m_Name: Fire3 - descriptiveName: - descriptiveNegativeName: - negativeButton: - positiveButton: joystick button 2 - altNegativeButton: - altPositiveButton: - gravity: 1000 - dead: 0.001 - sensitivity: 1000 - snap: 0 - invert: 0 - type: 0 - axis: 0 - joyNum: 0 - - serializedVersion: 3 - m_Name: Jump - descriptiveName: - descriptiveNegativeName: - negativeButton: - positiveButton: joystick button 3 - altNegativeButton: - altPositiveButton: - gravity: 1000 - dead: 0.001 - sensitivity: 1000 - snap: 0 - invert: 0 - type: 0 - axis: 0 - joyNum: 0 - - serializedVersion: 3 - m_Name: Submit - descriptiveName: - descriptiveNegativeName: - negativeButton: - positiveButton: return - altNegativeButton: - altPositiveButton: joystick button 0 - gravity: 1000 - dead: 0.001 - sensitivity: 1000 - snap: 0 - invert: 0 - type: 0 - axis: 0 - joyNum: 0 - - serializedVersion: 3 - m_Name: Submit - descriptiveName: - descriptiveNegativeName: - negativeButton: - positiveButton: enter - altNegativeButton: - altPositiveButton: space - gravity: 1000 - dead: 0.001 - sensitivity: 1000 - snap: 0 - invert: 0 - type: 0 - axis: 0 - joyNum: 0 - - serializedVersion: 3 - m_Name: Cancel - descriptiveName: - descriptiveNegativeName: - negativeButton: - positiveButton: escape - altNegativeButton: - altPositiveButton: joystick button 1 - gravity: 1000 - dead: 0.001 - sensitivity: 1000 - snap: 0 - invert: 0 - type: 0 - axis: 0 - joyNum: 0 diff --git a/NativeWebSocket/ProjectSettings/NavMeshAreas.asset b/NativeWebSocket/ProjectSettings/NavMeshAreas.asset deleted file mode 100644 index ad2654e..0000000 --- a/NativeWebSocket/ProjectSettings/NavMeshAreas.asset +++ /dev/null @@ -1,93 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!126 &1 -NavMeshProjectSettings: - m_ObjectHideFlags: 0 - serializedVersion: 2 - areas: - - name: Walkable - cost: 1 - - name: Not Walkable - cost: 1 - - name: Jump - cost: 2 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - m_LastAgentTypeID: -887442657 - m_Settings: - - serializedVersion: 2 - agentTypeID: 0 - agentRadius: 0.5 - agentHeight: 2 - agentSlope: 45 - agentClimb: 0.75 - ledgeDropHeight: 0 - maxJumpAcrossDistance: 0 - minRegionArea: 2 - manualCellSize: 0 - cellSize: 0.16666667 - manualTileSize: 0 - tileSize: 256 - accuratePlacement: 0 - maxJobWorkers: 0 - preserveTilesOutsideBounds: 0 - debug: - m_Flags: 0 - m_SettingNames: - - Humanoid diff --git a/NativeWebSocket/ProjectSettings/Physics2DSettings.asset b/NativeWebSocket/ProjectSettings/Physics2DSettings.asset deleted file mode 100644 index 47880b1..0000000 --- a/NativeWebSocket/ProjectSettings/Physics2DSettings.asset +++ /dev/null @@ -1,56 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!19 &1 -Physics2DSettings: - m_ObjectHideFlags: 0 - serializedVersion: 4 - m_Gravity: {x: 0, y: -9.81} - m_DefaultMaterial: {fileID: 0} - m_VelocityIterations: 8 - m_PositionIterations: 3 - m_VelocityThreshold: 1 - m_MaxLinearCorrection: 0.2 - m_MaxAngularCorrection: 8 - m_MaxTranslationSpeed: 100 - m_MaxRotationSpeed: 360 - m_BaumgarteScale: 0.2 - m_BaumgarteTimeOfImpactScale: 0.75 - m_TimeToSleep: 0.5 - m_LinearSleepTolerance: 0.01 - m_AngularSleepTolerance: 2 - m_DefaultContactOffset: 0.01 - m_JobOptions: - serializedVersion: 2 - useMultithreading: 0 - useConsistencySorting: 0 - m_InterpolationPosesPerJob: 100 - m_NewContactsPerJob: 30 - m_CollideContactsPerJob: 100 - m_ClearFlagsPerJob: 200 - m_ClearBodyForcesPerJob: 200 - m_SyncDiscreteFixturesPerJob: 50 - m_SyncContinuousFixturesPerJob: 50 - m_FindNearestContactsPerJob: 100 - m_UpdateTriggerContactsPerJob: 100 - m_IslandSolverCostThreshold: 100 - m_IslandSolverBodyCostScale: 1 - m_IslandSolverContactCostScale: 10 - m_IslandSolverJointCostScale: 10 - m_IslandSolverBodiesPerJob: 50 - m_IslandSolverContactsPerJob: 50 - m_AutoSimulation: 1 - m_QueriesHitTriggers: 1 - m_QueriesStartInColliders: 1 - m_CallbacksOnDisable: 1 - m_ReuseCollisionCallbacks: 1 - m_AutoSyncTransforms: 0 - m_AlwaysShowColliders: 0 - m_ShowColliderSleep: 1 - m_ShowColliderContacts: 0 - m_ShowColliderAABB: 0 - m_ContactArrowScale: 0.2 - m_ColliderAwakeColor: {r: 0.5686275, g: 0.95686275, b: 0.54509807, a: 0.7529412} - m_ColliderAsleepColor: {r: 0.5686275, g: 0.95686275, b: 0.54509807, a: 0.36078432} - m_ColliderContactColor: {r: 1, g: 0, b: 1, a: 0.6862745} - m_ColliderAABBColor: {r: 1, g: 1, b: 0, a: 0.2509804} - m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff diff --git a/NativeWebSocket/ProjectSettings/PresetManager.asset b/NativeWebSocket/ProjectSettings/PresetManager.asset deleted file mode 100644 index 67a94da..0000000 --- a/NativeWebSocket/ProjectSettings/PresetManager.asset +++ /dev/null @@ -1,7 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!1386491679 &1 -PresetManager: - m_ObjectHideFlags: 0 - serializedVersion: 2 - m_DefaultPresets: {} diff --git a/NativeWebSocket/ProjectSettings/ProjectSettings.asset b/NativeWebSocket/ProjectSettings/ProjectSettings.asset deleted file mode 100644 index 3f11c92..0000000 --- a/NativeWebSocket/ProjectSettings/ProjectSettings.asset +++ /dev/null @@ -1,650 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!129 &1 -PlayerSettings: - m_ObjectHideFlags: 0 - serializedVersion: 18 - productGUID: dc7225b1f8ee64a3abfd6eb883cd32ec - AndroidProfiler: 0 - AndroidFilterTouchesWhenObscured: 0 - AndroidEnableSustainedPerformanceMode: 0 - defaultScreenOrientation: 4 - targetDevice: 2 - useOnDemandResources: 0 - accelerometerFrequency: 60 - companyName: gamestdio - productName: UnityWebSockets - defaultCursor: {fileID: 0} - cursorHotspot: {x: 0, y: 0} - m_SplashScreenBackgroundColor: {r: 0.13725491, g: 0.12156863, b: 0.1254902, a: 1} - m_ShowUnitySplashScreen: 1 - m_ShowUnitySplashLogo: 1 - m_SplashScreenOverlayOpacity: 1 - m_SplashScreenAnimation: 1 - m_SplashScreenLogoStyle: 1 - m_SplashScreenDrawMode: 0 - m_SplashScreenBackgroundAnimationZoom: 1 - m_SplashScreenLogoAnimationZoom: 1 - m_SplashScreenBackgroundLandscapeAspect: 1 - m_SplashScreenBackgroundPortraitAspect: 1 - m_SplashScreenBackgroundLandscapeUvs: - serializedVersion: 2 - x: 0 - y: 0 - width: 1 - height: 1 - m_SplashScreenBackgroundPortraitUvs: - serializedVersion: 2 - x: 0 - y: 0 - width: 1 - height: 1 - m_SplashScreenLogos: [] - m_VirtualRealitySplashScreen: {fileID: 0} - m_HolographicTrackingLossScreen: {fileID: 0} - defaultScreenWidth: 1024 - defaultScreenHeight: 768 - defaultScreenWidthWeb: 960 - defaultScreenHeightWeb: 600 - m_StereoRenderingPath: 0 - m_ActiveColorSpace: 0 - m_MTRendering: 1 - m_StackTraceTypes: 010000000100000001000000010000000100000001000000 - iosShowActivityIndicatorOnLoading: -1 - androidShowActivityIndicatorOnLoading: -1 - displayResolutionDialog: 0 - iosUseCustomAppBackgroundBehavior: 0 - iosAllowHTTPDownload: 1 - allowedAutorotateToPortrait: 1 - allowedAutorotateToPortraitUpsideDown: 1 - allowedAutorotateToLandscapeRight: 1 - allowedAutorotateToLandscapeLeft: 1 - useOSAutorotation: 1 - use32BitDisplayBuffer: 1 - preserveFramebufferAlpha: 0 - disableDepthAndStencilBuffers: 0 - androidStartInFullscreen: 1 - androidRenderOutsideSafeArea: 1 - androidUseSwappy: 0 - androidBlitType: 0 - defaultIsNativeResolution: 1 - macRetinaSupport: 1 - runInBackground: 1 - captureSingleScreen: 0 - muteOtherAudioSources: 0 - Prepare IOS For Recording: 0 - Force IOS Speakers When Recording: 0 - deferSystemGesturesMode: 0 - hideHomeButton: 0 - submitAnalytics: 1 - usePlayerLog: 1 - bakeCollisionMeshes: 0 - forceSingleInstance: 0 - useFlipModelSwapchain: 1 - resizableWindow: 0 - useMacAppStoreValidation: 0 - macAppStoreCategory: public.app-category.games - gpuSkinning: 1 - graphicsJobs: 0 - xboxPIXTextureCapture: 0 - xboxEnableAvatar: 0 - xboxEnableKinect: 0 - xboxEnableKinectAutoTracking: 0 - xboxEnableFitness: 0 - visibleInBackground: 1 - allowFullscreenSwitch: 1 - graphicsJobMode: 0 - fullscreenMode: 1 - xboxSpeechDB: 0 - xboxEnableHeadOrientation: 0 - xboxEnableGuest: 0 - xboxEnablePIXSampling: 0 - metalFramebufferOnly: 0 - xboxOneResolution: 0 - xboxOneSResolution: 0 - xboxOneXResolution: 3 - xboxOneMonoLoggingLevel: 0 - xboxOneLoggingLevel: 1 - xboxOneDisableEsram: 0 - xboxOnePresentImmediateThreshold: 0 - switchQueueCommandMemory: 0 - switchQueueControlMemory: 16384 - switchQueueComputeMemory: 262144 - switchNVNShaderPoolsGranularity: 33554432 - switchNVNDefaultPoolsGranularity: 16777216 - switchNVNOtherPoolsGranularity: 16777216 - vulkanEnableSetSRGBWrite: 0 - m_SupportedAspectRatios: - 4:3: 1 - 5:4: 1 - 16:10: 1 - 16:9: 1 - Others: 1 - bundleVersion: 1.0 - preloadedAssets: [] - metroInputSource: 0 - wsaTransparentSwapchain: 0 - m_HolographicPauseOnTrackingLoss: 1 - xboxOneDisableKinectGpuReservation: 1 - xboxOneEnable7thCore: 1 - vrSettings: - cardboard: - depthFormat: 0 - enableTransitionView: 0 - daydream: - depthFormat: 0 - useSustainedPerformanceMode: 0 - enableVideoLayer: 0 - useProtectedVideoMemory: 0 - minimumSupportedHeadTracking: 0 - maximumSupportedHeadTracking: 1 - hololens: - depthFormat: 1 - depthBufferSharingEnabled: 1 - lumin: - depthFormat: 0 - frameTiming: 2 - enableGLCache: 0 - glCacheMaxBlobSize: 524288 - glCacheMaxFileSize: 8388608 - oculus: - sharedDepthBuffer: 1 - dashSupport: 1 - lowOverheadMode: 0 - enable360StereoCapture: 0 - isWsaHolographicRemotingEnabled: 0 - protectGraphicsMemory: 0 - enableFrameTimingStats: 0 - useHDRDisplay: 0 - m_ColorGamuts: 00000000 - targetPixelDensity: 30 - resolutionScalingMode: 0 - androidSupportedAspectRatio: 1 - androidMaxAspectRatio: 2.1 - applicationIdentifier: {} - buildNumber: {} - AndroidBundleVersionCode: 1 - AndroidMinSdkVersion: 16 - AndroidTargetSdkVersion: 0 - AndroidPreferredInstallLocation: 1 - aotOptions: - stripEngineCode: 1 - iPhoneStrippingLevel: 0 - iPhoneScriptCallOptimization: 0 - ForceInternetPermission: 0 - ForceSDCardPermission: 0 - CreateWallpaper: 0 - APKExpansionFiles: 0 - keepLoadedShadersAlive: 0 - StripUnusedMeshComponents: 1 - VertexChannelCompressionMask: 4054 - iPhoneSdkVersion: 988 - iOSTargetOSVersionString: 9.0 - tvOSSdkVersion: 0 - tvOSRequireExtendedGameController: 0 - tvOSTargetOSVersionString: 9.0 - uIPrerenderedIcon: 0 - uIRequiresPersistentWiFi: 0 - uIRequiresFullScreen: 1 - uIStatusBarHidden: 1 - uIExitOnSuspend: 0 - uIStatusBarStyle: 0 - iPhoneSplashScreen: {fileID: 0} - iPhoneHighResSplashScreen: {fileID: 0} - iPhoneTallHighResSplashScreen: {fileID: 0} - iPhone47inSplashScreen: {fileID: 0} - iPhone55inPortraitSplashScreen: {fileID: 0} - iPhone55inLandscapeSplashScreen: {fileID: 0} - iPhone58inPortraitSplashScreen: {fileID: 0} - iPhone58inLandscapeSplashScreen: {fileID: 0} - iPadPortraitSplashScreen: {fileID: 0} - iPadHighResPortraitSplashScreen: {fileID: 0} - iPadLandscapeSplashScreen: {fileID: 0} - iPadHighResLandscapeSplashScreen: {fileID: 0} - iPhone65inPortraitSplashScreen: {fileID: 0} - iPhone65inLandscapeSplashScreen: {fileID: 0} - iPhone61inPortraitSplashScreen: {fileID: 0} - iPhone61inLandscapeSplashScreen: {fileID: 0} - appleTVSplashScreen: {fileID: 0} - appleTVSplashScreen2x: {fileID: 0} - tvOSSmallIconLayers: [] - tvOSSmallIconLayers2x: [] - tvOSLargeIconLayers: [] - tvOSLargeIconLayers2x: [] - tvOSTopShelfImageLayers: [] - tvOSTopShelfImageLayers2x: [] - tvOSTopShelfImageWideLayers: [] - tvOSTopShelfImageWideLayers2x: [] - iOSLaunchScreenType: 0 - iOSLaunchScreenPortrait: {fileID: 0} - iOSLaunchScreenLandscape: {fileID: 0} - iOSLaunchScreenBackgroundColor: - serializedVersion: 2 - rgba: 0 - iOSLaunchScreenFillPct: 100 - iOSLaunchScreenSize: 100 - iOSLaunchScreenCustomXibPath: - iOSLaunchScreeniPadType: 0 - iOSLaunchScreeniPadImage: {fileID: 0} - iOSLaunchScreeniPadBackgroundColor: - serializedVersion: 2 - rgba: 0 - iOSLaunchScreeniPadFillPct: 100 - iOSLaunchScreeniPadSize: 100 - iOSLaunchScreeniPadCustomXibPath: - iOSUseLaunchScreenStoryboard: 0 - iOSLaunchScreenCustomStoryboardPath: - iOSDeviceRequirements: [] - iOSURLSchemes: [] - iOSBackgroundModes: 0 - iOSMetalForceHardShadows: 0 - metalEditorSupport: 1 - metalAPIValidation: 1 - iOSRenderExtraFrameOnPause: 0 - appleDeveloperTeamID: - iOSManualSigningProvisioningProfileID: - tvOSManualSigningProvisioningProfileID: - iOSManualSigningProvisioningProfileType: 0 - tvOSManualSigningProvisioningProfileType: 0 - appleEnableAutomaticSigning: 0 - iOSRequireARKit: 0 - iOSAutomaticallyDetectAndAddCapabilities: 1 - appleEnableProMotion: 0 - clonedFromGUID: c0afd0d1d80e3634a9dac47e8a0426ea - templatePackageId: com.unity.template.3d@3.1.0 - templateDefaultScene: Assets/Scenes/SampleScene.unity - AndroidTargetArchitectures: 1 - AndroidSplashScreenScale: 0 - androidSplashScreen: {fileID: 0} - AndroidKeystoreName: '{inproject}: ' - AndroidKeyaliasName: - AndroidBuildApkPerCpuArchitecture: 0 - AndroidTVCompatibility: 0 - AndroidIsGame: 1 - AndroidEnableTango: 0 - androidEnableBanner: 1 - androidUseLowAccuracyLocation: 0 - androidUseCustomKeystore: 0 - m_AndroidBanners: - - width: 320 - height: 180 - banner: {fileID: 0} - androidGamepadSupportLevel: 0 - AndroidValidateAppBundleSize: 1 - AndroidAppBundleSizeToValidate: 150 - resolutionDialogBanner: {fileID: 0} - m_BuildTargetIcons: [] - m_BuildTargetPlatformIcons: [] - m_BuildTargetBatching: - - m_BuildTarget: Standalone - m_StaticBatching: 1 - m_DynamicBatching: 0 - - m_BuildTarget: tvOS - m_StaticBatching: 1 - m_DynamicBatching: 0 - - m_BuildTarget: Android - m_StaticBatching: 1 - m_DynamicBatching: 0 - - m_BuildTarget: iPhone - m_StaticBatching: 1 - m_DynamicBatching: 0 - - m_BuildTarget: WebGL - m_StaticBatching: 0 - m_DynamicBatching: 0 - m_BuildTargetGraphicsAPIs: - - m_BuildTarget: AndroidPlayer - m_APIs: 150000000b000000 - m_Automatic: 0 - - m_BuildTarget: iOSSupport - m_APIs: 10000000 - m_Automatic: 1 - - m_BuildTarget: AppleTVSupport - m_APIs: 10000000 - m_Automatic: 0 - - m_BuildTarget: WebGLSupport - m_APIs: 0b000000 - m_Automatic: 1 - m_BuildTargetVRSettings: - - m_BuildTarget: Standalone - m_Enabled: 0 - m_Devices: - - Oculus - - OpenVR - openGLRequireES31: 0 - openGLRequireES31AEP: 0 - openGLRequireES32: 0 - vuforiaEnabled: 0 - m_TemplateCustomTags: {} - mobileMTRendering: - Android: 1 - iPhone: 1 - tvOS: 1 - m_BuildTargetGroupLightmapEncodingQuality: [] - m_BuildTargetGroupLightmapSettings: [] - playModeTestRunnerEnabled: 0 - runPlayModeTestAsEditModeTest: 0 - actionOnDotNetUnhandledException: 1 - enableInternalProfiler: 0 - logObjCUncaughtExceptions: 1 - enableCrashReportAPI: 0 - cameraUsageDescription: - locationUsageDescription: - microphoneUsageDescription: - switchNetLibKey: - switchSocketMemoryPoolSize: 6144 - switchSocketAllocatorPoolSize: 128 - switchSocketConcurrencyLimit: 14 - switchScreenResolutionBehavior: 2 - switchUseCPUProfiler: 0 - switchApplicationID: 0x01004b9000490000 - switchNSODependencies: - switchTitleNames_0: - switchTitleNames_1: - switchTitleNames_2: - switchTitleNames_3: - switchTitleNames_4: - switchTitleNames_5: - switchTitleNames_6: - switchTitleNames_7: - switchTitleNames_8: - switchTitleNames_9: - switchTitleNames_10: - switchTitleNames_11: - switchTitleNames_12: - switchTitleNames_13: - switchTitleNames_14: - switchPublisherNames_0: - switchPublisherNames_1: - switchPublisherNames_2: - switchPublisherNames_3: - switchPublisherNames_4: - switchPublisherNames_5: - switchPublisherNames_6: - switchPublisherNames_7: - switchPublisherNames_8: - switchPublisherNames_9: - switchPublisherNames_10: - switchPublisherNames_11: - switchPublisherNames_12: - switchPublisherNames_13: - switchPublisherNames_14: - switchIcons_0: {fileID: 0} - switchIcons_1: {fileID: 0} - switchIcons_2: {fileID: 0} - switchIcons_3: {fileID: 0} - switchIcons_4: {fileID: 0} - switchIcons_5: {fileID: 0} - switchIcons_6: {fileID: 0} - switchIcons_7: {fileID: 0} - switchIcons_8: {fileID: 0} - switchIcons_9: {fileID: 0} - switchIcons_10: {fileID: 0} - switchIcons_11: {fileID: 0} - switchIcons_12: {fileID: 0} - switchIcons_13: {fileID: 0} - switchIcons_14: {fileID: 0} - switchSmallIcons_0: {fileID: 0} - switchSmallIcons_1: {fileID: 0} - switchSmallIcons_2: {fileID: 0} - switchSmallIcons_3: {fileID: 0} - switchSmallIcons_4: {fileID: 0} - switchSmallIcons_5: {fileID: 0} - switchSmallIcons_6: {fileID: 0} - switchSmallIcons_7: {fileID: 0} - switchSmallIcons_8: {fileID: 0} - switchSmallIcons_9: {fileID: 0} - switchSmallIcons_10: {fileID: 0} - switchSmallIcons_11: {fileID: 0} - switchSmallIcons_12: {fileID: 0} - switchSmallIcons_13: {fileID: 0} - switchSmallIcons_14: {fileID: 0} - switchManualHTML: - switchAccessibleURLs: - switchLegalInformation: - switchMainThreadStackSize: 1048576 - switchPresenceGroupId: - switchLogoHandling: 0 - switchReleaseVersion: 0 - switchDisplayVersion: 1.0.0 - switchStartupUserAccount: 0 - switchTouchScreenUsage: 0 - switchSupportedLanguagesMask: 0 - switchLogoType: 0 - switchApplicationErrorCodeCategory: - switchUserAccountSaveDataSize: 0 - switchUserAccountSaveDataJournalSize: 0 - switchApplicationAttribute: 0 - switchCardSpecSize: -1 - switchCardSpecClock: -1 - switchRatingsMask: 0 - switchRatingsInt_0: 0 - switchRatingsInt_1: 0 - switchRatingsInt_2: 0 - switchRatingsInt_3: 0 - switchRatingsInt_4: 0 - switchRatingsInt_5: 0 - switchRatingsInt_6: 0 - switchRatingsInt_7: 0 - switchRatingsInt_8: 0 - switchRatingsInt_9: 0 - switchRatingsInt_10: 0 - switchRatingsInt_11: 0 - switchLocalCommunicationIds_0: - switchLocalCommunicationIds_1: - switchLocalCommunicationIds_2: - switchLocalCommunicationIds_3: - switchLocalCommunicationIds_4: - switchLocalCommunicationIds_5: - switchLocalCommunicationIds_6: - switchLocalCommunicationIds_7: - switchParentalControl: 0 - switchAllowsScreenshot: 1 - switchAllowsVideoCapturing: 1 - switchAllowsRuntimeAddOnContentInstall: 0 - switchDataLossConfirmation: 0 - switchUserAccountLockEnabled: 0 - switchSystemResourceMemory: 16777216 - switchSupportedNpadStyles: 3 - switchNativeFsCacheSize: 32 - switchIsHoldTypeHorizontal: 0 - switchSupportedNpadCount: 8 - switchSocketConfigEnabled: 0 - switchTcpInitialSendBufferSize: 32 - switchTcpInitialReceiveBufferSize: 64 - switchTcpAutoSendBufferSizeMax: 256 - switchTcpAutoReceiveBufferSizeMax: 256 - switchUdpSendBufferSize: 9 - switchUdpReceiveBufferSize: 42 - switchSocketBufferEfficiency: 4 - switchSocketInitializeEnabled: 1 - switchNetworkInterfaceManagerInitializeEnabled: 1 - switchPlayerConnectionEnabled: 1 - ps4NPAgeRating: 12 - ps4NPTitleSecret: - ps4NPTrophyPackPath: - ps4ParentalLevel: 11 - ps4ContentID: ED1633-NPXX51362_00-0000000000000000 - ps4Category: 0 - ps4MasterVersion: 01.00 - ps4AppVersion: 01.00 - ps4AppType: 0 - ps4ParamSfxPath: - ps4VideoOutPixelFormat: 0 - ps4VideoOutInitialWidth: 1920 - ps4VideoOutBaseModeInitialWidth: 1920 - ps4VideoOutReprojectionRate: 60 - ps4PronunciationXMLPath: - ps4PronunciationSIGPath: - ps4BackgroundImagePath: - ps4StartupImagePath: - ps4StartupImagesFolder: - ps4IconImagesFolder: - ps4SaveDataImagePath: - ps4SdkOverride: - ps4BGMPath: - ps4ShareFilePath: - ps4ShareOverlayImagePath: - ps4PrivacyGuardImagePath: - ps4NPtitleDatPath: - ps4RemotePlayKeyAssignment: -1 - ps4RemotePlayKeyMappingDir: - ps4PlayTogetherPlayerCount: 0 - ps4EnterButtonAssignment: 1 - ps4ApplicationParam1: 0 - ps4ApplicationParam2: 0 - ps4ApplicationParam3: 0 - ps4ApplicationParam4: 0 - ps4DownloadDataSize: 0 - ps4GarlicHeapSize: 2048 - ps4ProGarlicHeapSize: 2560 - playerPrefsMaxSize: 32768 - ps4Passcode: frAQBc8Wsa1xVPfvJcrgRYwTiizs2trQ - ps4pnSessions: 1 - ps4pnPresence: 1 - ps4pnFriends: 1 - ps4pnGameCustomData: 1 - playerPrefsSupport: 0 - enableApplicationExit: 0 - resetTempFolder: 1 - restrictedAudioUsageRights: 0 - ps4UseResolutionFallback: 0 - ps4ReprojectionSupport: 0 - ps4UseAudio3dBackend: 0 - ps4SocialScreenEnabled: 0 - ps4ScriptOptimizationLevel: 0 - ps4Audio3dVirtualSpeakerCount: 14 - ps4attribCpuUsage: 0 - ps4PatchPkgPath: - ps4PatchLatestPkgPath: - ps4PatchChangeinfoPath: - ps4PatchDayOne: 0 - ps4attribUserManagement: 0 - ps4attribMoveSupport: 0 - ps4attrib3DSupport: 0 - ps4attribShareSupport: 0 - ps4attribExclusiveVR: 0 - ps4disableAutoHideSplash: 0 - ps4videoRecordingFeaturesUsed: 0 - ps4contentSearchFeaturesUsed: 0 - ps4attribEyeToEyeDistanceSettingVR: 0 - ps4IncludedModules: [] - monoEnv: - splashScreenBackgroundSourceLandscape: {fileID: 0} - splashScreenBackgroundSourcePortrait: {fileID: 0} - blurSplashScreenBackground: 1 - spritePackerPolicy: - webGLMemorySize: 16 - webGLExceptionSupport: 1 - webGLNameFilesAsHashes: 0 - webGLDataCaching: 1 - webGLDebugSymbols: 0 - webGLEmscriptenArgs: - webGLModulesDirectory: - webGLTemplate: APPLICATION:Default - webGLAnalyzeBuildSize: 0 - webGLUseEmbeddedResources: 0 - webGLCompressionFormat: 1 - webGLLinkerTarget: 1 - webGLThreadsSupport: 0 - webGLWasmStreaming: 0 - scriptingDefineSymbols: {} - platformArchitecture: {} - scriptingBackend: {} - il2cppCompilerConfiguration: {} - managedStrippingLevel: {} - incrementalIl2cppBuild: {} - allowUnsafeCode: 0 - additionalIl2CppArgs: - scriptingRuntimeVersion: 1 - gcIncremental: 0 - gcWBarrierValidation: 0 - apiCompatibilityLevelPerPlatform: - WebGL: 3 - m_RenderingPath: 1 - m_MobileRenderingPath: 1 - metroPackageName: Template_3D - metroPackageVersion: - metroCertificatePath: - metroCertificatePassword: - metroCertificateSubject: - metroCertificateIssuer: - metroCertificateNotAfter: 0000000000000000 - metroApplicationDescription: Template_3D - wsaImages: {} - metroTileShortName: - metroTileShowName: 0 - metroMediumTileShowName: 0 - metroLargeTileShowName: 0 - metroWideTileShowName: 0 - metroSupportStreamingInstall: 0 - metroLastRequiredScene: 0 - metroDefaultTileSize: 1 - metroTileForegroundText: 2 - metroTileBackgroundColor: {r: 0.13333334, g: 0.17254902, b: 0.21568628, a: 0} - metroSplashScreenBackgroundColor: {r: 0.12941177, g: 0.17254902, b: 0.21568628, - a: 1} - metroSplashScreenUseBackgroundColor: 0 - platformCapabilities: {} - metroTargetDeviceFamilies: {} - metroFTAName: - metroFTAFileTypes: [] - metroProtocolName: - XboxOneProductId: - XboxOneUpdateKey: - XboxOneSandboxId: - XboxOneContentId: - XboxOneTitleId: - XboxOneSCId: - XboxOneGameOsOverridePath: - XboxOnePackagingOverridePath: - XboxOneAppManifestOverridePath: - XboxOneVersion: 1.0.0.0 - XboxOnePackageEncryption: 0 - XboxOnePackageUpdateGranularity: 2 - XboxOneDescription: - XboxOneLanguage: - - enus - XboxOneCapability: [] - XboxOneGameRating: {} - XboxOneIsContentPackage: 0 - XboxOneEnableGPUVariability: 1 - XboxOneSockets: {} - XboxOneSplashScreen: {fileID: 0} - XboxOneAllowedProductIds: [] - XboxOnePersistentLocalStorageSize: 0 - XboxOneXTitleMemory: 8 - xboxOneScriptCompiler: 1 - XboxOneOverrideIdentityName: - vrEditorSettings: - daydream: - daydreamIconForeground: {fileID: 0} - daydreamIconBackground: {fileID: 0} - cloudServicesEnabled: - UNet: 1 - luminIcon: - m_Name: - m_ModelFolderPath: - m_PortalFolderPath: - luminCert: - m_CertPath: - m_SignPackage: 1 - luminIsChannelApp: 0 - luminVersion: - m_VersionCode: 1 - m_VersionName: - facebookSdkVersion: 7.9.4 - facebookAppId: - facebookCookies: 1 - facebookLogging: 1 - facebookStatus: 1 - facebookXfbml: 0 - facebookFrictionlessRequests: 1 - apiCompatibilityLevel: 6 - cloudProjectId: - framebufferDepthMemorylessMode: 0 - projectName: - organizationId: - cloudEnabled: 0 - enableNativePlatformBackendsForNewInputSystem: 0 - disableOldInputManagerSupport: 0 - legacyClampBlendShapeWeights: 1 diff --git a/NativeWebSocket/ProjectSettings/ProjectVersion.txt b/NativeWebSocket/ProjectSettings/ProjectVersion.txt deleted file mode 100644 index a4b5984..0000000 --- a/NativeWebSocket/ProjectSettings/ProjectVersion.txt +++ /dev/null @@ -1,2 +0,0 @@ -m_EditorVersion: 6000.3.6f1 -m_EditorVersionWithRevision: 6000.3.6f1 (bbb010bdb8a3) diff --git a/NativeWebSocket/ProjectSettings/QualitySettings.asset b/NativeWebSocket/ProjectSettings/QualitySettings.asset deleted file mode 100644 index ed26313..0000000 --- a/NativeWebSocket/ProjectSettings/QualitySettings.asset +++ /dev/null @@ -1,231 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!47 &1 -QualitySettings: - m_ObjectHideFlags: 0 - serializedVersion: 5 - m_CurrentQuality: 5 - m_QualitySettings: - - serializedVersion: 2 - name: Very Low - pixelLightCount: 0 - shadows: 0 - shadowResolution: 0 - shadowProjection: 1 - shadowCascades: 1 - shadowDistance: 15 - shadowNearPlaneOffset: 3 - shadowCascade2Split: 0.33333334 - shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} - shadowmaskMode: 0 - blendWeights: 1 - textureQuality: 1 - anisotropicTextures: 0 - antiAliasing: 0 - softParticles: 0 - softVegetation: 0 - realtimeReflectionProbes: 0 - billboardsFaceCameraPosition: 0 - vSyncCount: 0 - lodBias: 0.3 - maximumLODLevel: 0 - streamingMipmapsActive: 0 - streamingMipmapsAddAllCameras: 1 - streamingMipmapsMemoryBudget: 512 - streamingMipmapsRenderersPerFrame: 512 - streamingMipmapsMaxLevelReduction: 2 - streamingMipmapsMaxFileIORequests: 1024 - particleRaycastBudget: 4 - asyncUploadTimeSlice: 2 - asyncUploadBufferSize: 16 - asyncUploadPersistentBuffer: 1 - resolutionScalingFixedDPIFactor: 1 - excludedTargetPlatforms: [] - - serializedVersion: 2 - name: Low - pixelLightCount: 0 - shadows: 0 - shadowResolution: 0 - shadowProjection: 1 - shadowCascades: 1 - shadowDistance: 20 - shadowNearPlaneOffset: 3 - shadowCascade2Split: 0.33333334 - shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} - shadowmaskMode: 0 - blendWeights: 2 - textureQuality: 0 - anisotropicTextures: 0 - antiAliasing: 0 - softParticles: 0 - softVegetation: 0 - realtimeReflectionProbes: 0 - billboardsFaceCameraPosition: 0 - vSyncCount: 0 - lodBias: 0.4 - maximumLODLevel: 0 - streamingMipmapsActive: 0 - streamingMipmapsAddAllCameras: 1 - streamingMipmapsMemoryBudget: 512 - streamingMipmapsRenderersPerFrame: 512 - streamingMipmapsMaxLevelReduction: 2 - streamingMipmapsMaxFileIORequests: 1024 - particleRaycastBudget: 16 - asyncUploadTimeSlice: 2 - asyncUploadBufferSize: 16 - asyncUploadPersistentBuffer: 1 - resolutionScalingFixedDPIFactor: 1 - excludedTargetPlatforms: [] - - serializedVersion: 2 - name: Medium - pixelLightCount: 1 - shadows: 1 - shadowResolution: 0 - shadowProjection: 1 - shadowCascades: 1 - shadowDistance: 20 - shadowNearPlaneOffset: 3 - shadowCascade2Split: 0.33333334 - shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} - shadowmaskMode: 0 - blendWeights: 2 - textureQuality: 0 - anisotropicTextures: 1 - antiAliasing: 0 - softParticles: 0 - softVegetation: 0 - realtimeReflectionProbes: 0 - billboardsFaceCameraPosition: 0 - vSyncCount: 1 - lodBias: 0.7 - maximumLODLevel: 0 - streamingMipmapsActive: 0 - streamingMipmapsAddAllCameras: 1 - streamingMipmapsMemoryBudget: 512 - streamingMipmapsRenderersPerFrame: 512 - streamingMipmapsMaxLevelReduction: 2 - streamingMipmapsMaxFileIORequests: 1024 - particleRaycastBudget: 64 - asyncUploadTimeSlice: 2 - asyncUploadBufferSize: 16 - asyncUploadPersistentBuffer: 1 - resolutionScalingFixedDPIFactor: 1 - excludedTargetPlatforms: [] - - serializedVersion: 2 - name: High - pixelLightCount: 2 - shadows: 2 - shadowResolution: 1 - shadowProjection: 1 - shadowCascades: 2 - shadowDistance: 40 - shadowNearPlaneOffset: 3 - shadowCascade2Split: 0.33333334 - shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} - shadowmaskMode: 1 - blendWeights: 2 - textureQuality: 0 - anisotropicTextures: 1 - antiAliasing: 0 - softParticles: 0 - softVegetation: 1 - realtimeReflectionProbes: 1 - billboardsFaceCameraPosition: 1 - vSyncCount: 1 - lodBias: 1 - maximumLODLevel: 0 - streamingMipmapsActive: 0 - streamingMipmapsAddAllCameras: 1 - streamingMipmapsMemoryBudget: 512 - streamingMipmapsRenderersPerFrame: 512 - streamingMipmapsMaxLevelReduction: 2 - streamingMipmapsMaxFileIORequests: 1024 - particleRaycastBudget: 256 - asyncUploadTimeSlice: 2 - asyncUploadBufferSize: 16 - asyncUploadPersistentBuffer: 1 - resolutionScalingFixedDPIFactor: 1 - excludedTargetPlatforms: [] - - serializedVersion: 2 - name: Very High - pixelLightCount: 3 - shadows: 2 - shadowResolution: 2 - shadowProjection: 1 - shadowCascades: 2 - shadowDistance: 70 - shadowNearPlaneOffset: 3 - shadowCascade2Split: 0.33333334 - shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} - shadowmaskMode: 1 - blendWeights: 4 - textureQuality: 0 - anisotropicTextures: 2 - antiAliasing: 2 - softParticles: 1 - softVegetation: 1 - realtimeReflectionProbes: 1 - billboardsFaceCameraPosition: 1 - vSyncCount: 1 - lodBias: 1.5 - maximumLODLevel: 0 - streamingMipmapsActive: 0 - streamingMipmapsAddAllCameras: 1 - streamingMipmapsMemoryBudget: 512 - streamingMipmapsRenderersPerFrame: 512 - streamingMipmapsMaxLevelReduction: 2 - streamingMipmapsMaxFileIORequests: 1024 - particleRaycastBudget: 1024 - asyncUploadTimeSlice: 2 - asyncUploadBufferSize: 16 - asyncUploadPersistentBuffer: 1 - resolutionScalingFixedDPIFactor: 1 - excludedTargetPlatforms: [] - - serializedVersion: 2 - name: Ultra - pixelLightCount: 4 - shadows: 2 - shadowResolution: 2 - shadowProjection: 1 - shadowCascades: 4 - shadowDistance: 150 - shadowNearPlaneOffset: 3 - shadowCascade2Split: 0.33333334 - shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} - shadowmaskMode: 1 - blendWeights: 4 - textureQuality: 0 - anisotropicTextures: 2 - antiAliasing: 2 - softParticles: 1 - softVegetation: 1 - realtimeReflectionProbes: 1 - billboardsFaceCameraPosition: 1 - vSyncCount: 1 - lodBias: 2 - maximumLODLevel: 0 - streamingMipmapsActive: 0 - streamingMipmapsAddAllCameras: 1 - streamingMipmapsMemoryBudget: 512 - streamingMipmapsRenderersPerFrame: 512 - streamingMipmapsMaxLevelReduction: 2 - streamingMipmapsMaxFileIORequests: 1024 - particleRaycastBudget: 4096 - asyncUploadTimeSlice: 2 - asyncUploadBufferSize: 16 - asyncUploadPersistentBuffer: 1 - resolutionScalingFixedDPIFactor: 1 - excludedTargetPlatforms: [] - m_PerPlatformDefaultQuality: - Android: 2 - Lumin: 5 - Nintendo 3DS: 5 - Nintendo Switch: 5 - PS4: 5 - PSP2: 2 - Standalone: 5 - WebGL: 3 - Windows Store Apps: 5 - XboxOne: 5 - iPhone: 2 - tvOS: 2 diff --git a/NativeWebSocket/ProjectSettings/TagManager.asset b/NativeWebSocket/ProjectSettings/TagManager.asset deleted file mode 100644 index 1c92a78..0000000 --- a/NativeWebSocket/ProjectSettings/TagManager.asset +++ /dev/null @@ -1,43 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!78 &1 -TagManager: - serializedVersion: 2 - tags: [] - layers: - - Default - - TransparentFX - - Ignore Raycast - - - - Water - - UI - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - m_SortingLayers: - - name: Default - uniqueID: 0 - locked: 0 diff --git a/NativeWebSocket/ProjectSettings/TimeManager.asset b/NativeWebSocket/ProjectSettings/TimeManager.asset deleted file mode 100644 index 558a017..0000000 --- a/NativeWebSocket/ProjectSettings/TimeManager.asset +++ /dev/null @@ -1,9 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!5 &1 -TimeManager: - m_ObjectHideFlags: 0 - Fixed Timestep: 0.02 - Maximum Allowed Timestep: 0.33333334 - m_TimeScale: 1 - Maximum Particle Timestep: 0.03 diff --git a/NativeWebSocket/ProjectSettings/UnityConnectSettings.asset b/NativeWebSocket/ProjectSettings/UnityConnectSettings.asset deleted file mode 100644 index fa0b146..0000000 --- a/NativeWebSocket/ProjectSettings/UnityConnectSettings.asset +++ /dev/null @@ -1,34 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!310 &1 -UnityConnectSettings: - m_ObjectHideFlags: 0 - serializedVersion: 1 - m_Enabled: 0 - m_TestMode: 0 - m_EventOldUrl: https://api.uca.cloud.unity3d.com/v1/events - m_EventUrl: https://cdp.cloud.unity3d.com/v1/events - m_ConfigUrl: https://config.uca.cloud.unity3d.com - m_TestInitMode: 0 - CrashReportingSettings: - m_EventUrl: https://perf-events.cloud.unity3d.com - m_Enabled: 0 - m_LogBufferSize: 10 - m_CaptureEditorExceptions: 1 - UnityPurchasingSettings: - m_Enabled: 0 - m_TestMode: 0 - UnityAnalyticsSettings: - m_Enabled: 0 - m_TestMode: 0 - m_InitializeOnStartup: 1 - UnityAdsSettings: - m_Enabled: 0 - m_InitializeOnStartup: 1 - m_TestMode: 0 - m_IosGameId: - m_AndroidGameId: - m_GameIds: {} - m_GameId: - PerformanceReportingSettings: - m_Enabled: 0 diff --git a/NativeWebSocket/ProjectSettings/VFXManager.asset b/NativeWebSocket/ProjectSettings/VFXManager.asset deleted file mode 100644 index 46f38e1..0000000 --- a/NativeWebSocket/ProjectSettings/VFXManager.asset +++ /dev/null @@ -1,14 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!937362698 &1 -VFXManager: - m_ObjectHideFlags: 0 - m_IndirectShader: {fileID: 0} - m_CopyBufferShader: {fileID: 0} - m_SortShader: {fileID: 0} - m_StripUpdateShader: {fileID: 0} - m_RenderPipeSettingsPath: - m_FixedTimeStep: 0.016666668 - m_MaxDeltaTime: 0.05 - m_CompiledVersion: 0 - m_RuntimeVersion: 0 diff --git a/NativeWebSocket/ProjectSettings/XRSettings.asset b/NativeWebSocket/ProjectSettings/XRSettings.asset deleted file mode 100644 index 482590c..0000000 --- a/NativeWebSocket/ProjectSettings/XRSettings.asset +++ /dev/null @@ -1,10 +0,0 @@ -{ - "m_SettingKeys": [ - "VR Device Disabled", - "VR Device User Alert" - ], - "m_SettingValues": [ - "False", - "False" - ] -} \ No newline at end of file diff --git a/NodeServer/index.js b/NodeServer/index.js index 0428917..50533f1 100644 --- a/NodeServer/index.js +++ b/NodeServer/index.js @@ -1,13 +1,13 @@ -const crypto = require('crypto'); -const express = require('express'); -const { createServer } = require('http'); -const WebSocket = require('ws'); +import crypto from 'crypto'; +import express from 'express'; +import { createServer } from 'http'; +import { WebSocketServer } from 'ws'; const app = express(); const port = 3000; const server = createServer(app); -const wss = new WebSocket.Server({ server }); +const wss = new WebSocketServer({ server }); wss.on('connection', function(ws) { console.log("client joined."); diff --git a/NodeServer/package-lock.json b/NodeServer/package-lock.json index 37226fd..24f4779 100644 --- a/NodeServer/package-lock.json +++ b/NodeServer/package-lock.json @@ -9,322 +9,533 @@ "version": "1.0.0", "license": "ISC", "dependencies": { - "express": "^4.17.1", - "ws": "^7.1.2" - }, - "engines": { - "node": "12.x" + "express": "^5.1.0", + "ws": "^8.18.1" } }, "node_modules/accepts": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", - "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", + "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", + "license": "MIT", "dependencies": { - "mime-types": "~2.1.24", - "negotiator": "0.6.2" + "mime-types": "^3.0.0", + "negotiator": "^1.0.0" }, "engines": { "node": ">= 0.6" } }, - "node_modules/array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" - }, - "node_modules/async-limiter": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", - "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==" - }, "node_modules/body-parser": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", - "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.2.tgz", + "integrity": "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA==", + "license": "MIT", "dependencies": { - "bytes": "3.1.0", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.7.0", - "raw-body": "2.4.0", - "type-is": "~1.6.17" + "bytes": "^3.1.2", + "content-type": "^1.0.5", + "debug": "^4.4.3", + "http-errors": "^2.0.0", + "iconv-lite": "^0.7.0", + "on-finished": "^2.4.1", + "qs": "^6.14.1", + "raw-body": "^3.0.1", + "type-is": "^2.0.1" }, "engines": { - "node": ">= 0.8" + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", "engines": { "node": ">= 0.8" } }, - "node_modules/content-disposition": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", - "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", "dependencies": { - "safe-buffer": "5.1.2" + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" }, "engines": { - "node": ">= 0.6" + "node": ">= 0.4" } }, - "node_modules/content-type": { + "node_modules/call-bound": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/content-disposition": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.1.tgz", + "integrity": "sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/cookie": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", - "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", + "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", + "license": "MIT", + "engines": { + "node": ">=6.6.0" + } }, "node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", "dependencies": { - "ms": "2.0.0" + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, "node_modules/depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", "engines": { - "node": ">= 0.6" + "node": ">= 0.8" } }, - "node_modules/destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" }, "node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", "engines": { "node": ">= 0.8" } }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" }, "node_modules/etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/express": { - "version": "4.17.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", - "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz", + "integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==", + "license": "MIT", "dependencies": { - "accepts": "~1.3.7", - "array-flatten": "1.1.1", - "body-parser": "1.19.0", - "content-disposition": "0.5.3", - "content-type": "~1.0.4", - "cookie": "0.4.0", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "~1.1.2", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "~1.1.2", - "fresh": "0.5.2", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.5", - "qs": "6.7.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.1.2", - "send": "0.17.1", - "serve-static": "1.14.1", - "setprototypeof": "1.1.1", - "statuses": "~1.5.0", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.10.0" + "accepts": "^2.0.0", + "body-parser": "^2.2.1", + "content-disposition": "^1.0.0", + "content-type": "^1.0.5", + "cookie": "^0.7.1", + "cookie-signature": "^1.2.1", + "debug": "^4.4.0", + "depd": "^2.0.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "finalhandler": "^2.1.0", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "merge-descriptors": "^2.0.0", + "mime-types": "^3.0.0", + "on-finished": "^2.4.1", + "once": "^1.4.0", + "parseurl": "^1.3.3", + "proxy-addr": "^2.0.7", + "qs": "^6.14.0", + "range-parser": "^1.2.1", + "router": "^2.2.0", + "send": "^1.1.0", + "serve-static": "^2.2.0", + "statuses": "^2.0.1", + "type-is": "^2.0.1", + "vary": "^1.1.2" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/finalhandler": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz", + "integrity": "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==", + "license": "MIT", "dependencies": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "statuses": "~1.5.0", - "unpipe": "~1.0.0" + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "on-finished": "^2.4.1", + "parseurl": "^1.3.3", + "statuses": "^2.0.1" }, "engines": { - "node": ">= 0.8" + "node": ">= 18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/forwarded": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", - "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", + "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", + "license": "MIT", "engines": { - "node": ">= 0.6" + "node": ">= 0.8" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" } }, "node_modules/http-errors": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", - "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "license": "MIT", "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" }, "engines": { - "node": ">= 0.6" + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz", + "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==", + "license": "MIT", "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" + "safer-buffer": ">= 2.1.2 < 3.0.0" }, "engines": { "node": ">=0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" }, "node_modules/ipaddr.js": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.0.tgz", - "integrity": "sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA==", + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", "engines": { "node": ">= 0.10" } }, - "node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "node_modules/is-promise": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", + "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", + "license": "MIT" + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", "engines": { - "node": ">= 0.6" + "node": ">= 0.4" } }, - "node_modules/merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" - }, - "node_modules/methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "node_modules/media-typer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", + "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", + "license": "MIT", "engines": { - "node": ">= 0.6" + "node": ">= 0.8" } }, - "node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "bin": { - "mime": "cli.js" - }, + "node_modules/merge-descriptors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", + "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", + "license": "MIT", "engines": { - "node": ">=4" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/mime-db": { - "version": "1.40.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz", - "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==", + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/mime-types": { - "version": "2.1.24", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz", - "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz", + "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==", + "license": "MIT", "dependencies": { - "mime-db": "1.40.0" + "mime-db": "^1.54.0" }, "engines": { - "node": ">= 0.6" + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" }, "node_modules/negotiator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", - "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", + "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", + "license": "MIT", "engines": { "node": ">= 0.6" } }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", "dependencies": { "ee-first": "1.1.1" }, @@ -332,141 +543,258 @@ "node": ">= 0.8" } }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", "engines": { "node": ">= 0.8" } }, "node_modules/path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.3.0.tgz", + "integrity": "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } }, "node_modules/proxy-addr": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.5.tgz", - "integrity": "sha512-t/7RxHXPH6cJtP0pRG6smSr9QJidhB+3kXu0KgXnbGYMgzEnUxRQ4/LDdfOwZEMyIh3/xHb8PX3t+lfL9z+YVQ==", + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "license": "MIT", "dependencies": { - "forwarded": "~0.1.2", - "ipaddr.js": "1.9.0" + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" }, "engines": { "node": ">= 0.10" } }, "node_modules/qs": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.0.tgz", + "integrity": "sha512-mAZTtNCeetKMH+pSjrb76NAM8V9a05I9aBZOHztWy/UqcJdQYNsf59vrRKWnojAT9Y+GbIvoTBC++CPHqpDBhQ==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.1.0" + }, "engines": { "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/raw-body": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", - "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.2.tgz", + "integrity": "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==", + "license": "MIT", "dependencies": { - "bytes": "3.1.0", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.7.0", + "unpipe": "~1.0.0" }, "engines": { - "node": ">= 0.8" + "node": ">= 0.10" } }, - "node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + "node_modules/router": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", + "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "depd": "^2.0.0", + "is-promise": "^4.0.0", + "parseurl": "^1.3.3", + "path-to-regexp": "^8.0.0" + }, + "engines": { + "node": ">= 18" + } }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" }, "node_modules/send": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", - "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/send/-/send-1.2.1.tgz", + "integrity": "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==", + "license": "MIT", "dependencies": { - "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "~1.7.2", - "mime": "1.6.0", - "ms": "2.1.1", - "on-finished": "~2.3.0", - "range-parser": "~1.2.1", - "statuses": "~1.5.0" + "debug": "^4.4.3", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "fresh": "^2.0.0", + "http-errors": "^2.0.1", + "mime-types": "^3.0.2", + "ms": "^2.1.3", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "statuses": "^2.0.2" }, "engines": { - "node": ">= 0.8.0" + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, - "node_modules/send/node_modules/ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" - }, "node_modules/serve-static": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", - "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.1.tgz", + "integrity": "sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==", + "license": "MIT", "dependencies": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.17.1" + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "parseurl": "^1.3.3", + "send": "^1.2.0" }, "engines": { - "node": ">= 0.8.0" + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "license": "MIT", "engines": { - "node": ">= 0.6" + "node": ">= 0.8" } }, "node_modules/toidentifier": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", "engines": { "node": ">=0.6" } }, "node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", + "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", + "license": "MIT", "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" + "content-type": "^1.0.5", + "media-typer": "^1.1.0", + "mime-types": "^3.0.0" }, "engines": { "node": ">= 0.6" @@ -475,19 +803,12 @@ "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", "engines": { "node": ">= 0.8" } }, - "node_modules/utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", - "engines": { - "node": ">= 0.4.0" - } - }, "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -496,283 +817,391 @@ "node": ">= 0.8" } }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" + }, "node_modules/ws": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.1.2.tgz", - "integrity": "sha512-gftXq3XI81cJCgkUiAVixA0raD9IVmXqsylCrjRygw4+UOOGzPoxnQ6r/CnVL9i+mDncJo94tSkyrtuuQVBmrg==", - "dependencies": { - "async-limiter": "^1.0.0" + "version": "8.19.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.19.0.tgz", + "integrity": "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } } } }, "dependencies": { "accepts": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", - "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", + "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", "requires": { - "mime-types": "~2.1.24", - "negotiator": "0.6.2" + "mime-types": "^3.0.0", + "negotiator": "^1.0.0" } }, - "array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" - }, - "async-limiter": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", - "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==" - }, "body-parser": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", - "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.2.tgz", + "integrity": "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA==", "requires": { - "bytes": "3.1.0", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.7.0", - "raw-body": "2.4.0", - "type-is": "~1.6.17" + "bytes": "^3.1.2", + "content-type": "^1.0.5", + "debug": "^4.4.3", + "http-errors": "^2.0.0", + "iconv-lite": "^0.7.0", + "on-finished": "^2.4.1", + "qs": "^6.14.1", + "raw-body": "^3.0.1", + "type-is": "^2.0.1" } }, "bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" }, - "content-disposition": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", - "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", "requires": { - "safe-buffer": "5.1.2" + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" } }, - "content-type": { + "call-bound": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "requires": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + } + }, + "content-disposition": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.1.tgz", + "integrity": "sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q==" + }, + "content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==" }, "cookie": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", - "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==" + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==" }, "cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", + "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==" }, "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "requires": { - "ms": "2.0.0" + "ms": "^2.1.3" } }, "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" }, - "destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + "dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "requires": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + } }, "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==" + }, + "es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==" + }, + "es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==" + }, + "es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "requires": { + "es-errors": "^1.3.0" + } }, "escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" }, "etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==" }, "express": { - "version": "4.17.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", - "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz", + "integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==", "requires": { - "accepts": "~1.3.7", - "array-flatten": "1.1.1", - "body-parser": "1.19.0", - "content-disposition": "0.5.3", - "content-type": "~1.0.4", - "cookie": "0.4.0", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "~1.1.2", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "~1.1.2", - "fresh": "0.5.2", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.5", - "qs": "6.7.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.1.2", - "send": "0.17.1", - "serve-static": "1.14.1", - "setprototypeof": "1.1.1", - "statuses": "~1.5.0", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" + "accepts": "^2.0.0", + "body-parser": "^2.2.1", + "content-disposition": "^1.0.0", + "content-type": "^1.0.5", + "cookie": "^0.7.1", + "cookie-signature": "^1.2.1", + "debug": "^4.4.0", + "depd": "^2.0.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "finalhandler": "^2.1.0", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "merge-descriptors": "^2.0.0", + "mime-types": "^3.0.0", + "on-finished": "^2.4.1", + "once": "^1.4.0", + "parseurl": "^1.3.3", + "proxy-addr": "^2.0.7", + "qs": "^6.14.0", + "range-parser": "^1.2.1", + "router": "^2.2.0", + "send": "^1.1.0", + "serve-static": "^2.2.0", + "statuses": "^2.0.1", + "type-is": "^2.0.1", + "vary": "^1.1.2" } }, "finalhandler": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz", + "integrity": "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==", "requires": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "statuses": "~1.5.0", - "unpipe": "~1.0.0" + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "on-finished": "^2.4.1", + "parseurl": "^1.3.3", + "statuses": "^2.0.1" } }, "forwarded": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", - "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" }, "fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", + "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==" + }, + "function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==" + }, + "get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "requires": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + } + }, + "get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "requires": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + } + }, + "gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==" + }, + "has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==" + }, + "hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "requires": { + "function-bind": "^1.1.2" + } }, "http-errors": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", - "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", "requires": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" } }, "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz", + "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==", "requires": { - "safer-buffer": ">= 2.1.2 < 3" + "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "ipaddr.js": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.0.tgz", - "integrity": "sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA==" + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" }, - "media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" + "is-promise": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", + "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==" }, - "merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + "math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==" }, - "methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + "media-typer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", + "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==" }, - "mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" + "merge-descriptors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", + "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==" }, "mime-db": { - "version": "1.40.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz", - "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==" + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==" }, "mime-types": { - "version": "2.1.24", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz", - "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz", + "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==", "requires": { - "mime-db": "1.40.0" + "mime-db": "^1.54.0" } }, "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, "negotiator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", - "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", + "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==" + }, + "object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==" }, "on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", "requires": { "ee-first": "1.1.1" } }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "requires": { + "wrappy": "1" + } + }, "parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" }, "path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.3.0.tgz", + "integrity": "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==" }, "proxy-addr": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.5.tgz", - "integrity": "sha512-t/7RxHXPH6cJtP0pRG6smSr9QJidhB+3kXu0KgXnbGYMgzEnUxRQ4/LDdfOwZEMyIh3/xHb8PX3t+lfL9z+YVQ==", + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", "requires": { - "forwarded": "~0.1.2", - "ipaddr.js": "1.9.0" + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" } }, "qs": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.0.tgz", + "integrity": "sha512-mAZTtNCeetKMH+pSjrb76NAM8V9a05I9aBZOHztWy/UqcJdQYNsf59vrRKWnojAT9Y+GbIvoTBC++CPHqpDBhQ==", + "requires": { + "side-channel": "^1.1.0" + } }, "range-parser": { "version": "1.2.1", @@ -780,20 +1209,27 @@ "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" }, "raw-body": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", - "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.2.tgz", + "integrity": "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==", "requires": { - "bytes": "3.1.0", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.7.0", + "unpipe": "~1.0.0" } }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + "router": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", + "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", + "requires": { + "debug": "^4.4.0", + "depd": "^2.0.0", + "is-promise": "^4.0.0", + "parseurl": "^1.3.3", + "path-to-regexp": "^8.0.0" + } }, "safer-buffer": { "version": "2.1.2", @@ -801,89 +1237,123 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "send": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", - "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/send/-/send-1.2.1.tgz", + "integrity": "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==", "requires": { - "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "~1.7.2", - "mime": "1.6.0", - "ms": "2.1.1", - "on-finished": "~2.3.0", - "range-parser": "~1.2.1", - "statuses": "~1.5.0" - }, - "dependencies": { - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" - } + "debug": "^4.4.3", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "fresh": "^2.0.0", + "http-errors": "^2.0.1", + "mime-types": "^3.0.2", + "ms": "^2.1.3", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "statuses": "^2.0.2" } }, "serve-static": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", - "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.1.tgz", + "integrity": "sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==", "requires": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.17.1" + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "parseurl": "^1.3.3", + "send": "^1.2.0" } }, "setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "requires": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + } + }, + "side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "requires": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + } + }, + "side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "requires": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + } + }, + "side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "requires": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + } }, "statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==" }, "toidentifier": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" }, "type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", + "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", "requires": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" + "content-type": "^1.0.5", + "media-typer": "^1.1.0", + "mime-types": "^3.0.0" } }, "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" - }, - "utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==" }, "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, "ws": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.1.2.tgz", - "integrity": "sha512-gftXq3XI81cJCgkUiAVixA0raD9IVmXqsylCrjRygw4+UOOGzPoxnQ6r/CnVL9i+mDncJo94tSkyrtuuQVBmrg==", - "requires": { - "async-limiter": "^1.0.0" - } + "version": "8.19.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.19.0.tgz", + "integrity": "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==", + "requires": {} } } } diff --git a/NodeServer/package.json b/NodeServer/package.json index 16102b1..503eb4c 100644 --- a/NodeServer/package.json +++ b/NodeServer/package.json @@ -2,18 +2,16 @@ "name": "nodeserver", "version": "1.0.0", "description": "", + "type": "module", "main": "index.js", "scripts": { "start": "node index.js", "test": "echo \"Error: no test specified\" && exit 1" }, - "engines": { - "node": "12.x" - }, "author": "", "license": "ISC", "dependencies": { - "express": "^4.17.1", - "ws": "^7.1.2" + "express": "^5.1.0", + "ws": "^8.18.1" } } diff --git a/README.md b/README.md index f04440d..3793331 100644 --- a/README.md +++ b/README.md @@ -1,121 +1,262 @@ Native WebSocket -This is the simplest and easiest WebSocket library for Unity you can find! +A simple, dependency-free WebSocket client library for **Unity**, **MonoGame**, **Godot**, and any **.NET** project. - No external DLL's required (uses built-in `System.Net.WebSockets`) -- WebGL/HTML5 support +- WebGL/HTML5 support (Unity) - Supports all major build targets +- Automatic main-thread event dispatching via `SynchronizationContext` - Very simple API -- (Used in [Colyseus Unity SDK](https://github.com/colyseus/colyseus-unity-sdk)) -### Consider supporting my work on [Patreon](https://patreon.com/endel) | [Ko-fi](https://ko-fi.com/endeld) | [PayPal](https://www.paypal.me/endeld) +Used in [Colyseus Unity SDK](https://github.com/colyseus/colyseus-unity-sdk). -[![Support me on Patreon](https://img.shields.io/endpoint.svg?url=https%3A%2F%2Fshieldsio-patreon.vercel.app%2Fapi%3Fusername%3Dendel%26type%3Dpatrons&style=for-the-badge)](https://patreon.com/endel) +# Installation -## Installation +## Unity *Requires Unity 2019.1+ with .NET 4.x+ Runtime* -### Install via UPM (Unity Package Manager) +**Via UPM (Unity Package Manager):** 1. Open Unity 2. Open Package Manager Window 3. Click Add Package From Git URL -4. Enter URL: ```https://github.com/endel/NativeWebSocket.git#upm``` +4. Enter URL: `https://github.com/endel/NativeWebSocket.git#upm` -### Install manually +**Manually:** 1. [Download this project](https://github.com/endel/NativeWebSocket/archive/master.zip) 2. Copy the sources from `NativeWebSocket/Assets/WebSocket` into your `Assets` directory. -## Usage +## MonoGame / .NET + +Add a project reference to `src/NativeWebSocket/NativeWebSocket.csproj` and +`integrations/MonoGame/NativeWebSocket.MonoGame.csproj`: + +```bash +dotnet add reference path/to/NativeWebSocket.csproj +dotnet add reference path/to/NativeWebSocket.MonoGame.csproj +``` + +## Godot (C#) + +Add a project reference to `src/NativeWebSocket/NativeWebSocket.csproj` in your `.csproj`: + +```xml + + + +``` + +# Usage + +## Unity ```csharp -using System; -using System.Collections; -using System.Collections.Generic; using UnityEngine; - using NativeWebSocket; public class Connection : MonoBehaviour { - WebSocket websocket; - - // Start is called before the first frame update - async void Start() - { - websocket = new WebSocket("ws://localhost:3000"); + WebSocket websocket; - websocket.OnOpen += () => + async void Start() { - Debug.Log("Connection open!"); - }; + websocket = new WebSocket("ws://localhost:3000"); + + websocket.OnOpen += () => Debug.Log("Connection open!"); + websocket.OnError += (e) => Debug.Log("Error! " + e); + websocket.OnClose += (code) => Debug.Log("Connection closed!"); + + websocket.OnMessage += (bytes) => + { + var message = System.Text.Encoding.UTF8.GetString(bytes); + Debug.Log("Received: " + message); + }; - websocket.OnError += (e) => + InvokeRepeating("SendWebSocketMessage", 0.0f, 0.3f); + + await websocket.Connect(); + } + + async void SendWebSocketMessage() { - Debug.Log("Error! " + e); - }; + if (websocket.State == WebSocketState.Open) + { + await websocket.Send(new byte[] { 10, 20, 30 }); + await websocket.SendText("plain text message"); + } + } - websocket.OnClose += (e) => + private async void OnApplicationQuit() { - Debug.Log("Connection closed!"); - }; + await websocket.Close(); + } +} +``` + +## MonoGame + +Add the `WebSocketGameComponent` to your game. This installs a +`SynchronizationContext` so all WebSocket events fire on the game thread +automatically. + +```csharp +using System; +using System.Text; +using Microsoft.Xna.Framework; +using NativeWebSocket; +using NativeWebSocket.MonoGame; - websocket.OnMessage += (bytes) => +public class Game1 : Game +{ + private WebSocket _websocket; + + protected override void Initialize() { - Debug.Log("OnMessage!"); - Debug.Log(bytes); - - // getting the message as a string - // var message = System.Text.Encoding.UTF8.GetString(bytes); - // Debug.Log("OnMessage! " + message); - }; - - // Keep sending messages at every 0.3s - InvokeRepeating("SendWebSocketMessage", 0.0f, 0.3f); - - // waiting for messages - await websocket.Connect(); - } - - void Update() - { - #if !UNITY_WEBGL || UNITY_EDITOR - websocket.DispatchMessageQueue(); - #endif - } - - async void SendWebSocketMessage() - { - if (websocket.State == WebSocketState.Open) + Components.Add(new WebSocketGameComponent(this)); + base.Initialize(); + } + + protected override async void LoadContent() { - // Sending bytes - await websocket.Send(new byte[] { 10, 20, 30 }); + _websocket = new WebSocket("ws://localhost:3000"); + + _websocket.OnOpen += () => Console.WriteLine("Connected!"); + _websocket.OnError += (e) => Console.WriteLine("Error! " + e); + _websocket.OnClose += (code) => Console.WriteLine("Closed: " + code); - // Sending plain text - await websocket.SendText("plain text message"); + _websocket.OnMessage += (bytes) => + { + var message = Encoding.UTF8.GetString(bytes); + Console.WriteLine("Received: (" + bytes.Length + " bytes) " + message); + }; + + await _websocket.Connect(); + } + + protected override async void OnExiting(object sender, EventArgs args) + { + if (_websocket != null) + await _websocket.Close(); + base.OnExiting(sender, args); } - } +} +``` + +## Godot + +Godot Mono has a built-in `GodotSynchronizationContext`, so no special +integration is needed. All WebSocket events fire on the main thread +automatically. + +```csharp +using System.Text; +using Godot; +using NativeWebSocket; + +public partial class WebSocketExample : Node +{ + private WebSocket _websocket; - private async void OnApplicationQuit() - { - await websocket.Close(); - } + public override async void _Ready() + { + _websocket = new WebSocket("ws://localhost:3000"); + + _websocket.OnOpen += () => GD.Print("Connected!"); + _websocket.OnError += (e) => GD.Print("Error! " + e); + _websocket.OnClose += (code) => GD.Print("Closed: " + code); + + _websocket.OnMessage += (bytes) => + { + var message = Encoding.UTF8.GetString(bytes); + GD.Print("Received: (" + bytes.Length + " bytes) " + message); + }; + + await _websocket.Connect(); + } + public override void _ExitTree() + { + _websocket?.Close(); + } } ``` -# Demonstration +## Generic .NET (no SynchronizationContext) -**1.** Start the local WebSocket server: +If your environment doesn't have a `SynchronizationContext` (e.g. a console +app), call `DispatchMessageQueue()` from your main loop to process events: + +```csharp +var ws = new WebSocket("ws://localhost:3000"); +ws.OnMessage += (bytes) => Console.WriteLine("Received " + bytes.Length + " bytes"); +_ = ws.Connect(); +while (true) +{ + ws.DispatchMessageQueue(); + Thread.Sleep(16); +} ``` -cd Server + +# Examples + +Full runnable examples are in the [`examples/`](examples/) directory: + +| Engine | Path | How to run | +|--------|------|------------| +| **MonoGame** | [`examples/MonoGame/`](examples/MonoGame/) | `dotnet run --project examples/MonoGame/MonoGameExample.csproj` | +| **Godot** | [`examples/Godot/`](examples/Godot/) | Open in Godot Editor (4.x+ with C#), build, and press Play | +| **Unity** | [`examples/Unity/`](examples/Unity/) | Import NativeWebSocket via UPM, add `Connection.cs` to a GameObject | + +All examples connect to the included test server: + +```bash +cd NodeServer npm install -npm start +node index.js +``` + +The server listens on `ws://localhost:3000`, sends periodic text and binary +messages, and logs anything received from the client. + +# API + +## Constructor + +```csharp +new WebSocket(string url) +new WebSocket(string url, Dictionary headers) +new WebSocket(string url, string subprotocol) +new WebSocket(string url, List subprotocols) ``` -**2.** Open the `NativeWebSocket/Assets/WebSocketExample/WebSocketExampleScene.unity` on Unity and Run. +## Events + +| Event | Signature | Description | +|-------|-----------|-------------| +| `OnOpen` | `()` | Connection established | +| `OnMessage` | `(byte[] data)` | Message received (text or binary) | +| `OnError` | `(string errorMsg)` | Error occurred | +| `OnClose` | `(WebSocketCloseCode code)` | Connection closed | + +## Methods + +| Method | Description | +|--------|-------------| +| `Connect()` | Connect to the server (async) | +| `Close(code, reason)` | Gracefully close the connection (async) | +| `Send(byte[])` | Send binary data (async) | +| `SendText(string)` | Send text data (async) | +| `CancelConnection()` | Cancel a pending connection attempt | +| `DispatchMessageQueue()` | Manually dispatch queued events (only needed without a `SynchronizationContext`) | + +## Properties + +| Property | Type | Description | +|----------|------|-------------| +| `State` | `WebSocketState` | `Connecting`, `Open`, `Closing`, or `Closed` | +--- ## Acknowledgements diff --git a/examples/Godot/GodotExample.csproj.old b/examples/Godot/GodotExample.csproj.old new file mode 100644 index 0000000..f4c8121 --- /dev/null +++ b/examples/Godot/GodotExample.csproj.old @@ -0,0 +1,10 @@ + + + net6.0 + true + + + + + + diff --git a/examples/Godot/Main.tscn b/examples/Godot/Main.tscn new file mode 100644 index 0000000..2ab1e8b --- /dev/null +++ b/examples/Godot/Main.tscn @@ -0,0 +1,6 @@ +[gd_scene load_steps=2 format=3] + +[ext_resource type="Script" path="res://WebSocketExample.cs" id="1"] + +[node name="Main" type="Node"] +script = ExtResource("1") diff --git a/examples/Godot/WebSocketExample.cs b/examples/Godot/WebSocketExample.cs new file mode 100644 index 0000000..5e003bf --- /dev/null +++ b/examples/Godot/WebSocketExample.cs @@ -0,0 +1,65 @@ +using System.Text; +using Godot; +using NativeWebSocket; + +/// +/// Godot has a built-in GodotSynchronizationContext, so all WebSocket +/// events (OnOpen, OnMessage, OnError, OnClose) automatically fire on the main thread. +/// No special integration or DispatchMessageQueue() call is needed. +/// +public partial class WebSocketExample : Node +{ + private WebSocket _websocket; + private double _sendTimer; + + public override async void _Ready() + { + _websocket = new WebSocket("ws://localhost:3000"); + + _websocket.OnOpen += () => + { + GD.Print("Connection open!"); + }; + + _websocket.OnError += (e) => + { + GD.Print("Error! " + e); + }; + + _websocket.OnClose += (code) => + { + GD.Print("Connection closed! Code: " + code); + }; + + _websocket.OnMessage += (bytes) => + { + var message = Encoding.UTF8.GetString(bytes); + GD.Print("Received OnMessage! (" + bytes.Length + " bytes) " + message); + }; + + await _websocket.Connect(); + } + + public override async void _Process(double delta) + { + if (_websocket?.State == WebSocketState.Open) + { + _sendTimer += delta; + if (_sendTimer >= 0.3) + { + _sendTimer = 0; + + // Send binary data + await _websocket.Send(new byte[] { 10, 20, 30 }); + + // Send text data + await _websocket.SendText("hello from Godot!"); + } + } + } + + public override void _ExitTree() + { + _websocket?.Close(); + } +} diff --git a/examples/Godot/WebSocketExample.cs.uid b/examples/Godot/WebSocketExample.cs.uid new file mode 100644 index 0000000..bce9565 --- /dev/null +++ b/examples/Godot/WebSocketExample.cs.uid @@ -0,0 +1 @@ +uid://by13uhwlsa07w diff --git a/examples/Godot/project.godot b/examples/Godot/project.godot new file mode 100644 index 0000000..41c5f31 --- /dev/null +++ b/examples/Godot/project.godot @@ -0,0 +1,23 @@ +; Engine configuration file. +; It's best edited using the editor UI and not directly, +; since the parameters that go here are not all obvious. +; +; Format: +; [section] ; section goes between [] +; param=value ; assign values to parameters + +config_version=5 + +[animation] + +compatibility/default_parent_skeleton_in_mesh_instance_3d=true + +[application] + +config/name="NativeWebSocket Example" +run/main_scene="res://Main.tscn" +config/features=PackedStringArray("4.6", "C#") + +[dotnet] + +project/assembly_name="GodotExample" diff --git a/examples/MonoGame/Game1.cs b/examples/MonoGame/Game1.cs new file mode 100644 index 0000000..e6f934d --- /dev/null +++ b/examples/MonoGame/Game1.cs @@ -0,0 +1,92 @@ +using System; +using System.Text; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Input; +using NativeWebSocket; +using NativeWebSocket.MonoGame; + +namespace MonoGameExample +{ + public class Game1 : Game + { + private GraphicsDeviceManager _graphics; + private WebSocket _websocket; + private float _sendTimer; + + public Game1() + { + _graphics = new GraphicsDeviceManager(this); + IsMouseVisible = true; + } + + protected override void Initialize() + { + // Install the WebSocket game component. + // This sets up a SynchronizationContext so all WebSocket events + // fire on the game thread automatically. + Components.Add(new WebSocketGameComponent(this)); + base.Initialize(); + } + + protected override async void LoadContent() + { + _websocket = new WebSocket("ws://localhost:3000"); + + _websocket.OnOpen += () => + { + Console.WriteLine("Connection open!"); + }; + + _websocket.OnError += (e) => + { + Console.WriteLine("Error! " + e); + }; + + _websocket.OnClose += (code) => + { + Console.WriteLine("Connection closed! Code: " + code); + }; + + _websocket.OnMessage += (bytes) => + { + var message = Encoding.UTF8.GetString(bytes); + Console.WriteLine("Received OnMessage! (" + bytes.Length + " bytes) " + message); + }; + + await _websocket.Connect(); + } + + protected override async void Update(GameTime gameTime) + { + if (Keyboard.GetState().IsKeyDown(Keys.Escape)) + Exit(); + + // Send a message every 0.3 seconds + if (_websocket?.State == WebSocketState.Open) + { + _sendTimer += (float)gameTime.ElapsedGameTime.TotalSeconds; + if (_sendTimer >= 0.3f) + { + _sendTimer = 0; + + // Send binary data + await _websocket.Send(new byte[] { 10, 20, 30 }); + + // Send text data + await _websocket.SendText("hello from MonoGame!"); + } + } + + base.Update(gameTime); + } + + protected override async void OnExiting(object sender, EventArgs args) + { + if (_websocket != null) + { + await _websocket.Close(); + } + base.OnExiting(sender, args); + } + } +} diff --git a/examples/MonoGame/Program.cs b/examples/MonoGame/Program.cs new file mode 100644 index 0000000..877116b --- /dev/null +++ b/examples/MonoGame/Program.cs @@ -0,0 +1,2 @@ +using var game = new MonoGameExample.Game1(); +game.Run(); diff --git a/examples/Unity/Connection.cs b/examples/Unity/Connection.cs new file mode 100644 index 0000000..8da3f40 --- /dev/null +++ b/examples/Unity/Connection.cs @@ -0,0 +1,73 @@ +using System.Text; +using UnityEngine; +using NativeWebSocket; + +/// +/// Unity example — attach this script to a GameObject in your scene. +/// +/// Setup: +/// 1. Import NativeWebSocket via UPM: +/// Window > Package Manager > "+" > Add package from git URL: +/// https://github.com/endel/NativeWebSocket.git#upm +/// +/// 2. Create an empty GameObject and attach this script. +/// +/// 3. Start the test server: cd NodeServer && npm install && node index.js +/// +/// 4. Press Play. +/// +/// Unity's UnitySynchronizationContext handles event dispatching automatically, +/// so no DispatchMessageQueue() call is needed in Update(). +/// +public class Connection : MonoBehaviour +{ + WebSocket websocket; + + async void Start() + { + websocket = new WebSocket("ws://localhost:3000"); + + websocket.OnOpen += () => + { + Debug.Log("Connection open!"); + }; + + websocket.OnError += (e) => + { + Debug.Log("Error! " + e); + }; + + websocket.OnClose += (code) => + { + Debug.Log("Connection closed! Code: " + code); + }; + + websocket.OnMessage += (bytes) => + { + var message = Encoding.UTF8.GetString(bytes); + Debug.Log("Received OnMessage! (" + bytes.Length + " bytes) " + message); + }; + + // Send messages every 0.3 seconds + InvokeRepeating("SendWebSocketMessage", 0.0f, 0.3f); + + await websocket.Connect(); + } + + async void SendWebSocketMessage() + { + if (websocket.State == WebSocketState.Open) + { + // Send binary data + await websocket.Send(new byte[] { 10, 20, 30 }); + + // Send text data + await websocket.SendText("hello from Unity!"); + } + } + + private async void OnApplicationQuit() + { + await websocket.Close(); + } +} diff --git a/integrations/Godot/Example.cs b/integrations/Godot/Example.cs new file mode 100644 index 0000000..605aa44 --- /dev/null +++ b/integrations/Godot/Example.cs @@ -0,0 +1,45 @@ +using Godot; +using NativeWebSocket; + +/// +/// Godot example - no special integration needed. +/// Godot Mono has a built-in GodotSynchronizationContext, so all WebSocket +/// events (OnOpen, OnMessage, OnError, OnClose) automatically fire on the main thread. +/// +public partial class WebSocketExample : Node +{ + private WebSocket _websocket; + + public override async void _Ready() + { + _websocket = new WebSocket("ws://localhost:3000"); + + _websocket.OnOpen += () => + { + GD.Print("Connection open!"); + }; + + _websocket.OnError += (e) => + { + GD.Print("Error! " + e); + }; + + _websocket.OnClose += (e) => + { + GD.Print("Connection closed!"); + }; + + _websocket.OnMessage += (bytes) => + { + var message = System.Text.Encoding.UTF8.GetString(bytes); + GD.Print("Received OnMessage! (" + bytes.Length + " bytes) " + message); + }; + + await _websocket.Connect(); + } + + public override void _ExitTree() + { + _websocket?.Close(); + } +} diff --git a/integrations/MonoGame/NativeWebSocket.MonoGame.csproj b/integrations/MonoGame/NativeWebSocket.MonoGame.csproj new file mode 100644 index 0000000..5c49614 --- /dev/null +++ b/integrations/MonoGame/NativeWebSocket.MonoGame.csproj @@ -0,0 +1,21 @@ + + + net6.0 + NativeWebSocket.MonoGame + NativeWebSocket.MonoGame + 2.0.0 + Endel Dreyer + MonoGame integration for NativeWebSocket - provides a GameComponent that enables automatic main-thread event dispatching. + NativeWebSocket.MonoGame + MIT + https://github.com/endel/NativeWebSocket + + + + + + + + + + diff --git a/integrations/MonoGame/WebSocketGameComponent.cs b/integrations/MonoGame/WebSocketGameComponent.cs new file mode 100644 index 0000000..6b84c19 --- /dev/null +++ b/integrations/MonoGame/WebSocketGameComponent.cs @@ -0,0 +1,61 @@ +using System; +using System.Collections.Concurrent; +using System.Threading; +using Microsoft.Xna.Framework; + +namespace NativeWebSocket.MonoGame +{ + /// + /// A SynchronizationContext that queues callbacks to be executed on the game thread. + /// + public class SingleThreadSynchronizationContext : SynchronizationContext + { + private readonly ConcurrentQueue _queue = new ConcurrentQueue(); + + public override void Post(SendOrPostCallback d, object state) + { + _queue.Enqueue(() => d(state)); + } + + public override void Send(SendOrPostCallback d, object state) + { + // Queue for execution on the game thread (same as Post for single-threaded pump) + _queue.Enqueue(() => d(state)); + } + + public void ProcessQueue() + { + while (_queue.TryDequeue(out var action)) + { + action(); + } + } + } + + /// + /// GameComponent that installs a SynchronizationContext on the game thread + /// and pumps queued callbacks each frame. + /// + /// Usage: + /// Components.Add(new WebSocketGameComponent(this)); + /// + /// After this, all NativeWebSocket events (OnOpen, OnMessage, OnError, OnClose) + /// will automatically fire on the game thread. + /// + public class WebSocketGameComponent : GameComponent + { + private readonly SingleThreadSynchronizationContext _syncContext; + + public WebSocketGameComponent(Game game) : base(game) + { + _syncContext = new SingleThreadSynchronizationContext(); + SynchronizationContext.SetSynchronizationContext(_syncContext); + } + + public override void Update(GameTime gameTime) + { + _syncContext.ProcessQueue(); + base.Update(gameTime); + } + } +} diff --git a/integrations/Unity/Samples~/WebSocketExample/Connection.cs b/integrations/Unity/Samples~/WebSocketExample/Connection.cs new file mode 100644 index 0000000..524feab --- /dev/null +++ b/integrations/Unity/Samples~/WebSocketExample/Connection.cs @@ -0,0 +1,61 @@ +using System; +using UnityEngine; + +using NativeWebSocket; + +public class Connection : MonoBehaviour +{ + WebSocket websocket; + + // Start is called before the first frame update + async void Start() + { + websocket = new WebSocket("ws://localhost:3000"); + + websocket.OnOpen += () => + { + Debug.Log("Connection open!"); + }; + + websocket.OnError += (e) => + { + Debug.Log("Error! " + e); + }; + + websocket.OnClose += (e) => + { + Debug.Log("Connection closed!"); + }; + + websocket.OnMessage += (bytes) => + { + // Reading a plain text message + var message = System.Text.Encoding.UTF8.GetString(bytes); + Debug.Log("Received OnMessage! (" + bytes.Length + " bytes) " + message); + }; + + // Keep sending messages at every 0.3s + InvokeRepeating("SendWebSocketMessage", 0.0f, 0.3f); + + // No DispatchMessageQueue() needed in Update()! + // Unity's SynchronizationContext handles event dispatching automatically. + await websocket.Connect(); + } + + async void SendWebSocketMessage() + { + if (websocket.State == WebSocketState.Open) + { + // Sending bytes + await websocket.Send(new byte[] { 10, 20, 30 }); + + // Sending plain text + await websocket.SendText("plain text message"); + } + } + + private async void OnApplicationQuit() + { + await websocket.Close(); + } +} diff --git a/integrations/Unity/WebSocket.cs b/integrations/Unity/WebSocket.cs new file mode 100644 index 0000000..6d284b8 --- /dev/null +++ b/integrations/Unity/WebSocket.cs @@ -0,0 +1,357 @@ +#if !UNITY_WEBGL || UNITY_EDITOR + +using System; +using System.Collections.Generic; +using System.IO; +using System.Net.WebSockets; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace NativeWebSocket +{ + public class WebSocket : IWebSocket + { + public event WebSocketOpenEventHandler OnOpen; + public event WebSocketMessageEventHandler OnMessage; + public event WebSocketErrorEventHandler OnError; + public event WebSocketCloseEventHandler OnClose; + + private Uri uri; + private Dictionary headers; + private List subprotocols; + private ClientWebSocket m_Socket = new ClientWebSocket(); + + private CancellationTokenSource m_TokenSource; + private CancellationToken m_CancellationToken; + + private readonly SynchronizationContext _syncContext; + private List m_EventQueue = new List(); + private List m_DispatchQueue = new List(); + private readonly object EventQueueLock = new object(); + + private readonly object OutgoingMessageLock = new object(); + private readonly object SocketLock = new object(); + private bool isSending = false; + private Queue> sendBytesQueue = new Queue>(); + private Queue> sendTextQueue = new Queue>(); + + public WebSocket(string url, Dictionary headers = null) + { + uri = new Uri(url); + _syncContext = SynchronizationContext.Current; + this.headers = headers ?? new Dictionary(); + subprotocols = new List(); + + string protocol = uri.Scheme; + if (!protocol.Equals("ws") && !protocol.Equals("wss")) + throw new ArgumentException("Unsupported protocol: " + protocol); + } + + public WebSocket(string url, string subprotocol, Dictionary headers = null) + { + uri = new Uri(url); + _syncContext = SynchronizationContext.Current; + this.headers = headers ?? new Dictionary(); + subprotocols = new List { subprotocol }; + + string protocol = uri.Scheme; + if (!protocol.Equals("ws") && !protocol.Equals("wss")) + throw new ArgumentException("Unsupported protocol: " + protocol); + } + + public WebSocket(string url, List subprotocols, Dictionary headers = null) + { + uri = new Uri(url); + _syncContext = SynchronizationContext.Current; + this.headers = headers ?? new Dictionary(); + this.subprotocols = subprotocols; + + string protocol = uri.Scheme; + if (!protocol.Equals("ws") && !protocol.Equals("wss")) + throw new ArgumentException("Unsupported protocol: " + protocol); + } + + private void EnqueueEvent(Action action) + { + if (_syncContext != null) + { + _syncContext.Post(_ => action(), null); + } + else + { + lock (EventQueueLock) + { + m_EventQueue.Add(action); + } + } + } + + /// + /// Dispatches queued events when no SynchronizationContext is available. + /// Not needed in Unity — UnitySynchronizationContext handles dispatch automatically. + /// Kept for backward compatibility. + /// + public void DispatchMessageQueue() + { + if (m_EventQueue.Count == 0) return; + + lock (EventQueueLock) + { + var tmp = m_DispatchQueue; + m_DispatchQueue = m_EventQueue; + m_EventQueue = tmp; + } + + foreach (var action in m_DispatchQueue) + { + action(); + } + + m_DispatchQueue.Clear(); + } + + public void CancelConnection() + { + m_TokenSource?.Cancel(); + } + + public async Task Connect() + { + try + { + m_TokenSource = new CancellationTokenSource(); + m_CancellationToken = m_TokenSource.Token; + + m_Socket = new ClientWebSocket(); + + foreach (var header in headers) + { + m_Socket.Options.SetRequestHeader(header.Key, header.Value); + } + + foreach (string subprotocol in subprotocols) + { + m_Socket.Options.AddSubProtocol(subprotocol); + } + + await m_Socket.ConnectAsync(uri, m_CancellationToken).ConfigureAwait(false); + + EnqueueEvent(() => OnOpen?.Invoke()); + + await Receive().ConfigureAwait(false); + } + catch (Exception ex) + { + EnqueueEvent(() => OnError?.Invoke(ex.Message)); + EnqueueEvent(() => OnClose?.Invoke(WebSocketCloseCode.Abnormal)); + } + finally + { + if (m_Socket != null) + { + m_TokenSource.Cancel(); + m_Socket.Dispose(); + } + } + } + + public WebSocketState State + { + get + { + switch (m_Socket.State) + { + case System.Net.WebSockets.WebSocketState.Connecting: + return WebSocketState.Connecting; + + case System.Net.WebSockets.WebSocketState.Open: + return WebSocketState.Open; + + case System.Net.WebSockets.WebSocketState.CloseSent: + case System.Net.WebSockets.WebSocketState.CloseReceived: + return WebSocketState.Closing; + + case System.Net.WebSockets.WebSocketState.Closed: + return WebSocketState.Closed; + + default: + return WebSocketState.Closed; + } + } + } + + public Task Send(byte[] bytes) + { + return SendMessage(sendBytesQueue, WebSocketMessageType.Binary, new ArraySegment(bytes)); + } + + public Task SendText(string message) + { + var encoded = Encoding.UTF8.GetBytes(message); + return SendMessage(sendTextQueue, WebSocketMessageType.Text, new ArraySegment(encoded, 0, encoded.Length)); + } + + private async Task SendMessage(Queue> queue, WebSocketMessageType messageType, ArraySegment buffer) + { + if (buffer.Count == 0) + { + return; + } + + bool sending; + + lock (OutgoingMessageLock) + { + sending = isSending; + + if (!isSending) + { + isSending = true; + } + } + + if (!sending) + { + try + { + if (!Monitor.TryEnter(SocketLock, 1000)) + { + await m_Socket.CloseAsync(WebSocketCloseStatus.InternalServerError, string.Empty, m_CancellationToken).ConfigureAwait(false); + return; + } + + try + { + await m_Socket.SendAsync(buffer, messageType, true, m_CancellationToken).ConfigureAwait(false); + } + finally + { + Monitor.Exit(SocketLock); + } + + // Drain the queue iteratively instead of recursively + while (true) + { + ArraySegment next; + lock (OutgoingMessageLock) + { + if (queue.Count == 0) + break; + next = queue.Dequeue(); + } + + if (!Monitor.TryEnter(SocketLock, 1000)) + { + await m_Socket.CloseAsync(WebSocketCloseStatus.InternalServerError, string.Empty, m_CancellationToken).ConfigureAwait(false); + return; + } + + try + { + await m_Socket.SendAsync(next, messageType, true, m_CancellationToken).ConfigureAwait(false); + } + finally + { + Monitor.Exit(SocketLock); + } + } + } + finally + { + lock (OutgoingMessageLock) + { + isSending = false; + } + } + } + else + { + lock (OutgoingMessageLock) + { + queue.Enqueue(buffer); + } + } + } + + public async Task Receive() + { + WebSocketCloseCode closeCode = WebSocketCloseCode.Abnormal; + ArraySegment buffer = new ArraySegment(new byte[8192]); + try + { + while (m_Socket.State == System.Net.WebSockets.WebSocketState.Open) + { + var result = await m_Socket.ReceiveAsync(buffer, m_CancellationToken).ConfigureAwait(false); + + if (result.MessageType == WebSocketMessageType.Close) + { + await Close().ConfigureAwait(false); + closeCode = WebSocketHelpers.ParseCloseCodeEnum((int)result.CloseStatus); + break; + } + + if (result.EndOfMessage) + { + // Fast path: single-frame message, avoid MemoryStream + var data = new byte[result.Count]; + Buffer.BlockCopy(buffer.Array, buffer.Offset, data, 0, result.Count); + EnqueueEvent(() => OnMessage?.Invoke(data)); + } + else + { + // Multi-frame message: accumulate in MemoryStream + using (var ms = new MemoryStream()) + { + ms.Write(buffer.Array, buffer.Offset, result.Count); + + do + { + result = await m_Socket.ReceiveAsync(buffer, m_CancellationToken).ConfigureAwait(false); + ms.Write(buffer.Array, buffer.Offset, result.Count); + } + while (!result.EndOfMessage); + + var data = ms.ToArray(); + EnqueueEvent(() => OnMessage?.Invoke(data)); + } + } + } + } + catch (Exception) + { + m_TokenSource.Cancel(); + } + finally + { + EnqueueEvent(() => OnClose?.Invoke(closeCode)); + } + } + + public async Task Close(WebSocketCloseCode code = WebSocketCloseCode.Normal, string reason = null) + { + if (State == WebSocketState.Open) + { + await m_Socket.CloseAsync((WebSocketCloseStatus)(int)code, reason ?? string.Empty, m_CancellationToken).ConfigureAwait(false); + } + } + } + + /// + /// Factory for creating WebSocket instances. + /// + public static class WebSocketFactory + { + /// + /// Create WebSocket client instance + /// + /// The WebSocket instance. + /// WebSocket valid URL. + public static WebSocket CreateInstance(string url) + { + return new WebSocket(url); + } + } +} + +#endif diff --git a/NativeWebSocket/Assets/WebSocket/WebSocket.jslib b/integrations/Unity/WebSocket.jslib similarity index 100% rename from NativeWebSocket/Assets/WebSocket/WebSocket.jslib rename to integrations/Unity/WebSocket.jslib diff --git a/NativeWebSocket/Assets/WebSocket/WebSocket.jspre b/integrations/Unity/WebSocket.jspre similarity index 100% rename from NativeWebSocket/Assets/WebSocket/WebSocket.jspre rename to integrations/Unity/WebSocket.jspre diff --git a/integrations/Unity/WebSocketFactoryWebGL.cs b/integrations/Unity/WebSocketFactoryWebGL.cs new file mode 100644 index 0000000..c6ab811 --- /dev/null +++ b/integrations/Unity/WebSocketFactoryWebGL.cs @@ -0,0 +1,133 @@ +#if UNITY_WEBGL && !UNITY_EDITOR + +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using AOT; + +namespace NativeWebSocket +{ + /// + /// Class providing static access methods to work with JSLIB WebSocket interface. + /// + public static class WebSocketFactory + { + /* Map of websocket instances */ + public static Dictionary instances = new Dictionary(); + + /* Delegates */ + public delegate void OnOpenCallback(int instanceId); + public delegate void OnMessageCallback(int instanceId, System.IntPtr msgPtr, int msgSize); + public delegate void OnErrorCallback(int instanceId, System.IntPtr errorPtr); + public delegate void OnCloseCallback(int instanceId, int closeCode); + + /* WebSocket JSLIB callback setters and other functions */ + [DllImport("__Internal")] + public static extern int WebSocketAllocate(string url); + + [DllImport("__Internal")] + public static extern int WebSocketAddSubProtocol(int instanceId, string subprotocol); + + [DllImport("__Internal")] + public static extern void WebSocketFree(int instanceId); + + [DllImport("__Internal")] + public static extern void WebSocketSetOnOpen(OnOpenCallback callback); + + [DllImport("__Internal")] + public static extern void WebSocketSetOnMessage(OnMessageCallback callback); + + [DllImport("__Internal")] + public static extern void WebSocketSetOnError(OnErrorCallback callback); + + [DllImport("__Internal")] + public static extern void WebSocketSetOnClose(OnCloseCallback callback); + + /* If callbacks was initialized and set */ + public static bool isInitialized = false; + + /* + * Initialize WebSocket callbacks to JSLIB + */ + public static void Initialize() + { + WebSocketSetOnOpen(DelegateOnOpenEvent); + WebSocketSetOnMessage(DelegateOnMessageEvent); + WebSocketSetOnError(DelegateOnErrorEvent); + WebSocketSetOnClose(DelegateOnCloseEvent); + + isInitialized = true; + } + + /// + /// Called when instance is destroyed (by destructor) + /// Method removes instance from map and free it in JSLIB implementation + /// + /// Instance identifier. + public static void HandleInstanceDestroy(int instanceId) + { + instances.Remove(instanceId); + WebSocketFree(instanceId); + } + + [MonoPInvokeCallback(typeof(OnOpenCallback))] + public static void DelegateOnOpenEvent(int instanceId) + { + WebSocket instanceRef; + + if (instances.TryGetValue(instanceId, out instanceRef)) + { + instanceRef.DelegateOnOpenEvent(); + } + } + + [MonoPInvokeCallback(typeof(OnMessageCallback))] + public static void DelegateOnMessageEvent(int instanceId, System.IntPtr msgPtr, int msgSize) + { + WebSocket instanceRef; + + if (instances.TryGetValue(instanceId, out instanceRef)) + { + byte[] msg = new byte[msgSize]; + Marshal.Copy(msgPtr, msg, 0, msgSize); + + instanceRef.DelegateOnMessageEvent(msg); + } + } + + [MonoPInvokeCallback(typeof(OnErrorCallback))] + public static void DelegateOnErrorEvent(int instanceId, System.IntPtr errorPtr) + { + WebSocket instanceRef; + + if (instances.TryGetValue(instanceId, out instanceRef)) + { + string errorMsg = Marshal.PtrToStringAuto(errorPtr); + instanceRef.DelegateOnErrorEvent(errorMsg); + } + } + + [MonoPInvokeCallback(typeof(OnCloseCallback))] + public static void DelegateOnCloseEvent(int instanceId, int closeCode) + { + WebSocket instanceRef; + + if (instances.TryGetValue(instanceId, out instanceRef)) + { + instanceRef.DelegateOnCloseEvent(closeCode); + } + } + + /// + /// Create WebSocket client instance + /// + /// The WebSocket instance. + /// WebSocket valid URL. + public static WebSocket CreateInstance(string url) + { + return new WebSocket(url); + } + } +} + +#endif diff --git a/integrations/Unity/WebSocketWebGL.cs b/integrations/Unity/WebSocketWebGL.cs new file mode 100644 index 0000000..4033501 --- /dev/null +++ b/integrations/Unity/WebSocketWebGL.cs @@ -0,0 +1,191 @@ +#if UNITY_WEBGL && !UNITY_EDITOR + +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Threading.Tasks; + +namespace NativeWebSocket +{ + /// + /// WebSocket class bound to JSLIB. + /// + public class WebSocket : IWebSocket + { + /* WebSocket JSLIB functions */ + [DllImport("__Internal")] + public static extern int WebSocketConnect(int instanceId); + + [DllImport("__Internal")] + public static extern int WebSocketClose(int instanceId, int code, string reason); + + [DllImport("__Internal")] + public static extern int WebSocketSend(int instanceId, byte[] dataPtr, int dataLength); + + [DllImport("__Internal")] + public static extern int WebSocketSendText(int instanceId, string message); + + [DllImport("__Internal")] + public static extern int WebSocketGetState(int instanceId); + + protected int instanceId; + + public event WebSocketOpenEventHandler OnOpen; + public event WebSocketMessageEventHandler OnMessage; + public event WebSocketErrorEventHandler OnError; + public event WebSocketCloseEventHandler OnClose; + + public WebSocket(string url, Dictionary headers = null) + { + if (!WebSocketFactory.isInitialized) + { + WebSocketFactory.Initialize(); + } + + int instanceId = WebSocketFactory.WebSocketAllocate(url); + WebSocketFactory.instances.Add(instanceId, this); + + this.instanceId = instanceId; + } + + public WebSocket(string url, string subprotocol, Dictionary headers = null) + { + if (!WebSocketFactory.isInitialized) + { + WebSocketFactory.Initialize(); + } + + int instanceId = WebSocketFactory.WebSocketAllocate(url); + WebSocketFactory.instances.Add(instanceId, this); + + WebSocketFactory.WebSocketAddSubProtocol(instanceId, subprotocol); + + this.instanceId = instanceId; + } + + public WebSocket(string url, List subprotocols, Dictionary headers = null) + { + if (!WebSocketFactory.isInitialized) + { + WebSocketFactory.Initialize(); + } + + int instanceId = WebSocketFactory.WebSocketAllocate(url); + WebSocketFactory.instances.Add(instanceId, this); + + foreach (string subprotocol in subprotocols) + { + WebSocketFactory.WebSocketAddSubProtocol(instanceId, subprotocol); + } + + this.instanceId = instanceId; + } + + ~WebSocket() + { + WebSocketFactory.HandleInstanceDestroy(this.instanceId); + } + + public int GetInstanceId() + { + return this.instanceId; + } + + public Task Connect() + { + int ret = WebSocketConnect(this.instanceId); + + if (ret < 0) + throw WebSocketHelpers.GetErrorMessageFromCode(ret, null); + + return Task.CompletedTask; + } + + public void CancelConnection() + { + if (State == WebSocketState.Open) + Close(WebSocketCloseCode.Abnormal); + } + + public Task Close(WebSocketCloseCode code = WebSocketCloseCode.Normal, string reason = null) + { + int ret = WebSocketClose(this.instanceId, (int)code, reason); + + if (ret < 0) + throw WebSocketHelpers.GetErrorMessageFromCode(ret, null); + + return Task.CompletedTask; + } + + public Task Send(byte[] data) + { + int ret = WebSocketSend(this.instanceId, data, data.Length); + + if (ret < 0) + throw WebSocketHelpers.GetErrorMessageFromCode(ret, null); + + return Task.CompletedTask; + } + + public Task SendText(string message) + { + int ret = WebSocketSendText(this.instanceId, message); + + if (ret < 0) + throw WebSocketHelpers.GetErrorMessageFromCode(ret, null); + + return Task.CompletedTask; + } + + public WebSocketState State + { + get + { + int state = WebSocketGetState(this.instanceId); + + if (state < 0) + throw WebSocketHelpers.GetErrorMessageFromCode(state, null); + + switch (state) + { + case 0: + return WebSocketState.Connecting; + + case 1: + return WebSocketState.Open; + + case 2: + return WebSocketState.Closing; + + case 3: + return WebSocketState.Closed; + + default: + return WebSocketState.Closed; + } + } + } + + public void DelegateOnOpenEvent() + { + this.OnOpen?.Invoke(); + } + + public void DelegateOnMessageEvent(byte[] data) + { + this.OnMessage?.Invoke(data); + } + + public void DelegateOnErrorEvent(string errorMsg) + { + this.OnError?.Invoke(errorMsg); + } + + public void DelegateOnCloseEvent(int closeCode) + { + this.OnClose?.Invoke(WebSocketHelpers.ParseCloseCodeEnum(closeCode)); + } + } +} + +#endif diff --git a/NativeWebSocket/Assets/WebSocket/endel.nativewebsocket.asmdef b/integrations/Unity/endel.nativewebsocket.asmdef similarity index 81% rename from NativeWebSocket/Assets/WebSocket/endel.nativewebsocket.asmdef rename to integrations/Unity/endel.nativewebsocket.asmdef index 9d477f8..b8b3f57 100644 --- a/NativeWebSocket/Assets/WebSocket/endel.nativewebsocket.asmdef +++ b/integrations/Unity/endel.nativewebsocket.asmdef @@ -1,3 +1,3 @@ -{ - "name": "endel.nativewebsocket" -} +{ + "name": "endel.nativewebsocket" +} diff --git a/NativeWebSocket/Assets/package.json b/integrations/Unity/package.json similarity index 78% rename from NativeWebSocket/Assets/package.json rename to integrations/Unity/package.json index ca878de..b23f0bd 100644 --- a/NativeWebSocket/Assets/package.json +++ b/integrations/Unity/package.json @@ -1,8 +1,8 @@ { "name": "com.endel.nativewebsocket", - "version": "1.1.6", - "description": "WebSocket client for Unity - with no external dependencies (WebGL, Native, Android, iOS, UWP).", - "license": "Apache 2.0", + "version": "2.0.0", + "description": "WebSocket client for Unity - with no external dependencies (WebGL, Native, Android, iOS, UWP). Events auto-dispatch to the main thread via SynchronizationContext.", + "license": "MIT", "repository": { "type": "git", "url": "https://github.com/endel/NativeWebSocket.git" @@ -22,9 +22,10 @@ "unity": "2019.1", "dependencies": {}, "samples": [ - { + { "displayName": "Example", "description": "WebSocket Example", "path": "Samples~/WebSocketExample" - } ] + } + ] } diff --git a/src/NativeWebSocket/IWebSocket.cs b/src/NativeWebSocket/IWebSocket.cs new file mode 100644 index 0000000..30f587e --- /dev/null +++ b/src/NativeWebSocket/IWebSocket.cs @@ -0,0 +1,51 @@ +using System.Threading.Tasks; + +namespace NativeWebSocket +{ + public delegate void WebSocketOpenEventHandler(); + public delegate void WebSocketMessageEventHandler(byte[] data); + public delegate void WebSocketErrorEventHandler(string errorMsg); + public delegate void WebSocketCloseEventHandler(WebSocketCloseCode closeCode); + + public enum WebSocketCloseCode + { + /* Do NOT use NotSet - it's only purpose is to indicate that the close code cannot be parsed. */ + NotSet = 0, + Normal = 1000, + Away = 1001, + ProtocolError = 1002, + UnsupportedData = 1003, + Undefined = 1004, + NoStatus = 1005, + Abnormal = 1006, + InvalidData = 1007, + PolicyViolation = 1008, + TooBig = 1009, + MandatoryExtension = 1010, + ServerError = 1011, + TlsHandshakeFailure = 1015 + } + + public enum WebSocketState + { + Connecting, + Open, + Closing, + Closed + } + + public interface IWebSocket + { + event WebSocketOpenEventHandler OnOpen; + event WebSocketMessageEventHandler OnMessage; + event WebSocketErrorEventHandler OnError; + event WebSocketCloseEventHandler OnClose; + + WebSocketState State { get; } + + Task Connect(); + Task Close(WebSocketCloseCode code = WebSocketCloseCode.Normal, string reason = null); + Task Send(byte[] data); + Task SendText(string message); + } +} diff --git a/src/NativeWebSocket/NativeWebSocket.csproj b/src/NativeWebSocket/NativeWebSocket.csproj new file mode 100644 index 0000000..e79eaa7 --- /dev/null +++ b/src/NativeWebSocket/NativeWebSocket.csproj @@ -0,0 +1,14 @@ + + + netstandard2.0;net6.0 + NativeWebSocket + NativeWebSocket + 2.0.0 + Endel Dreyer + WebSocket client for .NET - works with Unity, MonoGame, Godot, and any .NET application. + NativeWebSocket + MIT + https://github.com/endel/NativeWebSocket + 7.3 + + diff --git a/src/NativeWebSocket/WebSocket.cs b/src/NativeWebSocket/WebSocket.cs new file mode 100644 index 0000000..398cbb4 --- /dev/null +++ b/src/NativeWebSocket/WebSocket.cs @@ -0,0 +1,352 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Net.WebSockets; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace NativeWebSocket +{ + public class WebSocket : IWebSocket + { + public event WebSocketOpenEventHandler OnOpen; + public event WebSocketMessageEventHandler OnMessage; + public event WebSocketErrorEventHandler OnError; + public event WebSocketCloseEventHandler OnClose; + + private Uri uri; + private Dictionary headers; + private List subprotocols; + private ClientWebSocket m_Socket = new ClientWebSocket(); + + private CancellationTokenSource m_TokenSource; + private CancellationToken m_CancellationToken; + + private readonly SynchronizationContext _syncContext; + private List m_EventQueue = new List(); + private List m_DispatchQueue = new List(); + private readonly object EventQueueLock = new object(); + + private readonly object OutgoingMessageLock = new object(); + private readonly object SocketLock = new object(); + private bool isSending = false; + private Queue> sendBytesQueue = new Queue>(); + private Queue> sendTextQueue = new Queue>(); + + public WebSocket(string url, Dictionary headers = null) + { + uri = new Uri(url); + _syncContext = SynchronizationContext.Current; + this.headers = headers ?? new Dictionary(); + subprotocols = new List(); + + string protocol = uri.Scheme; + if (!protocol.Equals("ws") && !protocol.Equals("wss")) + throw new ArgumentException("Unsupported protocol: " + protocol); + } + + public WebSocket(string url, string subprotocol, Dictionary headers = null) + { + uri = new Uri(url); + _syncContext = SynchronizationContext.Current; + this.headers = headers ?? new Dictionary(); + subprotocols = new List { subprotocol }; + + string protocol = uri.Scheme; + if (!protocol.Equals("ws") && !protocol.Equals("wss")) + throw new ArgumentException("Unsupported protocol: " + protocol); + } + + public WebSocket(string url, List subprotocols, Dictionary headers = null) + { + uri = new Uri(url); + _syncContext = SynchronizationContext.Current; + this.headers = headers ?? new Dictionary(); + this.subprotocols = subprotocols; + + string protocol = uri.Scheme; + if (!protocol.Equals("ws") && !protocol.Equals("wss")) + throw new ArgumentException("Unsupported protocol: " + protocol); + } + + private void EnqueueEvent(Action action) + { + if (_syncContext != null) + { + _syncContext.Post(_ => action(), null); + } + else + { + lock (EventQueueLock) + { + m_EventQueue.Add(action); + } + } + } + + /// + /// Dispatches queued events when no SynchronizationContext is available. + /// Not needed when a SynchronizationContext is present (Unity, Godot, MonoGame with WebSocketGameComponent). + /// + public void DispatchMessageQueue() + { + if (m_EventQueue.Count == 0) return; + + lock (EventQueueLock) + { + var tmp = m_DispatchQueue; + m_DispatchQueue = m_EventQueue; + m_EventQueue = tmp; + } + + foreach (var action in m_DispatchQueue) + { + action(); + } + + m_DispatchQueue.Clear(); + } + + public void CancelConnection() + { + m_TokenSource?.Cancel(); + } + + public async Task Connect() + { + try + { + m_TokenSource = new CancellationTokenSource(); + m_CancellationToken = m_TokenSource.Token; + + m_Socket = new ClientWebSocket(); + + foreach (var header in headers) + { + m_Socket.Options.SetRequestHeader(header.Key, header.Value); + } + + foreach (string subprotocol in subprotocols) + { + m_Socket.Options.AddSubProtocol(subprotocol); + } + + await m_Socket.ConnectAsync(uri, m_CancellationToken).ConfigureAwait(false); + + EnqueueEvent(() => OnOpen?.Invoke()); + + await Receive().ConfigureAwait(false); + } + catch (Exception ex) + { + EnqueueEvent(() => OnError?.Invoke(ex.Message)); + EnqueueEvent(() => OnClose?.Invoke(WebSocketCloseCode.Abnormal)); + } + finally + { + if (m_Socket != null) + { + m_TokenSource.Cancel(); + m_Socket.Dispose(); + } + } + } + + public WebSocketState State + { + get + { + switch (m_Socket.State) + { + case System.Net.WebSockets.WebSocketState.Connecting: + return WebSocketState.Connecting; + + case System.Net.WebSockets.WebSocketState.Open: + return WebSocketState.Open; + + case System.Net.WebSockets.WebSocketState.CloseSent: + case System.Net.WebSockets.WebSocketState.CloseReceived: + return WebSocketState.Closing; + + case System.Net.WebSockets.WebSocketState.Closed: + return WebSocketState.Closed; + + default: + return WebSocketState.Closed; + } + } + } + + public Task Send(byte[] bytes) + { + return SendMessage(sendBytesQueue, WebSocketMessageType.Binary, new ArraySegment(bytes)); + } + + public Task SendText(string message) + { + var encoded = Encoding.UTF8.GetBytes(message); + return SendMessage(sendTextQueue, WebSocketMessageType.Text, new ArraySegment(encoded, 0, encoded.Length)); + } + + private async Task SendMessage(Queue> queue, WebSocketMessageType messageType, ArraySegment buffer) + { + if (buffer.Count == 0) + { + return; + } + + bool sending; + + lock (OutgoingMessageLock) + { + sending = isSending; + + if (!isSending) + { + isSending = true; + } + } + + if (!sending) + { + try + { + if (!Monitor.TryEnter(SocketLock, 1000)) + { + await m_Socket.CloseAsync(WebSocketCloseStatus.InternalServerError, string.Empty, m_CancellationToken).ConfigureAwait(false); + return; + } + + try + { + await m_Socket.SendAsync(buffer, messageType, true, m_CancellationToken).ConfigureAwait(false); + } + finally + { + Monitor.Exit(SocketLock); + } + + // Drain the queue iteratively instead of recursively + while (true) + { + ArraySegment next; + lock (OutgoingMessageLock) + { + if (queue.Count == 0) + break; + next = queue.Dequeue(); + } + + if (!Monitor.TryEnter(SocketLock, 1000)) + { + await m_Socket.CloseAsync(WebSocketCloseStatus.InternalServerError, string.Empty, m_CancellationToken).ConfigureAwait(false); + return; + } + + try + { + await m_Socket.SendAsync(next, messageType, true, m_CancellationToken).ConfigureAwait(false); + } + finally + { + Monitor.Exit(SocketLock); + } + } + } + finally + { + lock (OutgoingMessageLock) + { + isSending = false; + } + } + } + else + { + lock (OutgoingMessageLock) + { + queue.Enqueue(buffer); + } + } + } + + public async Task Receive() + { + WebSocketCloseCode closeCode = WebSocketCloseCode.Abnormal; + ArraySegment buffer = new ArraySegment(new byte[8192]); + try + { + while (m_Socket.State == System.Net.WebSockets.WebSocketState.Open) + { + var result = await m_Socket.ReceiveAsync(buffer, m_CancellationToken).ConfigureAwait(false); + + if (result.MessageType == WebSocketMessageType.Close) + { + await Close().ConfigureAwait(false); + closeCode = WebSocketHelpers.ParseCloseCodeEnum((int)result.CloseStatus); + break; + } + + if (result.EndOfMessage) + { + // Fast path: single-frame message, avoid MemoryStream + var data = new byte[result.Count]; + Buffer.BlockCopy(buffer.Array, buffer.Offset, data, 0, result.Count); + EnqueueEvent(() => OnMessage?.Invoke(data)); + } + else + { + // Multi-frame message: accumulate in MemoryStream + using (var ms = new MemoryStream()) + { + ms.Write(buffer.Array, buffer.Offset, result.Count); + + do + { + result = await m_Socket.ReceiveAsync(buffer, m_CancellationToken).ConfigureAwait(false); + ms.Write(buffer.Array, buffer.Offset, result.Count); + } + while (!result.EndOfMessage); + + var data = ms.ToArray(); + EnqueueEvent(() => OnMessage?.Invoke(data)); + } + } + } + } + catch (Exception) + { + m_TokenSource.Cancel(); + } + finally + { + EnqueueEvent(() => OnClose?.Invoke(closeCode)); + } + } + + public async Task Close(WebSocketCloseCode code = WebSocketCloseCode.Normal, string reason = null) + { + if (State == WebSocketState.Open) + { + await m_Socket.CloseAsync((WebSocketCloseStatus)(int)code, reason ?? string.Empty, m_CancellationToken).ConfigureAwait(false); + } + } + } + + /// + /// Factory for creating WebSocket instances. + /// + public static class WebSocketFactory + { + /// + /// Create WebSocket client instance + /// + /// The WebSocket instance. + /// WebSocket valid URL. + public static WebSocket CreateInstance(string url) + { + return new WebSocket(url); + } + } +} diff --git a/src/NativeWebSocket/WebSocketTypes.cs b/src/NativeWebSocket/WebSocketTypes.cs new file mode 100644 index 0000000..8055b3b --- /dev/null +++ b/src/NativeWebSocket/WebSocketTypes.cs @@ -0,0 +1,70 @@ +using System; + +namespace NativeWebSocket +{ + public static class WebSocketHelpers + { + public static WebSocketCloseCode ParseCloseCodeEnum(int closeCode) + { + if (WebSocketCloseCode.IsDefined(typeof(WebSocketCloseCode), closeCode)) + { + return (WebSocketCloseCode)closeCode; + } + else + { + return WebSocketCloseCode.Undefined; + } + } + + public static WebSocketException GetErrorMessageFromCode(int errorCode, Exception inner) + { + switch (errorCode) + { + case -1: + return new WebSocketUnexpectedException("WebSocket instance not found.", inner); + case -2: + return new WebSocketInvalidStateException("WebSocket is already connected or in connecting state.", inner); + case -3: + return new WebSocketInvalidStateException("WebSocket is not connected.", inner); + case -4: + return new WebSocketInvalidStateException("WebSocket is already closing.", inner); + case -5: + return new WebSocketInvalidStateException("WebSocket is already closed.", inner); + case -6: + return new WebSocketInvalidStateException("WebSocket is not in open state.", inner); + case -7: + return new WebSocketInvalidArgumentException("Cannot close WebSocket. An invalid code was specified or reason is too long.", inner); + default: + return new WebSocketUnexpectedException("Unknown error.", inner); + } + } + } + + public class WebSocketException : Exception + { + public WebSocketException() { } + public WebSocketException(string message) : base(message) { } + public WebSocketException(string message, Exception inner) : base(message, inner) { } + } + + public class WebSocketUnexpectedException : WebSocketException + { + public WebSocketUnexpectedException() { } + public WebSocketUnexpectedException(string message) : base(message) { } + public WebSocketUnexpectedException(string message, Exception inner) : base(message, inner) { } + } + + public class WebSocketInvalidArgumentException : WebSocketException + { + public WebSocketInvalidArgumentException() { } + public WebSocketInvalidArgumentException(string message) : base(message) { } + public WebSocketInvalidArgumentException(string message, Exception inner) : base(message, inner) { } + } + + public class WebSocketInvalidStateException : WebSocketException + { + public WebSocketInvalidStateException() { } + public WebSocketInvalidStateException(string message) : base(message) { } + public WebSocketInvalidStateException(string message, Exception inner) : base(message, inner) { } + } +} From 17625591c38182759842acd70cfe5b3f35828600 Mon Sep 17 00:00:00 2001 From: Endel Dreyer Date: Wed, 11 Mar 2026 16:33:52 -0300 Subject: [PATCH 2/9] fix: resolve double-prefixed path in .unitypackage generation metaList paths were absolute (upm-package/...) but project-folder also prepended upm-package/, causing ENOENT. Now writes paths relative to upm-package/ so the action resolves them correctly. --- .github/workflows/unity-upm-release.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/unity-upm-release.yml b/.github/workflows/unity-upm-release.yml index ef46208..b69cf17 100644 --- a/.github/workflows/unity-upm-release.yml +++ b/.github/workflows/unity-upm-release.yml @@ -174,8 +174,9 @@ jobs: - name: Gather meta files run: | - find upm-package/ -name '*.meta' > metaList - cat metaList + cd upm-package + find . -name '*.meta' | sed 's|^\./||' > ../metaList + cat ../metaList - name: Extract Version id: version From 1df7673987b8fa3facea66f061de678a04d7b71d Mon Sep 17 00:00:00 2001 From: Endel Dreyer Date: Wed, 11 Mar 2026 16:50:43 -0300 Subject: [PATCH 3/9] fix: use Assets/ prefix in .unitypackage so Unity imports files correctly The .unitypackage format requires internal paths under Assets/ for Unity to place files into the project. The createPackage job now assembles into Assets/WebSocket/ while the UPM branch keeps the flat structure. --- .github/workflows/unity-upm-release.yml | 44 ++++++++++++------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/.github/workflows/unity-upm-release.yml b/.github/workflows/unity-upm-release.yml index b69cf17..9424c0a 100644 --- a/.github/workflows/unity-upm-release.yml +++ b/.github/workflows/unity-upm-release.yml @@ -75,22 +75,22 @@ jobs: - name: Assemble package directory run: | - mkdir -p upm-package/WebSocket + mkdir -p upm-package/Assets/WebSocket # Core library files - cp src/NativeWebSocket/IWebSocket.cs upm-package/WebSocket/ - cp src/NativeWebSocket/WebSocketTypes.cs upm-package/WebSocket/ + cp src/NativeWebSocket/IWebSocket.cs upm-package/Assets/WebSocket/ + cp src/NativeWebSocket/WebSocketTypes.cs upm-package/Assets/WebSocket/ # Unity-specific files - cp integrations/Unity/WebSocket.cs upm-package/WebSocket/ - cp integrations/Unity/WebSocketWebGL.cs upm-package/WebSocket/ - cp integrations/Unity/WebSocketFactoryWebGL.cs upm-package/WebSocket/ - cp integrations/Unity/WebSocket.jslib upm-package/WebSocket/ - cp integrations/Unity/WebSocket.jspre upm-package/WebSocket/ - cp integrations/Unity/endel.nativewebsocket.asmdef upm-package/WebSocket/ + cp integrations/Unity/WebSocket.cs upm-package/Assets/WebSocket/ + cp integrations/Unity/WebSocketWebGL.cs upm-package/Assets/WebSocket/ + cp integrations/Unity/WebSocketFactoryWebGL.cs upm-package/Assets/WebSocket/ + cp integrations/Unity/WebSocket.jslib upm-package/Assets/WebSocket/ + cp integrations/Unity/WebSocket.jspre upm-package/Assets/WebSocket/ + cp integrations/Unity/endel.nativewebsocket.asmdef upm-package/Assets/WebSocket/ # Package metadata - cp integrations/Unity/package.json upm-package/ + cp integrations/Unity/package.json upm-package/Assets/ - name: Generate .meta files run: | @@ -103,7 +103,7 @@ jobs: case "$ext" in cs) - cat > "$meta" < "$meta" < "$meta" < "$meta" < "$meta" < "$meta" < upm-package/WebSocket.meta < upm-package/Assets/WebSocket.meta < ../metaList + find Assets -name '*.meta' > ../metaList cat ../metaList - name: Extract Version From 0eb797cdd87102b7e4da9dda10d2959c0d7d54ca Mon Sep 17 00:00:00 2001 From: Endel Dreyer Date: Wed, 11 Mar 2026 17:58:14 -0300 Subject: [PATCH 4/9] improve unity release --- .github/workflows/unity-upm-release.yml | 11 +- README.md | 20 +- examples/Unity/Connection.cs | 2 + integrations/Unity/WebSocket.cs | 357 ------------------------ src/NativeWebSocket/WebSocket.cs | 41 +-- 5 files changed, 32 insertions(+), 399 deletions(-) delete mode 100644 integrations/Unity/WebSocket.cs diff --git a/.github/workflows/unity-upm-release.yml b/.github/workflows/unity-upm-release.yml index 9424c0a..3db3217 100644 --- a/.github/workflows/unity-upm-release.yml +++ b/.github/workflows/unity-upm-release.yml @@ -43,9 +43,10 @@ jobs: cp src/NativeWebSocket/IWebSocket.cs upm-package/WebSocket/ cp src/NativeWebSocket/WebSocketTypes.cs upm-package/WebSocket/ - # Unity-specific files (WebSocket.cs has #if !UNITY_WEBGL guard, - # WebSocketWebGL.cs + WebSocketFactoryWebGL.cs have #if UNITY_WEBGL guard) - cp integrations/Unity/WebSocket.cs upm-package/WebSocket/ + # Wrap core WebSocket.cs with Unity conditional compilation guard + { echo '#if !UNITY_WEBGL || UNITY_EDITOR'; echo ''; cat src/NativeWebSocket/WebSocket.cs; echo ''; echo '#endif'; } > upm-package/WebSocket/WebSocket.cs + + # Unity-specific files (WebGL platform support) cp integrations/Unity/WebSocketWebGL.cs upm-package/WebSocket/ cp integrations/Unity/WebSocketFactoryWebGL.cs upm-package/WebSocket/ cp integrations/Unity/WebSocket.jslib upm-package/WebSocket/ @@ -81,8 +82,10 @@ jobs: cp src/NativeWebSocket/IWebSocket.cs upm-package/Assets/WebSocket/ cp src/NativeWebSocket/WebSocketTypes.cs upm-package/Assets/WebSocket/ + # Wrap core WebSocket.cs with Unity conditional compilation guard + { echo '#if !UNITY_WEBGL || UNITY_EDITOR'; echo ''; cat src/NativeWebSocket/WebSocket.cs; echo ''; echo '#endif'; } > upm-package/Assets/WebSocket/WebSocket.cs + # Unity-specific files - cp integrations/Unity/WebSocket.cs upm-package/Assets/WebSocket/ cp integrations/Unity/WebSocketWebGL.cs upm-package/Assets/WebSocket/ cp integrations/Unity/WebSocketFactoryWebGL.cs upm-package/Assets/WebSocket/ cp integrations/Unity/WebSocket.jslib upm-package/Assets/WebSocket/ diff --git a/README.md b/README.md index 3793331..181cda4 100644 --- a/README.md +++ b/README.md @@ -16,15 +16,20 @@ Used in [Colyseus Unity SDK](https://github.com/colyseus/colyseus-unity-sdk). *Requires Unity 2019.1+ with .NET 4.x+ Runtime* +> **Note:** Do not copy the raw source files from this repository directly into +> your Unity project. The core `WebSocket.cs` requires a build-time +> transformation to add WebGL conditional compilation guards. Use one of the +> install methods below instead. + **Via UPM (Unity Package Manager):** 1. Open Unity 2. Open Package Manager Window 3. Click Add Package From Git URL -4. Enter URL: `https://github.com/endel/NativeWebSocket.git#upm` +4. Enter URL: `https://github.com/endel/NativeWebSocket.git#upm-2.0` -**Manually:** -1. [Download this project](https://github.com/endel/NativeWebSocket/archive/master.zip) -2. Copy the sources from `NativeWebSocket/Assets/WebSocket` into your `Assets` directory. +**Via .unitypackage:** +1. Download `NativeWebSocket.unitypackage` from the [Releases](https://github.com/endel/NativeWebSocket/releases) page +2. In Unity, go to Assets > Import Package > Custom Package and select the downloaded file ## MonoGame / .NET @@ -60,6 +65,8 @@ public class Connection : MonoBehaviour async void Start() { + Application.runInBackground = true; // Recommended for WebGL + websocket = new WebSocket("ws://localhost:3000"); websocket.OnOpen += () => Debug.Log("Connection open!"); @@ -93,6 +100,11 @@ public class Connection : MonoBehaviour } ``` +**WebGL note:** Unity pauses the game loop when the browser tab loses focus, which +stops all WebSocket send/receive callbacks. To keep the connection active in the +background, set `Application.runInBackground = true` in your script or enable +**Run In Background** in Player Settings > Resolution and Presentation. + ## MonoGame Add the `WebSocketGameComponent` to your game. This installs a diff --git a/examples/Unity/Connection.cs b/examples/Unity/Connection.cs index 8da3f40..b0cd023 100644 --- a/examples/Unity/Connection.cs +++ b/examples/Unity/Connection.cs @@ -25,6 +25,8 @@ public class Connection : MonoBehaviour async void Start() { + Application.runInBackground = true; + websocket = new WebSocket("ws://localhost:3000"); websocket.OnOpen += () => diff --git a/integrations/Unity/WebSocket.cs b/integrations/Unity/WebSocket.cs deleted file mode 100644 index 6d284b8..0000000 --- a/integrations/Unity/WebSocket.cs +++ /dev/null @@ -1,357 +0,0 @@ -#if !UNITY_WEBGL || UNITY_EDITOR - -using System; -using System.Collections.Generic; -using System.IO; -using System.Net.WebSockets; -using System.Text; -using System.Threading; -using System.Threading.Tasks; - -namespace NativeWebSocket -{ - public class WebSocket : IWebSocket - { - public event WebSocketOpenEventHandler OnOpen; - public event WebSocketMessageEventHandler OnMessage; - public event WebSocketErrorEventHandler OnError; - public event WebSocketCloseEventHandler OnClose; - - private Uri uri; - private Dictionary headers; - private List subprotocols; - private ClientWebSocket m_Socket = new ClientWebSocket(); - - private CancellationTokenSource m_TokenSource; - private CancellationToken m_CancellationToken; - - private readonly SynchronizationContext _syncContext; - private List m_EventQueue = new List(); - private List m_DispatchQueue = new List(); - private readonly object EventQueueLock = new object(); - - private readonly object OutgoingMessageLock = new object(); - private readonly object SocketLock = new object(); - private bool isSending = false; - private Queue> sendBytesQueue = new Queue>(); - private Queue> sendTextQueue = new Queue>(); - - public WebSocket(string url, Dictionary headers = null) - { - uri = new Uri(url); - _syncContext = SynchronizationContext.Current; - this.headers = headers ?? new Dictionary(); - subprotocols = new List(); - - string protocol = uri.Scheme; - if (!protocol.Equals("ws") && !protocol.Equals("wss")) - throw new ArgumentException("Unsupported protocol: " + protocol); - } - - public WebSocket(string url, string subprotocol, Dictionary headers = null) - { - uri = new Uri(url); - _syncContext = SynchronizationContext.Current; - this.headers = headers ?? new Dictionary(); - subprotocols = new List { subprotocol }; - - string protocol = uri.Scheme; - if (!protocol.Equals("ws") && !protocol.Equals("wss")) - throw new ArgumentException("Unsupported protocol: " + protocol); - } - - public WebSocket(string url, List subprotocols, Dictionary headers = null) - { - uri = new Uri(url); - _syncContext = SynchronizationContext.Current; - this.headers = headers ?? new Dictionary(); - this.subprotocols = subprotocols; - - string protocol = uri.Scheme; - if (!protocol.Equals("ws") && !protocol.Equals("wss")) - throw new ArgumentException("Unsupported protocol: " + protocol); - } - - private void EnqueueEvent(Action action) - { - if (_syncContext != null) - { - _syncContext.Post(_ => action(), null); - } - else - { - lock (EventQueueLock) - { - m_EventQueue.Add(action); - } - } - } - - /// - /// Dispatches queued events when no SynchronizationContext is available. - /// Not needed in Unity — UnitySynchronizationContext handles dispatch automatically. - /// Kept for backward compatibility. - /// - public void DispatchMessageQueue() - { - if (m_EventQueue.Count == 0) return; - - lock (EventQueueLock) - { - var tmp = m_DispatchQueue; - m_DispatchQueue = m_EventQueue; - m_EventQueue = tmp; - } - - foreach (var action in m_DispatchQueue) - { - action(); - } - - m_DispatchQueue.Clear(); - } - - public void CancelConnection() - { - m_TokenSource?.Cancel(); - } - - public async Task Connect() - { - try - { - m_TokenSource = new CancellationTokenSource(); - m_CancellationToken = m_TokenSource.Token; - - m_Socket = new ClientWebSocket(); - - foreach (var header in headers) - { - m_Socket.Options.SetRequestHeader(header.Key, header.Value); - } - - foreach (string subprotocol in subprotocols) - { - m_Socket.Options.AddSubProtocol(subprotocol); - } - - await m_Socket.ConnectAsync(uri, m_CancellationToken).ConfigureAwait(false); - - EnqueueEvent(() => OnOpen?.Invoke()); - - await Receive().ConfigureAwait(false); - } - catch (Exception ex) - { - EnqueueEvent(() => OnError?.Invoke(ex.Message)); - EnqueueEvent(() => OnClose?.Invoke(WebSocketCloseCode.Abnormal)); - } - finally - { - if (m_Socket != null) - { - m_TokenSource.Cancel(); - m_Socket.Dispose(); - } - } - } - - public WebSocketState State - { - get - { - switch (m_Socket.State) - { - case System.Net.WebSockets.WebSocketState.Connecting: - return WebSocketState.Connecting; - - case System.Net.WebSockets.WebSocketState.Open: - return WebSocketState.Open; - - case System.Net.WebSockets.WebSocketState.CloseSent: - case System.Net.WebSockets.WebSocketState.CloseReceived: - return WebSocketState.Closing; - - case System.Net.WebSockets.WebSocketState.Closed: - return WebSocketState.Closed; - - default: - return WebSocketState.Closed; - } - } - } - - public Task Send(byte[] bytes) - { - return SendMessage(sendBytesQueue, WebSocketMessageType.Binary, new ArraySegment(bytes)); - } - - public Task SendText(string message) - { - var encoded = Encoding.UTF8.GetBytes(message); - return SendMessage(sendTextQueue, WebSocketMessageType.Text, new ArraySegment(encoded, 0, encoded.Length)); - } - - private async Task SendMessage(Queue> queue, WebSocketMessageType messageType, ArraySegment buffer) - { - if (buffer.Count == 0) - { - return; - } - - bool sending; - - lock (OutgoingMessageLock) - { - sending = isSending; - - if (!isSending) - { - isSending = true; - } - } - - if (!sending) - { - try - { - if (!Monitor.TryEnter(SocketLock, 1000)) - { - await m_Socket.CloseAsync(WebSocketCloseStatus.InternalServerError, string.Empty, m_CancellationToken).ConfigureAwait(false); - return; - } - - try - { - await m_Socket.SendAsync(buffer, messageType, true, m_CancellationToken).ConfigureAwait(false); - } - finally - { - Monitor.Exit(SocketLock); - } - - // Drain the queue iteratively instead of recursively - while (true) - { - ArraySegment next; - lock (OutgoingMessageLock) - { - if (queue.Count == 0) - break; - next = queue.Dequeue(); - } - - if (!Monitor.TryEnter(SocketLock, 1000)) - { - await m_Socket.CloseAsync(WebSocketCloseStatus.InternalServerError, string.Empty, m_CancellationToken).ConfigureAwait(false); - return; - } - - try - { - await m_Socket.SendAsync(next, messageType, true, m_CancellationToken).ConfigureAwait(false); - } - finally - { - Monitor.Exit(SocketLock); - } - } - } - finally - { - lock (OutgoingMessageLock) - { - isSending = false; - } - } - } - else - { - lock (OutgoingMessageLock) - { - queue.Enqueue(buffer); - } - } - } - - public async Task Receive() - { - WebSocketCloseCode closeCode = WebSocketCloseCode.Abnormal; - ArraySegment buffer = new ArraySegment(new byte[8192]); - try - { - while (m_Socket.State == System.Net.WebSockets.WebSocketState.Open) - { - var result = await m_Socket.ReceiveAsync(buffer, m_CancellationToken).ConfigureAwait(false); - - if (result.MessageType == WebSocketMessageType.Close) - { - await Close().ConfigureAwait(false); - closeCode = WebSocketHelpers.ParseCloseCodeEnum((int)result.CloseStatus); - break; - } - - if (result.EndOfMessage) - { - // Fast path: single-frame message, avoid MemoryStream - var data = new byte[result.Count]; - Buffer.BlockCopy(buffer.Array, buffer.Offset, data, 0, result.Count); - EnqueueEvent(() => OnMessage?.Invoke(data)); - } - else - { - // Multi-frame message: accumulate in MemoryStream - using (var ms = new MemoryStream()) - { - ms.Write(buffer.Array, buffer.Offset, result.Count); - - do - { - result = await m_Socket.ReceiveAsync(buffer, m_CancellationToken).ConfigureAwait(false); - ms.Write(buffer.Array, buffer.Offset, result.Count); - } - while (!result.EndOfMessage); - - var data = ms.ToArray(); - EnqueueEvent(() => OnMessage?.Invoke(data)); - } - } - } - } - catch (Exception) - { - m_TokenSource.Cancel(); - } - finally - { - EnqueueEvent(() => OnClose?.Invoke(closeCode)); - } - } - - public async Task Close(WebSocketCloseCode code = WebSocketCloseCode.Normal, string reason = null) - { - if (State == WebSocketState.Open) - { - await m_Socket.CloseAsync((WebSocketCloseStatus)(int)code, reason ?? string.Empty, m_CancellationToken).ConfigureAwait(false); - } - } - } - - /// - /// Factory for creating WebSocket instances. - /// - public static class WebSocketFactory - { - /// - /// Create WebSocket client instance - /// - /// The WebSocket instance. - /// WebSocket valid URL. - public static WebSocket CreateInstance(string url) - { - return new WebSocket(url); - } - } -} - -#endif diff --git a/src/NativeWebSocket/WebSocket.cs b/src/NativeWebSocket/WebSocket.cs index 398cbb4..2946d88 100644 --- a/src/NativeWebSocket/WebSocket.cs +++ b/src/NativeWebSocket/WebSocket.cs @@ -29,7 +29,6 @@ public class WebSocket : IWebSocket private readonly object EventQueueLock = new object(); private readonly object OutgoingMessageLock = new object(); - private readonly object SocketLock = new object(); private bool isSending = false; private Queue> sendBytesQueue = new Queue>(); private Queue> sendTextQueue = new Queue>(); @@ -191,7 +190,7 @@ public Task SendText(string message) private async Task SendMessage(Queue> queue, WebSocketMessageType messageType, ArraySegment buffer) { - if (buffer.Count == 0) + if (buffer.Count == 0 || State != WebSocketState.Open) { return; } @@ -212,20 +211,7 @@ private async Task SendMessage(Queue> queue, WebSocketMessage { try { - if (!Monitor.TryEnter(SocketLock, 1000)) - { - await m_Socket.CloseAsync(WebSocketCloseStatus.InternalServerError, string.Empty, m_CancellationToken).ConfigureAwait(false); - return; - } - - try - { - await m_Socket.SendAsync(buffer, messageType, true, m_CancellationToken).ConfigureAwait(false); - } - finally - { - Monitor.Exit(SocketLock); - } + await m_Socket.SendAsync(buffer, messageType, true, m_CancellationToken).ConfigureAwait(false); // Drain the queue iteratively instead of recursively while (true) @@ -238,20 +224,7 @@ private async Task SendMessage(Queue> queue, WebSocketMessage next = queue.Dequeue(); } - if (!Monitor.TryEnter(SocketLock, 1000)) - { - await m_Socket.CloseAsync(WebSocketCloseStatus.InternalServerError, string.Empty, m_CancellationToken).ConfigureAwait(false); - return; - } - - try - { - await m_Socket.SendAsync(next, messageType, true, m_CancellationToken).ConfigureAwait(false); - } - finally - { - Monitor.Exit(SocketLock); - } + await m_Socket.SendAsync(next, messageType, true, m_CancellationToken).ConfigureAwait(false); } } finally @@ -327,10 +300,10 @@ public async Task Receive() public async Task Close(WebSocketCloseCode code = WebSocketCloseCode.Normal, string reason = null) { - if (State == WebSocketState.Open) - { - await m_Socket.CloseAsync((WebSocketCloseStatus)(int)code, reason ?? string.Empty, m_CancellationToken).ConfigureAwait(false); - } + if (State != WebSocketState.Open) + return; + + await m_Socket.CloseAsync((WebSocketCloseStatus)(int)code, reason ?? string.Empty, CancellationToken.None).ConfigureAwait(false); } } From dd539e7025f82c42541a162eaa92b9c4373de363 Mon Sep 17 00:00:00 2001 From: Endel Dreyer Date: Wed, 11 Mar 2026 18:06:06 -0300 Subject: [PATCH 5/9] nuget publish CI --- .github/workflows/nuget-publish.yml | 69 +++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 .github/workflows/nuget-publish.yml diff --git a/.github/workflows/nuget-publish.yml b/.github/workflows/nuget-publish.yml new file mode 100644 index 0000000..bffa1d8 --- /dev/null +++ b/.github/workflows/nuget-publish.yml @@ -0,0 +1,69 @@ +name: NuGet Publish + +on: + push: + branches: + - master + pull_request: + branches: + - master + +jobs: + build: + name: Build & Test + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Setup .NET + uses: actions/setup-dotnet@v4 + with: + dotnet-version: '8.0.x' + + - name: Restore + run: dotnet restore src/NativeWebSocket/NativeWebSocket.csproj + + - name: Build + run: dotnet build src/NativeWebSocket/NativeWebSocket.csproj -c Release --no-restore + + publish: + name: Publish to NuGet + runs-on: ubuntu-latest + needs: [build] + if: github.event_name == 'push' && github.ref == 'refs/heads/master' + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 2 + + - name: Setup .NET + uses: actions/setup-dotnet@v4 + with: + dotnet-version: '8.0.x' + + - name: Check for version change + id: version + run: | + CURRENT=$(grep '' src/NativeWebSocket/NativeWebSocket.csproj | sed 's/.*\(.*\)<\/Version>.*/\1/') + PREVIOUS=$(git show HEAD~1:src/NativeWebSocket/NativeWebSocket.csproj 2>/dev/null | grep '' | sed 's/.*\(.*\)<\/Version>.*/\1/' || echo "") + echo "current=$CURRENT" >> $GITHUB_OUTPUT + echo "previous=$PREVIOUS" >> $GITHUB_OUTPUT + if [ "$CURRENT" != "$PREVIOUS" ]; then + echo "changed=true" >> $GITHUB_OUTPUT + echo "Version changed: $PREVIOUS -> $CURRENT" + else + echo "changed=false" >> $GITHUB_OUTPUT + echo "Version unchanged: $CURRENT" + fi + + - name: Pack NativeWebSocket + if: steps.version.outputs.changed == 'true' + run: dotnet pack src/NativeWebSocket/NativeWebSocket.csproj -c Release -o packages/ + + - name: Pack NativeWebSocket.MonoGame + if: steps.version.outputs.changed == 'true' + run: dotnet pack integrations/MonoGame/NativeWebSocket.MonoGame.csproj -c Release -o packages/ + + - name: Publish to NuGet + if: steps.version.outputs.changed == 'true' + run: dotnet nuget push packages/*.nupkg --api-key ${{ secrets.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json --skip-duplicate From aefbe776f1fa79e81afb7817d434db45b65ffd74 Mon Sep 17 00:00:00 2001 From: Endel Dreyer Date: Wed, 11 Mar 2026 18:10:07 -0300 Subject: [PATCH 6/9] testing nuget release ci --- .github/workflows/nuget-publish.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/nuget-publish.yml b/.github/workflows/nuget-publish.yml index bffa1d8..de91643 100644 --- a/.github/workflows/nuget-publish.yml +++ b/.github/workflows/nuget-publish.yml @@ -30,7 +30,7 @@ jobs: name: Publish to NuGet runs-on: ubuntu-latest needs: [build] - if: github.event_name == 'push' && github.ref == 'refs/heads/master' + # TODO: revert to: if: github.event_name == 'push' && github.ref == 'refs/heads/master' steps: - uses: actions/checkout@v4 with: @@ -57,13 +57,13 @@ jobs: fi - name: Pack NativeWebSocket - if: steps.version.outputs.changed == 'true' + # TODO: revert to: if: steps.version.outputs.changed == 'true' run: dotnet pack src/NativeWebSocket/NativeWebSocket.csproj -c Release -o packages/ - name: Pack NativeWebSocket.MonoGame - if: steps.version.outputs.changed == 'true' + # TODO: revert to: if: steps.version.outputs.changed == 'true' run: dotnet pack integrations/MonoGame/NativeWebSocket.MonoGame.csproj -c Release -o packages/ - name: Publish to NuGet - if: steps.version.outputs.changed == 'true' + # TODO: revert to: if: steps.version.outputs.changed == 'true' run: dotnet nuget push packages/*.nupkg --api-key ${{ secrets.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json --skip-duplicate From 1c0d91c4e9a99f3665c55f19fd83622c80628c73 Mon Sep 17 00:00:00 2001 From: Endel Dreyer Date: Wed, 11 Mar 2026 18:14:16 -0300 Subject: [PATCH 7/9] testing nuget release ci --- .github/workflows/nuget-publish.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/nuget-publish.yml b/.github/workflows/nuget-publish.yml index de91643..f93244c 100644 --- a/.github/workflows/nuget-publish.yml +++ b/.github/workflows/nuget-publish.yml @@ -66,4 +66,6 @@ jobs: - name: Publish to NuGet # TODO: revert to: if: steps.version.outputs.changed == 'true' - run: dotnet nuget push packages/*.nupkg --api-key ${{ secrets.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json --skip-duplicate + env: + NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }} + run: dotnet nuget push packages/*.nupkg --api-key "$NUGET_API_KEY" --source https://api.nuget.org/v3/index.json --skip-duplicate From 969c13db5c665164279a29ca9181974b1a8df9c9 Mon Sep 17 00:00:00 2001 From: Endel Dreyer Date: Wed, 11 Mar 2026 18:36:28 -0300 Subject: [PATCH 8/9] update NuGet package names to Colyseus.NativeWebSocket --- Media/header.png | Bin 19910 -> 229597 bytes .../MonoGame/NativeWebSocket.MonoGame.csproj | 2 +- src/NativeWebSocket/NativeWebSocket.csproj | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Media/header.png b/Media/header.png index d60f01f8b055bcd0c76b0d971c7ab92707742f10..d2465a824ff3e3e05dedc435d3c29095edd486d7 100644 GIT binary patch literal 229597 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 z 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

^01(LB2)rQAw*92qRaAZaQR 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.0.0
Endel Dreyer MonoGame integration for NativeWebSocket - provides a GameComponent that enables automatic main-thread event dispatching. - NativeWebSocket.MonoGame + Colyseus.NativeWebSocket.MonoGame MIT https://github.com/endel/NativeWebSocket diff --git a/src/NativeWebSocket/NativeWebSocket.csproj b/src/NativeWebSocket/NativeWebSocket.csproj index e79eaa7..f0106db 100644 --- a/src/NativeWebSocket/NativeWebSocket.csproj +++ b/src/NativeWebSocket/NativeWebSocket.csproj @@ -6,7 +6,7 @@ 2.0.0 Endel Dreyer WebSocket client for .NET - works with Unity, MonoGame, Godot, and any .NET application. - NativeWebSocket + Colyseus.NativeWebSocket MIT https://github.com/endel/NativeWebSocket 7.3 From e57991c5813ec261fc0fdc72c4cddc8a7b08360e Mon Sep 17 00:00:00 2001 From: Endel Dreyer Date: Wed, 11 Mar 2026 23:51:32 -0300 Subject: [PATCH 9/9] update readme --- README.md | 19 ++++++------------- .../index.js | 0 .../package-lock.json | 0 .../package.json | 0 4 files changed, 6 insertions(+), 13 deletions(-) rename {NodeServer => node-websocket-server}/index.js (100%) rename {NodeServer => node-websocket-server}/package-lock.json (100%) rename {NodeServer => node-websocket-server}/package.json (100%) diff --git a/README.md b/README.md index 181cda4..6e96aaa 100644 --- a/README.md +++ b/README.md @@ -33,22 +33,15 @@ Used in [Colyseus Unity SDK](https://github.com/colyseus/colyseus-unity-sdk). ## MonoGame / .NET -Add a project reference to `src/NativeWebSocket/NativeWebSocket.csproj` and -`integrations/MonoGame/NativeWebSocket.MonoGame.csproj`: - ```bash -dotnet add reference path/to/NativeWebSocket.csproj -dotnet add reference path/to/NativeWebSocket.MonoGame.csproj +dotnet add package Colyseus.NativeWebSocket +dotnet add package Colyseus.NativeWebSocket.MonoGame ``` ## Godot (C#) -Add a project reference to `src/NativeWebSocket/NativeWebSocket.csproj` in your `.csproj`: - -```xml - - - +```bash +dotnet add package Colyseus.NativeWebSocket ``` # Usage @@ -223,9 +216,9 @@ Full runnable examples are in the [`examples/`](examples/) directory: All examples connect to the included test server: ```bash -cd NodeServer +cd node-websocket-server npm install -node index.js +npm start ``` The server listens on `ws://localhost:3000`, sends periodic text and binary diff --git a/NodeServer/index.js b/node-websocket-server/index.js similarity index 100% rename from NodeServer/index.js rename to node-websocket-server/index.js diff --git a/NodeServer/package-lock.json b/node-websocket-server/package-lock.json similarity index 100% rename from NodeServer/package-lock.json rename to node-websocket-server/package-lock.json diff --git a/NodeServer/package.json b/node-websocket-server/package.json similarity index 100% rename from NodeServer/package.json rename to node-websocket-server/package.json