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.
Files changed (510) hide show
  1. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/AGENTS.md +22 -1
  2. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/CMakeLists.txt +1 -0
  3. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/MIGRATION.md +122 -0
  4. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/PKG-INFO +78 -15
  5. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/README.md +77 -14
  6. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/benchmarks/README.md +20 -0
  7. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/docs/compatibility.md +10 -1
  8. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/docs/e2e-coverage.md +7 -0
  9. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/docs/parity-matrix.md +48 -4
  10. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/native/common.hpp +1 -0
  11. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/native/module.cpp +3 -2
  12. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/native/replication.hpp +25 -5
  13. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/native/replication_binding.cpp +2 -0
  14. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/native/session_binding.cpp +90 -7
  15. crowdypy-0.9.0.dev1/native/voice_binding.cpp +177 -0
  16. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/native/wire_binding.cpp +23 -5
  17. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/appAccess/AppUserAccessByApp.graphql +2 -0
  18. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/appAccess/ClaimFreeAppAccess.graphql +1 -0
  19. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/appAccess/GrantAppAccess.graphql +1 -0
  20. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/appAccess/GrantMyAppAccess.graphql +1 -0
  21. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/appAccess/MyAppAccess.graphql +1 -0
  22. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/appAccess/RevokeAppAccess.graphql +1 -0
  23. crowdypy-0.9.0.dev1/operations/appAccess/SuspendAppAccess.graphql +45 -0
  24. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/apps/App.graphql +1 -0
  25. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/apps/UpdateApp.graphql +1 -0
  26. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/chunks/GetChunk.graphql +1 -0
  27. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/chunks/GetChunksByDistance.graphql +1 -0
  28. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/exec/Exec.graphql +14 -0
  29. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/serverStatus/GameClientBootstrap.graphql +5 -0
  30. crowdypy-0.9.0.dev1/operations/users/PlayerProfile.graphql +15 -0
  31. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/pyproject.toml +11 -9
  32. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/schema.gql +269 -66
  33. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/__init__.py +52 -0
  34. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_generated/enums.py +2 -1
  35. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_generated/inputs.py +8 -5
  36. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_generated/operations.py +76 -22
  37. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/domains/app_access.py +60 -2
  38. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/domains/apps.py +4 -1
  39. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/domains/channels.py +3 -1
  40. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/domains/chunks.py +6 -2
  41. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/domains/exec.py +16 -1
  42. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/domains/grids.py +2 -1
  43. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/domains/portal.py +6 -2
  44. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/domains/server_status.py +7 -1
  45. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/domains/udp.py +13 -0
  46. crowdypy-0.9.0.dev1/src/crowdypy/_sync/domains/users.py +75 -0
  47. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/grid_scope.py +10 -0
  48. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/stores.py +123 -43
  49. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_version.py +1 -1
  50. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/domains/app_access.py +60 -2
  51. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/domains/apps.py +4 -1
  52. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/domains/channels.py +3 -1
  53. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/domains/chunks.py +6 -2
  54. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/domains/exec.py +41 -2
  55. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/domains/grids.py +2 -1
  56. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/domains/portal.py +19 -1
  57. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/domains/server_status.py +7 -1
  58. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/domains/udp.py +13 -0
  59. crowdypy-0.9.0.dev1/src/crowdypy/domains/users.py +74 -0
  60. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/errors.py +114 -0
  61. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/grid_scope.py +10 -0
  62. crowdypy-0.9.0.dev1/src/crowdypy/media.py +527 -0
  63. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/player_host/schemas.v1.json +2 -2
  64. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/replication.py +34 -4
  65. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/stores.py +138 -43
  66. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/wire.py +70 -1
  67. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/fixtures/README.md +1 -0
  68. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/fixtures/player-host.v1.json +2 -2
  69. crowdypy-0.9.0.dev1/tests/fixtures/voice-frames.json +941 -0
  70. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/unit/domains/test_org_domains.py +49 -0
  71. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/unit/domains/test_studio_exec_domains.py +24 -1
  72. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/unit/test_durable_stores.py +64 -0
  73. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/unit/test_fixture_provenance.py +5 -5
  74. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/unit/test_grid_scope.py +4 -0
  75. crowdypy-0.9.0.dev1/tests/unit/test_refusals.py +155 -0
  76. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/unit/test_replication.py +80 -0
  77. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/unit/test_udp_api.py +50 -1
  78. crowdypy-0.9.0.dev1/tests/unit/test_voice_frames.py +284 -0
  79. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/unit/test_wire.py +77 -0
  80. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/unit/test_world_session.py +172 -1
  81. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tools/parity/classifications.toml +2 -0
  82. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/uv.lock +1 -1
  83. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/CMakeLists.txt +35 -1
  84. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/PROVENANCE.md +1 -1
  85. crowdypy-0.9.0.dev1/vendor/CrowdyCPP/cmake/CrowdyCPPConfig.cmake.in +26 -0
  86. crowdypy-0.9.0.dev1/vendor/CrowdyCPP/cmake/CrowdyFindOpus.cmake +36 -0
  87. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/domains/admin.hpp +58 -0
  88. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/domains/exec.hpp +17 -7
  89. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/domains/grids.hpp +16 -5
  90. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/domains/groups.hpp +4 -0
  91. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/domains/portal.hpp +7 -7
  92. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/domains/types.hpp +27 -0
  93. crowdypy-0.9.0.dev1/vendor/CrowdyCPP/include/crowdy/domains/users.hpp +154 -0
  94. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/generated/enums.hpp +5 -2
  95. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/generated/operations.hpp +210 -2
  96. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/graphql/errors.hpp +68 -0
  97. crowdypy-0.9.0.dev1/vendor/CrowdyCPP/include/crowdy/media/opus.hpp +90 -0
  98. crowdypy-0.9.0.dev1/vendor/CrowdyCPP/include/crowdy/media/voice_frames.hpp +470 -0
  99. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/replication/connection.hpp +13 -0
  100. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/replication/types.hpp +3 -0
  101. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/session/chunk_store.hpp +201 -29
  102. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/session/stores.hpp +3 -0
  103. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/session/world_session.hpp +13 -0
  104. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/wire/codec.hpp +27 -4
  105. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/wire/protocol.hpp +14 -0
  106. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/package.json +6 -7
  107. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/src/domains/exec.cpp +14 -0
  108. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/src/graphql/error_extensions.hpp +4 -0
  109. crowdypy-0.9.0.dev1/vendor/CrowdyCPP/src/media/opus.cpp +119 -0
  110. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/src/replication/connection.cpp +22 -7
  111. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/src/session/world_session.cpp +6 -10
  112. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/tools/parity/fixtures/crowdy-studio-diagnostics.v1.json +2 -2
  113. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/tools/parity/fixtures/crowdyjs-studio-layout.v1.json +2 -2
  114. crowdypy-0.9.0.dev1/vendor/CrowdyCPP/tools/parity/fixtures/voice-frames.json +941 -0
  115. crowdypy-0.7.0.dev1/src/crowdypy/_sync/domains/users.py +0 -45
  116. crowdypy-0.7.0.dev1/src/crowdypy/domains/users.py +0 -44
  117. crowdypy-0.7.0.dev1/src/crowdypy/media.py +0 -140
  118. crowdypy-0.7.0.dev1/vendor/CrowdyCPP/cmake/CrowdyCPPConfig.cmake.in +0 -15
  119. crowdypy-0.7.0.dev1/vendor/CrowdyCPP/include/crowdy/domains/users.hpp +0 -83
  120. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/.gitattributes +0 -0
  121. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/.gitignore +0 -0
  122. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/.gitleaks.toml +0 -0
  123. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/LICENSE +0 -0
  124. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/SECURITY.md +0 -0
  125. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/benchmarks/bench_replication.py +0 -0
  126. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/licenses/OpenSSL-LICENSE.txt +0 -0
  127. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/actors/Actor.graphql +0 -0
  128. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/actors/Actors.graphql +0 -0
  129. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/actors/BatchLookupActors.graphql +0 -0
  130. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/actors/CreateActor.graphql +0 -0
  131. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/actors/DeleteActor.graphql +0 -0
  132. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/actors/UpdateActor.graphql +0 -0
  133. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/actors/UpdateActorState.graphql +0 -0
  134. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/appAccess/AppAccessTiers.graphql +0 -0
  135. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/appAccess/AppFeatures.graphql +0 -0
  136. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/appAccess/AppGrantMemberCandidates.graphql +0 -0
  137. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/appAccess/ArchiveAccessTier.graphql +0 -0
  138. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/appAccess/CreateAccessTier.graphql +0 -0
  139. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/appAccess/DefineAppFeature.graphql +0 -0
  140. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/appAccess/GrantTierFeature.graphql +0 -0
  141. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/appAccess/RevokeTierFeature.graphql +0 -0
  142. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/appAccess/RuntimePermissions.graphql +0 -0
  143. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/appAccess/TierFeatures.graphql +0 -0
  144. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/appAccess/UpdateAccessTier.graphql +0 -0
  145. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/apps/AppBySlug.graphql +0 -0
  146. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/apps/AppDiscovery.graphql +0 -0
  147. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/apps/AppsForOrg.graphql +0 -0
  148. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/apps/ArchiveApp.graphql +0 -0
  149. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/apps/CodeAdmissions.graphql +0 -0
  150. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/apps/CreateApp.graphql +0 -0
  151. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/apps/MarketplaceApps.graphql +0 -0
  152. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/apps/MyApps.graphql +0 -0
  153. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/apps/PlaceableDatacenters.graphql +0 -0
  154. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/auth/Logout.graphql +0 -0
  155. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/auth/LogoutAllDevices.graphql +0 -0
  156. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/avatars/Avatars.graphql +0 -0
  157. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/billing/AppBudget.graphql +0 -0
  158. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/billing/AppBudgets.graphql +0 -0
  159. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/billing/SetAppBudget.graphql +0 -0
  160. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/billing/WalletBalance.graphql +0 -0
  161. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/billing/WalletTransactions.graphql +0 -0
  162. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/channels/AddChannelMember.graphql +0 -0
  163. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/channels/Channel.graphql +0 -0
  164. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/channels/ChannelMembers.graphql +0 -0
  165. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/channels/ChannelPolicy.graphql +0 -0
  166. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/channels/ChannelRoles.graphql +0 -0
  167. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/channels/Channels.graphql +0 -0
  168. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/channels/CreateChannel.graphql +0 -0
  169. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/channels/CreateChannelRole.graphql +0 -0
  170. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/channels/DeleteChannel.graphql +0 -0
  171. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/channels/DeleteChannelRole.graphql +0 -0
  172. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/channels/JoinChannel.graphql +0 -0
  173. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/channels/LeaveChannel.graphql +0 -0
  174. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/channels/MyChannels.graphql +0 -0
  175. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/channels/RemoveChannelMember.graphql +0 -0
  176. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/channels/RequestToJoinChannel.graphql +0 -0
  177. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/channels/SetChannelMemberRoles.graphql +0 -0
  178. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/channels/SetChannelPolicy.graphql +0 -0
  179. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/channels/UpdateChannel.graphql +0 -0
  180. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/channels/UpdateChannelRole.graphql +0 -0
  181. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/chunks/GetChunkLods.graphql +0 -0
  182. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/chunks/GetVoxelList.graphql +0 -0
  183. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/chunks/UpdateChunk.graphql +0 -0
  184. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/chunks/UpdateChunkLods.graphql +0 -0
  185. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/chunks/UpdateChunkState.graphql +0 -0
  186. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/crowdyStudio/CrowdyStudio.graphql +0 -0
  187. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/gameApps/GameApps.graphql +0 -0
  188. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/grids/CreateGridChannel.graphql +0 -0
  189. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/grids/GridChannels.graphql +0 -0
  190. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/grids/MintGridToken.graphql +0 -0
  191. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/host/Host.graphql +0 -0
  192. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/inputLog/InputLogMessages.graphql +0 -0
  193. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/inputLog/InputLogSessions.graphql +0 -0
  194. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/marketplace/Marketplace.graphql +0 -0
  195. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/organizations/CreateOrgRole.graphql +0 -0
  196. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/organizations/CreateOrgToken.graphql +0 -0
  197. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/organizations/CreateOrganization.graphql +0 -0
  198. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/organizations/DeleteOrgRole.graphql +0 -0
  199. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/organizations/InviteOrgMember.graphql +0 -0
  200. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/organizations/MemberRoles.graphql +0 -0
  201. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/organizations/MyOrganizations.graphql +0 -0
  202. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/organizations/OrgMembers.graphql +0 -0
  203. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/organizations/OrgPermissions.graphql +0 -0
  204. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/organizations/OrgRoles.graphql +0 -0
  205. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/organizations/OrgTokens.graphql +0 -0
  206. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/organizations/Organization.graphql +0 -0
  207. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/organizations/OrganizationBySlug.graphql +0 -0
  208. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/organizations/RemoveOrgMember.graphql +0 -0
  209. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/organizations/RevokeOrgToken.graphql +0 -0
  210. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/organizations/UpdateOrgMemberRoles.graphql +0 -0
  211. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/organizations/UpdateOrgRole.graphql +0 -0
  212. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/organizations/UpdateOrgToken.graphql +0 -0
  213. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/payments/CapturePaypalCheckout.graphql +0 -0
  214. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/payments/CreateCheckout.graphql +0 -0
  215. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/payments/MyCheckouts.graphql +0 -0
  216. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/platform/PlatformConfig.graphql +0 -0
  217. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/playerWallet/PlayerWallet.graphql +0 -0
  218. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/quotas/DeleteQuota.graphql +0 -0
  219. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/quotas/EffectiveQuota.graphql +0 -0
  220. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/quotas/QuotasForApp.graphql +0 -0
  221. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/quotas/QuotasForOrg.graphql +0 -0
  222. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/quotas/SetQuota.graphql +0 -0
  223. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/serverStatus/ActiveGraphQLServers.graphql +0 -0
  224. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/serverStatus/GraphqlServers.graphql +0 -0
  225. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/serverStatus/ServerWithLeastClients.graphql +0 -0
  226. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/serverStatus/VersionInfo.graphql +0 -0
  227. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/sharedEnvironment/SharedEnvironment.graphql +0 -0
  228. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/state/DeleteUserAppState.graphql +0 -0
  229. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/state/UpdateUserAppState.graphql +0 -0
  230. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/state/UserAppState.graphql +0 -0
  231. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/state/UserAppStates.graphql +0 -0
  232. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/teams/AddTeamMember.graphql +0 -0
  233. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/teams/CreateTeam.graphql +0 -0
  234. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/teams/CreateTeamRole.graphql +0 -0
  235. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/teams/DeleteTeam.graphql +0 -0
  236. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/teams/DeleteTeamRole.graphql +0 -0
  237. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/teams/JoinTeam.graphql +0 -0
  238. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/teams/LeaveTeam.graphql +0 -0
  239. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/teams/MyTeams.graphql +0 -0
  240. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/teams/RemoveTeamMember.graphql +0 -0
  241. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/teams/RequestToJoinTeam.graphql +0 -0
  242. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/teams/SetTeamMemberRoles.graphql +0 -0
  243. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/teams/SetTeamPolicy.graphql +0 -0
  244. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/teams/Team.graphql +0 -0
  245. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/teams/TeamMembers.graphql +0 -0
  246. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/teams/TeamPolicy.graphql +0 -0
  247. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/teams/TeamRoles.graphql +0 -0
  248. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/teams/Teams.graphql +0 -0
  249. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/teams/UpdateTeam.graphql +0 -0
  250. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/teams/UpdateTeamRole.graphql +0 -0
  251. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/teleport/TeleportRequest.graphql +0 -0
  252. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/usage/AppGraphqlOperations.graphql +0 -0
  253. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/usage/AppUsageSummary.graphql +0 -0
  254. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/usage/PlayerPulse.graphql +0 -0
  255. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/users/DeleteMyAccount.graphql +0 -0
  256. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/users/FreePlayWindow.graphql +0 -0
  257. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/users/Me.graphql +0 -0
  258. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/users/UpdateGamertag.graphql +0 -0
  259. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/users/UpdateUserState.graphql +0 -0
  260. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/users/User.graphql +0 -0
  261. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/voxels/ListVoxelUpdatesByDistance.graphql +0 -0
  262. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/voxels/ListVoxels.graphql +0 -0
  263. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/voxels/RollbackVoxelUpdates.graphql +0 -0
  264. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/voxels/UpdateVoxel.graphql +0 -0
  265. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/operations/voxels/VoxelUpdateHistory.graphql +0 -0
  266. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/scripts/_pins.py +0 -0
  267. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/scripts/ci/assert_default_origin.py +0 -0
  268. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/scripts/ci/build_openssl.sh +0 -0
  269. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/scripts/ci/check_content_policy.py +0 -0
  270. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/scripts/ci/check_pin_tiers.py +0 -0
  271. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/scripts/ci/cibw_before_all_linux.sh +0 -0
  272. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/scripts/ci/resolve-release-tier.sh +0 -0
  273. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/scripts/ci/resolve-release-tier.test.sh +0 -0
  274. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/scripts/ci/resolve_pypi_version.py +0 -0
  275. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/scripts/ci/stamp_version.py +0 -0
  276. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/scripts/ci/verify_artifacts.py +0 -0
  277. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/scripts/codegen.py +0 -0
  278. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/scripts/schema_drift.py +0 -0
  279. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/scripts/schema_sync.py +0 -0
  280. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/scripts/unasync.py +0 -0
  281. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/scripts/vendor_crowdycpp.py +0 -0
  282. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_concurrency.py +0 -0
  283. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_default_origin.py +0 -0
  284. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_generated/__init__.py +0 -0
  285. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_grid.py +0 -0
  286. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_native.pyi +0 -0
  287. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_operation.py +0 -0
  288. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/__init__.py +0 -0
  289. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/client.py +0 -0
  290. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/domains/__init__.py +0 -0
  291. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/domains/_base.py +0 -0
  292. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/domains/actors.py +0 -0
  293. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/domains/admin.py +0 -0
  294. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/domains/auth.py +0 -0
  295. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/domains/avatars.py +0 -0
  296. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/domains/billing.py +0 -0
  297. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/domains/crowdy_studio.py +0 -0
  298. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/domains/crowdy_studio_agent.py +0 -0
  299. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/domains/crowdy_studio_github.py +0 -0
  300. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/domains/discovery.py +0 -0
  301. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/domains/game_apps.py +0 -0
  302. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/domains/host.py +0 -0
  303. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/domains/input_log.py +0 -0
  304. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/domains/marketplace.py +0 -0
  305. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/domains/organizations.py +0 -0
  306. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/domains/payments.py +0 -0
  307. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/domains/platform.py +0 -0
  308. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/domains/player_wallet.py +0 -0
  309. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/domains/quotas.py +0 -0
  310. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/domains/shared_environment.py +0 -0
  311. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/domains/state.py +0 -0
  312. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/domains/teams.py +0 -0
  313. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/domains/teleport.py +0 -0
  314. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/domains/usage.py +0 -0
  315. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/domains/voxels.py +0 -0
  316. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/graphql.py +0 -0
  317. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/kit/__init__.py +0 -0
  318. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/kit/actions.py +0 -0
  319. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/kit/kit.py +0 -0
  320. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/kit/social.py +0 -0
  321. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/kit/wire.py +0 -0
  322. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/rediscover.py +0 -0
  323. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/_sync/world.py +0 -0
  324. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/auth_state.py +0 -0
  325. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/client.py +0 -0
  326. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/codecs.py +0 -0
  327. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/datacenter_redirect.py +0 -0
  328. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/domains/__init__.py +0 -0
  329. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/domains/_base.py +0 -0
  330. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/domains/actors.py +0 -0
  331. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/domains/admin.py +0 -0
  332. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/domains/auth.py +0 -0
  333. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/domains/avatars.py +0 -0
  334. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/domains/billing.py +0 -0
  335. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/domains/crowdy_studio.py +0 -0
  336. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/domains/crowdy_studio_agent.py +0 -0
  337. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/domains/crowdy_studio_github.py +0 -0
  338. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/domains/discovery.py +0 -0
  339. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/domains/game_apps.py +0 -0
  340. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/domains/host.py +0 -0
  341. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/domains/input_log.py +0 -0
  342. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/domains/marketplace.py +0 -0
  343. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/domains/organizations.py +0 -0
  344. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/domains/payments.py +0 -0
  345. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/domains/platform.py +0 -0
  346. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/domains/player_wallet.py +0 -0
  347. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/domains/quotas.py +0 -0
  348. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/domains/shared_environment.py +0 -0
  349. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/domains/state.py +0 -0
  350. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/domains/teams.py +0 -0
  351. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/domains/teleport.py +0 -0
  352. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/domains/usage.py +0 -0
  353. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/domains/voxels.py +0 -0
  354. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/enums.py +0 -0
  355. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/estate.py +0 -0
  356. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/exec_gateway.py +0 -0
  357. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/graphql.py +0 -0
  358. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/inputs.py +0 -0
  359. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/kit/__init__.py +0 -0
  360. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/kit/actions.py +0 -0
  361. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/kit/kit.py +0 -0
  362. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/kit/social.py +0 -0
  363. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/kit/wire.py +0 -0
  364. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/lb_cookie.py +0 -0
  365. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/pkce.py +0 -0
  366. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/player_host/__init__.py +0 -0
  367. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/player_host/agent_errors.py +0 -0
  368. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/player_host/agent_types.py +0 -0
  369. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/player_host/json_schema.py +0 -0
  370. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/player_host/schemas.py +0 -0
  371. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/player_host/types.py +0 -0
  372. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/py.typed +0 -0
  373. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/rediscover.py +0 -0
  374. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/session.py +0 -0
  375. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/studio/__init__.py +0 -0
  376. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/studio/client_tick_interval.py +0 -0
  377. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/studio/controller.py +0 -0
  378. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/studio/diagnostics.py +0 -0
  379. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/studio/github_new_repo.py +0 -0
  380. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/studio/layout.py +0 -0
  381. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/studio/models.py +0 -0
  382. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/studio/starter_projects.py +0 -0
  383. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/subscriptions.py +0 -0
  384. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/sync.py +0 -0
  385. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/utils.py +0 -0
  386. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/src/crowdypy/world.py +0 -0
  387. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/conftest.py +0 -0
  388. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/e2e/__init__.py +0 -0
  389. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/e2e/conftest.py +0 -0
  390. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/e2e/test_e2e_identity.py +0 -0
  391. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/e2e/test_e2e_open_grid_exec_gateway.py +0 -0
  392. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/e2e/test_e2e_ranged_channel.py +0 -0
  393. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/e2e/test_e2e_replication.py +0 -0
  394. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/e2e/test_e2e_studio.py +0 -0
  395. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/e2e/test_e2e_world.py +0 -0
  396. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/e2e/test_e2e_world_data.py +0 -0
  397. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/fixtures/binary-wire-fixtures.json +0 -0
  398. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/fixtures/exec-client-frames.json +0 -0
  399. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/unit/__init__.py +0 -0
  400. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/unit/domains/__init__.py +0 -0
  401. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/unit/domains/test_crowdycpp_roots.py +0 -0
  402. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/unit/domains/test_social_domains.py +0 -0
  403. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/unit/domains/test_world_domains.py +0 -0
  404. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/unit/test_core.py +0 -0
  405. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/unit/test_estate_moves.py +0 -0
  406. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/unit/test_exec_gateway.py +0 -0
  407. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/unit/test_kit.py +0 -0
  408. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/unit/test_lazy_exports.py +0 -0
  409. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/unit/test_player_host.py +0 -0
  410. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/unit/test_release_versions.py +0 -0
  411. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/unit/test_sdk_audience.py +0 -0
  412. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/unit/test_studio_controller.py +0 -0
  413. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/unit/test_studio_diagnostics.py +0 -0
  414. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/unit/test_studio_layout.py +0 -0
  415. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/unit/test_subscriptions.py +0 -0
  416. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tests/unit/test_transport.py +0 -0
  417. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tools/e2e/provision.py +0 -0
  418. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tools/fixtures/player_host.mjs +0 -0
  419. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/tools/parity/parity.py +0 -0
  420. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/LICENSE +0 -0
  421. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/cmake/CheckPublicHeaders.cmake +0 -0
  422. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/cmake/studio_layout_fixture.hpp.in +0 -0
  423. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/client.hpp +0 -0
  424. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/core/base64.hpp +0 -0
  425. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/core/bytes.hpp +0 -0
  426. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/core/clock.hpp +0 -0
  427. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/core/crypto.hpp +0 -0
  428. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/core/logger.hpp +0 -0
  429. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/core/result.hpp +0 -0
  430. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/core/spsc.hpp +0 -0
  431. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/core/uuid.hpp +0 -0
  432. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/crowdy.hpp +0 -0
  433. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/default_origin.hpp +0 -0
  434. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/domains/auth.hpp +0 -0
  435. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/domains/crowdy_studio.hpp +0 -0
  436. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/domains/crowdy_studio_agent.hpp +0 -0
  437. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/domains/crowdy_studio_github.hpp +0 -0
  438. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/domains/discovery.hpp +0 -0
  439. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/domains/domain_base.hpp +0 -0
  440. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/domains/game_apps.hpp +0 -0
  441. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/domains/marketplace.hpp +0 -0
  442. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/domains/player_wallet.hpp +0 -0
  443. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/domains/realtime_control.hpp +0 -0
  444. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/domains/server_status.hpp +0 -0
  445. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/domains/world_data.hpp +0 -0
  446. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/graphql/async_scope.hpp +0 -0
  447. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/graphql/auth_state.hpp +0 -0
  448. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/graphql/datacenter_redirect.hpp +0 -0
  449. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/graphql/dispatcher.hpp +0 -0
  450. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/graphql/estate.hpp +0 -0
  451. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/graphql/graphql_client.hpp +0 -0
  452. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/graphql/http.hpp +0 -0
  453. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/graphql/json.hpp +0 -0
  454. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/graphql/rediscover.hpp +0 -0
  455. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/graphql/subscription_client.hpp +0 -0
  456. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/graphql/websocket.hpp +0 -0
  457. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/kit/actions.hpp +0 -0
  458. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/kit/kit.hpp +0 -0
  459. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/kit/social.hpp +0 -0
  460. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/kit/wire.hpp +0 -0
  461. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/media/video_frames.hpp +0 -0
  462. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/player_host/adapter.hpp +0 -0
  463. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/player_host/player_host.hpp +0 -0
  464. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/player_host/schemas.hpp +0 -0
  465. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/player_host/types.hpp +0 -0
  466. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/replication/session_provider.hpp +0 -0
  467. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/replication/udp_socket.hpp +0 -0
  468. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/session/codec.hpp +0 -0
  469. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/session/durable.hpp +0 -0
  470. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/session/keys.hpp +0 -0
  471. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/studio/controller.hpp +0 -0
  472. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/studio/diagnostics.hpp +0 -0
  473. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/studio/editor.hpp +0 -0
  474. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/studio/github.hpp +0 -0
  475. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/studio/github_layout.hpp +0 -0
  476. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/studio/integration.hpp +0 -0
  477. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/studio/layout.hpp +0 -0
  478. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/studio/models.hpp +0 -0
  479. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/studio/runtime.hpp +0 -0
  480. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/include/crowdy/world.hpp +0 -0
  481. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/src/client.cpp +0 -0
  482. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/src/core/base64.cpp +0 -0
  483. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/src/core/clock.cpp +0 -0
  484. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/src/core/crypto_default_unavailable.cpp +0 -0
  485. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/src/core/crypto_openssl.cpp +0 -0
  486. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/src/core/crypto_unavailable.cpp +0 -0
  487. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/src/core/logger.cpp +0 -0
  488. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/src/core/uuid.cpp +0 -0
  489. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/src/graphql/async_transport.cpp +0 -0
  490. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/src/graphql/auth_state.cpp +0 -0
  491. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/src/graphql/errors.cpp +0 -0
  492. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/src/graphql/graphql_client.cpp +0 -0
  493. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/src/graphql/http_curl.cpp +0 -0
  494. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/src/graphql/http_none.cpp +0 -0
  495. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/src/graphql/json.cpp +0 -0
  496. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/src/graphql/subscription_client.cpp +0 -0
  497. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/src/graphql/websocket_curl.cpp +0 -0
  498. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/src/graphql/websocket_none.cpp +0 -0
  499. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/src/player_host/schemas.cpp +0 -0
  500. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/src/player_host/types.cpp +0 -0
  501. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/src/replication/socket_errors.hpp +0 -0
  502. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/src/replication/udp_socket.cpp +0 -0
  503. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/src/studio/diagnostics.cpp +0 -0
  504. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/src/studio/editor.cpp +0 -0
  505. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/src/studio/integration.cpp +0 -0
  506. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/third_party/yyjson/LICENSE +0 -0
  507. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/third_party/yyjson/yyjson.c +0 -0
  508. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/third_party/yyjson/yyjson.h +0 -0
  509. {crowdypy-0.7.0.dev1 → crowdypy-0.9.0.dev1}/vendor/CrowdyCPP/tools/parity/fixtures/exec-client-frames.json +0 -0
  510. {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. Build CrowdyJS at the new pin (`npm ci && npm run build`) and run
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.
@@ -59,6 +59,7 @@ nanobind_add_module(_native
59
59
  native/module.cpp
60
60
  native/replication_binding.cpp
61
61
  native/session_binding.cpp
62
+ native/voice_binding.cpp
62
63
  native/wire_binding.cpp
63
64
  )
64
65
  target_include_directories(_native PRIVATE native)
@@ -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.7.0.dev1
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.7.0: the input log (CrowdyJS 18.6.0, CrowdyCPP 0.59.0).**
55
- - `client.input_log.sessions(app_id)` and `messages(app_id, game_token_id)` read the client
56
- inputs recorded for an app with replay logging on (`replayLoggingEnabled`, now on every app
57
- read and set with `client.apps.update`). A player reads their own; `manage_apps` reads every
58
- session. Keep paging while `pageInfo.hasNextPage` is true: a messages page can be short.
59
-
60
- **v0.6.0: distance-limited channel messages and the terms gate (CrowdyJS 18.5.0, CrowdyCPP 0.58.0).**
61
- - `client.udp.send_ranged_channel_message(..., chunk=, max_distance=)` publishes to a channel
62
- but reaches only the members whose own actor is within `max_distance` chunks of `chunk`,
63
- by straight-line distance. Members receive the ordinary `channel_message`.
64
- - `client.auth.record_player_consents()` and `player_legal_acceptance()`, `register`'s
65
- `accept_legal` and `attest_age_of_majority`, and `is_legal_acceptance_required_error`: a
66
- gameplay token now waits for the player's agreement to the legal documents and age
67
- attestation.
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.7.0: the input log (CrowdyJS 18.6.0, CrowdyCPP 0.59.0).**
15
- - `client.input_log.sessions(app_id)` and `messages(app_id, game_token_id)` read the client
16
- inputs recorded for an app with replay logging on (`replayLoggingEnabled`, now on every app
17
- read and set with `client.apps.update`). A player reads their own; `manage_apps` reads every
18
- session. Keep paging while `pageInfo.hasNextPage` is true: a messages page can be short.
19
-
20
- **v0.6.0: distance-limited channel messages and the terms gate (CrowdyJS 18.5.0, CrowdyCPP 0.58.0).**
21
- - `client.udp.send_ranged_channel_message(..., chunk=, max_distance=)` publishes to a channel
22
- but reaches only the members whose own actor is within `max_distance` chunks of `chunk`,
23
- by straight-line distance. Members receive the ordinary `channel_message`.
24
- - `client.auth.record_player_consents()` and `player_legal_acceptance()`, `register`'s
25
- `accept_legal` and `attest_age_of_majority`, and `is_legal_acceptance_required_error`: a
26
- gameplay token now waits for the player's agreement to the legal documents and age
27
- attestation.
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.7.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.