crowdypy 0.7.0.dev1__tar.gz → 0.9.0.dev1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/AGENTS.md +22 -1
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/CMakeLists.txt +1 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/MIGRATION.md +122 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/PKG-INFO +78 -15
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/README.md +77 -14
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/benchmarks/README.md +20 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/docs/compatibility.md +10 -1
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/docs/e2e-coverage.md +7 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/docs/parity-matrix.md +48 -4
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/native/common.hpp +1 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/native/module.cpp +3 -2
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/native/replication.hpp +25 -5
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/native/replication_binding.cpp +2 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/native/session_binding.cpp +90 -7
- crowdypy-0.9.0.dev1/native/voice_binding.cpp +177 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/native/wire_binding.cpp +23 -5
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/appAccess/AppUserAccessByApp.graphql +2 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/appAccess/ClaimFreeAppAccess.graphql +1 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/appAccess/GrantAppAccess.graphql +1 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/appAccess/GrantMyAppAccess.graphql +1 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/appAccess/MyAppAccess.graphql +1 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/appAccess/RevokeAppAccess.graphql +1 -0
- crowdypy-0.9.0.dev1/operations/appAccess/SuspendAppAccess.graphql +45 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/apps/App.graphql +1 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/apps/UpdateApp.graphql +1 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/chunks/GetChunk.graphql +1 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/chunks/GetChunksByDistance.graphql +1 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/exec/Exec.graphql +14 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/serverStatus/GameClientBootstrap.graphql +5 -0
- crowdypy-0.9.0.dev1/operations/users/PlayerProfile.graphql +15 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/pyproject.toml +11 -9
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/schema.gql +269 -66
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/__init__.py +52 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_generated/enums.py +2 -1
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_generated/inputs.py +8 -5
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_generated/operations.py +76 -22
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/domains/app_access.py +60 -2
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/domains/apps.py +4 -1
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/domains/channels.py +3 -1
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/domains/chunks.py +6 -2
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/domains/exec.py +16 -1
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/domains/grids.py +2 -1
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/domains/portal.py +6 -2
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/domains/server_status.py +7 -1
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/domains/udp.py +13 -0
- crowdypy-0.9.0.dev1/src/crowdypy/_sync/domains/users.py +75 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/grid_scope.py +10 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/stores.py +123 -43
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_version.py +1 -1
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/domains/app_access.py +60 -2
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/domains/apps.py +4 -1
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/domains/channels.py +3 -1
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/domains/chunks.py +6 -2
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/domains/exec.py +41 -2
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/domains/grids.py +2 -1
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/domains/portal.py +19 -1
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/domains/server_status.py +7 -1
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/domains/udp.py +13 -0
- crowdypy-0.9.0.dev1/src/crowdypy/domains/users.py +74 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/errors.py +114 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/grid_scope.py +10 -0
- crowdypy-0.9.0.dev1/src/crowdypy/media.py +527 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/player_host/schemas.v1.json +2 -2
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/replication.py +34 -4
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/stores.py +138 -43
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/wire.py +70 -1
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/fixtures/README.md +1 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/fixtures/player-host.v1.json +2 -2
- crowdypy-0.9.0.dev1/tests/fixtures/voice-frames.json +941 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/unit/domains/test_org_domains.py +49 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/unit/domains/test_studio_exec_domains.py +24 -1
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/unit/test_durable_stores.py +64 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/unit/test_fixture_provenance.py +5 -5
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/unit/test_grid_scope.py +4 -0
- crowdypy-0.9.0.dev1/tests/unit/test_refusals.py +155 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/unit/test_replication.py +80 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/unit/test_udp_api.py +50 -1
- crowdypy-0.9.0.dev1/tests/unit/test_voice_frames.py +284 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/unit/test_wire.py +77 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/unit/test_world_session.py +172 -1
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tools/parity/classifications.toml +2 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/uv.lock +1 -1
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/CMakeLists.txt +35 -1
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/PROVENANCE.md +1 -1
- crowdypy-0.9.0.dev1/vendor/CrowdyCPP/cmake/CrowdyCPPConfig.cmake.in +26 -0
- crowdypy-0.9.0.dev1/vendor/CrowdyCPP/cmake/CrowdyFindOpus.cmake +36 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/domains/admin.hpp +58 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/domains/exec.hpp +17 -7
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/domains/grids.hpp +16 -5
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/domains/groups.hpp +4 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/domains/portal.hpp +7 -7
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/domains/types.hpp +27 -0
- crowdypy-0.9.0.dev1/vendor/CrowdyCPP/include/crowdy/domains/users.hpp +154 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/generated/enums.hpp +5 -2
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/generated/operations.hpp +210 -2
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/graphql/errors.hpp +68 -0
- crowdypy-0.9.0.dev1/vendor/CrowdyCPP/include/crowdy/media/opus.hpp +90 -0
- crowdypy-0.9.0.dev1/vendor/CrowdyCPP/include/crowdy/media/voice_frames.hpp +470 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/replication/connection.hpp +13 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/replication/types.hpp +3 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/session/chunk_store.hpp +201 -29
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/session/stores.hpp +3 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/session/world_session.hpp +13 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/wire/codec.hpp +27 -4
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/wire/protocol.hpp +14 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/package.json +6 -7
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/src/domains/exec.cpp +14 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/src/graphql/error_extensions.hpp +4 -0
- crowdypy-0.9.0.dev1/vendor/CrowdyCPP/src/media/opus.cpp +119 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/src/replication/connection.cpp +22 -7
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/src/session/world_session.cpp +6 -10
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/tools/parity/fixtures/crowdy-studio-diagnostics.v1.json +2 -2
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/tools/parity/fixtures/crowdyjs-studio-layout.v1.json +2 -2
- crowdypy-0.9.0.dev1/vendor/CrowdyCPP/tools/parity/fixtures/voice-frames.json +941 -0
- crowdypy-0.7.0.dev1/src/crowdypy/_sync/domains/users.py +0 -45
- crowdypy-0.7.0.dev1/src/crowdypy/domains/users.py +0 -44
- crowdypy-0.7.0.dev1/src/crowdypy/media.py +0 -140
- crowdypy-0.7.0.dev1/vendor/CrowdyCPP/cmake/CrowdyCPPConfig.cmake.in +0 -15
- crowdypy-0.7.0.dev1/vendor/CrowdyCPP/include/crowdy/domains/users.hpp +0 -83
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/.gitattributes +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/.gitignore +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/.gitleaks.toml +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/LICENSE +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/SECURITY.md +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/benchmarks/bench_replication.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/licenses/OpenSSL-LICENSE.txt +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/actors/Actor.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/actors/Actors.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/actors/BatchLookupActors.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/actors/CreateActor.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/actors/DeleteActor.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/actors/UpdateActor.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/actors/UpdateActorState.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/appAccess/AppAccessTiers.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/appAccess/AppFeatures.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/appAccess/AppGrantMemberCandidates.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/appAccess/ArchiveAccessTier.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/appAccess/CreateAccessTier.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/appAccess/DefineAppFeature.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/appAccess/GrantTierFeature.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/appAccess/RevokeTierFeature.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/appAccess/RuntimePermissions.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/appAccess/TierFeatures.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/appAccess/UpdateAccessTier.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/apps/AppBySlug.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/apps/AppDiscovery.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/apps/AppsForOrg.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/apps/ArchiveApp.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/apps/CodeAdmissions.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/apps/CreateApp.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/apps/MarketplaceApps.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/apps/MyApps.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/apps/PlaceableDatacenters.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/auth/Logout.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/auth/LogoutAllDevices.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/avatars/Avatars.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/billing/AppBudget.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/billing/AppBudgets.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/billing/SetAppBudget.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/billing/WalletBalance.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/billing/WalletTransactions.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/channels/AddChannelMember.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/channels/Channel.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/channels/ChannelMembers.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/channels/ChannelPolicy.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/channels/ChannelRoles.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/channels/Channels.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/channels/CreateChannel.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/channels/CreateChannelRole.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/channels/DeleteChannel.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/channels/DeleteChannelRole.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/channels/JoinChannel.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/channels/LeaveChannel.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/channels/MyChannels.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/channels/RemoveChannelMember.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/channels/RequestToJoinChannel.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/channels/SetChannelMemberRoles.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/channels/SetChannelPolicy.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/channels/UpdateChannel.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/channels/UpdateChannelRole.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/chunks/GetChunkLods.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/chunks/GetVoxelList.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/chunks/UpdateChunk.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/chunks/UpdateChunkLods.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/chunks/UpdateChunkState.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/crowdyStudio/CrowdyStudio.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/gameApps/GameApps.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/grids/CreateGridChannel.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/grids/GridChannels.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/grids/MintGridToken.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/host/Host.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/inputLog/InputLogMessages.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/inputLog/InputLogSessions.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/marketplace/Marketplace.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/organizations/CreateOrgRole.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/organizations/CreateOrgToken.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/organizations/CreateOrganization.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/organizations/DeleteOrgRole.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/organizations/InviteOrgMember.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/organizations/MemberRoles.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/organizations/MyOrganizations.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/organizations/OrgMembers.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/organizations/OrgPermissions.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/organizations/OrgRoles.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/organizations/OrgTokens.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/organizations/Organization.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/organizations/OrganizationBySlug.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/organizations/RemoveOrgMember.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/organizations/RevokeOrgToken.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/organizations/UpdateOrgMemberRoles.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/organizations/UpdateOrgRole.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/organizations/UpdateOrgToken.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/payments/CapturePaypalCheckout.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/payments/CreateCheckout.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/payments/MyCheckouts.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/platform/PlatformConfig.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/playerWallet/PlayerWallet.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/quotas/DeleteQuota.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/quotas/EffectiveQuota.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/quotas/QuotasForApp.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/quotas/QuotasForOrg.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/quotas/SetQuota.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/serverStatus/ActiveGraphQLServers.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/serverStatus/GraphqlServers.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/serverStatus/ServerWithLeastClients.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/serverStatus/VersionInfo.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/sharedEnvironment/SharedEnvironment.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/state/DeleteUserAppState.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/state/UpdateUserAppState.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/state/UserAppState.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/state/UserAppStates.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/teams/AddTeamMember.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/teams/CreateTeam.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/teams/CreateTeamRole.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/teams/DeleteTeam.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/teams/DeleteTeamRole.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/teams/JoinTeam.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/teams/LeaveTeam.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/teams/MyTeams.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/teams/RemoveTeamMember.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/teams/RequestToJoinTeam.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/teams/SetTeamMemberRoles.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/teams/SetTeamPolicy.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/teams/Team.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/teams/TeamMembers.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/teams/TeamPolicy.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/teams/TeamRoles.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/teams/Teams.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/teams/UpdateTeam.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/teams/UpdateTeamRole.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/teleport/TeleportRequest.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/usage/AppGraphqlOperations.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/usage/AppUsageSummary.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/usage/PlayerPulse.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/users/DeleteMyAccount.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/users/FreePlayWindow.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/users/Me.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/users/UpdateGamertag.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/users/UpdateUserState.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/users/User.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/voxels/ListVoxelUpdatesByDistance.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/voxels/ListVoxels.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/voxels/RollbackVoxelUpdates.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/voxels/UpdateVoxel.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/voxels/VoxelUpdateHistory.graphql +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/scripts/_pins.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/scripts/ci/assert_default_origin.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/scripts/ci/build_openssl.sh +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/scripts/ci/check_content_policy.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/scripts/ci/check_pin_tiers.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/scripts/ci/cibw_before_all_linux.sh +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/scripts/ci/resolve-release-tier.sh +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/scripts/ci/resolve-release-tier.test.sh +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/scripts/ci/resolve_pypi_version.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/scripts/ci/stamp_version.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/scripts/ci/verify_artifacts.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/scripts/codegen.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/scripts/schema_drift.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/scripts/schema_sync.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/scripts/unasync.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/scripts/vendor_crowdycpp.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_concurrency.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_default_origin.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_generated/__init__.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_grid.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_native.pyi +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_operation.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/__init__.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/client.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/domains/__init__.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/domains/_base.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/domains/actors.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/domains/admin.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/domains/auth.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/domains/avatars.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/domains/billing.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/domains/crowdy_studio.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/domains/crowdy_studio_agent.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/domains/crowdy_studio_github.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/domains/discovery.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/domains/game_apps.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/domains/host.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/domains/input_log.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/domains/marketplace.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/domains/organizations.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/domains/payments.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/domains/platform.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/domains/player_wallet.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/domains/quotas.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/domains/shared_environment.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/domains/state.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/domains/teams.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/domains/teleport.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/domains/usage.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/domains/voxels.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/graphql.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/kit/__init__.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/kit/actions.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/kit/kit.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/kit/social.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/kit/wire.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/rediscover.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/world.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/auth_state.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/client.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/codecs.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/datacenter_redirect.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/domains/__init__.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/domains/_base.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/domains/actors.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/domains/admin.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/domains/auth.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/domains/avatars.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/domains/billing.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/domains/crowdy_studio.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/domains/crowdy_studio_agent.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/domains/crowdy_studio_github.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/domains/discovery.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/domains/game_apps.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/domains/host.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/domains/input_log.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/domains/marketplace.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/domains/organizations.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/domains/payments.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/domains/platform.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/domains/player_wallet.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/domains/quotas.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/domains/shared_environment.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/domains/state.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/domains/teams.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/domains/teleport.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/domains/usage.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/domains/voxels.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/enums.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/estate.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/exec_gateway.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/graphql.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/inputs.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/kit/__init__.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/kit/actions.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/kit/kit.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/kit/social.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/kit/wire.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/lb_cookie.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/pkce.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/player_host/__init__.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/player_host/agent_errors.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/player_host/agent_types.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/player_host/json_schema.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/player_host/schemas.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/player_host/types.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/py.typed +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/rediscover.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/session.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/studio/__init__.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/studio/client_tick_interval.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/studio/controller.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/studio/diagnostics.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/studio/github_new_repo.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/studio/layout.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/studio/models.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/studio/starter_projects.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/subscriptions.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/sync.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/utils.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/world.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/conftest.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/e2e/__init__.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/e2e/conftest.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/e2e/test_e2e_identity.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/e2e/test_e2e_open_grid_exec_gateway.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/e2e/test_e2e_ranged_channel.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/e2e/test_e2e_replication.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/e2e/test_e2e_studio.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/e2e/test_e2e_world.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/e2e/test_e2e_world_data.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/fixtures/binary-wire-fixtures.json +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/fixtures/exec-client-frames.json +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/unit/__init__.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/unit/domains/__init__.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/unit/domains/test_crowdycpp_roots.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/unit/domains/test_social_domains.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/unit/domains/test_world_domains.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/unit/test_core.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/unit/test_estate_moves.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/unit/test_exec_gateway.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/unit/test_kit.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/unit/test_lazy_exports.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/unit/test_player_host.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/unit/test_release_versions.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/unit/test_sdk_audience.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/unit/test_studio_controller.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/unit/test_studio_diagnostics.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/unit/test_studio_layout.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/unit/test_subscriptions.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/unit/test_transport.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tools/e2e/provision.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tools/fixtures/player_host.mjs +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tools/parity/parity.py +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/LICENSE +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/cmake/CheckPublicHeaders.cmake +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/cmake/studio_layout_fixture.hpp.in +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/client.hpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/core/base64.hpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/core/bytes.hpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/core/clock.hpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/core/crypto.hpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/core/logger.hpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/core/result.hpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/core/spsc.hpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/core/uuid.hpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/crowdy.hpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/default_origin.hpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/domains/auth.hpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/domains/crowdy_studio.hpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/domains/crowdy_studio_agent.hpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/domains/crowdy_studio_github.hpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/domains/discovery.hpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/domains/domain_base.hpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/domains/game_apps.hpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/domains/marketplace.hpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/domains/player_wallet.hpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/domains/realtime_control.hpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/domains/server_status.hpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/domains/world_data.hpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/graphql/async_scope.hpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/graphql/auth_state.hpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/graphql/datacenter_redirect.hpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/graphql/dispatcher.hpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/graphql/estate.hpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/graphql/graphql_client.hpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/graphql/http.hpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/graphql/json.hpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/graphql/rediscover.hpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/graphql/subscription_client.hpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/graphql/websocket.hpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/kit/actions.hpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/kit/kit.hpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/kit/social.hpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/kit/wire.hpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/media/video_frames.hpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/player_host/adapter.hpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/player_host/player_host.hpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/player_host/schemas.hpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/player_host/types.hpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/replication/session_provider.hpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/replication/udp_socket.hpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/session/codec.hpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/session/durable.hpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/session/keys.hpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/studio/controller.hpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/studio/diagnostics.hpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/studio/editor.hpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/studio/github.hpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/studio/github_layout.hpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/studio/integration.hpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/studio/layout.hpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/studio/models.hpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/studio/runtime.hpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/world.hpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/src/client.cpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/src/core/base64.cpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/src/core/clock.cpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/src/core/crypto_default_unavailable.cpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/src/core/crypto_openssl.cpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/src/core/crypto_unavailable.cpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/src/core/logger.cpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/src/core/uuid.cpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/src/graphql/async_transport.cpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/src/graphql/auth_state.cpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/src/graphql/errors.cpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/src/graphql/graphql_client.cpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/src/graphql/http_curl.cpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/src/graphql/http_none.cpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/src/graphql/json.cpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/src/graphql/subscription_client.cpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/src/graphql/websocket_curl.cpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/src/graphql/websocket_none.cpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/src/player_host/schemas.cpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/src/player_host/types.cpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/src/replication/socket_errors.hpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/src/replication/udp_socket.cpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/src/studio/diagnostics.cpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/src/studio/editor.cpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/src/studio/integration.cpp +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/third_party/yyjson/LICENSE +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/third_party/yyjson/yyjson.c +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/third_party/yyjson/yyjson.h +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/tools/parity/fixtures/exec-client-frames.json +0 -0
- {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/tools/parity/fixtures/exec-gateway-cases.json +0 -0
|
@@ -60,7 +60,9 @@ python tools/parity/parity.py --crowdyjs ../CrowdyJS --write docs/parity-matrix.
|
|
|
60
60
|
```
|
|
61
61
|
|
|
62
62
|
then port what changed, refresh `tests/fixtures/` from the same commit, and classify or
|
|
63
|
-
cover every new difference.
|
|
63
|
+
cover every new difference. `tests/unit/test_fixture_provenance.py` holds each copied fixture
|
|
64
|
+
to its CrowdyJS source, and `exec-client-frames.json` and `voice-frames.json` to the vendored
|
|
65
|
+
CrowdyCPP copies too. Build CrowdyJS at the new pin (`npm ci && npm run build`) and run
|
|
64
66
|
`node tools/fixtures/player_host.mjs ../CrowdyJS`: it rewrites the player-host schemas and
|
|
65
67
|
their fixture, and `tests/unit/test_player_host.py` refuses either one from another commit. Moving the CrowdyCPP pin:
|
|
66
68
|
|
|
@@ -145,5 +147,24 @@ The replication system saturates the local network stack, so the binding
|
|
|
145
147
|
- Sends are batched, and the GIL is released while a batch is encoded and sent.
|
|
146
148
|
- An asyncio loop is woken through `Config::onEventsReady` and a socket pair, never by a
|
|
147
149
|
sleep-poll.
|
|
150
|
+
- While a World Stores session is attached it owns the connection's handlers. What its stores
|
|
151
|
+
do not keep (audio, video, text, opcode 140, channel audio) is forwarded into the batch
|
|
152
|
+
rows; voxel updates are forwarded only once Python watches them (`watch_voxels`, set by
|
|
153
|
+
`session.on("voxel_update")`), since the chunk store already merges every one.
|
|
148
154
|
- Every change to the hot path reruns `benchmarks/bench_replication.py` and CrowdyCPP's
|
|
149
155
|
`bench_send` on the same machine, and updates `benchmarks/README.md`.
|
|
156
|
+
|
|
157
|
+
## The native session and its chunk store
|
|
158
|
+
|
|
159
|
+
- The session is built without host election and with native write-back off. Both are
|
|
160
|
+
GraphQL work the Python facade does on its timers.
|
|
161
|
+
- Its chunk source, `StagedChunks` in `native/session_binding.cpp`, only applies what the
|
|
162
|
+
facade loaded. `ChunkStore.hydrate()` and `prune_beyond()` hand a chunk to it through
|
|
163
|
+
`WorldSession.hydrate`, so stored edits follow CrowdyCPP's overlay rules: an edit the
|
|
164
|
+
16x16x16 one-byte grid cannot hold goes to `ChunkData::overlay`.
|
|
165
|
+
- Do not write voxel types or states into the dense grid from Python. That bypasses the
|
|
166
|
+
overlay, and the echo matching of local edits.
|
|
167
|
+
- The voice helpers (`native/voice_binding.cpp`) bind CrowdyCPP's `voice_frames.hpp`.
|
|
168
|
+
`crowdypy.media` checks every argument as CrowdyJS does first, because CrowdyCPP clamps the
|
|
169
|
+
options CrowdyJS refuses.
|
|
170
|
+
- `CROWDY_WITH_OPUS` stays `OFF` in `pyproject.toml`: the wheels link no audio codec.
|
|
@@ -3,6 +3,128 @@
|
|
|
3
3
|
CrowdyPy is pre-1.0. Within a minor line, patch releases keep source compatibility; each
|
|
4
4
|
new minor may change the API. Read the section for every minor you skip.
|
|
5
5
|
|
|
6
|
+
## 0.9.0
|
|
7
|
+
|
|
8
|
+
CrowdyJS 18.8.0 and CrowdyCPP 0.61.0. Additive, with one floor: the build documents select
|
|
9
|
+
`ExecBuild.sdkVersion`, so `exec.build`, `build_status`, `wait_for_build`, `mod_build`,
|
|
10
|
+
`mod_client_build`, `mod_build_status` and `wait_for_mod_build` need ck-api v2.40.2 (an older
|
|
11
|
+
one refuses the selection).
|
|
12
|
+
|
|
13
|
+
- **`ExecBuild.sdk_version`**: the version of `ckx-sdk` the platform compiled the build against
|
|
14
|
+
(`crowdy-client-sdk` for a CLIENT half), from the toolchain of the API instance that ran it. The
|
|
15
|
+
platform points a crate at its own copy of the SDK whatever version the crate names, so this,
|
|
16
|
+
not your manifest, says what your code was checked against. `None` until the build starts.
|
|
17
|
+
|
|
18
|
+
## 0.8.0
|
|
19
|
+
|
|
20
|
+
CrowdyJS 18.7.0 and CrowdyCPP 0.60.0. Additive, with reads that change for values they used to
|
|
21
|
+
get wrong (wide voxels) and one new floor: every token mutation (`portal.mint_app_token`,
|
|
22
|
+
`exchange_code`, `refresh`) selects `runtimeGate`, so 0.8.0 needs the ck-api release after
|
|
23
|
+
v2.39.0 that serves it; an older one refuses the selection. Channel audio and the echo of your
|
|
24
|
+
own voxel edits need replication server v0.37.0.
|
|
25
|
+
|
|
26
|
+
- **Voice helpers** (`crowdypy.media`), an optional convention for what an audio payload
|
|
27
|
+
carries: a 10-byte little-endian header in front of each codec frame (version 1, codec 0 raw,
|
|
28
|
+
1 Opus 48 kHz mono or 2 G.711 µ-law 8 kHz, `u16` seq, `u32` timestamp in codec samples,
|
|
29
|
+
the frame's duration in ms, and the talk-spurt flags `VoiceFlag.SPURT_START` and
|
|
30
|
+
`SPURT_END`).
|
|
31
|
+
- `encode_voice_header(VoiceHeader(...))` and `encode_voice_packet(header, frame)` write it;
|
|
32
|
+
`decode_voice_packet(packet)` returns `None` for a packet shorter than 10 bytes or of
|
|
33
|
+
another version, and never raises on bytes from the network.
|
|
34
|
+
- `VoicePacketizer(codec, frame_ms, *, seq=0, timestamp=0)` numbers one sender's frames
|
|
35
|
+
across the seq and timestamp wraps (`packetize(frame, last=)`, `skip(frames)` for
|
|
36
|
+
silence).
|
|
37
|
+
- `VoiceJitterBuffer(target_delay_ms=60, max_frames=64, reset_after_ms=200)`:
|
|
38
|
+
`push(key, packet, now_ms)` answers `"buffered"`, `"late"`, `"duplicate"` or
|
|
39
|
+
`"malformed"`, and `pull(key, now_ms)` / `poll(now_ms)` return the due `VoicePlayout`s in
|
|
40
|
+
seq order, a gap (`frame` `None`) for each frame that never came.
|
|
41
|
+
- CrowdyCPP's implementation runs natively. Arguments are checked as CrowdyJS checks them, so
|
|
42
|
+
an option or field out of range raises `ValueError` where CrowdyCPP would clamp it.
|
|
43
|
+
- The helpers replay CrowdyJS's `voice-frames.json` byte for byte.
|
|
44
|
+
- No codec ships, and the wheel links none: which codec an app uses, and the library that
|
|
45
|
+
encodes it, is the app's choice.
|
|
46
|
+
- **Channel audio** (party and guild voice).
|
|
47
|
+
- `client.udp.send_channel_audio(channel_id, uuid, payload)` sends message type 35, the
|
|
48
|
+
channel message's layout and signing with its own type byte, at most 1,024 bytes. It needs
|
|
49
|
+
the channel's `send_voice` and the player's `use_voice_chat`; without them the server
|
|
50
|
+
answers `UNAUTHORIZED` for the returned sequence. The sender gets no echo.
|
|
51
|
+
- Members receive message type 36, standalone or bundled, on the new `channel_audio` handler
|
|
52
|
+
of `udp.subscribe` (`notification.channel_id`, the sender's `uuid`, `payload`).
|
|
53
|
+
- In the World Stores it is `session.on("channel_audio", ...)`; the channel inbox does not
|
|
54
|
+
get it. Key a jitter buffer by channel and sender, so one player in two channels is two
|
|
55
|
+
streams.
|
|
56
|
+
- `channels.create`, `grids.create_channel` and `GridScope.channels.create` take
|
|
57
|
+
`members_can_speak` (default false), which gives the member role `send_voice`.
|
|
58
|
+
`GridScope.channels.send_audio(channel_id, uuid, payload)` sends on the grid's channels.
|
|
59
|
+
- Underneath are `ReplicationConnection.send_channel_audio`, and
|
|
60
|
+
`crowdypy.wire.encode_channel_audio` and `ChannelAudioNotification` (from `parse_datagram`)
|
|
61
|
+
for a custom transport.
|
|
62
|
+
- **App-defined spatial messages** (`GENERIC_SPATIAL_1`, 140) reach
|
|
63
|
+
`session.on("generic_spatial", ...)` while a World Stores session is attached
|
|
64
|
+
(CrowdyCPP's `onGenericSpatial`). Without a session, `udp.subscribe`'s `generic_spatial`
|
|
65
|
+
already received them.
|
|
66
|
+
- **`session.on("voxel_update", ...)`** fires for every inbound voxel edit after
|
|
67
|
+
`session.chunks` merged it, with its sender, voxel and state: CrowdyCPP's `onVoxel`, for a
|
|
68
|
+
game that keeps its own world. It includes the echo of your own edits; compare the uuid and
|
|
69
|
+
sequence with your send's.
|
|
70
|
+
- **`ChunkStore` keeps wide voxel types and other addresses.** Positions and types are the app's
|
|
71
|
+
signed 16-bit values, which the platform does not check.
|
|
72
|
+
- An edit the 16x16x16 one-byte grid cannot hold (a type outside 0-255, a position outside
|
|
73
|
+
0-15) is kept whole in the chunk's overlay. That covers a realtime update, a hydrated
|
|
74
|
+
`voxelStates` entry and a local `set_voxel`.
|
|
75
|
+
- `ChunkStore.overlay(chunk)` returns the overlay as `ChunkOverlayVoxel(x, y, z,
|
|
76
|
+
voxel_type, state)` values keyed by `voxel_key(x, y, z)` (`"x:y:z"`), and `voxel_type_at`
|
|
77
|
+
and `voxel_state_at` read it first.
|
|
78
|
+
- What changes: hydration no longer stores a type outside 0-255 truncated (300 used to read
|
|
79
|
+
as 44), and keeps an entry outside 0-15 instead of skipping it. `voxels()` holds 0 under
|
|
80
|
+
an in-grid voxel whose type is in the overlay.
|
|
81
|
+
- `set_voxel` keeps a position outside 0-15 in the overlay and sends it, where it used to be
|
|
82
|
+
refused. It raises `ValueError`, before anything changes or is sent, for a position or type
|
|
83
|
+
outside 16 bits or a state over 1,024 bytes (`crowdypy.wire.assert_voxel_edit`,
|
|
84
|
+
`VOXEL_STATE_MAX_BYTES`).
|
|
85
|
+
- `udp.send_voxel_update` and `ReplicationConnection.send_voxel_update` refuse a state over
|
|
86
|
+
1,024 bytes (`CrowdyReplicationError`, `InvalidArgument`); the server refuses one with
|
|
87
|
+
`INVALID_REQUEST`.
|
|
88
|
+
- **The echo of your own voxel edit.** Replication server v0.37.0 delivers every accepted edit
|
|
89
|
+
back to its sender. `ChunkStore` matches the echo to the `set_voxel` that sent it (sender,
|
|
90
|
+
sequence, voxel) and does not apply it again, so a local edit fires `on_chunk_changed` once.
|
|
91
|
+
The echo is applied only when another client's edit of the voxel arrived in between (the
|
|
92
|
+
server ordered yours last).
|
|
93
|
+
- **Hydration goes through the native store.** `ChunkStore.hydrate()` hands each loaded chunk
|
|
94
|
+
to CrowdyCPP's `ChunkStore`, which puts the entries the grid cannot hold in the overlay. An
|
|
95
|
+
entry without a state now clears the voxel's state, also one a local `set_voxel` gave it (0.5.1
|
|
96
|
+
kept that until the next realtime update). `voxel_state_at` reads the native cache only, and
|
|
97
|
+
`prune_beyond` keeps a dirty chunk's states and overlay as well as its grid.
|
|
98
|
+
- **UDP error 33, `APP_PAUSED`** (`crowdypy.wire.ErrorCode.APP_PAUSED`): the replication
|
|
99
|
+
server refuses a paused app's sends.
|
|
100
|
+
- **Pause and access refusals.**
|
|
101
|
+
- `crowdypy.is_app_paused(gate)` reads `AppTokenResponse.runtime_gate` (`AppRuntimeGate`,
|
|
102
|
+
`status` and `reason`) and the `runtimeGate` of `server_status.game_client_bootstrap`.
|
|
103
|
+
Anything but `ACTIVE` is paused. A paused app still mints, so check before entering the
|
|
104
|
+
world.
|
|
105
|
+
- `crowdypy.app_paused_of(error)` reads `APP_PAUSED` (`reason`).
|
|
106
|
+
- `crowdypy.access_refusal_of(error)` reads `ACCESS_REVOKED`, `ACCESS_SUSPENDED`
|
|
107
|
+
(`suspended_until`) or `ACCESS_NOT_GRANTED`.
|
|
108
|
+
- `crowdypy.actor_exists_of(error)` reads `ACTOR_EXISTS` (`owned_by_caller`).
|
|
109
|
+
- Each reader takes a raised `CrowdyGraphQLError` or one raw error entry. The `*_CODE`
|
|
110
|
+
constants name the codes.
|
|
111
|
+
- **New API wraps.**
|
|
112
|
+
- `users.player_profile(user_id)` and `users.player_profiles(user_ids)` return the public
|
|
113
|
+
`userId`, `gamertag` and `disambiguation`. `player_profiles` takes at most
|
|
114
|
+
`PLAYER_PROFILES_MAX` (100) ids, raises `ValueError` above that, and sends nothing for
|
|
115
|
+
none. `users.get` documents that another user's private fields come back `None`.
|
|
116
|
+
- `app_access.suspend(app_id, user_id, until, idempotency_key=None)` takes a timezone-aware
|
|
117
|
+
`datetime` or an ISO-8601 string. With it come `unsuspend` and
|
|
118
|
+
`resync_tier_grid_permissions` (`manage_access_tiers`), and `suspendedUntil` on every
|
|
119
|
+
access record.
|
|
120
|
+
- `exec.restart_type(app_id, node_type)` returns `ExecRestartResult(node_type, stopped)`
|
|
121
|
+
(`manage_compute`). `ExecAppStatus` gains `budget_pause_reason`, `max_instances`,
|
|
122
|
+
`max_reserved_mb`, `instance_limit`, `instances` and `reserved_mb`.
|
|
123
|
+
- `apps.get` and `apps.update` carry `claimOwnerKeys`, chunk reads `voxelStatesTruncated`,
|
|
124
|
+
and `game_client_bootstrap` `runtimeGate` and `wildernessWritesOpen`.
|
|
125
|
+
- The keyframe and heartbeat defaults stay. Idle players on different servers meet at the first
|
|
126
|
+
full update after joining (replication server v0.37.0).
|
|
127
|
+
|
|
6
128
|
## 0.7.0
|
|
7
129
|
|
|
8
130
|
CrowdyJS 18.6.0 and CrowdyCPP 0.59.0. Additive.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: crowdypy
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.9.0.dev1
|
|
4
4
|
Summary: Official Python SDK for Crowded Kingdoms: typed GraphQL clients and a native UDP replication core
|
|
5
5
|
Keywords: crowded-kingdoms,multiplayer,replication,graphql,sdk,udp
|
|
6
6
|
Author: Crowded Kingdoms
|
|
@@ -51,20 +51,29 @@ CrowdyPy follows the [CrowdyJS](https://github.com/CrowdedKingdoms/CrowdyJS) API
|
|
|
51
51
|
client, bound with [nanobind](https://github.com/wjakob/nanobind) and shipped inside the
|
|
52
52
|
wheel. Python never touches a datagram.
|
|
53
53
|
|
|
54
|
-
**v0.
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
54
|
+
**v0.9.0: builds report the SDK they compiled against (CrowdyJS 18.8.0, CrowdyCPP 0.61.0).** See the 0.9.0
|
|
55
|
+
bullet below.
|
|
56
|
+
|
|
57
|
+
**v0.8.0: voice, channel audio, wide voxels, and pause and access refusals (CrowdyJS 18.7.0, CrowdyCPP 0.60.0).**
|
|
58
|
+
- Voice: `crowdypy.media`'s voice helpers (an optional 10-byte header per codec frame,
|
|
59
|
+
`VoicePacketizer`, `VoiceJitterBuffer`), and `client.udp.send_channel_audio()` with the
|
|
60
|
+
`channel_audio` handler, which reaches every member of a channel wherever they are (party
|
|
61
|
+
and guild voice).
|
|
62
|
+
- World Stores: `ChunkStore` keeps voxel edits the 16x16x16 one-byte grid cannot hold in an
|
|
63
|
+
overlay, and applies the echo of your own edit once. `session.on("voxel_update")` and
|
|
64
|
+
`session.on("generic_spatial")` reach a game that keeps its own world.
|
|
65
|
+
- Refusals: `crowdypy.is_app_paused()` reads the runtime gate that tokens and the bootstrap
|
|
66
|
+
carry, and `app_paused_of`, `access_refusal_of` and `actor_exists_of` read the new refusals.
|
|
67
|
+
- New calls: `users.player_profile(s)`, `app_access.suspend` and `unsuspend`, and
|
|
68
|
+
`exec.restart_type`.
|
|
69
|
+
- 0.9.0: every build (`exec.build`, `build_status`, `wait_for_build` and the mod builds) carries
|
|
70
|
+
`sdk_version`, the `ckx-sdk` (CLIENT half: `crowdy-client-sdk`) version the platform compiled it
|
|
71
|
+
against, whatever the crate names. It needs ck-api v2.40.2, since the build documents select it.
|
|
72
|
+
- 0.8.0 needs the ck-api release after v2.39.0, since the token mutations select
|
|
73
|
+
`runtimeGate`. Channel audio and the voxel echo need replication server v0.37.0.
|
|
74
|
+
- 0.7.0 brought the input log (`client.input_log.sessions()` and `messages()`, and
|
|
75
|
+
`replayLoggingEnabled`). 0.6.0 brought distance-limited channel messages
|
|
76
|
+
(`udp.send_ranged_channel_message()`) and the terms gate (`auth.record_player_consents()`).
|
|
68
77
|
- 0.5.1 made `ChunkStore.hydrate()` keep every recorded voxel edit (`voxelStates`) and
|
|
69
78
|
`ensure_around()` keep a chunk it already loaded.
|
|
70
79
|
- 0.5.0 brought the ck-exec gateway check (`client.exec.connect()` sends the connect token
|
|
@@ -180,6 +189,13 @@ is not serving) and `CrowdyUserCodeFaultError` (a player module faulted;
|
|
|
180
189
|
`player_fault_of(error)` reads the fault) mirror CrowdyJS. A `WRONG_DATACENTER` refusal
|
|
181
190
|
moves the client to the app's datacenter and retries once, by itself.
|
|
182
191
|
|
|
192
|
+
A paused app (its organization ran out of funds, hit a spend cap, or let a subscription
|
|
193
|
+
lapse) still mints a token, so check `crowdypy.is_app_paused(minted.runtime_gate)` before
|
|
194
|
+
entering the world, and tell the player it is paused. Replication then refuses sends with UDP
|
|
195
|
+
error 33 (`APP_PAUSED`). `crowdypy.app_paused_of(error)`, `access_refusal_of(error)`
|
|
196
|
+
(`ACCESS_REVOKED`, `ACCESS_SUSPENDED` with `suspended_until`, `ACCESS_NOT_GRANTED`) and
|
|
197
|
+
`actor_exists_of(error)` read those refusals. None of them clears by retrying.
|
|
198
|
+
|
|
183
199
|
## Replication
|
|
184
200
|
|
|
185
201
|
```python
|
|
@@ -207,6 +223,47 @@ async for batch in conn.batches():
|
|
|
207
223
|
`crowdypy.replication.ReplicationConnection` is the same for code without an event loop:
|
|
208
224
|
`wait()` and then `poll()` from your own loop.
|
|
209
225
|
|
|
226
|
+
Voxel positions and types are the app's signed 16-bit values, and a voxel state is at most
|
|
227
|
+
1,024 bytes (`InvalidArgument` otherwise, nothing sent). Replication server v0.37.0 echoes
|
|
228
|
+
every accepted voxel edit back to its sender as a `voxel_update`.
|
|
229
|
+
|
|
230
|
+
## Voice
|
|
231
|
+
|
|
232
|
+
`send_audio_packet` reaches players near a chunk and carries whatever bytes it is given; a game
|
|
233
|
+
with a voice format of its own keeps it. The voice helpers in `crowdypy.media` are an optional
|
|
234
|
+
format that every Crowded Kingdoms SDK shares, byte for byte. Each packet is a 10-byte header
|
|
235
|
+
(version 1, the codec, a `u16` seq, a `u32` timestamp in codec samples, the frame's duration
|
|
236
|
+
and two talk-spurt flags) followed by one codec frame. `VoicePacketizer` numbers one sender's
|
|
237
|
+
frames. `VoiceJitterBuffer` puts each sender's packets back in order and plays them out 60 ms
|
|
238
|
+
after the first packet of a talk spurt arrived. It reports a frame that never came as a gap,
|
|
239
|
+
drops one that arrives after its playout time, and holds at most 64 frames a sender.
|
|
240
|
+
|
|
241
|
+
`send_channel_audio` reaches every member of a channel wherever they are (party or guild
|
|
242
|
+
voice), at most 1,024 bytes a packet. The sender needs the channel's `send_voice`
|
|
243
|
+
(`members_can_speak=True` on creation gives it to the member role) and the player's
|
|
244
|
+
`use_voice_chat`. There is no echo, and members receive `channel_audio`:
|
|
245
|
+
|
|
246
|
+
```python
|
|
247
|
+
from crowdypy.media import VoiceCodec, VoiceJitterBuffer, VoicePacketizer
|
|
248
|
+
|
|
249
|
+
party = VoicePacketizer(VoiceCodec.OPUS, 20)
|
|
250
|
+
# Every 20 ms while the player talks (`opus_frame` from your own encoder):
|
|
251
|
+
await game.udp.send_channel_audio(channel_id, my_uuid, party.packetize(opus_frame, last=released))
|
|
252
|
+
# ...and party.skip() for every 20 ms of silence that is not sent.
|
|
253
|
+
|
|
254
|
+
voices = VoiceJitterBuffer()
|
|
255
|
+
game.udp.subscribe({"channel_audio": lambda n: voices.push(f"{n.channel_id}:{n.uuid}", n.payload)})
|
|
256
|
+
for slot in voices.poll(): # at least once a frame, from your audio clock
|
|
257
|
+
if slot.gap:
|
|
258
|
+
conceal(slot.key, slot.frame_ms) # the frame never came
|
|
259
|
+
else:
|
|
260
|
+
play(slot.key, slot.codec, slot.frame)
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
No codec ships with CrowdyPy, and the wheel links none: which codec an app uses (Opus, or
|
|
264
|
+
G.711 µ-law where it has no Opus), and the library that encodes and decodes it, is the app's
|
|
265
|
+
choice. Where a voice sits in the world (panning, distance attenuation) is the game's too.
|
|
266
|
+
|
|
210
267
|
## World Stores
|
|
211
268
|
|
|
212
269
|
```python
|
|
@@ -223,6 +280,12 @@ snapshot = session.actors.snapshot() # once a frame: every actor at once
|
|
|
223
280
|
states = pose.decode_many(snapshot.state_offsets, snapshot.state_data) # numpy, no loop
|
|
224
281
|
```
|
|
225
282
|
|
|
283
|
+
`session.chunks` is a helper for 16x16x16 chunks with one byte per voxel. An edit that grid
|
|
284
|
+
cannot hold (a type outside 0-255, a position outside 0-15) is kept in the chunk's
|
|
285
|
+
`overlay()`, and `voxel_type_at` reads it first. The echo of your own `set_voxel` is not
|
|
286
|
+
applied a second time. A game with other addressing reads every edit from
|
|
287
|
+
`session.on("voxel_update", ...)`, which includes those echoes.
|
|
288
|
+
|
|
226
289
|
## Crowdy Studio
|
|
227
290
|
|
|
228
291
|
```python
|
|
@@ -11,20 +11,29 @@ CrowdyPy follows the [CrowdyJS](https://github.com/CrowdedKingdoms/CrowdyJS) API
|
|
|
11
11
|
client, bound with [nanobind](https://github.com/wjakob/nanobind) and shipped inside the
|
|
12
12
|
wheel. Python never touches a datagram.
|
|
13
13
|
|
|
14
|
-
**v0.
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
14
|
+
**v0.9.0: builds report the SDK they compiled against (CrowdyJS 18.8.0, CrowdyCPP 0.61.0).** See the 0.9.0
|
|
15
|
+
bullet below.
|
|
16
|
+
|
|
17
|
+
**v0.8.0: voice, channel audio, wide voxels, and pause and access refusals (CrowdyJS 18.7.0, CrowdyCPP 0.60.0).**
|
|
18
|
+
- Voice: `crowdypy.media`'s voice helpers (an optional 10-byte header per codec frame,
|
|
19
|
+
`VoicePacketizer`, `VoiceJitterBuffer`), and `client.udp.send_channel_audio()` with the
|
|
20
|
+
`channel_audio` handler, which reaches every member of a channel wherever they are (party
|
|
21
|
+
and guild voice).
|
|
22
|
+
- World Stores: `ChunkStore` keeps voxel edits the 16x16x16 one-byte grid cannot hold in an
|
|
23
|
+
overlay, and applies the echo of your own edit once. `session.on("voxel_update")` and
|
|
24
|
+
`session.on("generic_spatial")` reach a game that keeps its own world.
|
|
25
|
+
- Refusals: `crowdypy.is_app_paused()` reads the runtime gate that tokens and the bootstrap
|
|
26
|
+
carry, and `app_paused_of`, `access_refusal_of` and `actor_exists_of` read the new refusals.
|
|
27
|
+
- New calls: `users.player_profile(s)`, `app_access.suspend` and `unsuspend`, and
|
|
28
|
+
`exec.restart_type`.
|
|
29
|
+
- 0.9.0: every build (`exec.build`, `build_status`, `wait_for_build` and the mod builds) carries
|
|
30
|
+
`sdk_version`, the `ckx-sdk` (CLIENT half: `crowdy-client-sdk`) version the platform compiled it
|
|
31
|
+
against, whatever the crate names. It needs ck-api v2.40.2, since the build documents select it.
|
|
32
|
+
- 0.8.0 needs the ck-api release after v2.39.0, since the token mutations select
|
|
33
|
+
`runtimeGate`. Channel audio and the voxel echo need replication server v0.37.0.
|
|
34
|
+
- 0.7.0 brought the input log (`client.input_log.sessions()` and `messages()`, and
|
|
35
|
+
`replayLoggingEnabled`). 0.6.0 brought distance-limited channel messages
|
|
36
|
+
(`udp.send_ranged_channel_message()`) and the terms gate (`auth.record_player_consents()`).
|
|
28
37
|
- 0.5.1 made `ChunkStore.hydrate()` keep every recorded voxel edit (`voxelStates`) and
|
|
29
38
|
`ensure_around()` keep a chunk it already loaded.
|
|
30
39
|
- 0.5.0 brought the ck-exec gateway check (`client.exec.connect()` sends the connect token
|
|
@@ -140,6 +149,13 @@ is not serving) and `CrowdyUserCodeFaultError` (a player module faulted;
|
|
|
140
149
|
`player_fault_of(error)` reads the fault) mirror CrowdyJS. A `WRONG_DATACENTER` refusal
|
|
141
150
|
moves the client to the app's datacenter and retries once, by itself.
|
|
142
151
|
|
|
152
|
+
A paused app (its organization ran out of funds, hit a spend cap, or let a subscription
|
|
153
|
+
lapse) still mints a token, so check `crowdypy.is_app_paused(minted.runtime_gate)` before
|
|
154
|
+
entering the world, and tell the player it is paused. Replication then refuses sends with UDP
|
|
155
|
+
error 33 (`APP_PAUSED`). `crowdypy.app_paused_of(error)`, `access_refusal_of(error)`
|
|
156
|
+
(`ACCESS_REVOKED`, `ACCESS_SUSPENDED` with `suspended_until`, `ACCESS_NOT_GRANTED`) and
|
|
157
|
+
`actor_exists_of(error)` read those refusals. None of them clears by retrying.
|
|
158
|
+
|
|
143
159
|
## Replication
|
|
144
160
|
|
|
145
161
|
```python
|
|
@@ -167,6 +183,47 @@ async for batch in conn.batches():
|
|
|
167
183
|
`crowdypy.replication.ReplicationConnection` is the same for code without an event loop:
|
|
168
184
|
`wait()` and then `poll()` from your own loop.
|
|
169
185
|
|
|
186
|
+
Voxel positions and types are the app's signed 16-bit values, and a voxel state is at most
|
|
187
|
+
1,024 bytes (`InvalidArgument` otherwise, nothing sent). Replication server v0.37.0 echoes
|
|
188
|
+
every accepted voxel edit back to its sender as a `voxel_update`.
|
|
189
|
+
|
|
190
|
+
## Voice
|
|
191
|
+
|
|
192
|
+
`send_audio_packet` reaches players near a chunk and carries whatever bytes it is given; a game
|
|
193
|
+
with a voice format of its own keeps it. The voice helpers in `crowdypy.media` are an optional
|
|
194
|
+
format that every Crowded Kingdoms SDK shares, byte for byte. Each packet is a 10-byte header
|
|
195
|
+
(version 1, the codec, a `u16` seq, a `u32` timestamp in codec samples, the frame's duration
|
|
196
|
+
and two talk-spurt flags) followed by one codec frame. `VoicePacketizer` numbers one sender's
|
|
197
|
+
frames. `VoiceJitterBuffer` puts each sender's packets back in order and plays them out 60 ms
|
|
198
|
+
after the first packet of a talk spurt arrived. It reports a frame that never came as a gap,
|
|
199
|
+
drops one that arrives after its playout time, and holds at most 64 frames a sender.
|
|
200
|
+
|
|
201
|
+
`send_channel_audio` reaches every member of a channel wherever they are (party or guild
|
|
202
|
+
voice), at most 1,024 bytes a packet. The sender needs the channel's `send_voice`
|
|
203
|
+
(`members_can_speak=True` on creation gives it to the member role) and the player's
|
|
204
|
+
`use_voice_chat`. There is no echo, and members receive `channel_audio`:
|
|
205
|
+
|
|
206
|
+
```python
|
|
207
|
+
from crowdypy.media import VoiceCodec, VoiceJitterBuffer, VoicePacketizer
|
|
208
|
+
|
|
209
|
+
party = VoicePacketizer(VoiceCodec.OPUS, 20)
|
|
210
|
+
# Every 20 ms while the player talks (`opus_frame` from your own encoder):
|
|
211
|
+
await game.udp.send_channel_audio(channel_id, my_uuid, party.packetize(opus_frame, last=released))
|
|
212
|
+
# ...and party.skip() for every 20 ms of silence that is not sent.
|
|
213
|
+
|
|
214
|
+
voices = VoiceJitterBuffer()
|
|
215
|
+
game.udp.subscribe({"channel_audio": lambda n: voices.push(f"{n.channel_id}:{n.uuid}", n.payload)})
|
|
216
|
+
for slot in voices.poll(): # at least once a frame, from your audio clock
|
|
217
|
+
if slot.gap:
|
|
218
|
+
conceal(slot.key, slot.frame_ms) # the frame never came
|
|
219
|
+
else:
|
|
220
|
+
play(slot.key, slot.codec, slot.frame)
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
No codec ships with CrowdyPy, and the wheel links none: which codec an app uses (Opus, or
|
|
224
|
+
G.711 µ-law where it has no Opus), and the library that encodes and decodes it, is the app's
|
|
225
|
+
choice. Where a voice sits in the world (panning, distance attenuation) is the game's too.
|
|
226
|
+
|
|
170
227
|
## World Stores
|
|
171
228
|
|
|
172
229
|
```python
|
|
@@ -183,6 +240,12 @@ snapshot = session.actors.snapshot() # once a frame: every actor at once
|
|
|
183
240
|
states = pose.decode_many(snapshot.state_offsets, snapshot.state_data) # numpy, no loop
|
|
184
241
|
```
|
|
185
242
|
|
|
243
|
+
`session.chunks` is a helper for 16x16x16 chunks with one byte per voxel. An edit that grid
|
|
244
|
+
cannot hold (a type outside 0-255, a position outside 0-15) is kept in the chunk's
|
|
245
|
+
`overlay()`, and `voxel_type_at` reads it first. The echo of your own `set_voxel` is not
|
|
246
|
+
applied a second time. A game with other addressing reads every edit from
|
|
247
|
+
`session.on("voxel_update", ...)`, which includes those echoes.
|
|
248
|
+
|
|
186
249
|
## Crowdy Studio
|
|
187
250
|
|
|
188
251
|
```python
|
|
@@ -93,3 +93,23 @@ A 60 Hz asyncio loop sends 200 entities a frame (one batch) while about 60,000
|
|
|
93
93
|
notifications a second arrive and are dispatched to a handler. Lateness of each frame
|
|
94
94
|
against its schedule, ten seconds: p50 0.1 ms, p99 0.1 ms, max 0.2 ms. Receiving never
|
|
95
95
|
holds the loop: it is woken once per batch, not per datagram.
|
|
96
|
+
|
|
97
|
+
## Re-check, 0.8.0
|
|
98
|
+
|
|
99
|
+
0.8.0 added handlers to the binding (channel audio, and the session's forwarding of
|
|
100
|
+
app-defined spatial messages, channel audio and watched voxel updates) and re-vendored
|
|
101
|
+
CrowdyCPP 0.60.0. Both builds below ran back to back on the CKS builder (the machine above),
|
|
102
|
+
under CPython 3.12.3 and the system's shared OpenSSL 3.0.13 rather than the wheels' static
|
|
103
|
+
3.5.9, so compare them with each other, not with the 0.2.0 tables.
|
|
104
|
+
|
|
105
|
+
| | 0.7.0 (CrowdyCPP 0.59.0) | 0.8.0 (CrowdyCPP 0.60.0) |
|
|
106
|
+
|---|---|---|
|
|
107
|
+
| 1a. `send_actor_updates`, one batch of 200 | 647.1 ns/entity | 647.2 ns/entity |
|
|
108
|
+
| 1a. `native.send_spatial` x200 | 838.1 ns/entity | 840.1 ns/entity |
|
|
109
|
+
| 2. notifications delivered to Python, three interleaved runs | 1.774, 1.763, 1.765 million/s | 1.774, 1.762, 1.772 million/s |
|
|
110
|
+
| 4. echo round trip, p50 | 74.8 µs | 74.8 µs |
|
|
111
|
+
| 5. game-loop lateness, p99 | 0.3 ms | 0.2 ms |
|
|
112
|
+
|
|
113
|
+
CrowdyCPP 0.60.0's own `bench_send` section 5 (`sendActorUpdate` x200, Release, same machine
|
|
114
|
+
and OpenSSL) measured 623.9 ns/entity, so one batch costs 1.04x CrowdyCPP's send path per
|
|
115
|
+
entity (1.06x at 0.2.0).
|
|
@@ -5,7 +5,7 @@ are in `pyproject.toml` (`[project].version`, `[tool.crowdypy.crowdyjs]`,
|
|
|
5
5
|
`[tool.crowdypy.crowdycpp]`); `tests/unit/test_release_versions.py` refuses this page when
|
|
6
6
|
its version disagrees.
|
|
7
7
|
|
|
8
|
-
- CrowdyPy `0.
|
|
8
|
+
- CrowdyPy `0.9.0`
|
|
9
9
|
- API surface: CrowdyJS (the pinned version and commit in `pyproject.toml`); the generated
|
|
10
10
|
`docs/parity-matrix.md` lists every covered method, every native equivalent and every
|
|
11
11
|
browser exclusion with its reason. The gate is strict: there are no portable gaps, and a
|
|
@@ -43,3 +43,12 @@ requirement names one exactly, the same way a caret never matches an npm prerele
|
|
|
43
43
|
waits for both consents (`LEGAL_ACCEPTANCE_REQUIRED`).
|
|
44
44
|
- `udp.send_ranged_channel_message` needs a replication server that serves message type 32
|
|
45
45
|
(CHANNEL_MESSAGE_RANGED_REQUEST); one that does not delivers nothing.
|
|
46
|
+
- 0.8.0 selects `runtimeGate` on every token mutation (`portal.mint_app_token`,
|
|
47
|
+
`exchange_code`, `refresh`) and on `game_client_bootstrap`, so it needs the ck-api release
|
|
48
|
+
after v2.39.0 that serves it; an older API refuses those calls with a GraphQL validation
|
|
49
|
+
error. The same release serves `playerProfile(s)`, the access suspension and
|
|
50
|
+
`execRestartType`.
|
|
51
|
+
- Channel audio (message types 35 and 36) and the echo of your own voxel edits need replication
|
|
52
|
+
server v0.37.0; an older one drops message type 35 and echoes nothing.
|
|
53
|
+
- The wheels link no audio codec (CrowdyCPP's optional libopus wrapper is built OFF): the
|
|
54
|
+
voice helpers carry an app's codec frames without reading them.
|
|
@@ -71,3 +71,10 @@ These CrowdyCPP suites have no CrowdyPy counterpart yet; the reason is in each r
|
|
|
71
71
|
| `e2e_soak_two_clients`, `e2e_permission_refresh` | long-running; slated for `CROWDY_E2E_SLOW=1` suites |
|
|
72
72
|
| `e2e_host_election`, `e2e_durable_stores`, `e2e_chunk_store_live` | the World Stores' host, save and chunk persistence run over GraphQL timers covered by unit suites against fakes; live coverage needs a dedicated app (chunk write-back closes the wilderness) |
|
|
73
73
|
| `e2e_cross_app`, `e2e_cross_tenant`, `e2e_malicious_input` | platform isolation properties the CrowdyCPP suites already exercise against the same API |
|
|
74
|
+
|
|
75
|
+
0.8.0's additions (channel audio, the echo of your own voxel edit, `APP_PAUSED`, access
|
|
76
|
+
suspension, player profiles, `exec.restart_type`) have no live suite yet, in CrowdyPy or in
|
|
77
|
+
CrowdyCPP. The unit suites cover them against a fake replication server and a mocked API. From
|
|
78
|
+
0.8.0 every suite mints with `runtimeGate` selected, so run them only against a tier whose
|
|
79
|
+
ck-api is the release after v2.39.0 or later; an older one refuses the mint as a GraphQL
|
|
80
|
+
validation error. Channel audio and the voxel echo need replication server v0.37.0 as well.
|