crowdypy 0.30.0.dev1__tar.gz → 0.31.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 (632) hide show
  1. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/MIGRATION.md +18 -0
  2. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/PKG-INFO +3 -1
  3. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/README.md +2 -0
  4. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/docs/compatibility.md +1 -1
  5. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/docs/e2e-coverage.md +1 -0
  6. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/docs/parity-matrix.md +1 -1
  7. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/native/replication.hpp +3 -0
  8. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/native/replication_binding.cpp +4 -2
  9. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/pyproject.toml +5 -5
  10. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_version.py +1 -1
  11. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/tests/unit/test_replication.py +46 -0
  12. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/uv.lock +1 -1
  13. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/CMakeLists.txt +1 -1
  14. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/PROVENANCE.md +1 -1
  15. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/domains/world_data.hpp +34 -0
  16. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/generated/enums.hpp +1 -1
  17. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/generated/operations.hpp +99 -1
  18. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/graphql/json.hpp +14 -4
  19. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/replication/connection.hpp +26 -8
  20. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/replication/types.hpp +8 -0
  21. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/package.json +1 -1
  22. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/src/graphql/json.cpp +33 -5
  23. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/src/replication/connection.cpp +32 -12
  24. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/src/session/chunk_store.cpp +1 -0
  25. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/.gitattributes +0 -0
  26. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/.gitignore +0 -0
  27. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/.gitleaks.toml +0 -0
  28. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/AGENTS.md +0 -0
  29. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/CMakeLists.txt +0 -0
  30. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/LICENSE +0 -0
  31. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/SECURITY.md +0 -0
  32. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/benchmarks/README.md +0 -0
  33. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/benchmarks/bench_replication.py +0 -0
  34. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/licenses/OpenSSL-LICENSE.txt +0 -0
  35. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/native/common.hpp +0 -0
  36. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/native/module.cpp +0 -0
  37. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/native/session_binding.cpp +0 -0
  38. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/native/voice_binding.cpp +0 -0
  39. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/native/wire_binding.cpp +0 -0
  40. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/actors/Actor.graphql +0 -0
  41. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/actors/Actors.graphql +0 -0
  42. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/actors/BatchLookupActors.graphql +0 -0
  43. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/actors/CreateActor.graphql +0 -0
  44. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/actors/DeleteActor.graphql +0 -0
  45. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/actors/UpdateActor.graphql +0 -0
  46. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/actors/UpdateActorState.graphql +0 -0
  47. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/appAccess/AppAccessTiers.graphql +0 -0
  48. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/appAccess/AppFeatures.graphql +0 -0
  49. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/appAccess/AppGrantMemberCandidates.graphql +0 -0
  50. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/appAccess/AppUserAccessByApp.graphql +0 -0
  51. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/appAccess/ArchiveAccessTier.graphql +0 -0
  52. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/appAccess/ClaimFreeAppAccess.graphql +0 -0
  53. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/appAccess/CreateAccessTier.graphql +0 -0
  54. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/appAccess/DefineAppFeature.graphql +0 -0
  55. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/appAccess/GrantAppAccess.graphql +0 -0
  56. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/appAccess/GrantMyAppAccess.graphql +0 -0
  57. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/appAccess/GrantTierFeature.graphql +0 -0
  58. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/appAccess/MyAppAccess.graphql +0 -0
  59. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/appAccess/RevokeAppAccess.graphql +0 -0
  60. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/appAccess/RevokeTierFeature.graphql +0 -0
  61. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/appAccess/RuntimePermissions.graphql +0 -0
  62. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/appAccess/SuspendAppAccess.graphql +0 -0
  63. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/appAccess/TierFeatures.graphql +0 -0
  64. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/appAccess/UpdateAccessTier.graphql +0 -0
  65. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/apps/App.graphql +0 -0
  66. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/apps/AppBySlug.graphql +0 -0
  67. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/apps/AppDiscovery.graphql +0 -0
  68. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/apps/AppRecording.graphql +0 -0
  69. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/apps/AppsForOrg.graphql +0 -0
  70. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/apps/ArchiveApp.graphql +0 -0
  71. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/apps/CodeAdmissions.graphql +0 -0
  72. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/apps/CreateApp.graphql +0 -0
  73. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/apps/MarketplaceApps.graphql +0 -0
  74. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/apps/MyApps.graphql +0 -0
  75. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/apps/PlaceableDatacenters.graphql +0 -0
  76. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/apps/SetAppRequiredDocuments.graphql +0 -0
  77. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/apps/UpdateApp.graphql +0 -0
  78. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/auth/Logout.graphql +0 -0
  79. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/auth/LogoutAllDevices.graphql +0 -0
  80. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/avatars/Avatars.graphql +0 -0
  81. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/billing/AppBudget.graphql +0 -0
  82. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/billing/AppBudgets.graphql +0 -0
  83. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/billing/SetAppBudget.graphql +0 -0
  84. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/billing/WalletBalance.graphql +0 -0
  85. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/billing/WalletTransactions.graphql +0 -0
  86. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/channels/AddChannelMember.graphql +0 -0
  87. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/channels/BanChannelMember.graphql +0 -0
  88. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/channels/Channel.graphql +0 -0
  89. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/channels/ChannelMembers.graphql +0 -0
  90. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/channels/ChannelPolicy.graphql +0 -0
  91. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/channels/ChannelRoles.graphql +0 -0
  92. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/channels/Channels.graphql +0 -0
  93. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/channels/CreateChannel.graphql +0 -0
  94. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/channels/CreateChannelRole.graphql +0 -0
  95. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/channels/DeleteChannel.graphql +0 -0
  96. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/channels/DeleteChannelRole.graphql +0 -0
  97. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/channels/JoinChannel.graphql +0 -0
  98. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/channels/LeaveChannel.graphql +0 -0
  99. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/channels/MyChannels.graphql +0 -0
  100. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/channels/RemoveChannelMember.graphql +0 -0
  101. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/channels/RequestToJoinChannel.graphql +0 -0
  102. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/channels/SetChannelMemberRoles.graphql +0 -0
  103. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/channels/SetChannelPolicy.graphql +0 -0
  104. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/channels/UnbanChannelMember.graphql +0 -0
  105. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/channels/UpdateChannel.graphql +0 -0
  106. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/channels/UpdateChannelRole.graphql +0 -0
  107. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/chunks/GetChunk.graphql +0 -0
  108. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/chunks/GetChunkLods.graphql +0 -0
  109. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/chunks/GetChunksByDistance.graphql +0 -0
  110. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/chunks/GetVoxelList.graphql +0 -0
  111. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/chunks/UpdateChunk.graphql +0 -0
  112. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/chunks/UpdateChunkLods.graphql +0 -0
  113. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/chunks/UpdateChunkState.graphql +0 -0
  114. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/crowdyStudio/CrowdyStudio.graphql +0 -0
  115. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/exec/Exec.graphql +0 -0
  116. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/gameApps/GameApps.graphql +0 -0
  117. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/grids/CreateGridChannel.graphql +0 -0
  118. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/grids/GridChannels.graphql +0 -0
  119. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/grids/MintGridToken.graphql +0 -0
  120. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/host/Host.graphql +0 -0
  121. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/inputLog/InputLogMessages.graphql +0 -0
  122. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/inputLog/InputLogSessions.graphql +0 -0
  123. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/managedPlayers/AppManagedPlayerMods.graphql +0 -0
  124. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/managedPlayers/DeleteManagedPlayer.graphql +0 -0
  125. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/managedPlayers/EndManagedPlayerSessions.graphql +0 -0
  126. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/managedPlayers/ManagedPlayer.graphql +0 -0
  127. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/managedPlayers/ManagedPlayerFields.graphql +0 -0
  128. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/managedPlayers/ManagedPlayers.graphql +0 -0
  129. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/managedPlayers/OrgManagedPlayerSettings.graphql +0 -0
  130. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/managedPlayers/OrgSigningKeyFields.graphql +0 -0
  131. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/managedPlayers/OrgSigningKeys.graphql +0 -0
  132. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/managedPlayers/ProvisionManagedPlayers.graphql +0 -0
  133. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/managedPlayers/RegisterOrgSigningKey.graphql +0 -0
  134. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/managedPlayers/RevokeOrgSigningKey.graphql +0 -0
  135. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/managedPlayers/SetAppManagedPlayerMods.graphql +0 -0
  136. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/managedPlayers/UpdateManagedPlayer.graphql +0 -0
  137. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/marketplace/Marketplace.graphql +0 -0
  138. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/moderation/EscalateSafetyReport.graphql +0 -0
  139. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/moderation/ResolveSafetyReport.graphql +0 -0
  140. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/moderation/SafetyReportFields.graphql +0 -0
  141. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/moderation/SafetyReports.graphql +0 -0
  142. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/organizations/CreateOrgRole.graphql +0 -0
  143. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/organizations/CreateOrgToken.graphql +0 -0
  144. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/organizations/CreateOrganization.graphql +0 -0
  145. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/organizations/DeleteOrgRole.graphql +0 -0
  146. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/organizations/InviteOrgMember.graphql +0 -0
  147. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/organizations/MemberRoles.graphql +0 -0
  148. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/organizations/MyOrganizations.graphql +0 -0
  149. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/organizations/OrgMembers.graphql +0 -0
  150. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/organizations/OrgPermissions.graphql +0 -0
  151. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/organizations/OrgRoles.graphql +0 -0
  152. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/organizations/OrgTokens.graphql +0 -0
  153. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/organizations/Organization.graphql +0 -0
  154. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/organizations/OrganizationBySlug.graphql +0 -0
  155. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/organizations/RemoveOrgMember.graphql +0 -0
  156. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/organizations/RevokeOrgToken.graphql +0 -0
  157. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/organizations/UpdateOrgMemberRoles.graphql +0 -0
  158. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/organizations/UpdateOrgRole.graphql +0 -0
  159. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/organizations/UpdateOrgToken.graphql +0 -0
  160. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/payments/CapturePaypalCheckout.graphql +0 -0
  161. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/payments/CreateCheckout.graphql +0 -0
  162. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/payments/MyCheckouts.graphql +0 -0
  163. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/platform/PlatformConfig.graphql +0 -0
  164. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/platform/TerritoryPolicies.graphql +0 -0
  165. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/playerWallet/PlayerWallet.graphql +0 -0
  166. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/quotas/DeleteQuota.graphql +0 -0
  167. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/quotas/EffectiveQuota.graphql +0 -0
  168. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/quotas/QuotasForApp.graphql +0 -0
  169. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/quotas/QuotasForOrg.graphql +0 -0
  170. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/quotas/SetQuota.graphql +0 -0
  171. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/safety/AcceptContact.graphql +0 -0
  172. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/safety/BlockPlayer.graphql +0 -0
  173. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/safety/CommSettingsFields.graphql +0 -0
  174. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/safety/ContactRequests.graphql +0 -0
  175. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/safety/FileSafetyReport.graphql +0 -0
  176. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/safety/MyBlocks.graphql +0 -0
  177. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/safety/MyCommSettings.graphql +0 -0
  178. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/safety/MyContacts.graphql +0 -0
  179. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/safety/PlayerContactFields.graphql +0 -0
  180. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/safety/RemoveContact.graphql +0 -0
  181. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/safety/RequestContact.graphql +0 -0
  182. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/safety/RequestParentalConsent.graphql +0 -0
  183. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/safety/SetMyCommSettings.graphql +0 -0
  184. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/safety/UnblockPlayer.graphql +0 -0
  185. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/serverStatus/ActiveGraphQLServers.graphql +0 -0
  186. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/serverStatus/GameClientBootstrap.graphql +0 -0
  187. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/serverStatus/GraphqlServers.graphql +0 -0
  188. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/serverStatus/ServerWithLeastClients.graphql +0 -0
  189. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/serverStatus/VersionInfo.graphql +0 -0
  190. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/sharedEnvironment/SharedEnvironment.graphql +0 -0
  191. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/state/DeleteUserAppState.graphql +0 -0
  192. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/state/UpdateUserAppState.graphql +0 -0
  193. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/state/UserAppState.graphql +0 -0
  194. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/state/UserAppStates.graphql +0 -0
  195. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/teams/AddTeamMember.graphql +0 -0
  196. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/teams/BanTeamMember.graphql +0 -0
  197. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/teams/CreateTeam.graphql +0 -0
  198. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/teams/CreateTeamRole.graphql +0 -0
  199. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/teams/DeleteTeam.graphql +0 -0
  200. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/teams/DeleteTeamRole.graphql +0 -0
  201. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/teams/JoinTeam.graphql +0 -0
  202. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/teams/LeaveTeam.graphql +0 -0
  203. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/teams/MyTeams.graphql +0 -0
  204. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/teams/RemoveTeamMember.graphql +0 -0
  205. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/teams/RequestToJoinTeam.graphql +0 -0
  206. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/teams/SetTeamMemberRoles.graphql +0 -0
  207. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/teams/SetTeamPolicy.graphql +0 -0
  208. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/teams/Team.graphql +0 -0
  209. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/teams/TeamMembers.graphql +0 -0
  210. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/teams/TeamPolicy.graphql +0 -0
  211. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/teams/TeamRoles.graphql +0 -0
  212. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/teams/Teams.graphql +0 -0
  213. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/teams/UnbanTeamMember.graphql +0 -0
  214. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/teams/UpdateTeam.graphql +0 -0
  215. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/teams/UpdateTeamRole.graphql +0 -0
  216. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/teleport/TeleportRequest.graphql +0 -0
  217. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/usage/AppGraphqlOperations.graphql +0 -0
  218. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/usage/AppUsageSummary.graphql +0 -0
  219. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/usage/PlayerPulse.graphql +0 -0
  220. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/users/DeleteMyAccount.graphql +0 -0
  221. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/users/FreePlayWindow.graphql +0 -0
  222. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/users/Me.graphql +0 -0
  223. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/users/PlayerProfile.graphql +0 -0
  224. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/users/UpdateGamertag.graphql +0 -0
  225. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/users/UpdateUserState.graphql +0 -0
  226. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/users/User.graphql +0 -0
  227. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/voxels/ListVoxelUpdatesByDistance.graphql +0 -0
  228. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/voxels/ListVoxels.graphql +0 -0
  229. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/voxels/RollbackVoxelUpdates.graphql +0 -0
  230. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/voxels/UpdateVoxel.graphql +0 -0
  231. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/operations/voxels/VoxelUpdateHistory.graphql +0 -0
  232. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/schema.gql +0 -0
  233. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/scripts/_pins.py +0 -0
  234. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/scripts/ci/assert_default_origin.py +0 -0
  235. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/scripts/ci/build_openssl.sh +0 -0
  236. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/scripts/ci/check_content_policy.py +0 -0
  237. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/scripts/ci/check_pin_tiers.py +0 -0
  238. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/scripts/ci/cibw_before_all_linux.sh +0 -0
  239. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/scripts/ci/resolve-release-tier.sh +0 -0
  240. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/scripts/ci/resolve-release-tier.test.sh +0 -0
  241. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/scripts/ci/resolve_pypi_version.py +0 -0
  242. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/scripts/ci/stamp_version.py +0 -0
  243. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/scripts/ci/verify_artifacts.py +0 -0
  244. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/scripts/codegen.py +0 -0
  245. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/scripts/schema_drift.py +0 -0
  246. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/scripts/schema_sync.py +0 -0
  247. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/scripts/unasync.py +0 -0
  248. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/scripts/vendor_crowdycpp.py +0 -0
  249. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/__init__.py +0 -0
  250. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_concurrency.py +0 -0
  251. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_default_origin.py +0 -0
  252. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_generated/__init__.py +0 -0
  253. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_generated/enums.py +0 -0
  254. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_generated/inputs.py +0 -0
  255. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_generated/operations.py +0 -0
  256. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_grid.py +0 -0
  257. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_native.pyi +0 -0
  258. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_operation.py +0 -0
  259. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_sync/__init__.py +0 -0
  260. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_sync/client.py +0 -0
  261. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_sync/domains/__init__.py +0 -0
  262. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_sync/domains/_base.py +0 -0
  263. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_sync/domains/actors.py +0 -0
  264. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_sync/domains/admin.py +0 -0
  265. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_sync/domains/app_access.py +0 -0
  266. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_sync/domains/apps.py +0 -0
  267. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_sync/domains/auth.py +0 -0
  268. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_sync/domains/avatars.py +0 -0
  269. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_sync/domains/billing.py +0 -0
  270. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_sync/domains/channels.py +0 -0
  271. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_sync/domains/chunks.py +0 -0
  272. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_sync/domains/crowdy_studio.py +0 -0
  273. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_sync/domains/crowdy_studio_agent.py +0 -0
  274. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_sync/domains/crowdy_studio_github.py +0 -0
  275. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_sync/domains/discovery.py +0 -0
  276. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_sync/domains/exec.py +0 -0
  277. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_sync/domains/game_apps.py +0 -0
  278. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_sync/domains/grids.py +0 -0
  279. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_sync/domains/host.py +0 -0
  280. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_sync/domains/input_log.py +0 -0
  281. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_sync/domains/managed_players.py +0 -0
  282. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_sync/domains/marketplace.py +0 -0
  283. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_sync/domains/moderation.py +0 -0
  284. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_sync/domains/organizations.py +0 -0
  285. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_sync/domains/payments.py +0 -0
  286. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_sync/domains/platform.py +0 -0
  287. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_sync/domains/player_wallet.py +0 -0
  288. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_sync/domains/portal.py +0 -0
  289. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_sync/domains/quotas.py +0 -0
  290. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_sync/domains/safety.py +0 -0
  291. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_sync/domains/server_status.py +0 -0
  292. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_sync/domains/shared_environment.py +0 -0
  293. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_sync/domains/state.py +0 -0
  294. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_sync/domains/teams.py +0 -0
  295. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_sync/domains/teleport.py +0 -0
  296. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_sync/domains/udp.py +0 -0
  297. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_sync/domains/usage.py +0 -0
  298. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_sync/domains/users.py +0 -0
  299. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_sync/domains/voxels.py +0 -0
  300. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_sync/graphql.py +0 -0
  301. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_sync/grid_scope.py +0 -0
  302. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_sync/kit/__init__.py +0 -0
  303. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_sync/kit/actions.py +0 -0
  304. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_sync/kit/kit.py +0 -0
  305. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_sync/kit/mirror.py +0 -0
  306. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_sync/kit/modules/__init__.py +0 -0
  307. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_sync/kit/modules/arenas.py +0 -0
  308. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_sync/kit/modules/encounters.py +0 -0
  309. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_sync/kit/modules/instances.py +0 -0
  310. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_sync/kit/modules/leaderboards.py +0 -0
  311. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_sync/kit/modules/market.py +0 -0
  312. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_sync/kit/modules/matchmaking.py +0 -0
  313. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_sync/kit/modules/minigames.py +0 -0
  314. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_sync/kit/modules/npcs.py +0 -0
  315. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_sync/kit/modules/player.py +0 -0
  316. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_sync/kit/modules/presence.py +0 -0
  317. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_sync/kit/modules/racing.py +0 -0
  318. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_sync/kit/modules/sessions.py +0 -0
  319. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_sync/kit/modules/tables.py +0 -0
  320. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_sync/kit/modules/tactics.py +0 -0
  321. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_sync/kit/modules/territory.py +0 -0
  322. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_sync/kit/modules/world.py +0 -0
  323. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_sync/kit/protocol.py +0 -0
  324. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_sync/kit/realtime.py +0 -0
  325. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_sync/kit/runtime.py +0 -0
  326. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_sync/kit/social.py +0 -0
  327. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_sync/kit/store.py +0 -0
  328. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_sync/kit/topology.py +0 -0
  329. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_sync/kit/wire.py +0 -0
  330. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_sync/rediscover.py +0 -0
  331. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_sync/stores.py +0 -0
  332. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/_sync/world.py +0 -0
  333. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/auth_state.py +0 -0
  334. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/client.py +0 -0
  335. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/codecs.py +0 -0
  336. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/datacenter_redirect.py +0 -0
  337. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/domains/__init__.py +0 -0
  338. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/domains/_base.py +0 -0
  339. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/domains/actors.py +0 -0
  340. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/domains/admin.py +0 -0
  341. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/domains/app_access.py +0 -0
  342. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/domains/apps.py +0 -0
  343. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/domains/auth.py +0 -0
  344. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/domains/avatars.py +0 -0
  345. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/domains/billing.py +0 -0
  346. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/domains/channels.py +0 -0
  347. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/domains/chunks.py +0 -0
  348. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/domains/crowdy_studio.py +0 -0
  349. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/domains/crowdy_studio_agent.py +0 -0
  350. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/domains/crowdy_studio_github.py +0 -0
  351. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/domains/discovery.py +0 -0
  352. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/domains/exec.py +0 -0
  353. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/domains/game_apps.py +0 -0
  354. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/domains/grids.py +0 -0
  355. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/domains/host.py +0 -0
  356. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/domains/input_log.py +0 -0
  357. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/domains/managed_players.py +0 -0
  358. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/domains/marketplace.py +0 -0
  359. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/domains/moderation.py +0 -0
  360. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/domains/organizations.py +0 -0
  361. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/domains/payments.py +0 -0
  362. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/domains/platform.py +0 -0
  363. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/domains/player_wallet.py +0 -0
  364. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/domains/portal.py +0 -0
  365. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/domains/quotas.py +0 -0
  366. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/domains/safety.py +0 -0
  367. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/domains/server_status.py +0 -0
  368. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/domains/shared_environment.py +0 -0
  369. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/domains/state.py +0 -0
  370. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/domains/teams.py +0 -0
  371. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/domains/teleport.py +0 -0
  372. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/domains/udp.py +0 -0
  373. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/domains/usage.py +0 -0
  374. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/domains/users.py +0 -0
  375. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/domains/voxels.py +0 -0
  376. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/enums.py +0 -0
  377. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/errors.py +0 -0
  378. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/estate.py +0 -0
  379. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/exec_gateway.py +0 -0
  380. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/graphql.py +0 -0
  381. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/grid_scope.py +0 -0
  382. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/inputs.py +0 -0
  383. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/kit/__init__.py +0 -0
  384. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/kit/actions.py +0 -0
  385. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/kit/kit.py +0 -0
  386. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/kit/mirror.py +0 -0
  387. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/kit/modules/__init__.py +0 -0
  388. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/kit/modules/arenas.py +0 -0
  389. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/kit/modules/encounters.py +0 -0
  390. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/kit/modules/instances.py +0 -0
  391. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/kit/modules/leaderboards.py +0 -0
  392. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/kit/modules/market.py +0 -0
  393. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/kit/modules/matchmaking.py +0 -0
  394. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/kit/modules/minigames.py +0 -0
  395. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/kit/modules/npcs.py +0 -0
  396. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/kit/modules/player.py +0 -0
  397. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/kit/modules/presence.py +0 -0
  398. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/kit/modules/racing.py +0 -0
  399. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/kit/modules/sessions.py +0 -0
  400. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/kit/modules/tables.py +0 -0
  401. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/kit/modules/tactics.py +0 -0
  402. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/kit/modules/territory.py +0 -0
  403. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/kit/modules/world.py +0 -0
  404. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/kit/protocol.py +0 -0
  405. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/kit/realtime.py +0 -0
  406. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/kit/runtime.py +0 -0
  407. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/kit/social.py +0 -0
  408. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/kit/store.py +0 -0
  409. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/kit/topology.py +0 -0
  410. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/kit/wire.py +0 -0
  411. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/lb_cookie.py +0 -0
  412. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/media.py +0 -0
  413. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/pkce.py +0 -0
  414. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/player_host/__init__.py +0 -0
  415. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/player_host/agent_errors.py +0 -0
  416. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/player_host/agent_types.py +0 -0
  417. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/player_host/json_schema.py +0 -0
  418. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/player_host/schemas.py +0 -0
  419. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/player_host/schemas.v1.json +0 -0
  420. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/player_host/types.py +0 -0
  421. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/py.typed +0 -0
  422. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/rediscover.py +0 -0
  423. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/replication.py +0 -0
  424. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/session.py +0 -0
  425. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/stores.py +0 -0
  426. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/studio/__init__.py +0 -0
  427. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/studio/client_tick_interval.py +0 -0
  428. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/studio/controller.py +0 -0
  429. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/studio/diagnostics.py +0 -0
  430. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/studio/draft.py +0 -0
  431. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/studio/github_draft_store.py +0 -0
  432. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/studio/github_new_repo.py +0 -0
  433. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/studio/layout.py +0 -0
  434. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/studio/models.py +0 -0
  435. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/studio/starter_projects.py +0 -0
  436. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/subscriptions.py +0 -0
  437. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/sync.py +0 -0
  438. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/utils.py +0 -0
  439. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/wire.py +0 -0
  440. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/src/crowdypy/world.py +0 -0
  441. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/tests/conftest.py +0 -0
  442. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/tests/e2e/__init__.py +0 -0
  443. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/tests/e2e/conftest.py +0 -0
  444. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/tests/e2e/test_e2e_identity.py +0 -0
  445. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/tests/e2e/test_e2e_idle_release.py +0 -0
  446. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/tests/e2e/test_e2e_input_log.py +0 -0
  447. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/tests/e2e/test_e2e_open_grid_exec_gateway.py +0 -0
  448. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/tests/e2e/test_e2e_ranged_channel.py +0 -0
  449. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/tests/e2e/test_e2e_replication.py +0 -0
  450. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/tests/e2e/test_e2e_studio.py +0 -0
  451. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/tests/e2e/test_e2e_teen_safety.py +0 -0
  452. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/tests/e2e/test_e2e_world.py +0 -0
  453. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/tests/e2e/test_e2e_world_data.py +0 -0
  454. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/tests/fixtures/README.md +0 -0
  455. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/tests/fixtures/binary-wire-fixtures.json +0 -0
  456. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/tests/fixtures/exec-client-frames.json +0 -0
  457. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/tests/fixtures/kit-protocol.json +0 -0
  458. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/tests/fixtures/player-host.v1.json +0 -0
  459. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/tests/fixtures/voice-frames.json +0 -0
  460. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/tests/unit/__init__.py +0 -0
  461. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/tests/unit/domains/__init__.py +0 -0
  462. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/tests/unit/domains/test_crowdycpp_roots.py +0 -0
  463. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/tests/unit/domains/test_input_log_reads.py +0 -0
  464. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/tests/unit/domains/test_managed_players.py +0 -0
  465. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/tests/unit/domains/test_org_domains.py +0 -0
  466. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/tests/unit/domains/test_safety_domains.py +0 -0
  467. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/tests/unit/domains/test_social_domains.py +0 -0
  468. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/tests/unit/domains/test_studio_exec_domains.py +0 -0
  469. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/tests/unit/domains/test_world_domains.py +0 -0
  470. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/tests/unit/test_check_pin_tiers.py +0 -0
  471. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/tests/unit/test_core.py +0 -0
  472. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/tests/unit/test_durable_stores.py +0 -0
  473. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/tests/unit/test_estate_moves.py +0 -0
  474. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/tests/unit/test_exec_gateway.py +0 -0
  475. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/tests/unit/test_fixture_provenance.py +0 -0
  476. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/tests/unit/test_github_draft_store.py +0 -0
  477. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/tests/unit/test_grid_scope.py +0 -0
  478. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/tests/unit/test_kit.py +0 -0
  479. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/tests/unit/test_kit_protocol.py +0 -0
  480. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/tests/unit/test_lazy_exports.py +0 -0
  481. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/tests/unit/test_lb_cookie.py +0 -0
  482. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/tests/unit/test_player_host.py +0 -0
  483. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/tests/unit/test_refusals.py +0 -0
  484. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/tests/unit/test_release_versions.py +0 -0
  485. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/tests/unit/test_sdk_audience.py +0 -0
  486. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/tests/unit/test_studio_controller.py +0 -0
  487. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/tests/unit/test_studio_diagnostics.py +0 -0
  488. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/tests/unit/test_studio_game_editor.py +0 -0
  489. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/tests/unit/test_studio_layout.py +0 -0
  490. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/tests/unit/test_subscriptions.py +0 -0
  491. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/tests/unit/test_transport.py +0 -0
  492. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/tests/unit/test_udp_api.py +0 -0
  493. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/tests/unit/test_udp_first_send_retry.py +0 -0
  494. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/tests/unit/test_voice_frames.py +0 -0
  495. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/tests/unit/test_wire.py +0 -0
  496. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/tests/unit/test_world_session.py +0 -0
  497. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/tools/e2e/provision.py +0 -0
  498. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/tools/fixtures/player_host.mjs +0 -0
  499. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/tools/parity/classifications.toml +0 -0
  500. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/tools/parity/parity.py +0 -0
  501. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/LICENSE +0 -0
  502. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/cmake/CheckPublicHeaders.cmake +0 -0
  503. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/cmake/CrowdyCPPConfig.cmake.in +0 -0
  504. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/cmake/CrowdyFindOpus.cmake +0 -0
  505. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/cmake/studio_layout_fixture.hpp.in +0 -0
  506. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/client.hpp +0 -0
  507. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/core/base64.hpp +0 -0
  508. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/core/bytes.hpp +0 -0
  509. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/core/clock.hpp +0 -0
  510. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/core/crypto.hpp +0 -0
  511. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/core/logger.hpp +0 -0
  512. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/core/result.hpp +0 -0
  513. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/core/spsc.hpp +0 -0
  514. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/core/uuid.hpp +0 -0
  515. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/crowdy.hpp +0 -0
  516. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/default_origin.hpp +0 -0
  517. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/domains/admin.hpp +0 -0
  518. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/domains/auth.hpp +0 -0
  519. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/domains/crowdy_studio.hpp +0 -0
  520. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/domains/crowdy_studio_agent.hpp +0 -0
  521. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/domains/crowdy_studio_github.hpp +0 -0
  522. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/domains/discovery.hpp +0 -0
  523. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/domains/domain_base.hpp +0 -0
  524. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/domains/exec.hpp +0 -0
  525. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/domains/game_apps.hpp +0 -0
  526. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/domains/grids.hpp +0 -0
  527. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/domains/groups.hpp +0 -0
  528. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/domains/marketplace.hpp +0 -0
  529. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/domains/player_wallet.hpp +0 -0
  530. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/domains/portal.hpp +0 -0
  531. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/domains/realtime_control.hpp +0 -0
  532. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/domains/safety.hpp +0 -0
  533. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/domains/server_status.hpp +0 -0
  534. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/domains/types.hpp +0 -0
  535. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/domains/users.hpp +0 -0
  536. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/game_session.hpp +0 -0
  537. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/graphql/async_scope.hpp +0 -0
  538. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/graphql/auth_state.hpp +0 -0
  539. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/graphql/cancel.hpp +0 -0
  540. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/graphql/datacenter_redirect.hpp +0 -0
  541. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/graphql/dispatcher.hpp +0 -0
  542. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/graphql/errors.hpp +0 -0
  543. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/graphql/estate.hpp +0 -0
  544. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/graphql/graphql_client.hpp +0 -0
  545. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/graphql/http.hpp +0 -0
  546. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/graphql/rediscover.hpp +0 -0
  547. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/graphql/subscription_client.hpp +0 -0
  548. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/graphql/websocket.hpp +0 -0
  549. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/kit/actions.hpp +0 -0
  550. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/kit/economy.hpp +0 -0
  551. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/kit/genres.hpp +0 -0
  552. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/kit/kit.hpp +0 -0
  553. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/kit/mirror.hpp +0 -0
  554. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/kit/modules.hpp +0 -0
  555. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/kit/protocol.hpp +0 -0
  556. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/kit/realtime.hpp +0 -0
  557. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/kit/runtime.hpp +0 -0
  558. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/kit/social.hpp +0 -0
  559. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/kit/topology.hpp +0 -0
  560. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/kit/wire.hpp +0 -0
  561. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/media/opus.hpp +0 -0
  562. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/media/video_frames.hpp +0 -0
  563. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/media/voice_frames.hpp +0 -0
  564. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/player_host/adapter.hpp +0 -0
  565. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/player_host/player_host.hpp +0 -0
  566. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/player_host/schemas.hpp +0 -0
  567. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/player_host/types.hpp +0 -0
  568. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/replication/session_provider.hpp +0 -0
  569. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/replication/udp_socket.hpp +0 -0
  570. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/session/chunk_store.hpp +0 -0
  571. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/session/codec.hpp +0 -0
  572. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/session/durable.hpp +0 -0
  573. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/session/keys.hpp +0 -0
  574. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/session/stores.hpp +0 -0
  575. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/session/world_session.hpp +0 -0
  576. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/studio/controller.hpp +0 -0
  577. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/studio/diagnostics.hpp +0 -0
  578. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/studio/editor.hpp +0 -0
  579. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/studio/github.hpp +0 -0
  580. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/studio/github_layout.hpp +0 -0
  581. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/studio/integration.hpp +0 -0
  582. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/studio/layout.hpp +0 -0
  583. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/studio/models.hpp +0 -0
  584. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/studio/runtime.hpp +0 -0
  585. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/wire/codec.hpp +0 -0
  586. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/wire/protocol.hpp +0 -0
  587. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/include/crowdy/world.hpp +0 -0
  588. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/src/client.cpp +0 -0
  589. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/src/core/base64.cpp +0 -0
  590. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/src/core/clock.cpp +0 -0
  591. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/src/core/crypto_default_unavailable.cpp +0 -0
  592. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/src/core/crypto_openssl.cpp +0 -0
  593. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/src/core/crypto_unavailable.cpp +0 -0
  594. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/src/core/logger.cpp +0 -0
  595. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/src/core/uuid.cpp +0 -0
  596. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/src/domains/exec.cpp +0 -0
  597. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/src/game_session.cpp +0 -0
  598. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/src/graphql/async_transport.cpp +0 -0
  599. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/src/graphql/auth_state.cpp +0 -0
  600. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/src/graphql/error_extensions.hpp +0 -0
  601. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/src/graphql/errors.cpp +0 -0
  602. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/src/graphql/graphql_client.cpp +0 -0
  603. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/src/graphql/http_curl.cpp +0 -0
  604. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/src/graphql/http_none.cpp +0 -0
  605. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/src/graphql/subscription_client.cpp +0 -0
  606. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/src/graphql/websocket_curl.cpp +0 -0
  607. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/src/graphql/websocket_none.cpp +0 -0
  608. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/src/kit/economy.cpp +0 -0
  609. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/src/kit/genres.cpp +0 -0
  610. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/src/kit/mirror.cpp +0 -0
  611. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/src/kit/modules.cpp +0 -0
  612. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/src/kit/protocol.cpp +0 -0
  613. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/src/kit/runtime.cpp +0 -0
  614. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/src/kit/topology.cpp +0 -0
  615. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/src/media/opus.cpp +0 -0
  616. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/src/player_host/schemas.cpp +0 -0
  617. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/src/player_host/types.cpp +0 -0
  618. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/src/replication/socket_errors.hpp +0 -0
  619. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/src/replication/udp_socket.cpp +0 -0
  620. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/src/session/world_session.cpp +0 -0
  621. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/src/studio/diagnostics.cpp +0 -0
  622. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/src/studio/editor.cpp +0 -0
  623. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/src/studio/integration.cpp +0 -0
  624. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/third_party/yyjson/LICENSE +0 -0
  625. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/third_party/yyjson/yyjson.c +0 -0
  626. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/third_party/yyjson/yyjson.h +0 -0
  627. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/tools/parity/fixtures/crowdy-studio-diagnostics.v1.json +0 -0
  628. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/tools/parity/fixtures/crowdyjs-studio-layout.v1.json +0 -0
  629. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/tools/parity/fixtures/exec-client-frames.json +0 -0
  630. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/tools/parity/fixtures/exec-gateway-cases.json +0 -0
  631. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/tools/parity/fixtures/kit-protocol.json +0 -0
  632. {crowdypy-0.30.0.dev1 → crowdypy-0.31.0.dev1}/vendor/CrowdyCPP/tools/parity/fixtures/voice-frames.json +0 -0
@@ -3,6 +3,24 @@
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.31.0
7
+
8
+ Vendors CrowdyCPP 0.83.0 (the Unreal team's hardening, A1 to A6). Nothing new is needed on the tier.
9
+
10
+ - **MessagePack maps with an array, map, binary or extension key fail to decode** (a kit actor state
11
+ or a mod's reply): a key nested in keys was escaped again at every level, so about 130 bytes asked
12
+ for gigabytes and froze or crashed the decoding thread. Number, boolean and nil keys still become
13
+ their JSON text.
14
+ - **A NaN or an infinity in a decoded value is written as `null` in place** when the native core
15
+ serialises it, instead of turning the whole value into `null`.
16
+ - **Unchanged keyframes of more than 8 actors no longer count as gameplay input** for
17
+ `idle_release_guard_ms`, so a genuine idle release ends a session whose host keeps many actors'
18
+ keyframes going.
19
+ - **A legacy `COMMAND_RECONNECT` (22) is paced** (`client.udp.connect(legacy_reconnect_window_ms=...)`,
20
+ 30 s): one per assignment, each at least a window after the last honoured one, the window
21
+ doubling to 10 minutes; the rest are dropped and counted in
22
+ `stats()["legacy_reconnects_suppressed"]`. `0` honours every verified one, as before.
23
+
6
24
  ## 0.30.0
7
25
 
8
26
  CrowdyJS 18.30.0 and CrowdyCPP 0.82.0 (the ChunkStore rework). Box reads and `since` need ck-api
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: crowdypy
3
- Version: 0.30.0.dev1
3
+ Version: 0.31.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,6 +51,8 @@ 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.31.0: hardening from CrowdyCPP 0.83.0.** MessagePack keys that are containers are refused (a nested key blew up memory), a NaN serialises as `null` in place, unchanged keyframes of many actors are not gameplay input, and a legacy reconnect command is paced (`legacy_reconnect_window_ms`). See [MIGRATION.md](MIGRATION.md).
55
+
54
56
  **v0.30.0: the ChunkStore rework.** `ensure_around` reads only what is missing, as boxes, paged; `set_voxel` is paced and returns an edit id, and an edit the server refuses or never echoes is undone (`on_edit_refused`); a replaced chunk is read again and a reconnect catches up; realtime edits are no longer written back. CrowdyJS 18.30.0 and CrowdyCPP 0.82.0. See [MIGRATION.md](MIGRATION.md).
55
57
 
56
58
  **v0.29.0: reconnect commands verify, bound control frames, and `chunk_changed`.** A server's `COMMAND_RECONNECT` verifies again; against replication servers v0.45.0 the reconnect and release frames carry a per-assignment nonce under their HMAC, so one captured earlier is refused (`stats()["stale_bound_control"]`); `chunk_changed` reports a chunk a hub's or mod's `world.set_chunk` replaced. CrowdyJS 18.29.0 and CrowdyCPP 0.81.0. See [MIGRATION.md](MIGRATION.md).
@@ -11,6 +11,8 @@ 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.31.0: hardening from CrowdyCPP 0.83.0.** MessagePack keys that are containers are refused (a nested key blew up memory), a NaN serialises as `null` in place, unchanged keyframes of many actors are not gameplay input, and a legacy reconnect command is paced (`legacy_reconnect_window_ms`). See [MIGRATION.md](MIGRATION.md).
15
+
14
16
  **v0.30.0: the ChunkStore rework.** `ensure_around` reads only what is missing, as boxes, paged; `set_voxel` is paced and returns an edit id, and an edit the server refuses or never echoes is undone (`on_edit_refused`); a replaced chunk is read again and a reconnect catches up; realtime edits are no longer written back. CrowdyJS 18.30.0 and CrowdyCPP 0.82.0. See [MIGRATION.md](MIGRATION.md).
15
17
 
16
18
  **v0.29.0: reconnect commands verify, bound control frames, and `chunk_changed`.** A server's `COMMAND_RECONNECT` verifies again; against replication servers v0.45.0 the reconnect and release frames carry a per-assignment nonce under their HMAC, so one captured earlier is refused (`stats()["stale_bound_control"]`); `chunk_changed` reports a chunk a hub's or mod's `world.set_chunk` replaced. CrowdyJS 18.29.0 and CrowdyCPP 0.81.0. See [MIGRATION.md](MIGRATION.md).
@@ -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.30.0`
8
+ - CrowdyPy `0.31.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
@@ -73,6 +73,7 @@ suites.
73
73
  | 2026-10-31 | dev tier (ck-api v2.60.0), app `96701660793088`; managed players in app `107209219611648` | `crowdypy 0.23.0.dev1` from PyPI (installed into a clean Python 3.12 with uv) | the teen safety scenarios that register no one (the Minecraft challenge refused; the managed adult; the managed 12-year-old and the blocked country refused): 3 passed |
74
74
  | 2026-11-03 | dev tier (ck-api v2.61.0, players from 13), app `96701660793088`, the `harness` provisioning token with `CROWDY_E2E_EMAIL=crowdy-e2e-py@test.invalid`; the existing player and the managed players of the 13+ test org (app `107209219611648`) | 0.24.0 (branch `feat/13plus-v2.61`: CrowdyJS `dev/v18.25.0`, vendoring CrowdyCPP `dev/v0.76.0`) | the teen safety suite only, two registrations in all and none under 13: the sign-up with an age (its account deleted), the DE sign-up refused, the Minecraft challenge, the existing accounts (`hasSafetyModerator` as the org admin and `None` as the outsider, its own sessions, every row's `regionCode`) and the managed players (UA-09 and UA without a region refused, UA-30 admitted): 5 passed. The two-player scenarios failed at their setup: dev now asks an org admin for the developer documents, and the CK org admin behind `CROWDY_E2E_OWNER_EMAIL` has not accepted them, so its `grant` is refused ("Accept the current developer terms (recordDeveloperConsents) before creating or administering an organization"); they were not rerun with another owner, which would have registered two more players |
75
75
  | 2026-11-11 | dev tier (ck-api v2.65.0, the email gate), app `96701660793088`, the `harness` provisioning token with `CROWDY_E2E_EMAIL=crowdy-e2e-py@test.invalid` | 0.26.0 (branch `feat/email-confirmation-required`: CrowdyJS `dev/v18.27.0`, vendoring CrowdyCPP `dev/v0.78.0`) | identity, replication and teen safety suites: 12 passed, 2 skipped (the teen safety suite's existing player and managed players, not configured). Accounts the provisioning token makes are not asked to confirm their email, so every mint went through |
76
+ | 2026-11-12 | dev tier (ck-api v2.68.1, replication servers v0.45.0), app `96701660793088`, the `harness` provisioning token with `CROWDY_E2E_EMAIL=crowdy-e2e-py@test.invalid` | 0.30.0 (`dev` at `60de17f`, vendoring CrowdyCPP `dev/v0.82.0`: the ChunkStore rework) | world and replication suites: 4 passed |
76
77
 
77
78
  ## Not covered here
78
79
 
@@ -5,7 +5,7 @@ Generated by `tools/parity/parity.py`; do not edit by hand. Classifications live
5
5
  ## Target
6
6
 
7
7
  - CrowdyJS: `18.30.0` at `4840d76029ffb15a6de6232dab9336f2e9ab6514`
8
- - CrowdyCPP (native core): `0.82.0` at `c6875412bcea97120b4540b80d9b34504c29acf9`
8
+ - CrowdyCPP (native core): `0.83.0` at `73eb66cdf1c435bc67e405b9a5bd606740209df2`
9
9
  - schema.gql identical to CrowdyJS's: yes
10
10
  - Gate mode: strict portable parity (every portable gap is release-blocking)
11
11
 
@@ -396,6 +396,7 @@ struct ConnectionOptions {
396
396
  std::int64_t advertiseIntervalMs = 15 * 1000;
397
397
  std::int64_t watchdogSilenceMs = 0;
398
398
  std::int64_t idleReleaseGuardMs = 60 * 1000;
399
+ std::int64_t legacyReconnectWindowMs = 30 * 1000;
399
400
  std::size_t ringCapacity = 4096;
400
401
  int socketRecvBufferBytes = 1 << 20;
401
402
  int socketSendBufferBytes = 1 << 20;
@@ -432,6 +433,7 @@ class PyConnection {
432
433
  config.advertiseIntervalMs = options.advertiseIntervalMs;
433
434
  config.watchdogSilenceMs = options.watchdogSilenceMs;
434
435
  config.idleReleaseGuardMs = options.idleReleaseGuardMs;
436
+ config.legacyReconnectWindowMs = options.legacyReconnectWindowMs;
435
437
  config.ringCapacity = options.ringCapacity;
436
438
  config.socketRecvBufferBytes = options.socketRecvBufferBytes;
437
439
  config.socketSendBufferBytes = options.socketSendBufferBytes;
@@ -739,6 +741,7 @@ class PyConnection {
739
741
  d["reconnects"] = s.reconnects;
740
742
  d["idle_releases_after_input"] = s.idleReleasesAfterInput;
741
743
  d["stale_bound_control"] = s.staleBoundControl;
744
+ d["legacy_reconnects_suppressed"] = s.legacyReconnectsSuppressed;
742
745
  d["last_server_epoch_ms"] = s.lastServerEpochMs;
743
746
  nb::dict sentByType;
744
747
  nb::dict receivedByType;
@@ -232,7 +232,7 @@ void register_replication(nb::module_& m) {
232
232
  bool advertiseCapabilities, std::int64_t advertiseIntervalMs,
233
233
  std::int64_t watchdogSilenceMs, std::size_t ringCapacity, int recvBuffer,
234
234
  int sendBuffer, bool bundleSends, int bundleWindowMs, std::int64_t providerTimeoutMs,
235
- std::int64_t idleReleaseGuardMs) {
235
+ std::int64_t idleReleaseGuardMs, std::int64_t legacyReconnectWindowMs) {
236
236
  ConnectionOptions o;
237
237
  o.appId = appId;
238
238
  o.manualPump = manualPump;
@@ -249,6 +249,7 @@ void register_replication(nb::module_& m) {
249
249
  o.bundleSends = bundleSends;
250
250
  o.bundleWindowMs = bundleWindowMs;
251
251
  o.idleReleaseGuardMs = idleReleaseGuardMs;
252
+ o.legacyReconnectWindowMs = legacyReconnectWindowMs;
252
253
  new (self) PyConnection(o, token, gameTokenId, expiresAtMs, providerTimeoutMs);
253
254
  },
254
255
  nb::arg("app_id"), nb::arg("token"), nb::arg("game_token_id"),
@@ -260,7 +261,8 @@ void register_replication(nb::module_& m) {
260
261
  nb::arg("socket_recv_buffer_bytes") = 1 << 20,
261
262
  nb::arg("socket_send_buffer_bytes") = 1 << 20, nb::arg("bundle_sends") = true,
262
263
  nb::arg("bundle_window_ms") = 1, nb::arg("provider_timeout_ms") = 30000,
263
- nb::arg("idle_release_guard_ms") = 60 * 1000)
264
+ nb::arg("idle_release_guard_ms") = 60 * 1000,
265
+ nb::arg("legacy_reconnect_window_ms") = 30 * 1000)
264
266
  .def_prop_ro("bridge", &PyConnection::bridge, nb::rv_policy::reference_internal)
265
267
  .def("connect", &PyConnection::connect)
266
268
  .def("disconnect", &PyConnection::disconnect)
@@ -4,7 +4,7 @@ build-backend = "scikit_build_core.build"
4
4
 
5
5
  [project]
6
6
  name = "crowdypy"
7
- version = "0.30.0.dev1"
7
+ version = "0.31.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"
@@ -123,10 +123,10 @@ version = "18.30.0"
123
123
  commit = "4840d76029ffb15a6de6232dab9336f2e9ab6514"
124
124
 
125
125
  [tool.crowdypy.crowdycpp]
126
- version = "0.82.0"
127
- tag = "dev/v0.82.0"
128
- commit = "c6875412bcea97120b4540b80d9b34504c29acf9"
129
- tree-sha256 = "44dca0b0bd34d575808e5bf7a1ca6944ce779a790b9187894761541623a0f3ec"
126
+ version = "0.83.0"
127
+ tag = "dev/v0.83.0"
128
+ commit = "73eb66cdf1c435bc67e405b9a5bd606740209df2"
129
+ tree-sha256 = "fc2d2a460cdc403a9a389e99fa6c402c95c87df05529bbe08167bb5bf20cdffd"
130
130
 
131
131
  # schema.gql and operations/ are CrowdyJS's, copied from the commit pinned above by
132
132
  # scripts/schema_sync.py, which records these hashes and re-derives them in CI.
@@ -1,3 +1,3 @@
1
1
  """The CrowdyPy release this source tree builds."""
2
2
 
3
- __version__ = "0.30.0"
3
+ __version__ = "0.31.0"
@@ -351,6 +351,52 @@ def test_an_idle_release_right_after_input_reassigns(server: FakeServer) -> None
351
351
  assert guardless.assigned == 1
352
352
 
353
353
 
354
+ def command_reconnect(key: str = TOKEN) -> bytes:
355
+ prefix = bytes([MessageType.COMMAND_RECONNECT])
356
+ return prefix + hmac.new(key.encode("latin-1"), prefix, hashlib.sha256).digest()
357
+
358
+
359
+ def test_a_legacy_reconnect_is_paced(server: FakeServer) -> None:
360
+ # CrowdyCPP 0.83.0: a legacy 22 signs fixed bytes, so a captured one verifies for the token's
361
+ # life. One is honoured, and another moments later is dropped and counted.
362
+ provider = Provider(server)
363
+ with ReplicationConnection(provider, token(), app_id=7, **QUIET) as connection:
364
+ for honoured in (True, False):
365
+ # A reassignment finishes before the next send: it goes out on the new socket.
366
+ wait_for_state(connection, ConnState.CONNECTED)
367
+ connection.send_heartbeat((0, 0, 0), ME)
368
+ connection.flush_sends()
369
+ server.recv() # the server learns where this assignment's socket is
370
+ before = provider.assigned
371
+ server.send(command_reconnect())
372
+ deadline = time.monotonic() + 2
373
+ while time.monotonic() < deadline:
374
+ connection.wait(0.05)
375
+ connection.poll()
376
+ if honoured and provider.assigned > before:
377
+ break
378
+ if not honoured and connection.stats()["legacy_reconnects_suppressed"] == 1:
379
+ break
380
+ assert provider.assigned == (before + 1 if honoured else before)
381
+ assert connection.stats()["legacy_reconnects_suppressed"] == 1
382
+
383
+ unpaced = Provider(server)
384
+ with ReplicationConnection(
385
+ unpaced, token(), app_id=7, legacy_reconnect_window_ms=0, **QUIET
386
+ ) as connection:
387
+ for n in (2, 3):
388
+ wait_for_state(connection, ConnState.CONNECTED)
389
+ connection.send_heartbeat((0, 0, 0), ME)
390
+ connection.flush_sends()
391
+ server.recv()
392
+ server.send(command_reconnect())
393
+ deadline = time.monotonic() + 2
394
+ while unpaced.assigned < n and time.monotonic() < deadline:
395
+ connection.wait(0.05)
396
+ connection.poll()
397
+ assert unpaced.assigned == n
398
+
399
+
354
400
  def test_a_release_that_does_not_verify_is_ignored(server: FakeServer) -> None:
355
401
  provider = Provider(server)
356
402
  with ReplicationConnection(provider, token(), app_id=7, **QUIET) as connection:
@@ -103,7 +103,7 @@ wheels = [
103
103
 
104
104
  [[package]]
105
105
  name = "crowdypy"
106
- version = "0.30.0"
106
+ version = "0.31.0"
107
107
  source = { editable = "." }
108
108
  dependencies = [
109
109
  { name = "httpx" },
@@ -1,5 +1,5 @@
1
1
  cmake_minimum_required(VERSION 3.22)
2
- project(CrowdyCPP VERSION 0.82.0 LANGUAGES C CXX)
2
+ project(CrowdyCPP VERSION 0.83.0 LANGUAGES C CXX)
3
3
 
4
4
  set(CMAKE_CXX_STANDARD 20)
5
5
  set(CMAKE_CXX_STANDARD_REQUIRED ON)
@@ -5,4 +5,4 @@ pins under `[tool.crowdypy.crowdycpp]`. It is written by
5
5
  `scripts/vendor_crowdycpp.py` and checked in CI by re-deriving it from that commit.
6
6
  Do not edit it: change CrowdyCPP, release it on the same tier, and re-vendor.
7
7
 
8
- Vendored from `dev/v0.82.0` (`c6875412bcea97120b4540b80d9b34504c29acf9`).
8
+ Vendored from `dev/v0.83.0` (`73eb66cdf1c435bc67e405b9a5bd606740209df2`).
@@ -331,6 +331,40 @@ class VoxelsAPI : public DomainBase {
331
331
  listByDistanceAsync(area.toInput(appId), std::move(cb));
332
332
  }
333
333
 
334
+ /// listInRegion() selecting only what rebuilds a cell: each chunk's `coordinates`, and each
335
+ /// edit's `location`, `voxelType` and `state` (operation ListVoxelUpdatesByDistanceCells).
336
+ /// The log keeps one row per position, the latest write, so a chunk's answer is bounded by
337
+ /// the positions ever edited in it, not by its history.
338
+ graphql::Json listInRegionCells(std::string_view appId, const ChunkRegion& area) const {
339
+ graphql::JVal vars;
340
+ vars["input"] = area.toInput(appId);
341
+ return execUnwrap(gen::voxels::kListVoxelUpdatesByDistanceCellsDocument, vars);
342
+ }
343
+
344
+ void listInRegionCellsAsync(std::string_view appId, const ChunkRegion& area,
345
+ graphql::GraphQLCallback cb) const {
346
+ graphql::JVal vars;
347
+ vars["input"] = area.toInput(appId);
348
+ execUnwrapAsync(gen::voxels::kListVoxelUpdatesByDistanceCellsDocument, vars, {},
349
+ std::move(cb));
350
+ }
351
+
352
+ /// listInRegionCells() with each edit's `createdAt`, the server time of its latest write,
353
+ /// for a reader that orders edits by time (operation ListVoxelUpdatesByDistanceCellsTimed).
354
+ graphql::Json listInRegionCellsTimed(std::string_view appId, const ChunkRegion& area) const {
355
+ graphql::JVal vars;
356
+ vars["input"] = area.toInput(appId);
357
+ return execUnwrap(gen::voxels::kListVoxelUpdatesByDistanceCellsTimedDocument, vars);
358
+ }
359
+
360
+ void listInRegionCellsTimedAsync(std::string_view appId, const ChunkRegion& area,
361
+ graphql::GraphQLCallback cb) const {
362
+ graphql::JVal vars;
363
+ vars["input"] = area.toInput(appId);
364
+ execUnwrapAsync(gen::voxels::kListVoxelUpdatesByDistanceCellsTimedDocument, vars, {},
365
+ std::move(cb));
366
+ }
367
+
334
368
  /// Durable single-voxel update (requires update_voxel_data permission).
335
369
  graphql::Json update(const graphql::JVal& input) const {
336
370
  graphql::JVal vars;
@@ -3,7 +3,7 @@
3
3
  // Inputs: operations/**/*.graphql and schema.gql (synced from the published
4
4
  // SDL at https://docs.crowdedkingdoms.com/schema/game-api.graphql).
5
5
  // schema.gql sha256: 13094c2757b41d50c8aee996009a00d0995ef597bd792c778c25585576a45f33
6
- // operations sha256: 004cb5807f8f859a8c07e2cf75930521350d242fdca088393b463aa5c300c05f
6
+ // operations sha256: eca7de01bfc5d967afbf6c230b6596a9ae42bf9a584ac1021c9f6e9399873f1c
7
7
 
8
8
  #pragma once
9
9
 
@@ -3,7 +3,7 @@
3
3
  // Inputs: operations/**/*.graphql and schema.gql (synced from the published
4
4
  // SDL at https://docs.crowdedkingdoms.com/schema/game-api.graphql).
5
5
  // schema.gql sha256: 13094c2757b41d50c8aee996009a00d0995ef597bd792c778c25585576a45f33
6
- // operations sha256: 004cb5807f8f859a8c07e2cf75930521350d242fdca088393b463aa5c300c05f
6
+ // operations sha256: eca7de01bfc5d967afbf6c230b6596a9ae42bf9a584ac1021c9f6e9399873f1c
7
7
 
8
8
  #pragma once
9
9
 
@@ -11053,6 +11053,102 @@ inline constexpr std::string_view kListVoxelUpdatesByDistanceIsolatedDocument =
11053
11053
  })gql";
11054
11054
  inline constexpr std::string_view kListVoxelUpdatesByDistanceOperationName = "ListVoxelUpdatesByDistance";
11055
11055
 
11056
+ /// voxels/ListVoxelUpdatesByDistanceCells.graphql
11057
+ inline constexpr std::string_view kListVoxelUpdatesByDistanceCellsDocument = R"gql(query ListVoxelUpdatesByDistanceCells($input: ListVoxelUpdatesByDistanceInput!) {
11058
+ listVoxelUpdatesByDistance(input: $input) {
11059
+ limit
11060
+ skip
11061
+ chunks {
11062
+ coordinates {
11063
+ x
11064
+ y
11065
+ z
11066
+ }
11067
+ voxels {
11068
+ location {
11069
+ x
11070
+ y
11071
+ z
11072
+ }
11073
+ voxelType
11074
+ state
11075
+ }
11076
+ }
11077
+ }
11078
+ })gql";
11079
+ inline constexpr std::string_view kListVoxelUpdatesByDistanceCellsIsolatedDocument = R"gql(query ListVoxelUpdatesByDistanceCells($input: ListVoxelUpdatesByDistanceInput!) {
11080
+ listVoxelUpdatesByDistance(input: $input) {
11081
+ limit
11082
+ skip
11083
+ chunks {
11084
+ coordinates {
11085
+ x
11086
+ y
11087
+ z
11088
+ }
11089
+ voxels {
11090
+ location {
11091
+ x
11092
+ y
11093
+ z
11094
+ }
11095
+ voxelType
11096
+ state
11097
+ }
11098
+ }
11099
+ }
11100
+ })gql";
11101
+ inline constexpr std::string_view kListVoxelUpdatesByDistanceCellsOperationName = "ListVoxelUpdatesByDistanceCells";
11102
+
11103
+ /// voxels/ListVoxelUpdatesByDistanceCellsTimed.graphql
11104
+ inline constexpr std::string_view kListVoxelUpdatesByDistanceCellsTimedDocument = R"gql(query ListVoxelUpdatesByDistanceCellsTimed($input: ListVoxelUpdatesByDistanceInput!) {
11105
+ listVoxelUpdatesByDistance(input: $input) {
11106
+ limit
11107
+ skip
11108
+ chunks {
11109
+ coordinates {
11110
+ x
11111
+ y
11112
+ z
11113
+ }
11114
+ voxels {
11115
+ location {
11116
+ x
11117
+ y
11118
+ z
11119
+ }
11120
+ voxelType
11121
+ state
11122
+ createdAt
11123
+ }
11124
+ }
11125
+ }
11126
+ })gql";
11127
+ inline constexpr std::string_view kListVoxelUpdatesByDistanceCellsTimedIsolatedDocument = R"gql(query ListVoxelUpdatesByDistanceCellsTimed($input: ListVoxelUpdatesByDistanceInput!) {
11128
+ listVoxelUpdatesByDistance(input: $input) {
11129
+ limit
11130
+ skip
11131
+ chunks {
11132
+ coordinates {
11133
+ x
11134
+ y
11135
+ z
11136
+ }
11137
+ voxels {
11138
+ location {
11139
+ x
11140
+ y
11141
+ z
11142
+ }
11143
+ voxelType
11144
+ state
11145
+ createdAt
11146
+ }
11147
+ }
11148
+ }
11149
+ })gql";
11150
+ inline constexpr std::string_view kListVoxelUpdatesByDistanceCellsTimedOperationName = "ListVoxelUpdatesByDistanceCellsTimed";
11151
+
11056
11152
  /// voxels/ListVoxels.graphql
11057
11153
  inline constexpr std::string_view kListVoxelsDocument = R"gql(query ListVoxels($input: ListVoxelsInput!) {
11058
11154
  listVoxels(input: $input) {
@@ -11335,6 +11431,8 @@ inline constexpr std::string_view kVoxelUpdateHistoryConnectionOperationName = "
11335
11431
 
11336
11432
  inline constexpr std::string_view documentFor(std::string_view operationName) {
11337
11433
  if (operationName == "ListVoxelUpdatesByDistance") return kListVoxelUpdatesByDistanceIsolatedDocument;
11434
+ if (operationName == "ListVoxelUpdatesByDistanceCells") return kListVoxelUpdatesByDistanceCellsIsolatedDocument;
11435
+ if (operationName == "ListVoxelUpdatesByDistanceCellsTimed") return kListVoxelUpdatesByDistanceCellsTimedIsolatedDocument;
11338
11436
  if (operationName == "ListVoxels") return kListVoxelsIsolatedDocument;
11339
11437
  if (operationName == "RollbackVoxelUpdates") return kRollbackVoxelUpdatesIsolatedDocument;
11340
11438
  if (operationName == "UpdateVoxel") return kUpdateVoxelIsolatedDocument;
@@ -10,6 +10,8 @@
10
10
  #include <variant>
11
11
  #include <vector>
12
12
 
13
+ #include "crowdy/core/result.hpp"
14
+
13
15
  /// JSON support for the GraphQL layer (never used on the UDP path).
14
16
  ///
15
17
  /// Two shapes:
@@ -66,7 +68,8 @@ class JVal {
66
68
  /// JVal::array(...).
67
69
  JVal& operator[](std::nullptr_t) = delete;
68
70
 
69
- /// Serialize to a compact JSON string (RFC 8259 escaping).
71
+ /// Serialize to a compact JSON string (RFC 8259 escaping). NaN and infinity are written
72
+ /// as `null`, as JSON.stringify writes them.
70
73
  std::string dump() const;
71
74
 
72
75
  private:
@@ -122,8 +125,13 @@ class Json {
122
125
  /// int64. Integer JSON numbers are converted losslessly.
123
126
  std::string asBigIntString(std::string_view fallback = {}) const;
124
127
 
125
- /// Serialize this value back to a JSON string.
128
+ /// Serialize this value back to a JSON string. NaN and infinity are written as `null` in
129
+ /// place, so the rest of the value survives. A value that still cannot be written (a
130
+ /// string that is not valid UTF-8, which fromMsgpack can produce) comes back as "null":
131
+ /// use tryDump() to tell that apart from a null value.
126
132
  std::string dump() const;
133
+ /// dump(), reporting a value it cannot write as Errc::Malformed instead of "null".
134
+ Result<std::string> tryDump() const;
127
135
 
128
136
  /// This value as MessagePack, the payload format of ck-exec calls: integers
129
137
  /// keep their exact width and sign, objects become maps with string keys. A
@@ -132,9 +140,11 @@ class Json {
132
140
  /// the calling thread's stack.
133
141
  std::string toMsgpack() const;
134
142
  /// Parse one MessagePack value into a document. Binary becomes a base64
135
- /// string and extension types null; nesting deeper than 64 is refused.
143
+ /// string and extension types null; nesting deeper than 64 is refused. A map
144
+ /// key must be a string, a number, a boolean or nil (the last three become
145
+ /// their JSON text); an array, map, binary or extension key is refused.
136
146
  /// Returns a null Json (ok() == false) on malformed, truncated or trailing
137
- /// input.
147
+ /// input, or on a refused key.
138
148
  static Json fromMsgpack(std::string_view bytes);
139
149
 
140
150
  /// Iterate object members / array elements, in order, one step each: linear in
@@ -5,6 +5,7 @@
5
5
  #include <memory>
6
6
  #include <mutex>
7
7
  #include <thread>
8
+ #include <unordered_map>
8
9
 
9
10
  #include "crowdy/core/clock.hpp"
10
11
  #include "crowdy/core/crypto.hpp"
@@ -301,6 +302,10 @@ class Connection {
301
302
  /// Bound control frames (44, 45) carrying another assignment's nonce, dropped: a
302
303
  /// frame captured earlier and sent again.
303
304
  std::uint64_t staleBoundControl = 0;
305
+ /// Verified legacy COMMAND_RECONNECTs (22) dropped because one was honoured too
306
+ /// recently (0.83.0): a 22 signs fixed bytes, so a captured one verifies for the
307
+ /// game token's life, and each honoured one moves the player to another server.
308
+ std::uint64_t legacyReconnectsSuppressed = 0;
304
309
  std::int64_t lastServerEpochMs = 0;
305
310
  /// Messages sent, by wire opcode (actor/voxel/audio/text/event/channel/
306
311
  /// heartbeat requests).
@@ -422,16 +427,29 @@ class Connection {
422
427
 
423
428
  /// Monotonic ms of the last send that counts as gameplay input (0: none yet).
424
429
  std::atomic<std::int64_t> lastGameplayMs_{0};
425
- /// The last actor-update payload hash per actor this session, so a keyframe that
426
- /// repeats an unchanged state is not input. A lookup that misses counts as a change.
427
- struct ActorStateHash {
428
- core::ActorUuid uuid{};
429
- std::uint64_t hash = 0;
430
- bool used = false;
430
+ /// The last actor-update payload hash per actor this assignment, so a keyframe that
431
+ /// repeats an unchanged state is not input. An actor's first update is a change. Past
432
+ /// kMaxTrackedActors actors, an untracked actor's keyframe counts as unchanged, so a host
433
+ /// keeping a large world's keyframes going still looks idle when it is.
434
+ struct ActorUuidHasher {
435
+ std::size_t operator()(const core::ActorUuid& u) const noexcept {
436
+ std::uint64_t h = 1469598103934665603ULL;
437
+ for (char c : u) h = (h ^ static_cast<std::uint8_t>(c)) * 1099511628211ULL;
438
+ return static_cast<std::size_t>(h);
439
+ }
431
440
  };
432
- std::array<ActorStateHash, 8> actorStateHashes_{};
433
- std::size_t actorStateNext_ = 0;
441
+ static constexpr std::size_t kMaxTrackedActors = 4096;
442
+ std::unordered_map<core::ActorUuid, std::uint64_t, ActorUuidHasher> actorStateHashes_;
434
443
  std::mutex actorStateMutex_;
444
+
445
+ /// Config::legacyReconnectWindowMs: a legacy COMMAND_RECONNECT (22) is honoured once per
446
+ /// assignment, and each honoured one must follow the last by the current window. Touched
447
+ /// only on the receive path and in doAssign().
448
+ static constexpr std::int64_t kLegacyReconnectWindowMaxMs = 600'000;
449
+ std::int64_t lastLegacyReconnectMs_ = 0;
450
+ std::int64_t legacyReconnectWindowMs_ = 0;
451
+ bool legacyReconnectHonoured_ = false;
452
+ bool honourLegacyReconnect();
435
453
  void noteGameplaySend(wire::MessageType type, const SpatialSend& p);
436
454
  bool actorStateChanged(const SpatialSend& p);
437
455
  bool idleReleaseFollowsInput() const;
@@ -105,6 +105,14 @@ struct Config {
105
105
  /// release final.
106
106
  std::int64_t idleReleaseGuardMs = 60 * 1000;
107
107
 
108
+ /// A verified legacy COMMAND_RECONNECT (22) reassigns at most once per assignment, and
109
+ /// only this long after the last one it honoured; the window doubles with each honoured
110
+ /// one up to 10 minutes, and goes back to this after 10 minutes without one. A 22 signs
111
+ /// fixed bytes, so one captured earlier verifies again for the game token's life; the
112
+ /// rest are dropped and count in Stats::legacyReconnectsSuppressed. The bound form (44)
113
+ /// is not limited. 0 honours every verified 22, as before 0.83.0.
114
+ std::int64_t legacyReconnectWindowMs = 30 * 1000;
115
+
108
116
  /// Capacity (events) of the net->game notification ring.
109
117
  std::size_t ringCapacity = 4096;
110
118
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "crowdycpp-maintainer-tools",
3
- "version": "0.82.0",
3
+ "version": "0.83.0",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "description": "Offline parity and schema maintenance tools for CrowdyCPP",
@@ -94,6 +94,10 @@ void JVal::dumpTo(std::string& out) const {
94
94
  void operator()(bool b) { out += b ? "true" : "false"; }
95
95
  void operator()(std::int64_t i) { out += std::to_string(i); }
96
96
  void operator()(double d) {
97
+ if (!std::isfinite(d)) {
98
+ out += "null"; // as JSON.stringify writes NaN and infinity
99
+ return;
100
+ }
97
101
  char buf[32];
98
102
  std::snprintf(buf, sizeof(buf), "%.17g", d);
99
103
  out += buf;
@@ -243,9 +247,14 @@ std::string Json::asBigIntString(std::string_view fallback) const {
243
247
  }
244
248
 
245
249
  std::string Json::dump() const {
246
- if (!val_) return "null";
247
- char* s = yyjson_val_write(val(val_), 0, nullptr);
248
- if (!s) return "null";
250
+ auto out = tryDump();
251
+ return out.ok() ? std::move(out.value()) : std::string("null");
252
+ }
253
+
254
+ Result<std::string> Json::tryDump() const {
255
+ if (!val_) return std::string("null");
256
+ char* s = yyjson_val_write(val(val_), YYJSON_WRITE_INF_AND_NAN_AS_NULL, nullptr);
257
+ if (!s) return Errc::Malformed;
249
258
  std::string out(s);
250
259
  free(s);
251
260
  return out;
@@ -438,15 +447,34 @@ struct Unpacker {
438
447
  }
439
448
  return a;
440
449
  }
450
+ // A map key must be a scalar. A container key written as text is escaped again at every
451
+ // level it is nested in another key, so 130 bytes nested 60 deep asked for gigabytes.
452
+ static bool scalarKey(std::uint8_t t) {
453
+ if ((t & 0xf0) == 0x80 || (t & 0xf0) == 0x90) return false; // fixmap, fixarray
454
+ switch (t) {
455
+ case 0xc4: case 0xc5: case 0xc6: // bin
456
+ case 0xc7: case 0xc8: case 0xc9: // ext
457
+ case 0xd4: case 0xd5: case 0xd6: case 0xd7: case 0xd8: // fixext
458
+ case 0xdc: case 0xdd: case 0xde: case 0xdf: // array, map
459
+ return false;
460
+ default:
461
+ return true;
462
+ }
463
+ }
441
464
  yyjson_mut_val* map(std::size_t n, int depth) {
442
465
  yyjson_mut_val* o = yyjson_mut_obj(doc);
443
466
  for (std::size_t i = 0; i < n && ok; ++i) {
467
+ if (!need(1)) break;
468
+ if (!scalarKey(*p)) {
469
+ ok = false;
470
+ break;
471
+ }
444
472
  yyjson_mut_val* k = value(depth + 1);
445
473
  yyjson_mut_val* v = value(depth + 1);
446
474
  if (!ok || !k || !v) break;
447
475
  if (!yyjson_mut_is_str(k)) {
448
- // A non-string key keeps its value as text, as JSON has only string keys.
449
- char* text = yyjson_mut_val_write(k, 0, nullptr);
476
+ // A number, boolean or nil key keeps its value as text, as JSON has only string keys.
477
+ char* text = yyjson_mut_val_write(k, YYJSON_WRITE_INF_AND_NAN_AS_NULL, nullptr);
450
478
  k = yyjson_mut_strcpy(doc, text ? text : "null");
451
479
  free(text);
452
480
  }