crowdypy 0.5.1.dev1__tar.gz → 0.6.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 (490) hide show
  1. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/MIGRATION.md +31 -0
  2. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/PKG-INFO +15 -6
  3. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/README.md +14 -5
  4. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/docs/compatibility.md +6 -1
  5. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/docs/e2e-coverage.md +3 -1
  6. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/docs/parity-matrix.md +13 -4
  7. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/native/replication.hpp +13 -0
  8. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/native/replication_binding.cpp +3 -0
  9. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/native/wire_binding.cpp +28 -0
  10. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/pyproject.toml +8 -8
  11. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/schema.gql +109 -4
  12. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/__init__.py +4 -0
  13. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/_generated/enums.py +1 -1
  14. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/_generated/inputs.py +25 -3
  15. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/_generated/operations.py +1 -1
  16. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/_sync/domains/auth.py +61 -2
  17. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/_sync/domains/portal.py +19 -0
  18. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/_sync/domains/udp.py +19 -0
  19. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/_version.py +1 -1
  20. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/domains/auth.py +61 -2
  21. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/domains/portal.py +19 -0
  22. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/domains/udp.py +19 -0
  23. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/player_host/schemas.v1.json +2 -2
  24. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/replication.py +24 -1
  25. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/wire.py +41 -0
  26. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/tests/e2e/conftest.py +5 -2
  27. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/tests/e2e/test_e2e_identity.py +32 -1
  28. crowdypy-0.6.0.dev1/tests/e2e/test_e2e_ranged_channel.py +120 -0
  29. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/tests/fixtures/binary-wire-fixtures.json +17 -0
  30. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/tests/fixtures/player-host.v1.json +2 -2
  31. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/tests/unit/test_replication.py +15 -0
  32. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/tests/unit/test_wire.py +55 -0
  33. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/tools/e2e/provision.py +3 -1
  34. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/tools/parity/classifications.toml +2 -0
  35. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/uv.lock +62 -62
  36. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/CMakeLists.txt +1 -1
  37. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/PROVENANCE.md +1 -1
  38. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/include/crowdy/domains/auth.hpp +75 -0
  39. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/include/crowdy/generated/enums.hpp +1 -1
  40. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/include/crowdy/generated/operations.hpp +1 -1
  41. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/include/crowdy/replication/connection.hpp +9 -0
  42. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/include/crowdy/wire/codec.hpp +51 -0
  43. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/include/crowdy/wire/protocol.hpp +23 -0
  44. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/package.json +7 -7
  45. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/src/replication/connection.cpp +28 -0
  46. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/tools/parity/fixtures/crowdy-studio-diagnostics.v1.json +2 -2
  47. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/tools/parity/fixtures/crowdyjs-studio-layout.v1.json +2 -2
  48. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/.gitattributes +0 -0
  49. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/.gitignore +0 -0
  50. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/.gitleaks.toml +0 -0
  51. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/AGENTS.md +0 -0
  52. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/CMakeLists.txt +0 -0
  53. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/LICENSE +0 -0
  54. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/SECURITY.md +0 -0
  55. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/benchmarks/README.md +0 -0
  56. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/benchmarks/bench_replication.py +0 -0
  57. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/licenses/OpenSSL-LICENSE.txt +0 -0
  58. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/native/common.hpp +0 -0
  59. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/native/module.cpp +0 -0
  60. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/native/session_binding.cpp +0 -0
  61. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/actors/Actor.graphql +0 -0
  62. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/actors/Actors.graphql +0 -0
  63. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/actors/BatchLookupActors.graphql +0 -0
  64. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/actors/CreateActor.graphql +0 -0
  65. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/actors/DeleteActor.graphql +0 -0
  66. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/actors/UpdateActor.graphql +0 -0
  67. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/actors/UpdateActorState.graphql +0 -0
  68. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/appAccess/AppAccessTiers.graphql +0 -0
  69. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/appAccess/AppFeatures.graphql +0 -0
  70. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/appAccess/AppGrantMemberCandidates.graphql +0 -0
  71. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/appAccess/AppUserAccessByApp.graphql +0 -0
  72. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/appAccess/ArchiveAccessTier.graphql +0 -0
  73. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/appAccess/ClaimFreeAppAccess.graphql +0 -0
  74. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/appAccess/CreateAccessTier.graphql +0 -0
  75. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/appAccess/DefineAppFeature.graphql +0 -0
  76. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/appAccess/GrantAppAccess.graphql +0 -0
  77. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/appAccess/GrantMyAppAccess.graphql +0 -0
  78. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/appAccess/GrantTierFeature.graphql +0 -0
  79. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/appAccess/MyAppAccess.graphql +0 -0
  80. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/appAccess/RevokeAppAccess.graphql +0 -0
  81. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/appAccess/RevokeTierFeature.graphql +0 -0
  82. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/appAccess/RuntimePermissions.graphql +0 -0
  83. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/appAccess/TierFeatures.graphql +0 -0
  84. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/appAccess/UpdateAccessTier.graphql +0 -0
  85. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/apps/App.graphql +0 -0
  86. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/apps/AppBySlug.graphql +0 -0
  87. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/apps/AppDiscovery.graphql +0 -0
  88. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/apps/AppsForOrg.graphql +0 -0
  89. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/apps/ArchiveApp.graphql +0 -0
  90. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/apps/CodeAdmissions.graphql +0 -0
  91. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/apps/CreateApp.graphql +0 -0
  92. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/apps/MarketplaceApps.graphql +0 -0
  93. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/apps/MyApps.graphql +0 -0
  94. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/apps/PlaceableDatacenters.graphql +0 -0
  95. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/apps/UpdateApp.graphql +0 -0
  96. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/auth/Logout.graphql +0 -0
  97. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/auth/LogoutAllDevices.graphql +0 -0
  98. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/avatars/Avatars.graphql +0 -0
  99. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/billing/AppBudget.graphql +0 -0
  100. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/billing/AppBudgets.graphql +0 -0
  101. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/billing/SetAppBudget.graphql +0 -0
  102. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/billing/WalletBalance.graphql +0 -0
  103. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/billing/WalletTransactions.graphql +0 -0
  104. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/channels/AddChannelMember.graphql +0 -0
  105. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/channels/Channel.graphql +0 -0
  106. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/channels/ChannelMembers.graphql +0 -0
  107. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/channels/ChannelPolicy.graphql +0 -0
  108. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/channels/ChannelRoles.graphql +0 -0
  109. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/channels/Channels.graphql +0 -0
  110. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/channels/CreateChannel.graphql +0 -0
  111. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/channels/CreateChannelRole.graphql +0 -0
  112. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/channels/DeleteChannel.graphql +0 -0
  113. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/channels/DeleteChannelRole.graphql +0 -0
  114. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/channels/JoinChannel.graphql +0 -0
  115. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/channels/LeaveChannel.graphql +0 -0
  116. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/channels/MyChannels.graphql +0 -0
  117. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/channels/RemoveChannelMember.graphql +0 -0
  118. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/channels/RequestToJoinChannel.graphql +0 -0
  119. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/channels/SetChannelMemberRoles.graphql +0 -0
  120. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/channels/SetChannelPolicy.graphql +0 -0
  121. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/channels/UpdateChannel.graphql +0 -0
  122. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/channels/UpdateChannelRole.graphql +0 -0
  123. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/chunks/GetChunk.graphql +0 -0
  124. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/chunks/GetChunkLods.graphql +0 -0
  125. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/chunks/GetChunksByDistance.graphql +0 -0
  126. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/chunks/GetVoxelList.graphql +0 -0
  127. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/chunks/UpdateChunk.graphql +0 -0
  128. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/chunks/UpdateChunkLods.graphql +0 -0
  129. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/chunks/UpdateChunkState.graphql +0 -0
  130. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/crowdyStudio/CrowdyStudio.graphql +0 -0
  131. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/exec/Exec.graphql +0 -0
  132. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/gameApps/GameApps.graphql +0 -0
  133. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/grids/CreateGridChannel.graphql +0 -0
  134. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/grids/GridChannels.graphql +0 -0
  135. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/grids/MintGridToken.graphql +0 -0
  136. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/host/Host.graphql +0 -0
  137. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/marketplace/Marketplace.graphql +0 -0
  138. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/organizations/CreateOrgRole.graphql +0 -0
  139. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/organizations/CreateOrgToken.graphql +0 -0
  140. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/organizations/CreateOrganization.graphql +0 -0
  141. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/organizations/DeleteOrgRole.graphql +0 -0
  142. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/organizations/InviteOrgMember.graphql +0 -0
  143. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/organizations/MemberRoles.graphql +0 -0
  144. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/organizations/MyOrganizations.graphql +0 -0
  145. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/organizations/OrgMembers.graphql +0 -0
  146. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/organizations/OrgPermissions.graphql +0 -0
  147. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/organizations/OrgRoles.graphql +0 -0
  148. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/organizations/OrgTokens.graphql +0 -0
  149. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/organizations/Organization.graphql +0 -0
  150. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/organizations/OrganizationBySlug.graphql +0 -0
  151. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/organizations/RemoveOrgMember.graphql +0 -0
  152. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/organizations/RevokeOrgToken.graphql +0 -0
  153. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/organizations/UpdateOrgMemberRoles.graphql +0 -0
  154. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/organizations/UpdateOrgRole.graphql +0 -0
  155. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/organizations/UpdateOrgToken.graphql +0 -0
  156. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/payments/CapturePaypalCheckout.graphql +0 -0
  157. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/payments/CreateCheckout.graphql +0 -0
  158. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/payments/MyCheckouts.graphql +0 -0
  159. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/platform/PlatformConfig.graphql +0 -0
  160. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/playerWallet/PlayerWallet.graphql +0 -0
  161. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/quotas/DeleteQuota.graphql +0 -0
  162. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/quotas/EffectiveQuota.graphql +0 -0
  163. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/quotas/QuotasForApp.graphql +0 -0
  164. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/quotas/QuotasForOrg.graphql +0 -0
  165. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/quotas/SetQuota.graphql +0 -0
  166. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/serverStatus/ActiveGraphQLServers.graphql +0 -0
  167. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/serverStatus/GameClientBootstrap.graphql +0 -0
  168. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/serverStatus/GraphqlServers.graphql +0 -0
  169. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/serverStatus/ServerWithLeastClients.graphql +0 -0
  170. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/serverStatus/VersionInfo.graphql +0 -0
  171. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/sharedEnvironment/SharedEnvironment.graphql +0 -0
  172. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/state/DeleteUserAppState.graphql +0 -0
  173. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/state/UpdateUserAppState.graphql +0 -0
  174. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/state/UserAppState.graphql +0 -0
  175. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/state/UserAppStates.graphql +0 -0
  176. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/teams/AddTeamMember.graphql +0 -0
  177. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/teams/CreateTeam.graphql +0 -0
  178. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/teams/CreateTeamRole.graphql +0 -0
  179. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/teams/DeleteTeam.graphql +0 -0
  180. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/teams/DeleteTeamRole.graphql +0 -0
  181. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/teams/JoinTeam.graphql +0 -0
  182. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/teams/LeaveTeam.graphql +0 -0
  183. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/teams/MyTeams.graphql +0 -0
  184. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/teams/RemoveTeamMember.graphql +0 -0
  185. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/teams/RequestToJoinTeam.graphql +0 -0
  186. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/teams/SetTeamMemberRoles.graphql +0 -0
  187. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/teams/SetTeamPolicy.graphql +0 -0
  188. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/teams/Team.graphql +0 -0
  189. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/teams/TeamMembers.graphql +0 -0
  190. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/teams/TeamPolicy.graphql +0 -0
  191. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/teams/TeamRoles.graphql +0 -0
  192. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/teams/Teams.graphql +0 -0
  193. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/teams/UpdateTeam.graphql +0 -0
  194. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/teams/UpdateTeamRole.graphql +0 -0
  195. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/teleport/TeleportRequest.graphql +0 -0
  196. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/usage/AppGraphqlOperations.graphql +0 -0
  197. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/usage/AppUsageSummary.graphql +0 -0
  198. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/usage/PlayerPulse.graphql +0 -0
  199. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/users/DeleteMyAccount.graphql +0 -0
  200. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/users/FreePlayWindow.graphql +0 -0
  201. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/users/Me.graphql +0 -0
  202. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/users/UpdateGamertag.graphql +0 -0
  203. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/users/UpdateUserState.graphql +0 -0
  204. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/users/User.graphql +0 -0
  205. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/voxels/ListVoxelUpdatesByDistance.graphql +0 -0
  206. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/voxels/ListVoxels.graphql +0 -0
  207. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/voxels/RollbackVoxelUpdates.graphql +0 -0
  208. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/voxels/UpdateVoxel.graphql +0 -0
  209. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/operations/voxels/VoxelUpdateHistory.graphql +0 -0
  210. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/scripts/_pins.py +0 -0
  211. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/scripts/ci/assert_default_origin.py +0 -0
  212. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/scripts/ci/build_openssl.sh +0 -0
  213. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/scripts/ci/check_content_policy.py +0 -0
  214. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/scripts/ci/check_pin_tiers.py +0 -0
  215. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/scripts/ci/cibw_before_all_linux.sh +0 -0
  216. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/scripts/ci/resolve-release-tier.sh +0 -0
  217. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/scripts/ci/resolve-release-tier.test.sh +0 -0
  218. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/scripts/ci/resolve_pypi_version.py +0 -0
  219. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/scripts/ci/stamp_version.py +0 -0
  220. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/scripts/ci/verify_artifacts.py +0 -0
  221. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/scripts/codegen.py +0 -0
  222. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/scripts/schema_drift.py +0 -0
  223. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/scripts/schema_sync.py +0 -0
  224. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/scripts/unasync.py +0 -0
  225. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/scripts/vendor_crowdycpp.py +0 -0
  226. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/_concurrency.py +0 -0
  227. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/_default_origin.py +0 -0
  228. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/_generated/__init__.py +0 -0
  229. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/_grid.py +0 -0
  230. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/_native.pyi +0 -0
  231. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/_operation.py +0 -0
  232. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/_sync/__init__.py +0 -0
  233. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/_sync/client.py +0 -0
  234. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/_sync/domains/__init__.py +0 -0
  235. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/_sync/domains/_base.py +0 -0
  236. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/_sync/domains/actors.py +0 -0
  237. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/_sync/domains/admin.py +0 -0
  238. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/_sync/domains/app_access.py +0 -0
  239. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/_sync/domains/apps.py +0 -0
  240. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/_sync/domains/avatars.py +0 -0
  241. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/_sync/domains/billing.py +0 -0
  242. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/_sync/domains/channels.py +0 -0
  243. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/_sync/domains/chunks.py +0 -0
  244. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/_sync/domains/crowdy_studio.py +0 -0
  245. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/_sync/domains/crowdy_studio_agent.py +0 -0
  246. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/_sync/domains/crowdy_studio_github.py +0 -0
  247. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/_sync/domains/discovery.py +0 -0
  248. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/_sync/domains/exec.py +0 -0
  249. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/_sync/domains/game_apps.py +0 -0
  250. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/_sync/domains/grids.py +0 -0
  251. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/_sync/domains/host.py +0 -0
  252. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/_sync/domains/marketplace.py +0 -0
  253. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/_sync/domains/organizations.py +0 -0
  254. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/_sync/domains/payments.py +0 -0
  255. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/_sync/domains/platform.py +0 -0
  256. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/_sync/domains/player_wallet.py +0 -0
  257. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/_sync/domains/quotas.py +0 -0
  258. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/_sync/domains/server_status.py +0 -0
  259. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/_sync/domains/shared_environment.py +0 -0
  260. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/_sync/domains/state.py +0 -0
  261. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/_sync/domains/teams.py +0 -0
  262. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/_sync/domains/teleport.py +0 -0
  263. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/_sync/domains/usage.py +0 -0
  264. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/_sync/domains/users.py +0 -0
  265. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/_sync/domains/voxels.py +0 -0
  266. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/_sync/graphql.py +0 -0
  267. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/_sync/grid_scope.py +0 -0
  268. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/_sync/kit/__init__.py +0 -0
  269. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/_sync/kit/actions.py +0 -0
  270. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/_sync/kit/kit.py +0 -0
  271. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/_sync/kit/social.py +0 -0
  272. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/_sync/kit/wire.py +0 -0
  273. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/_sync/rediscover.py +0 -0
  274. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/_sync/stores.py +0 -0
  275. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/_sync/world.py +0 -0
  276. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/auth_state.py +0 -0
  277. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/client.py +0 -0
  278. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/codecs.py +0 -0
  279. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/datacenter_redirect.py +0 -0
  280. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/domains/__init__.py +0 -0
  281. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/domains/_base.py +0 -0
  282. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/domains/actors.py +0 -0
  283. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/domains/admin.py +0 -0
  284. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/domains/app_access.py +0 -0
  285. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/domains/apps.py +0 -0
  286. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/domains/avatars.py +0 -0
  287. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/domains/billing.py +0 -0
  288. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/domains/channels.py +0 -0
  289. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/domains/chunks.py +0 -0
  290. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/domains/crowdy_studio.py +0 -0
  291. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/domains/crowdy_studio_agent.py +0 -0
  292. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/domains/crowdy_studio_github.py +0 -0
  293. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/domains/discovery.py +0 -0
  294. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/domains/exec.py +0 -0
  295. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/domains/game_apps.py +0 -0
  296. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/domains/grids.py +0 -0
  297. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/domains/host.py +0 -0
  298. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/domains/marketplace.py +0 -0
  299. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/domains/organizations.py +0 -0
  300. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/domains/payments.py +0 -0
  301. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/domains/platform.py +0 -0
  302. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/domains/player_wallet.py +0 -0
  303. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/domains/quotas.py +0 -0
  304. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/domains/server_status.py +0 -0
  305. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/domains/shared_environment.py +0 -0
  306. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/domains/state.py +0 -0
  307. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/domains/teams.py +0 -0
  308. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/domains/teleport.py +0 -0
  309. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/domains/usage.py +0 -0
  310. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/domains/users.py +0 -0
  311. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/domains/voxels.py +0 -0
  312. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/enums.py +0 -0
  313. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/errors.py +0 -0
  314. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/estate.py +0 -0
  315. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/exec_gateway.py +0 -0
  316. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/graphql.py +0 -0
  317. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/grid_scope.py +0 -0
  318. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/inputs.py +0 -0
  319. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/kit/__init__.py +0 -0
  320. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/kit/actions.py +0 -0
  321. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/kit/kit.py +0 -0
  322. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/kit/social.py +0 -0
  323. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/kit/wire.py +0 -0
  324. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/lb_cookie.py +0 -0
  325. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/media.py +0 -0
  326. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/pkce.py +0 -0
  327. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/player_host/__init__.py +0 -0
  328. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/player_host/agent_errors.py +0 -0
  329. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/player_host/agent_types.py +0 -0
  330. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/player_host/json_schema.py +0 -0
  331. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/player_host/schemas.py +0 -0
  332. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/player_host/types.py +0 -0
  333. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/py.typed +0 -0
  334. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/rediscover.py +0 -0
  335. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/session.py +0 -0
  336. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/stores.py +0 -0
  337. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/studio/__init__.py +0 -0
  338. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/studio/client_tick_interval.py +0 -0
  339. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/studio/controller.py +0 -0
  340. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/studio/diagnostics.py +0 -0
  341. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/studio/github_new_repo.py +0 -0
  342. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/studio/layout.py +0 -0
  343. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/studio/models.py +0 -0
  344. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/studio/starter_projects.py +0 -0
  345. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/subscriptions.py +0 -0
  346. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/sync.py +0 -0
  347. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/utils.py +0 -0
  348. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/src/crowdypy/world.py +0 -0
  349. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/tests/conftest.py +0 -0
  350. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/tests/e2e/__init__.py +0 -0
  351. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/tests/e2e/test_e2e_open_grid_exec_gateway.py +0 -0
  352. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/tests/e2e/test_e2e_replication.py +0 -0
  353. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/tests/e2e/test_e2e_studio.py +0 -0
  354. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/tests/e2e/test_e2e_world.py +0 -0
  355. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/tests/e2e/test_e2e_world_data.py +0 -0
  356. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/tests/fixtures/README.md +0 -0
  357. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/tests/fixtures/exec-client-frames.json +0 -0
  358. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/tests/unit/__init__.py +0 -0
  359. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/tests/unit/domains/__init__.py +0 -0
  360. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/tests/unit/domains/test_crowdycpp_roots.py +0 -0
  361. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/tests/unit/domains/test_org_domains.py +0 -0
  362. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/tests/unit/domains/test_social_domains.py +0 -0
  363. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/tests/unit/domains/test_studio_exec_domains.py +0 -0
  364. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/tests/unit/domains/test_world_domains.py +0 -0
  365. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/tests/unit/test_core.py +0 -0
  366. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/tests/unit/test_durable_stores.py +0 -0
  367. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/tests/unit/test_estate_moves.py +0 -0
  368. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/tests/unit/test_exec_gateway.py +0 -0
  369. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/tests/unit/test_fixture_provenance.py +0 -0
  370. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/tests/unit/test_grid_scope.py +0 -0
  371. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/tests/unit/test_kit.py +0 -0
  372. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/tests/unit/test_lazy_exports.py +0 -0
  373. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/tests/unit/test_player_host.py +0 -0
  374. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/tests/unit/test_release_versions.py +0 -0
  375. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/tests/unit/test_sdk_audience.py +0 -0
  376. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/tests/unit/test_studio_controller.py +0 -0
  377. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/tests/unit/test_studio_diagnostics.py +0 -0
  378. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/tests/unit/test_studio_layout.py +0 -0
  379. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/tests/unit/test_subscriptions.py +0 -0
  380. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/tests/unit/test_transport.py +0 -0
  381. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/tests/unit/test_udp_api.py +0 -0
  382. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/tests/unit/test_world_session.py +0 -0
  383. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/tools/fixtures/player_host.mjs +0 -0
  384. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/tools/parity/parity.py +0 -0
  385. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/LICENSE +0 -0
  386. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/cmake/CheckPublicHeaders.cmake +0 -0
  387. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/cmake/CrowdyCPPConfig.cmake.in +0 -0
  388. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/cmake/studio_layout_fixture.hpp.in +0 -0
  389. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/include/crowdy/client.hpp +0 -0
  390. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/include/crowdy/core/base64.hpp +0 -0
  391. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/include/crowdy/core/bytes.hpp +0 -0
  392. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/include/crowdy/core/clock.hpp +0 -0
  393. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/include/crowdy/core/crypto.hpp +0 -0
  394. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/include/crowdy/core/logger.hpp +0 -0
  395. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/include/crowdy/core/result.hpp +0 -0
  396. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/include/crowdy/core/spsc.hpp +0 -0
  397. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/include/crowdy/core/uuid.hpp +0 -0
  398. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/include/crowdy/crowdy.hpp +0 -0
  399. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/include/crowdy/default_origin.hpp +0 -0
  400. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/include/crowdy/domains/admin.hpp +0 -0
  401. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/include/crowdy/domains/crowdy_studio.hpp +0 -0
  402. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/include/crowdy/domains/crowdy_studio_agent.hpp +0 -0
  403. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/include/crowdy/domains/crowdy_studio_github.hpp +0 -0
  404. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/include/crowdy/domains/discovery.hpp +0 -0
  405. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/include/crowdy/domains/domain_base.hpp +0 -0
  406. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/include/crowdy/domains/exec.hpp +0 -0
  407. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/include/crowdy/domains/game_apps.hpp +0 -0
  408. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/include/crowdy/domains/grids.hpp +0 -0
  409. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/include/crowdy/domains/groups.hpp +0 -0
  410. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/include/crowdy/domains/marketplace.hpp +0 -0
  411. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/include/crowdy/domains/player_wallet.hpp +0 -0
  412. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/include/crowdy/domains/portal.hpp +0 -0
  413. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/include/crowdy/domains/realtime_control.hpp +0 -0
  414. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/include/crowdy/domains/server_status.hpp +0 -0
  415. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/include/crowdy/domains/types.hpp +0 -0
  416. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/include/crowdy/domains/users.hpp +0 -0
  417. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/include/crowdy/domains/world_data.hpp +0 -0
  418. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/include/crowdy/graphql/async_scope.hpp +0 -0
  419. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/include/crowdy/graphql/auth_state.hpp +0 -0
  420. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/include/crowdy/graphql/datacenter_redirect.hpp +0 -0
  421. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/include/crowdy/graphql/dispatcher.hpp +0 -0
  422. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/include/crowdy/graphql/errors.hpp +0 -0
  423. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/include/crowdy/graphql/estate.hpp +0 -0
  424. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/include/crowdy/graphql/graphql_client.hpp +0 -0
  425. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/include/crowdy/graphql/http.hpp +0 -0
  426. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/include/crowdy/graphql/json.hpp +0 -0
  427. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/include/crowdy/graphql/rediscover.hpp +0 -0
  428. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/include/crowdy/graphql/subscription_client.hpp +0 -0
  429. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/include/crowdy/graphql/websocket.hpp +0 -0
  430. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/include/crowdy/kit/actions.hpp +0 -0
  431. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/include/crowdy/kit/kit.hpp +0 -0
  432. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/include/crowdy/kit/social.hpp +0 -0
  433. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/include/crowdy/kit/wire.hpp +0 -0
  434. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/include/crowdy/media/video_frames.hpp +0 -0
  435. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/include/crowdy/player_host/adapter.hpp +0 -0
  436. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/include/crowdy/player_host/player_host.hpp +0 -0
  437. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/include/crowdy/player_host/schemas.hpp +0 -0
  438. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/include/crowdy/player_host/types.hpp +0 -0
  439. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/include/crowdy/replication/session_provider.hpp +0 -0
  440. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/include/crowdy/replication/types.hpp +0 -0
  441. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/include/crowdy/replication/udp_socket.hpp +0 -0
  442. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/include/crowdy/session/chunk_store.hpp +0 -0
  443. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/include/crowdy/session/codec.hpp +0 -0
  444. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/include/crowdy/session/durable.hpp +0 -0
  445. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/include/crowdy/session/keys.hpp +0 -0
  446. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/include/crowdy/session/stores.hpp +0 -0
  447. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/include/crowdy/session/world_session.hpp +0 -0
  448. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/include/crowdy/studio/controller.hpp +0 -0
  449. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/include/crowdy/studio/diagnostics.hpp +0 -0
  450. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/include/crowdy/studio/editor.hpp +0 -0
  451. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/include/crowdy/studio/github.hpp +0 -0
  452. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/include/crowdy/studio/github_layout.hpp +0 -0
  453. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/include/crowdy/studio/integration.hpp +0 -0
  454. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/include/crowdy/studio/layout.hpp +0 -0
  455. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/include/crowdy/studio/models.hpp +0 -0
  456. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/include/crowdy/studio/runtime.hpp +0 -0
  457. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/include/crowdy/world.hpp +0 -0
  458. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/src/client.cpp +0 -0
  459. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/src/core/base64.cpp +0 -0
  460. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/src/core/clock.cpp +0 -0
  461. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/src/core/crypto_default_unavailable.cpp +0 -0
  462. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/src/core/crypto_openssl.cpp +0 -0
  463. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/src/core/crypto_unavailable.cpp +0 -0
  464. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/src/core/logger.cpp +0 -0
  465. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/src/core/uuid.cpp +0 -0
  466. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/src/domains/exec.cpp +0 -0
  467. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/src/graphql/async_transport.cpp +0 -0
  468. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/src/graphql/auth_state.cpp +0 -0
  469. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/src/graphql/error_extensions.hpp +0 -0
  470. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/src/graphql/errors.cpp +0 -0
  471. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/src/graphql/graphql_client.cpp +0 -0
  472. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/src/graphql/http_curl.cpp +0 -0
  473. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/src/graphql/http_none.cpp +0 -0
  474. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/src/graphql/json.cpp +0 -0
  475. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/src/graphql/subscription_client.cpp +0 -0
  476. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/src/graphql/websocket_curl.cpp +0 -0
  477. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/src/graphql/websocket_none.cpp +0 -0
  478. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/src/player_host/schemas.cpp +0 -0
  479. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/src/player_host/types.cpp +0 -0
  480. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/src/replication/socket_errors.hpp +0 -0
  481. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/src/replication/udp_socket.cpp +0 -0
  482. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/src/session/world_session.cpp +0 -0
  483. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/src/studio/diagnostics.cpp +0 -0
  484. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/src/studio/editor.cpp +0 -0
  485. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/src/studio/integration.cpp +0 -0
  486. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/third_party/yyjson/LICENSE +0 -0
  487. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/third_party/yyjson/yyjson.c +0 -0
  488. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/third_party/yyjson/yyjson.h +0 -0
  489. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/tools/parity/fixtures/exec-client-frames.json +0 -0
  490. {crowdypy-0.5.1.dev1 → crowdypy-0.6.0.dev1}/vendor/CrowdyCPP/tools/parity/fixtures/exec-gateway-cases.json +0 -0
@@ -3,6 +3,37 @@
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.6.0
7
+
8
+ CrowdyJS 18.5.0 and CrowdyCPP 0.58.0. Additive.
9
+
10
+ - **Distance-limited channel messages.**
11
+ `client.udp.send_ranged_channel_message(channel_id, uuid, payload, *, chunk, max_distance)`
12
+ publishes to a channel but reaches only the members whose own actor is within
13
+ `max_distance` chunks of `chunk`. Distance is the straight line between chunk coordinates,
14
+ inclusive: 0 reaches only the origin chunk, and 5 reaches a member 3 chunks east and 4
15
+ north but not one 4 east and 4 north (about 5.66). It takes the same right as
16
+ `send_channel_message`, and members receive the ordinary `channel_message`, so receivers
17
+ change nothing. A member with no actor of its own is not reached, nor is the sender.
18
+ `max_distance` is 0 to `crowdypy.wire.CHANNEL_RANGED_MAX_DISTANCE` (2^31 - 1); the origin's
19
+ app is the connection's. Underneath it is
20
+ `ReplicationConnection.send_ranged_channel_message(channel_id, uuid, payload, chunk,
21
+ max_distance)`, and `crowdypy.wire.encode_ranged_channel_message` encodes the
22
+ CHANNEL_MESSAGE_RANGED_REQUEST (32) for a custom transport. It needs a replication server
23
+ that serves message type 32; one that does not delivers nothing.
24
+ - **The terms and age gate** (CrowdyJS 18.4.0). Since ck-api v2.35.0 no gameplay token
25
+ (`portal.mint_app_token`, `portal.create_authorization_code`, `portal.refresh`) is issued
26
+ until the player has agreed to the current required legal documents and attested that they
27
+ are at least 18, or the age of majority where they live if higher; the refusal is
28
+ `LEGAL_ACCEPTANCE_REQUIRED`, which `crowdypy.is_legal_acceptance_required_error` reads.
29
+ Show your own two checkboxes, linking each document, then call
30
+ `client.auth.record_player_consents(accept_legal=True, attest_age_of_majority=True)` before
31
+ minting; `client.auth.player_legal_acceptance()` says whether that is still needed.
32
+ `client.auth.register` takes `accept_legal` and `attest_age_of_majority`, and an account
33
+ registered with both `True` starts accepted. Record them only for a player who ticked both
34
+ boxes: they are the player's agreement. Against an older API the two new calls fail as
35
+ GraphQL validation errors.
36
+
6
37
  ## 0.5.1
7
38
 
8
39
  CrowdyJS 18.2.0 and CrowdyCPP 0.56.0. No API change; one behaviour fix.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: crowdypy
3
- Version: 0.5.1.dev1
3
+ Version: 0.6.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,10 +51,16 @@ 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.5.1: chunk loads keep recorded voxel edits (CrowdyJS 18.2.0, CrowdyCPP 0.56.0).**
55
- - `ChunkStore.hydrate()` puts every recorded voxel edit (`voxelStates`: a hub's or mod's
56
- `world.set_voxels`, `updateVoxel`, realtime updates) on the grid, and a later
57
- `ensure_around()` keeps a chunk it already loaded instead of reloading its bare voxels.
54
+ **v0.6.0: distance-limited channel messages and the terms gate (CrowdyJS 18.5.0, CrowdyCPP 0.58.0).**
55
+ - `client.udp.send_ranged_channel_message(..., chunk=, max_distance=)` publishes to a channel
56
+ but reaches only the members whose own actor is within `max_distance` chunks of `chunk`,
57
+ by straight-line distance. Members receive the ordinary `channel_message`.
58
+ - `client.auth.record_player_consents()` and `player_legal_acceptance()`, `register`'s
59
+ `accept_legal` and `attest_age_of_majority`, and `is_legal_acceptance_required_error`: a
60
+ gameplay token now waits for the player's agreement to the legal documents and age
61
+ attestation.
62
+ - 0.5.1 made `ChunkStore.hydrate()` keep every recorded voxel edit (`voxelStates`) and
63
+ `ensure_around()` keep a chunk it already loaded.
58
64
  - 0.5.0 brought the ck-exec gateway check (`client.exec.connect()` sends the connect token
59
65
  only to a gateway on the game API's estate, and reports a refusal as `Denied`) and open
60
66
  grids (`game_apps.open_permissions()` and `set_open_permissions()`).
@@ -136,7 +142,10 @@ There is one API origin but two tokens, as in every Crowded Kingdoms SDK:
136
142
  token**: account, studio administration and minting. It is not accepted for gameplay.
137
143
  2. Gameplay needs a short-lived **app-scoped token** per app
138
144
  (`portal.mint_app_token(app_id)`), which is also the HMAC key for native UDP. Refresh it
139
- with `client.refresh_gameplay_token()` (concurrent callers share one refresh).
145
+ with `client.refresh_gameplay_token()` (concurrent callers share one refresh). It is
146
+ refused with `LEGAL_ACCEPTANCE_REQUIRED` until the player's agreement to the legal
147
+ documents and age attestation are stored: show both checkboxes, then call
148
+ `auth.record_player_consents(accept_legal=True, attest_age_of_majority=True)`.
140
149
  3. Build one identity client and one client per game. The game client points at the app's
141
150
  datacenter (`game_api_url`) with `discovery_url` set, so it can find the app again if
142
151
  that instance stops answering.
@@ -11,10 +11,16 @@ 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.5.1: chunk loads keep recorded voxel edits (CrowdyJS 18.2.0, CrowdyCPP 0.56.0).**
15
- - `ChunkStore.hydrate()` puts every recorded voxel edit (`voxelStates`: a hub's or mod's
16
- `world.set_voxels`, `updateVoxel`, realtime updates) on the grid, and a later
17
- `ensure_around()` keeps a chunk it already loaded instead of reloading its bare voxels.
14
+ **v0.6.0: distance-limited channel messages and the terms gate (CrowdyJS 18.5.0, CrowdyCPP 0.58.0).**
15
+ - `client.udp.send_ranged_channel_message(..., chunk=, max_distance=)` publishes to a channel
16
+ but reaches only the members whose own actor is within `max_distance` chunks of `chunk`,
17
+ by straight-line distance. Members receive the ordinary `channel_message`.
18
+ - `client.auth.record_player_consents()` and `player_legal_acceptance()`, `register`'s
19
+ `accept_legal` and `attest_age_of_majority`, and `is_legal_acceptance_required_error`: a
20
+ gameplay token now waits for the player's agreement to the legal documents and age
21
+ attestation.
22
+ - 0.5.1 made `ChunkStore.hydrate()` keep every recorded voxel edit (`voxelStates`) and
23
+ `ensure_around()` keep a chunk it already loaded.
18
24
  - 0.5.0 brought the ck-exec gateway check (`client.exec.connect()` sends the connect token
19
25
  only to a gateway on the game API's estate, and reports a refusal as `Denied`) and open
20
26
  grids (`game_apps.open_permissions()` and `set_open_permissions()`).
@@ -96,7 +102,10 @@ There is one API origin but two tokens, as in every Crowded Kingdoms SDK:
96
102
  token**: account, studio administration and minting. It is not accepted for gameplay.
97
103
  2. Gameplay needs a short-lived **app-scoped token** per app
98
104
  (`portal.mint_app_token(app_id)`), which is also the HMAC key for native UDP. Refresh it
99
- with `client.refresh_gameplay_token()` (concurrent callers share one refresh).
105
+ with `client.refresh_gameplay_token()` (concurrent callers share one refresh). It is
106
+ refused with `LEGAL_ACCEPTANCE_REQUIRED` until the player's agreement to the legal
107
+ documents and age attestation are stored: show both checkboxes, then call
108
+ `auth.record_player_consents(accept_legal=True, attest_age_of_majority=True)`.
100
109
  3. Build one identity client and one client per game. The game client points at the app's
101
110
  datacenter (`game_api_url`) with `discovery_url` set, so it can find the app again if
102
111
  that instance stops answering.
@@ -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.5.1`
8
+ - CrowdyPy `0.6.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
@@ -38,3 +38,8 @@ requirement names one exactly, the same way a caret never matches an npm prerele
38
38
  `exec*` roots answers those calls with a GraphQL validation error.
39
39
  - Direct sign-in (`auth.login`, `auth.register`) is served to non-browser callers. CrowdyPy
40
40
  sends no `Origin` header, so it is exempt from `HOSTED_SIGN_IN_REQUIRED`.
41
+ - `auth.record_player_consents` and `auth.player_legal_acceptance` need ck-api v2.35.0; an
42
+ older API answers them with a GraphQL validation error. From v2.35.0 a gameplay token
43
+ waits for both consents (`LEGAL_ACCEPTANCE_REQUIRED`).
44
+ - `udp.send_ranged_channel_message` needs a replication server that serves message type 32
45
+ (CHANNEL_MESSAGE_RANGED_REQUEST); one that does not delivers nothing.
@@ -36,10 +36,11 @@ player once and signs it in for the later suites.
36
36
 
37
37
  | Suite | Scenarios | CrowdyCPP counterpart |
38
38
  |---|---|---|
39
- | `test_e2e_identity.py` | register and sign in; mint an app token (64 octets) and refresh it; `serverWithLeastClients` with the app token; a wrong password is refused; the identity session token is refused for gameplay | `e2e_auth_identities`, `e2e_negative_auth`, `e2e_gameplay_token_refresh` |
39
+ | `test_e2e_identity.py` | register and sign in; mint an app token (64 octets) and refresh it; `serverWithLeastClients` with the app token; a player registered without the legal consents is refused a gameplay token (`LEGAL_ACCEPTANCE_REQUIRED`) until `record_player_consents`, and `player_legal_acceptance` follows; a wrong password is refused; the identity session token is refused for gameplay | `e2e_auth_identities`, `e2e_negative_auth`, `e2e_gameplay_token_refresh` |
40
40
  | `test_e2e_replication.py` | two players over native UDP: an actor update reaches the other player and echoes back to the sender; a 16-entity batched frame (`send_actor_updates`) reaches the other player; voxel updates and client events reach the other player | `e2e_two_client_actor`, `e2e_self_echo`, `e2e_spatial_distance` |
41
41
  | `test_e2e_world.py` | two World Stores sessions: each sees the other's actor natively; a voxel edit lands in the other session's chunk store | `e2e_stores_live`, `e2e_world_session` |
42
42
  | `test_e2e_world_data.py` | a GraphQL voxel write by an entitled player is recorded and listed back | `e2e_chunks` |
43
+ | `test_e2e_ranged_channel.py` | the owner's invite channel with four members, each keeping an actor at its own chunk: a distance-limited channel message from A reaches B at 5 chunks with `max_distance` 5 but not C (about 5.66) or D (7); 6 adds C, 7 adds D; A never receives its own; no send is refused | `e2e_ranged_channel` |
43
44
  | `test_e2e_open_grid_exec_gateway.py` | as a throwaway org admin (`CROWDY_E2E_THROWAWAY_OWNER=1`): open a nested grid, read it back, a player holds its keys, a player-code key is refused `BAD_REQUEST`, close it; the tier's ck-exec gateway passes `exec_gateway_refusal`, a connection pings, and a tampered connect token is `Denied` with the gateway's HTTP 401 reason | `e2e_open_grid_exec_gateway` |
44
45
  | `test_e2e_studio.py` | the headless Studio controller creates a project from the mod starter, edits it with autosave, and archives it (optional: needs `CROWDY_E2E_STUDIO_GRID_ID`) | `e2e_crowdy_studio` |
45
46
 
@@ -52,6 +53,7 @@ player once and signs it in for the later suites.
52
53
  | 2026-10-01 | dev tier, app `96701660793088` | the published `dev/v0.4.0` wheel (`0.4.0.dev1`, manylinux x86_64, installed into a clean Python 3.12) | 8 passed |
53
54
  | 2026-10-01 | dev tier, app `96701660793088` | `crowdypy 0.4.1.dev1` from PyPI (`pip install crowdypy` in a clean Python 3.12; the first version published by trusted publishing) | 8 passed; Studio skipped |
54
55
  | 2026-10-01 | dev tier, app `96701660793088`; the open-grid suite in its own throwaway org and app (`CROWDY_E2E_THROWAWAY_OWNER=1`) | `crowdypy 0.5.0.dev1` from PyPI (`pip install crowdypy` in a clean Python 3.12) | 10 passed; Studio skipped |
56
+ | 2026-10-08 | local stack: ck-api at the distance-limited channel branch (off `dev`), two replication servers serving message type 32, the 3-node Citus lab | 0.6.0 (branch) | identity, ranged channel, replication, world and world data suites: 10 passed |
55
57
 
56
58
  ## Not covered here
57
59
 
@@ -4,16 +4,16 @@ Generated by `tools/parity/parity.py`; do not edit by hand. Classifications live
4
4
 
5
5
  ## Target
6
6
 
7
- - CrowdyJS: `18.2.0` at `269966d158f45749e9a563abf6032369ae0c258a`
8
- - CrowdyCPP (native core): `0.56.0` at `910ce23082940b570dc02f009d68d31594bd4be3`
7
+ - CrowdyJS: `18.5.0` at `ae249cbe5661c5d14394994f66083d2731fab7e0`
8
+ - CrowdyCPP (native core): `0.58.0` at `cae2f4af8a7af79cec12b612213b738c41969b1d`
9
9
  - schema.gql identical to CrowdyJS's: yes
10
10
  - Gate mode: strict portable parity (every portable gap is release-blocking)
11
11
 
12
12
  ## Summary
13
13
 
14
- - Covered: 1012
14
+ - Covered: 1019
15
15
  - Portable gap: 0
16
- - Native equivalent: 38
16
+ - Native equivalent: 40
17
17
  - Browser exclusion: 95
18
18
  - Deprecated roots: 2
19
19
  - Unclassified: 0
@@ -137,6 +137,7 @@ Generated by `tools/parity/parity.py`; do not edit by hand. Classifications live
137
137
  | `mutation.mintAppToken` | covered |
138
138
  | `mutation.mintGridToken` | covered |
139
139
  | `mutation.publishAppToShared` | covered |
140
+ | `mutation.recordPlayerConsents` | covered |
140
141
  | `mutation.refreshAppToken` | covered |
141
142
  | `mutation.register` | covered |
142
143
  | `mutation.reinstateOrganization` | browser exclusion — operator-only organization lifecycle; not a game-client surface |
@@ -164,6 +165,7 @@ Generated by `tools/parity/parity.py`; do not edit by hand. Classifications live
164
165
  | `mutation.sendAudioPacket` | native equivalent — client.udp sends and receives this over CrowdyCPP's native UDP connection; the GraphQL UDP proxy exists because a page cannot open a UDP socket |
165
166
  | `mutation.sendChannelMessage` | native equivalent — client.udp sends and receives this over CrowdyCPP's native UDP connection; the GraphQL UDP proxy exists because a page cannot open a UDP socket |
166
167
  | `mutation.sendClientEvent` | native equivalent — client.udp sends and receives this over CrowdyCPP's native UDP connection; the GraphQL UDP proxy exists because a page cannot open a UDP socket |
168
+ | `mutation.sendRangedChannelMessage` | native equivalent — client.udp sends and receives this over CrowdyCPP's native UDP connection; the GraphQL UDP proxy exists because a page cannot open a UDP socket |
167
169
  | `mutation.sendSingleActorMessage` | native equivalent — client.udp sends and receives this over CrowdyCPP's native UDP connection; the GraphQL UDP proxy exists because a page cannot open a UDP socket |
168
170
  | `mutation.sendTestEmail` | browser exclusion — operator-only email deliverability control; not a game-client surface |
169
171
  | `mutation.sendTextPacket` | native equivalent — client.udp sends and receives this over CrowdyCPP's native UDP connection; the GraphQL UDP proxy exists because a page cannot open a UDP socket |
@@ -376,6 +378,7 @@ Generated by `tools/parity/parity.py`; do not edit by hand. Classifications live
376
378
  | `query.placeableDatacenters` | covered |
377
379
  | `query.platformConfig` | covered |
378
380
  | `query.playerAutoBilling` | covered |
381
+ | `query.playerLegalAcceptance` | covered |
379
382
  | `query.playerPulse` | covered |
380
383
  | `query.playerRateMarkup` | covered |
381
384
  | `query.playerRuntimeStates` | covered |
@@ -546,6 +549,8 @@ Generated by `tools/parity/parity.py`; do not edit by hand. Classifications live
546
549
  | `AuthAPI.logout` | covered |
547
550
  | `AuthAPI.logoutAllDevices` | covered |
548
551
  | `AuthAPI.myIdentities` | covered |
552
+ | `AuthAPI.playerLegalAcceptance` | covered |
553
+ | `AuthAPI.recordPlayerConsents` | covered |
549
554
  | `AuthAPI.register` | covered |
550
555
  | `AuthAPI.requestLoginLink` | covered |
551
556
  | `AuthAPI.requestPasswordReset` | covered |
@@ -1000,6 +1005,7 @@ Generated by `tools/parity/parity.py`; do not edit by hand. Classifications live
1000
1005
  | `UdpAPI.sendChannelMessage` | covered |
1001
1006
  | `UdpAPI.sendClientEvent` | covered |
1002
1007
  | `UdpAPI.sendClientEventAndWait` | covered |
1008
+ | `UdpAPI.sendRangedChannelMessage` | covered |
1003
1009
  | `UdpAPI.sendSingleActorMessage` | covered |
1004
1010
  | `UdpAPI.sendTextPacket` | covered |
1005
1011
  | `UdpAPI.sendTextPacketAndWait` | covered |
@@ -1042,6 +1048,7 @@ Generated by `tools/parity/parity.py`; do not edit by hand. Classifications live
1042
1048
  | `BUNDLE_LENGTH_PREFIX_BYTES` | native equivalent — the same codec, CrowdyCPP's, through crowdypy.wire: crowdypy.wire.bundle() / split_datagram(), which own the bundle layout |
1043
1049
  | `BinaryRelayTransport` | browser exclusion — the raw-WebSocket relay exists because a page cannot open a UDP socket; CrowdyPy replicates over native UDP (CrowdyCPP's core) |
1044
1050
  | `BrowserLocalStorageTokenStore` | native equivalent — token persistence is TokenStore / SessionStore; the localStorage backing is browser-only, and FileTokenStore mirrors its session / app key split |
1051
+ | `CHANNEL_RANGED_MAX_DISTANCE` | covered |
1045
1052
  | `CLIENT_GRID_EVENT_MAX_CASCADE` | browser exclusion — page-local event bus between CLIENT mods running in this browser's glue workers |
1046
1053
  | `CROWDY_DEFAULT_HOST` | covered |
1047
1054
  | `CROWDY_DEFAULT_HTTP_ORIGIN` | covered |
@@ -1142,6 +1149,7 @@ Generated by `tools/parity/parity.py`; do not edit by hand. Classifications live
1142
1149
  | `isAlreadyRegisteredError` | covered |
1143
1150
  | `isHostedSignInRequiredError` | covered |
1144
1151
  | `isInvalidCurrentPasswordError` | covered |
1152
+ | `isLegalAcceptanceRequiredError` | covered |
1145
1153
  | `isNewerFrameId` | covered |
1146
1154
  | `isNoPasswordSetError` | covered |
1147
1155
  | `isPasswordAlreadySetError` | covered |
@@ -1172,6 +1180,7 @@ Generated by `tools/parity/parity.py`; do not edit by hand. Classifications live
1172
1180
  | `serializeAudioPacket` | native equivalent — the same codec, CrowdyCPP's, through crowdypy.wire: crowdypy.wire.encode_long_spatial with the message type |
1173
1181
  | `serializeChannelMessage` | native equivalent — the same codec, CrowdyCPP's, through crowdypy.wire: crowdypy.wire.encode_channel_message with the message type |
1174
1182
  | `serializeClientEvent` | native equivalent — the same codec, CrowdyCPP's, through crowdypy.wire: crowdypy.wire.encode_long_spatial with the message type |
1183
+ | `serializeRangedChannelMessage` | native equivalent — the same codec, CrowdyCPP's, through crowdypy.wire: crowdypy.wire.encode_ranged_channel_message |
1175
1184
  | `serializeSingleActorMessage` | native equivalent — the same codec, CrowdyCPP's, through crowdypy.wire: crowdypy.wire.encode_long_spatial with the message type |
1176
1185
  | `serializeTextPacket` | native equivalent — the same codec, CrowdyCPP's, through crowdypy.wire: crowdypy.wire.encode_long_spatial with the message type |
1177
1186
  | `serializeVideoPacket` | native equivalent — the same codec, CrowdyCPP's, through crowdypy.wire: crowdypy.wire.encode_long_spatial with the message type |
@@ -552,6 +552,19 @@ class PyConnection {
552
552
  return sent(result, "sendChannelMessage");
553
553
  }
554
554
 
555
+ int sendRangedChannel(std::int64_t channelId, nb::handle uuid, nb::handle payload, std::int64_t x,
556
+ std::int64_t y, std::int64_t z, std::uint32_t maxDistance) {
557
+ const core::ActorUuid id = uuid_from(uuid);
558
+ BufferView body(payload);
559
+ Result<std::uint8_t> result = Errc::InvalidArgument;
560
+ {
561
+ nb::gil_scoped_release release;
562
+ result = connection_->sendRangedChannelMessage(channelId, id, body.bytes(), {x, y, z},
563
+ maxDistance);
564
+ }
565
+ return sent(result, "sendRangedChannelMessage");
566
+ }
567
+
555
568
  int sendHeartbeat(std::int64_t x, std::int64_t y, std::int64_t z, nb::handle uuid) {
556
569
  const core::ActorUuid id = uuid_from(uuid);
557
570
  Result<std::uint8_t> result = Errc::InvalidArgument;
@@ -280,6 +280,9 @@ void register_replication(nb::module_& m) {
280
280
  nb::arg("z"), nb::arg("uuid"), nb::arg("payload"))
281
281
  .def("send_channel_message", &PyConnection::sendChannel, nb::arg("channel_id"),
282
282
  nb::arg("uuid"), nb::arg("payload"))
283
+ .def("send_ranged_channel_message", &PyConnection::sendRangedChannel, nb::arg("channel_id"),
284
+ nb::arg("uuid"), nb::arg("payload"), nb::arg("x"), nb::arg("y"), nb::arg("z"),
285
+ nb::arg("max_distance"))
283
286
  .def("send_heartbeat", &PyConnection::sendHeartbeat, nb::arg("x"), nb::arg("y"), nb::arg("z"),
284
287
  nb::arg("uuid"))
285
288
  .def("send_video_frame", &PyConnection::sendVideoFrame, nb::arg("x"), nb::arg("y"),
@@ -99,6 +99,29 @@ nb::bytes encode_channel_message(nb::handle token_obj, std::int64_t channel_id,
99
99
  return to_bytes(Bytes(buf, n.value()));
100
100
  }
101
101
 
102
+ nb::bytes encode_ranged_channel_message(nb::handle token_obj, std::int64_t channel_id,
103
+ nb::handle uuid_obj, nb::handle payload_obj,
104
+ std::int64_t app_id, std::int64_t chunk_x,
105
+ std::int64_t chunk_y, std::int64_t chunk_z,
106
+ std::uint32_t max_distance, std::int64_t game_token_id,
107
+ std::uint8_t sequence) {
108
+ const auto token = token_from(token_obj);
109
+ BufferView payload(payload_obj);
110
+ wire::RangedChannelMessageParams p;
111
+ p.channelId = channel_id;
112
+ p.uuid = uuid_from(uuid_obj);
113
+ p.appId = app_id;
114
+ p.origin = {chunk_x, chunk_y, chunk_z};
115
+ p.maxDistance = max_distance;
116
+ p.payload = payload.bytes();
117
+ p.gameTokenId = game_token_id;
118
+ p.sequence = sequence;
119
+ std::uint8_t buf[wire::kMaxDatagramSize];
120
+ auto n = wire::encodeRangedChannelMessage(crypto(), p, token, MutableBytes(buf, sizeof(buf)));
121
+ if (!n.ok()) raise(n.error(), "cannot encode this ranged channel message");
122
+ return to_bytes(Bytes(buf, n.value()));
123
+ }
124
+
102
125
  nb::tuple parse_channel_notification(nb::handle datagram_obj) {
103
126
  BufferView datagram(datagram_obj);
104
127
  auto v = wire::parseChannelNotification(datagram.bytes());
@@ -173,6 +196,7 @@ void register_wire(nb::module_& m) {
173
196
  m.attr("MAX_BUNDLE_MEMBERS") = wire::kMaxBundleMembers;
174
197
  m.attr("MAX_BUNDLE_MEMBER_SIZE") = wire::kMaxBundleMemberSize;
175
198
  m.attr("MAX_CHANNEL_PAYLOAD") = wire::channel::kMaxPayload;
199
+ m.attr("CHANNEL_RANGED_MAX_DISTANCE") = wire::channel_ranged::kMaxDistance;
176
200
  m.attr("MAX_DISTANCE") = wire::kMaxDistance;
177
201
  m.attr("CLIENT_CAPABILITIES_ALL") = wire::ClientCapability::kAll;
178
202
 
@@ -189,6 +213,10 @@ void register_wire(nb::module_& m) {
189
213
  m.def("encode_channel_message", &encode_channel_message, nb::arg("token"),
190
214
  nb::arg("channel_id"), nb::arg("uuid"), nb::arg("payload"), nb::arg("game_token_id"),
191
215
  nb::arg("sequence"));
216
+ m.def("encode_ranged_channel_message", &encode_ranged_channel_message, nb::arg("token"),
217
+ nb::arg("channel_id"), nb::arg("uuid"), nb::arg("payload"), nb::arg("app_id"),
218
+ nb::arg("chunk_x"), nb::arg("chunk_y"), nb::arg("chunk_z"), nb::arg("max_distance"),
219
+ nb::arg("game_token_id"), nb::arg("sequence"));
192
220
  m.def("parse_channel_notification", &parse_channel_notification, nb::arg("datagram"));
193
221
  m.def("parse_generic_error", &parse_generic_error, nb::arg("datagram"));
194
222
  m.def("encode_voxel_payload", &encode_voxel_payload, nb::arg("x"), nb::arg("y"),
@@ -4,7 +4,7 @@ build-backend = "scikit_build_core.build"
4
4
 
5
5
  [project]
6
6
  name = "crowdypy"
7
- version = "0.5.1.dev1"
7
+ version = "0.6.0.dev1"
8
8
  description = "Official Python SDK for Crowded Kingdoms: typed GraphQL clients and a native UDP replication core"
9
9
  readme = "README.md"
10
10
  license = "MIT AND Apache-2.0"
@@ -117,19 +117,19 @@ environment = { OPENSSL_ROOT_DIR = "C:/vcpkg/installed/x64-windows-static-md" }
117
117
  # --------------------------------------------------------------------------------------
118
118
 
119
119
  [tool.crowdypy.crowdyjs]
120
- version = "18.2.0"
121
- commit = "269966d158f45749e9a563abf6032369ae0c258a"
120
+ version = "18.5.0"
121
+ commit = "ae249cbe5661c5d14394994f66083d2731fab7e0"
122
122
 
123
123
  [tool.crowdypy.crowdycpp]
124
- version = "0.56.0"
125
- tag = "910ce23082940b570dc02f009d68d31594bd4be3"
126
- commit = "910ce23082940b570dc02f009d68d31594bd4be3"
127
- tree-sha256 = "1e294223900a84c064ba8c50281edfe5cea2c7c2ac042d842fa5a7804ad89cd4"
124
+ version = "0.58.0"
125
+ tag = "dev/v0.58.0"
126
+ commit = "cae2f4af8a7af79cec12b612213b738c41969b1d"
127
+ tree-sha256 = "18db491aa66a14e209437b296d1bdd002746ebb811c5f39309a93b7bbb9d98d2"
128
128
 
129
129
  # schema.gql and operations/ are CrowdyJS's, copied from the commit pinned above by
130
130
  # scripts/schema_sync.py, which records these hashes and re-derives them in CI.
131
131
  [tool.crowdypy.graphql]
132
- schema-sha256 = "f00952f685420f6c0f4bf58d56debda29aea8cce9b877754393611393ff63db1"
132
+ schema-sha256 = "29d59267d8bf5a0497b272ac22b5edfb702c4872087b0cffaa1542a81c917834"
133
133
  operations-sha256 = "d5e0c505589ea26ecc3398b12f02ad7bd786457f7010ad87dcb8af2ea9366c77"
134
134
 
135
135
  # The SDL the docs site publishes. scripts/schema_drift.py compares the snapshot against it
@@ -2057,6 +2057,20 @@ type PaymentMethodSetup {
2057
2057
  publishableKey: String
2058
2058
  }
2059
2059
 
2060
+ """
2061
+ One band of a graduated price. Each unit of the period's running total is priced at the band its position falls in, so the price of the next unit never rises as the total grows. Bands are edges on the whole total and count from zero: the free allowance fills the first band first.
2062
+ """
2063
+ type RateCardBandType {
2064
+ """
2065
+ Exclusive upper edge of this band on the period's running total, in raw metric units, as a BigInt decimal string. A band covers units from the previous band's edge up to this one. Null on the last band, which has no upper edge.
2066
+ """
2067
+ upToUnits: BigInt
2068
+ """
2069
+ Cents charged per the row's unitQuantity raw units for the units inside this band. Fractional values are permitted.
2070
+ """
2071
+ priceCents: Float!
2072
+ }
2073
+
2060
2074
  """
2061
2075
  One priced dimension: its rate and, where it has one, its hourly free allowance. A dimension with a price of 0 is metered but not charged.
2062
2076
  """
@@ -2099,6 +2113,10 @@ type RateCardEntryType {
2099
2113
  freePeriod: AllowancePeriod
2100
2114
  """Operator note on the seed row; null when unset."""
2101
2115
  description: String
2116
+ """
2117
+ The graduated price, band by band, or null when the dimension has one flat price. When present the bands price the period total and priceCents is the first band's price. aggregate_data_volume (egress) is the dimension priced this way.
2118
+ """
2119
+ priceBands: [RateCardBandType!]
2102
2120
  }
2103
2121
 
2104
2122
  """
@@ -2184,6 +2202,10 @@ type PublicRateCardEntryType {
2184
2202
  The period freeUnits resets on. Every dimension is billed as its period aggregate crosses each whole cent, within about a minute of the usage arriving.
2185
2203
  """
2186
2204
  freePeriod: AllowancePeriod
2205
+ """
2206
+ The graduated price, band by band, or null when the dimension has one flat price. Egress (aggregate_data_volume) is priced this way per app per calendar month: each GB is charged at the band the app's month-to-date total has reached, and priceCents is the first band's price.
2207
+ """
2208
+ priceBands: [RateCardBandType!]
2187
2209
  }
2188
2210
 
2189
2211
  """
@@ -2193,11 +2215,11 @@ type RateChangeType {
2193
2215
  scope: RateScope!
2194
2216
  metric: String!
2195
2217
  """
2196
- One of "priceCents", "unitLabel", "unitQuantity", "freeUnits", "freePeriod" or "freePerMonth".
2218
+ One of "priceCents", "priceBands", "unitLabel", "unitQuantity", "freeUnits", "freePeriod" or "freePerMonth".
2197
2219
  """
2198
2220
  field: String!
2199
2221
  """
2200
- The value before this call, as a decimal string. "none" when there was no allowance row.
2222
+ The value before this call, as a decimal string; for priceBands the schedule as JSON. "none" when there was no allowance row, or no bands.
2201
2223
  """
2202
2224
  previous: String!
2203
2225
  """The value after this call, as a decimal string."""
@@ -6241,6 +6263,10 @@ type Query {
6241
6263
  tierId: BigInt
6242
6264
  ): [GmTierFeature!]! @requiresPermission(scope: "app", permission: "manage_apps", scopeArg: "appId")
6243
6265
  """
6266
+ Whether the signed-in account has stored the current required legal documents and the age-of-majority attestation. False means createPortalAuthorizationCode and mintAppToken will refuse with LEGAL_ACCEPTANCE_REQUIRED until recordPlayerConsents. Requires a session token.
6267
+ """
6268
+ playerLegalAcceptance: Boolean!
6269
+ """
6244
6270
  The federated sign-in providers currently enabled (e.g. ['google']). Use one with socialLoginStart.
6245
6271
  """
6246
6272
  availableLoginProviders: [String!]!
@@ -7972,6 +7998,17 @@ type Mutation {
7972
7998
  input: GrantTierFeatureInput!
7973
7999
  ): Boolean! @requiresPermission(scope: "app", permission: "manage_apps", scopeArg: "input.appId")
7974
8000
  """
8001
+ Store acceptance of the current required legal documents (Game Terms, API Terms, SDK Developer Terms, Free Tier and Billing Basis, Overworld Privacy Policy) and the age-of-majority attestation. Both arguments must be true; a false value stores nothing and is refused with LEGAL_ACCEPTANCE_REQUIRED. Idempotent for a version already stored. Requires a session token. Gameplay tokens stay refused until this has succeeded for the current document set.
8002
+ """
8003
+ recordPlayerConsents(
8004
+ """True when the player agrees to the current required legal documents."""
8005
+ acceptLegal: Boolean!
8006
+ """
8007
+ True when the player attests they are at least 18, or the age of majority where they live if that is higher.
8008
+ """
8009
+ attestAgeOfMajority: Boolean!
8010
+ ): Boolean!
8011
+ """
7975
8012
  Passwordless: email a one-time magic sign-in link to the address (creates the account on first sign-in). Always reports sent=true (no account enumeration). Public; first-party origins only (HOSTED_SIGN_IN_REQUIRED otherwise); rate-limited.
7976
8013
  """
7977
8014
  requestLoginLink(input: RequestLoginLinkInput!): RequestLoginLinkResult!
@@ -7997,7 +8034,7 @@ type Mutation {
7997
8034
  loginUserInput: LoginUserInput!
7998
8035
  ): AuthResponse!
7999
8036
  """
8000
- Registers a new email + password account: creates the (initially unconfirmed) account, emails a confirmation link, and returns an AuthResponse with a session `token` for immediate use (send as `Authorization: Bearer <token>`). If an account already exists for the email it is refused with extensions.code EMAIL_ALREADY_REGISTERED (409) and no session is returned: an account that already has a password is left exactly as it was (sign in, or use the emailed reset), and only a password-less account (created via magic link/social) gets the password attached pending email confirmation. It is a routine outcome rather than a fault, and it reached clients as INTERNAL_SERVER_ERROR before v1.60.0, which is why several of them match it by its message text. Public; first-party origins only (HOSTED_SIGN_IN_REQUIRED otherwise); rate-limited.
8037
+ Registers a new email + password account: creates the (initially unconfirmed) account, emails a confirmation link, and returns an AuthResponse with a session `token` for immediate use (send as `Authorization: Bearer <token>`). If an account already exists for the email it is refused with extensions.code EMAIL_ALREADY_REGISTERED (409) and no session is returned: an account that already has a password is left exactly as it was (sign in, or use the emailed reset), and only a password-less account (created via magic link/social) gets the password attached pending email confirmation. It is a routine outcome rather than a fault, and it reached clients as INTERNAL_SERVER_ERROR before v1.60.0, which is why several of them match it by its message text. A browser request (Origin header present) must send acceptLegal and attestAgeOfMajority both true or it is refused with LEGAL_ACCEPTANCE_REQUIRED before an account is created; a request with no Origin may omit them, and gameplay tokens stay refused until the documents are stored. Public; first-party origins only (HOSTED_SIGN_IN_REQUIRED otherwise); rate-limited.
8001
8038
  """
8002
8039
  register(
8003
8040
  """
@@ -8376,7 +8413,7 @@ type Mutation {
8376
8413
  """
8377
8414
  runSharedUsageBillingTick: Boolean! @requiresPermission(scope: "operator", permission: "is_operator")
8378
8415
  """
8379
- OPERATOR ONLY. Sets a metered dimension's price, the UNIT that price is quoted in, its free allowances, or any combination, and returns the new row alongside the values that moved. THIS IS THE ONLY SANCTIONED WAY TO CHANGE A PRICE OR A UNIT: the schema seeds use ON CONFLICT DO NOTHING, so a rate reaches a tier once at install and a unit corrected in the declaration never reaches a tier that already exists. Refuses an unknown or unmetered metric (a rate for a dimension nothing meters bills nobody while appearing configured), refuses a negative price, refuses unitLabel without unitQuantity (which would restate the rate card while the arithmetic kept the old divisor), and refuses a call that would change nothing. A unit change that also moves the money needs acknowledgeRepricing: true, so restating a price and cutting it cannot be confused. NOT RETROACTIVE: charges already written are history and the tick is idempotent per closed hour, so a new rate applies to hours billed from now on. Takes effect within about a minute — both billing ticks reload the card on every run, so no restart is needed.
8416
+ OPERATOR ONLY. Sets a metered dimension's price, the UNIT that price is quoted in, its free allowances, or any combination, and returns the new row alongside the values that moved. THIS IS THE ONLY SANCTIONED WAY TO CHANGE A PRICE OR A UNIT: the schema seeds use ON CONFLICT DO NOTHING, so a rate reaches a tier once at install and a unit corrected in the declaration never reaches a tier that already exists. Refuses an unknown or unmetered metric (a rate for a dimension nothing meters bills nobody while appearing configured), refuses a negative price, refuses unitLabel without unitQuantity (which would restate the rate card while the arithmetic kept the old divisor), and refuses a call that would change nothing. A unit change that also moves the money needs acknowledgeRepricing: true, so restating a price and cutting it cannot be confused. priceBands sets a graduated schedule (SHARED aggregate_data_volume only; band 1 becomes priceCents) and clearPriceBands returns the dimension to one flat price; while a dimension is banded a bare priceCents or a unit change is refused. NOT RETROACTIVE: charges already written are history and the tick is idempotent per closed hour, so a new rate applies to hours billed from now on. Takes effect within about a minute — both billing ticks reload the card on every run, so no restart is needed.
8380
8417
  """
8381
8418
  setBillingRate(
8382
8419
  """Which dimension to reprice, the new price and/or allowance, and why."""
@@ -9504,6 +9541,15 @@ type Mutation {
9504
9541
  """
9505
9542
  input: ChannelMessageInput!
9506
9543
  ): Boolean!
9544
+ """
9545
+ Publish a message to a channel that only reaches members near an origin chunk: a member receives it, as an ordinary ChannelMessageNotification on udpNotifications, when one of its live actors is in the same app within maxDistance chunks of input.chunk (straight-line distance between chunk coordinates, boundary included). A member with no live actor does not receive it. Requires a bearer game token and the channel send_messages permission, as for sendChannelMessage; the origin app must be the token’s app. Opens a UDP proxy session automatically if none exists. The sender receives no echo. Returns Boolean! that is true only when the datagram was ACCEPTED FOR SENDING — NOT confirmation of delivery; failures arrive ASYNCHRONOUSLY as GenericErrorResponse on udpNotifications (UNAUTHORIZED without the send right, INVALID_APP_ID for another app), correlated by the request sequenceNumber (correlation only — not an idempotency key; the server does not dedupe replays).
9546
+ """
9547
+ sendRangedChannelMessage(
9548
+ """
9549
+ The channel message to publish: channelId (groups.group_id), the sender’s 32-byte actor uuid, base64 payload (max 1024 bytes), the origin appId and chunk, maxDistance in chunks, and optional sequenceNumber. See RangedChannelMessageInput.
9550
+ """
9551
+ input: RangedChannelMessageInput!
9552
+ ): Boolean!
9507
9553
  }
9508
9554
 
9509
9555
  input UpdateGamertagInput {
@@ -9812,6 +9858,14 @@ input RegisterUserInput {
9812
9858
  Optional initial public gamertag (min 3 characters). Can be set later via updateGamertag.
9813
9859
  """
9814
9860
  gamertag: String
9861
+ """
9862
+ True when the player has agreed to the current required legal documents (Game Terms, API Terms, SDK Developer Terms, Free Tier and Billing Basis, Overworld Privacy Policy). A browser signup that omits this, or sends false, is refused with LEGAL_ACCEPTANCE_REQUIRED. Calls with no Origin header may omit it; gameplay tokens stay refused until the documents are stored.
9863
+ """
9864
+ acceptLegal: Boolean
9865
+ """
9866
+ True when the player attests they are at least 18, or the age of majority where they live if that is higher. Same requirement as acceptLegal: required on a browser signup, optional when the request has no Origin.
9867
+ """
9868
+ attestAgeOfMajority: Boolean
9815
9869
  }
9816
9870
 
9817
9871
  input ResetPasswordInput {
@@ -10147,11 +10201,30 @@ input SetRateCardInput {
10147
10201
  """
10148
10202
  freePerMonth: BigInt
10149
10203
  """
10204
+ A whole graduated schedule, replacing the one the dimension holds: 1 to 10 bands, ascending edges, the last band open, no band dearer than the one below. Band 1's price becomes priceCents (supply priceCents only if it is the same). Accepted for SHARED aggregate_data_volume only. Like every price, it applies from a dimension's next period where a period has already been charged.
10205
+ """
10206
+ priceBands: [RateCardBandInput!]
10207
+ """
10208
+ true removes the dimension's bands so it is priced flat at priceCents (the former first band's price unless priceCents is also given). Not combinable with priceBands.
10209
+ """
10210
+ clearPriceBands: Boolean
10211
+ """
10150
10212
  Why this price is changing. Required: a rate change with no stated reason is not auditable after the fact. Recorded in the operator log with the before and after values.
10151
10213
  """
10152
10214
  reason: String!
10153
10215
  }
10154
10216
 
10217
+ input RateCardBandInput {
10218
+ """
10219
+ Exclusive upper edge of this band on the period's running total, in raw metric units, as a BigInt decimal string. Every band but the last needs one, strictly above the band before; the last band must leave it null.
10220
+ """
10221
+ upToUnits: BigInt
10222
+ """
10223
+ Cents per the row's unitQuantity raw units inside this band: >= 0, at most six decimals, and never more than the band below it.
10224
+ """
10225
+ priceCents: Float!
10226
+ }
10227
+
10155
10228
  """
10156
10229
  Set or change an app's reserved REALTIME (UDP) capacity on the shared environment. Reservations are sold in two independent dimensions and this mutation sets one of them; read both back from App.reservedUdpBytesPerSec and App.reservedGraphqlOpsPerSec.
10157
10230
  """
@@ -11611,6 +11684,38 @@ input ChannelMessageInput {
11611
11684
  sequenceNumber: Int
11612
11685
  }
11613
11686
 
11687
+ """
11688
+ Input for publishing a channel message that only reaches members near an origin chunk. A member receives it when one of its live actors is in the same app within maxDistance chunks of the origin, measured as the straight-line (Euclidean) distance between chunk coordinates, boundary included; a member with no live actor does not receive it. Members receive an ordinary ChannelMessageNotification. The sender must have the channel send_messages permission, exactly as for sendChannelMessage.
11689
+ """
11690
+ input RangedChannelMessageInput {
11691
+ """The channel id (groups.group_id) to publish to."""
11692
+ channelId: BigInt!
11693
+ """
11694
+ The sender's actor UUID (your own actor's UUID). Must be exactly 32 bytes when encoded as UTF-8.
11695
+ """
11696
+ uuid: String!
11697
+ """
11698
+ The message payload, base64-encoded. Opaque to the server; decode per your application protocol. Max 1024 bytes.
11699
+ """
11700
+ payload: String!
11701
+ """
11702
+ The app the origin chunk is in. Must be the app this token is scoped to (the game server answers INVALID_APP_ID otherwise).
11703
+ """
11704
+ appId: BigInt!
11705
+ """
11706
+ The origin chunk distance is measured from, usually the chunk of the sending actor. A chunk is a 16x16x16 voxel cube.
11707
+ """
11708
+ chunk: ChunkCoordinatesInput!
11709
+ """
11710
+ Largest straight-line distance from the origin chunk, in chunks, at which a member still receives the message: 0 (the origin chunk only) to 2147483647. Not capped at 8 and not the Chebyshev ring count spatial sends use.
11711
+ """
11712
+ maxDistance: Int!
11713
+ """
11714
+ Client-assigned correlation id for this datagram: a uint8 (0-255) that wraps at gameClientBootstrap.sequenceNumberModulo (256); defaults to 0 if omitted. For CORRELATION ONLY — it is NOT an idempotency key and the server does not dedupe replays. Echoed on any GenericErrorResponse for this send, delivered on the udpNotifications subscription.
11715
+ """
11716
+ sequenceNumber: Int
11717
+ }
11718
+
11614
11719
  type Subscription {
11615
11720
  """
11616
11721
  Realtime downlink from the game server: spatial notifications and responses, GenericErrorResponse (errors from your sends, correlated by sequenceNumber), and RealtimeConnectionEvent (lifecycle/setup failures). Requires a bearer game token AND an appId-scoped connection — the appId is read from the graphql-transport-ws connection (game tokens are app-agnostic and one UDP socket is shared across apps, so an app-agnostic subscription is rejected with a RealtimeConnectionEvent code APP_ID_REQUIRED, and a missing/invalid token with AUTH_REQUIRED). On subscribe, opens a UDP proxy session if none exists (binds to the least-loaded game server); open/transport failures are delivered as RealtimeConnectionEvent (code UDP_PROXY_CONNECTION_FAILED) and then the stream ends. Only this app’s spatial fan-out is delivered; appId-less control frames always pass. Subscribe before/while sending so async results are not missed. Unsubscribing stops delivery only — it does NOT close the UDP session; call disconnectUdpProxy (or rely on the server inactivity timeout) to release it.
@@ -95,6 +95,7 @@ _LAZY: dict[str, str] = {
95
95
  "PortalConsentRequiredError": "crowdypy.domains.portal",
96
96
  "default_hosted_sign_in_url": "crowdypy.domains.portal",
97
97
  "is_hosted_sign_in_required_error": "crowdypy.domains.portal",
98
+ "is_legal_acceptance_required_error": "crowdypy.domains.portal",
98
99
  "AuthResponse": "crowdypy.domains.auth",
99
100
  "is_already_registered_error": "crowdypy.domains.auth",
100
101
  "is_invalid_current_password_error": "crowdypy.domains.auth",
@@ -330,6 +331,9 @@ if TYPE_CHECKING:
330
331
  from crowdypy.domains.portal import (
331
332
  is_hosted_sign_in_required_error as is_hosted_sign_in_required_error,
332
333
  )
334
+ from crowdypy.domains.portal import (
335
+ is_legal_acceptance_required_error as is_legal_acceptance_required_error,
336
+ )
333
337
  from crowdypy.domains.quotas import (
334
338
  QuotasAPI as QuotasAPI,
335
339
  )
@@ -1,6 +1,6 @@
1
1
  """GENERATED by scripts/codegen.py from schema.gql. Do not edit.
2
2
 
3
- schema.gql sha256: f00952f685420f6c0f4bf58d56debda29aea8cce9b877754393611393ff63db1
3
+ schema.gql sha256: 29d59267d8bf5a0497b272ac22b5edfb702c4872087b0cffaa1542a81c917834
4
4
  """
5
5
 
6
6
  from enum import StrEnum