浏览代码

Added Lobby Package

/main
当前提交
367cd157
共有 104 个文件被更改,包括 4826 次插入5 次删除
  1. 4
      Assets/Scripts/LobbyRelaySample.asmdef
  2. 7
      Packages/com.unity.services.lobby/CHANGELOG.md.meta
  3. 7
      Packages/com.unity.services.lobby/README.md.meta
  4. 7
      Packages/com.unity.services.lobby/package.json.meta
  5. 5
      Packages/com.unity.services.lobby/LICENSE.md
  6. 7
      Packages/com.unity.services.lobby/LICENSE.md.meta
  7. 8
      Packages/com.unity.services.lobby/Runtime.meta
  8. 8
      Packages/com.unity.services.lobby/Samples~/HelloWorld.meta
  9. 5
      Packages/com.unity.services.lobby/Samples~/HelloWorld/.sample.json
  10. 430
      Packages/com.unity.services.lobby/Samples~/HelloWorld/LobbyHelloWorld.cs
  11. 11
      Packages/com.unity.services.lobby/Samples~/HelloWorld/LobbyHelloWorld.cs.meta
  12. 8
      Packages/com.unity.services.lobby/Runtime/Apis.meta
  13. 313
      Packages/com.unity.services.lobby/Runtime/Apis/LobbyApi.cs
  14. 11
      Packages/com.unity.services.lobby/Runtime/Apis/LobbyApi.cs.meta
  15. 975
      Packages/com.unity.services.lobby/Runtime/Apis/LobbyApiRequests.cs
  16. 11
      Packages/com.unity.services.lobby/Runtime/Apis/LobbyApiRequests.cs.meta
  17. 8
      Packages/com.unity.services.lobby/Runtime/Configuration.meta
  18. 69
      Packages/com.unity.services.lobby/Runtime/Configuration/Configuration.cs
  19. 11
      Packages/com.unity.services.lobby/Runtime/Configuration/Configuration.cs.meta
  20. 8
      Packages/com.unity.services.lobby/Runtime/Http.meta
  21. 109
      Packages/com.unity.services.lobby/Runtime/Http/AsyncOpRetry.cs
  22. 11
      Packages/com.unity.services.lobby/Runtime/Http/AsyncOpRetry.cs.meta
  23. 15
      Packages/com.unity.services.lobby/Runtime/Http/BaseApiClient.cs
  24. 11
      Packages/com.unity.services.lobby/Runtime/Http/BaseApiClient.cs.meta
  25. 35
      Packages/com.unity.services.lobby/Runtime/Http/BasicError.cs
  26. 11
      Packages/com.unity.services.lobby/Runtime/Http/BasicError.cs.meta
  27. 35
      Packages/com.unity.services.lobby/Runtime/Http/CommonErrors.cs
  28. 11
      Packages/com.unity.services.lobby/Runtime/Http/CommonErrors.cs.meta
  29. 34
      Packages/com.unity.services.lobby/Runtime/Http/DeserializationException.cs
  30. 11
      Packages/com.unity.services.lobby/Runtime/Http/DeserializationException.cs.meta
  31. 239
      Packages/com.unity.services.lobby/Runtime/Http/HttpClient.cs
  32. 11
      Packages/com.unity.services.lobby/Runtime/Http/HttpClient.cs.meta
  33. 26
      Packages/com.unity.services.lobby/Runtime/Http/HttpClientResponse.cs
  34. 11
      Packages/com.unity.services.lobby/Runtime/Http/HttpClientResponse.cs.meta
  35. 51
      Packages/com.unity.services.lobby/Runtime/Http/HttpException.cs
  36. 11
      Packages/com.unity.services.lobby/Runtime/Http/HttpException.cs.meta
  37. 11
      Packages/com.unity.services.lobby/Runtime/Http/IError.cs
  38. 11
      Packages/com.unity.services.lobby/Runtime/Http/IError.cs.meta
  39. 18
      Packages/com.unity.services.lobby/Runtime/Http/IHttpClient.cs
  40. 11
      Packages/com.unity.services.lobby/Runtime/Http/IHttpClient.cs.meta
  41. 32
      Packages/com.unity.services.lobby/Runtime/Http/JsonHelpers.cs
  42. 11
      Packages/com.unity.services.lobby/Runtime/Http/JsonHelpers.cs.meta
  43. 168
      Packages/com.unity.services.lobby/Runtime/Http/ResponseHandler.cs
  44. 11
      Packages/com.unity.services.lobby/Runtime/Http/ResponseHandler.cs.meta
  45. 27
      Packages/com.unity.services.lobby/Runtime/Http/Responses.cs
  46. 11
      Packages/com.unity.services.lobby/Runtime/Http/Responses.cs.meta
  47. 39
      Packages/com.unity.services.lobby/Runtime/Http/UnityWebRequestHelpers.cs
  48. 11
      Packages/com.unity.services.lobby/Runtime/Http/UnityWebRequestHelpers.cs.meta
  49. 15
      Packages/com.unity.services.lobby/Runtime/LobbyService.cs
  50. 11
      Packages/com.unity.services.lobby/Runtime/LobbyService.cs.meta
  51. 45
      Packages/com.unity.services.lobby/Runtime/LobbyServiceProvider.cs
  52. 11
      Packages/com.unity.services.lobby/Runtime/LobbyServiceProvider.cs.meta
  53. 8
      Packages/com.unity.services.lobby/Runtime/Models.meta
  54. 74
      Packages/com.unity.services.lobby/Runtime/Models/CreateRequest.cs
  55. 11
      Packages/com.unity.services.lobby/Runtime/Models/CreateRequest.cs.meta
  56. 155
      Packages/com.unity.services.lobby/Runtime/Models/DataObject.cs
  57. 11
      Packages/com.unity.services.lobby/Runtime/Models/DataObject.cs.meta
  58. 47
      Packages/com.unity.services.lobby/Runtime/Models/Detail.cs
  59. 11
      Packages/com.unity.services.lobby/Runtime/Models/Detail.cs.meta
  60. 56
      Packages/com.unity.services.lobby/Runtime/Models/ErrorStatus.cs
  61. 11
      Packages/com.unity.services.lobby/Runtime/Models/ErrorStatus.cs.meta
  62. 47
      Packages/com.unity.services.lobby/Runtime/Models/JoinByCodeRequest.cs
  63. 11
      Packages/com.unity.services.lobby/Runtime/Models/JoinByCodeRequest.cs.meta
  64. 137
      Packages/com.unity.services.lobby/Runtime/Models/Lobby.cs
  65. 11
      Packages/com.unity.services.lobby/Runtime/Models/Lobby.cs.meta
  66. 10
      Packages/com.unity.services.lobby/Runtime/Models/LobbyIOneOf.cs
  67. 11
      Packages/com.unity.services.lobby/Runtime/Models/LobbyIOneOf.cs.meta
  68. 83
      Packages/com.unity.services.lobby/Runtime/Models/Player.cs
  69. 11
      Packages/com.unity.services.lobby/Runtime/Models/Player.cs.meta
  70. 76
      Packages/com.unity.services.lobby/Runtime/Models/PlayerDataObject.cs
  71. 11
      Packages/com.unity.services.lobby/Runtime/Models/PlayerDataObject.cs.meta
  72. 56
      Packages/com.unity.services.lobby/Runtime/Models/PlayerUpdateRequest.cs
  73. 11
      Packages/com.unity.services.lobby/Runtime/Models/PlayerUpdateRequest.cs.meta
  74. 210
      Packages/com.unity.services.lobby/Runtime/Models/QueryFilter.cs
  75. 11
      Packages/com.unity.services.lobby/Runtime/Models/QueryFilter.cs.meta
  76. 154
      Packages/com.unity.services.lobby/Runtime/Models/QueryOrder.cs
  77. 11
      Packages/com.unity.services.lobby/Runtime/Models/QueryOrder.cs.meta
  78. 83
      Packages/com.unity.services.lobby/Runtime/Models/QueryRequest.cs
  79. 11
      Packages/com.unity.services.lobby/Runtime/Models/QueryRequest.cs.meta
  80. 47
      Packages/com.unity.services.lobby/Runtime/Models/QueryResponse.cs
  81. 11
      Packages/com.unity.services.lobby/Runtime/Models/QueryResponse.cs.meta
  82. 47
      Packages/com.unity.services.lobby/Runtime/Models/QuickJoinRequest.cs
  83. 11
      Packages/com.unity.services.lobby/Runtime/Models/QuickJoinRequest.cs.meta
  84. 74
      Packages/com.unity.services.lobby/Runtime/Models/UpdateRequest.cs
  85. 11
      Packages/com.unity.services.lobby/Runtime/Models/UpdateRequest.cs.meta
  86. 8
      Packages/com.unity.services.lobby/Runtime/Scheduler.meta
  87. 37
      Packages/com.unity.services.lobby/Runtime/Scheduler/GameObjectFactory.cs
  88. 11
      Packages/com.unity.services.lobby/Runtime/Scheduler/GameObjectFactory.cs.meta
  89. 59
      Packages/com.unity.services.lobby/Runtime/Scheduler/TaskScheduler.cs
  90. 11
      Packages/com.unity.services.lobby/Runtime/Scheduler/TaskScheduler.cs.meta
  91. 90
      Packages/com.unity.services.lobby/Runtime/Scheduler/TaskSchedulerThreaded.cs
  92. 11
      Packages/com.unity.services.lobby/Runtime/Scheduler/TaskSchedulerThreaded.cs.meta
  93. 65
      Packages/com.unity.services.lobby/Runtime/Scheduler/TaskSchedulerWebGL.cs
  94. 11
      Packages/com.unity.services.lobby/Runtime/Scheduler/TaskSchedulerWebGL.cs.meta

4
Assets/Scripts/LobbyRelaySample.asmdef


"references": [
"GUID:6055be8ebefd69e48b49212b09b47b2f",
"GUID:03058786646e84a4587858e9302c3f41",
"GUID:4c3f49d89436d478ea78315c03159dcc",
"GUID:fe25561d224ed4743af4c60938a59d0b"
"GUID:fe25561d224ed4743af4c60938a59d0b",
"GUID:4c3f49d89436d478ea78315c03159dcc"
],
"includePlatforms": [],
"excludePlatforms": [],

7
Packages/com.unity.services.lobby/CHANGELOG.md.meta


fileFormatVersion: 2
guid: 06d40308e46a74978beb69ddb7ae0d7b
guid: 06d40308e46a74978beb69ddb7ae0d7b
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

7
Packages/com.unity.services.lobby/README.md.meta


fileFormatVersion: 2
guid: 784a1d5bae6a048b4a1ad0b750d23a93
guid: 784a1d5bae6a048b4a1ad0b750d23a93
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

7
Packages/com.unity.services.lobby/package.json.meta


fileFormatVersion: 2
guid: 73931d4bd223347edab048dfcb509505
guid: 73931d4bd223347edab048dfcb509505
PackageManifestImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

5
Packages/com.unity.services.lobby/LICENSE.md


com.unity.services.lobby copyright © 2021 Unity Technologies
This software is subject to, and made available under, the terms of service for Unity Lobby (see [Operate Terms of Service](https://unity3d.com/legal/one-operate-services-terms-of-service)).
Unless expressly provided otherwise, the software under this license is made available strictly on an "AS IS" BASIS WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED. Please review the terms of service for details on these and other terms and conditions.

7
Packages/com.unity.services.lobby/LICENSE.md.meta


fileFormatVersion: 2
guid: 9a250b1c14b734726aa1f1cfa2c88464
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

8
Packages/com.unity.services.lobby/Runtime.meta


fileFormatVersion: 2
guid: 73245f28b46bd494b8ed4601d27921b2
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

8
Packages/com.unity.services.lobby/Samples~/HelloWorld.meta


fileFormatVersion: 2
guid: 9ada111e9bb0b9b40a4136e17c5b6003
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

5
Packages/com.unity.services.lobby/Samples~/HelloWorld/.sample.json


{
"displayName":"Hello World Sample",
"description": "This sample walks through using most of the Lobby APIs in a simple, linear way.",
"createSeparatePackage": false
}

430
Packages/com.unity.services.lobby/Samples~/HelloWorld/LobbyHelloWorld.cs


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
using UnityEngine;
using Unity.Services.Authentication;
using Unity.Services.Core;
using Unity.Services.Lobbies;
using Unity.Services.Lobbies.Http;
using Unity.Services.Lobbies.Models;
using Random = UnityEngine.Random;
public class LobbyHelloWorld : MonoBehaviour
{
// Inspector properties with initial values
public string newLobbyName = Guid.NewGuid().ToString();
public int maxPlayers = 8;
public bool isPrivate = false;
// We'll only be in one lobby at once for this demo, so let's track it here
private Lobby currentLobby;
async void Start()
{
try
{
await ExecuteLobbyDemoAsync();
}
catch (Exception ex)
{
Debug.LogException(ex);
}
finally
{
await CleanupDemoLobbyAsync();
}
}
// Clean up the lobby we're in if we're the host
async Task CleanupDemoLobbyAsync()
{
var localPlayerId = AuthenticationService.Instance.PlayerId;
// This is so that orphan lobbies aren't left around in case the demo fails partway through
if (currentLobby != null && currentLobby.HostId.Equals(localPlayerId))
{
await DeleteLobbyAsync(currentLobby.Id);
}
}
// A basic demo of lobby functionality
async Task ExecuteLobbyDemoAsync()
{
await UnityServices.Initialize();
// Log in a player for this game client
Player loggedInPlayer = await GetPlayerFromAnonymousLoginAsync();
// Add some data to our player
// This data will be included in a lobby under players -> player.data
loggedInPlayer.Data.Add("Ready", new PlayerDataObject(PlayerDataObject.VisibilityOptions.Member, "No"));
// Look for existing lobbies
List<Lobby> foundLobbies = await QueryLobbiesAsync(new QueryRequest(
count: 10, // Return up to 10 results
sampleResults: false, // Do not give random results
filter: new List<QueryFilter>
{
// Use filters to only return lobbies which match specific conditions
// You can only filter on built-in properties (Ex: AvailableSlots) or indexed custom data (S1, N1, etc.)
// Take a look at the API for other built-in fields you can filter on
// Let's search for games with open slots (AvailableSlots greater than 0)
new QueryFilter(
field: QueryFilter.FieldOptions.AvailableSlots,
op: QueryFilter.OpOptions.GT,
value: "0"),
// Let's add some filters for custom indexed fields
new QueryFilter(
field: QueryFilter.FieldOptions.S1, // S1 = "Test"
op: QueryFilter.OpOptions.EQ,
value: "true"),
new QueryFilter(
field: QueryFilter.FieldOptions.S2, // S2 = "GameMode"
op: QueryFilter.OpOptions.EQ,
value: "ctf"),
// Example "skill" range filter (skill is a custom numeric field in this example)
new QueryFilter(
field: QueryFilter.FieldOptions.N1, // N1 = "Skill"
op: QueryFilter.OpOptions.GT,
value: "0"),
new QueryFilter(
field: QueryFilter.FieldOptions.N1, // N1 = "Skill"
op: QueryFilter.OpOptions.LT,
value: "51"),
},
order: new List<QueryOrder>
{
// Order results by available player slots (least first), then by lobby age, then by lobby name
new QueryOrder(true, QueryOrder.FieldOptions.AvailableSlots),
new QueryOrder(false, QueryOrder.FieldOptions.Created),
new QueryOrder(false, QueryOrder.FieldOptions.Name),
}));
if (foundLobbies.Any()) // Try to join a random lobby if one exists
{
// Let's print info about the lobbies we found
Debug.Log("Found lobbies:\n" + JsonConvert.SerializeObject(foundLobbies));
// Let's pick a random lobby to join
var randomLobby = foundLobbies[Random.Range(0, foundLobbies.Count)];
// Try to join the lobby
// Player is optional because the service can pull the player data from the auth token
currentLobby = await JoinLobbyAsync(lobbyId: randomLobby.Id, player: null);
// You can also join via a Lobby Code instead of a lobby ID
// Lobby Codes are a short, unique codes that map to a specific lobby Id
// currentLobby = await JoinLobbyWithCodeAsync("MyLobbyCode");
}
else // Didn't find any lobbies, create a new lobby
{
// Populate the new lobby with some data; use indexes so it's easy to search for
var lobbyData = new Dictionary<string, DataObject>()
{
["Test"] = new DataObject(DataObject.VisibilityOptions.Public, "true", DataObject.IndexOptions.S1),
["GameMode"] = new DataObject(DataObject.VisibilityOptions.Public, "ctf", DataObject.IndexOptions.S2),
["Skill"] = new DataObject(DataObject.VisibilityOptions.Public, Random.Range(1, 51).ToString(), DataObject.IndexOptions.N1),
["Rank"] = new DataObject(DataObject.VisibilityOptions.Public, Random.Range(1, 51).ToString()),
};
// Create a new lobby
currentLobby = await CreateLobbyAsync(new CreateRequest(
name: newLobbyName,
player: loggedInPlayer,
maxPlayers: maxPlayers,
isPrivate: isPrivate,
data: lobbyData));
}
// Let's write a little info about the lobby we joined / created
Debug.Log("Lobby info:\n" + JsonConvert.SerializeObject(currentLobby));
// Let's add some new data for our player and update the lobby state
// Players can update their own data
loggedInPlayer.Data.Add("ExamplePublicPlayerData",
new PlayerDataObject(PlayerDataObject.VisibilityOptions.Public, "Everyone can see this"));
loggedInPlayer.Data.Add("ExamplePrivatePlayerData",
new PlayerDataObject(PlayerDataObject.VisibilityOptions.Private, "Only the host sees this"));
loggedInPlayer.Data.Add("ExampleMemberPlayerData",
new PlayerDataObject(PlayerDataObject.VisibilityOptions.Member, "Only lobby members see this"));
// Update the lobby
currentLobby = await UpdateLobbyPlayerDataAsync(currentLobby.Id, loggedInPlayer);
Debug.Log("Updated lobby info:\n" + JsonConvert.SerializeObject(currentLobby));
// Let's poll for the lobby data again just to see what it looks like
currentLobby = await GetLobbyAsync(currentLobby.Id);
Debug.Log("Updated lobby info:\n" + JsonConvert.SerializeObject(currentLobby));
if (!currentLobby.HostId.Equals(loggedInPlayer.Id))
{
// Since we're not the lobby host, let's just leave the lobby
await RemovePlayerFromLobbyAsync(currentLobby.Id, loggedInPlayer.Id);
}
else
{
// Only hosts can set lobby data, and we're the host, so let's set some
// Note that lobby host can be passed around intentionally (by the current host updating the host id)
// Host is randomly assigned if the previous host leaves
// Let's update some existing lobby data
currentLobby.Data["GameMode"] =
new DataObject(DataObject.VisibilityOptions.Public, "deathmatch", DataObject.IndexOptions.S2);
// Let's add some new data to the lobby
currentLobby.Data.Add("ExamplePublicLobbyData",
new DataObject(DataObject.VisibilityOptions.Public, "Everyone can see this"));
currentLobby.Data.Add("ExamplePrivateLobbyData",
new DataObject(DataObject.VisibilityOptions.Private, "Only the host sees this"));
currentLobby.Data.Add("ExampleMemberLobbyData",
new DataObject(DataObject.VisibilityOptions.Member, "Only lobby members see this"));
// OK, now let's try to push these local changes to the service
currentLobby = await UpdateLobbyDataAsync(currentLobby);
// Let's print the updated lobby
Debug.Log("Updated lobby info:\n" + JsonConvert.SerializeObject(currentLobby));
// OK, we're done with the lobby - let's delete it
await DeleteLobbyAsync(currentLobby.Id);
}
// Now, let's try the QuickJoin API, which just puts our player in a matching lobby automatically
// This is fast and reliable, but removes some user interactivity (can't choose from a list of lobbies)
// You can use filters to specify which types of lobbies can be joined
currentLobby = await QuickJoinLobbyAsync(loggedInPlayer, new List<QueryFilter>
{
// Let's search for games with open slots (AvailableSlots greater than 0)
new QueryFilter(
field: QueryFilter.FieldOptions.AvailableSlots,
op: QueryFilter.OpOptions.GT,
value: "0"),
// You can add more filters here, such as filters on custom data fields
});
// If we didn't find a lobby, abort run
if (currentLobby == null)
{
Debug.Log("Unable to find a lobby using Query and Join");
return;
}
// Let's write a little info about the lobby we quick-joined
Debug.Log("Lobby info:\n" + JsonConvert.SerializeObject(currentLobby));
// There's not anything else we can really do here, so let's leave the lobby
await RemovePlayerFromLobbyAsync(currentLobby.Id, loggedInPlayer.Id);
}
// Log in a player using Unity's "Anonymous Login" API and construct a Player object for use with the Lobbies APIs
static async Task<Player> GetPlayerFromAnonymousLoginAsync()
{
if (!AuthenticationService.Instance.IsSignedIn)
{
Debug.Log($"Trying to log in a player ...");
// Use Unity Authentication to log in
await AuthenticationService.Instance.SignInAnonymouslyAsync();
if (!AuthenticationService.Instance.IsSignedIn)
{
Debug.Log("Player was not signed in successfully?");
throw new InvalidOperationException("Unable to continue with no logged in player");
}
}
Debug.Log("Player signed in as " + AuthenticationService.Instance.PlayerId);
// Player objects have Get-only properties, so you need to initialize the data bag here if you want to use it
return new Player(AuthenticationService.Instance.PlayerId, null, new Dictionary<string, PlayerDataObject>());
}
// Create a new lobby
static async Task<Lobby> CreateLobbyAsync(CreateRequest createRequest)
{
Debug.Log($"Trying to create a new lobby ...");
Response<Lobby> response = await LobbyService.LobbyApiClient.CreateLobbyAsync(new CreateLobbyRequest(createRequest));
Debug.Log($"Player {createRequest.Player.Id} created lobby {response.Result.Id}");
return response.Result;
}
// Get a list of existing lobbies (Optional: use a filter)
static async Task<List<Lobby>> QueryLobbiesAsync(QueryRequest queryRequest)
{
Debug.Log($"Trying to query compatible lobbies ...");
Response<QueryResponse> response = await LobbyService.LobbyApiClient.QueryLobbiesAsync(new QueryLobbiesRequest(queryRequest));
Debug.Log($"Found {response.Result.Results.Count} matching lobbies");
return response.Result.Results;
}
// Ask the service to join any available lobby; can provide a filter
static async Task<Lobby> QuickJoinLobbyAsync(Player player, List<QueryFilter> filter = null)
{
Debug.Log($"Trying to query and join a compatible lobby ...");
var request = new QuickJoinLobbyRequest(new QuickJoinRequest(
player: player,
filter: filter
));
// This is an example of how to handle some common errors when calling the service
// 404s are expected if no lobby is found, and the API currently throws exceptions on 404
try
{
Response<Lobby> response = await LobbyService.LobbyApiClient.QuickJoinLobbyAsync(request);
Debug.Log($"Player {player.Id} joined lobby {response.Result.Id}");
return response.Result;
}
catch (HttpException ex)
{
if (TryGetErrorFromResponse(ex.Response, out var error))
{
// If we got a structured error we can deserialize, let's log it
Debug.Log($"Lobby service error; Http Status {ex.Response.StatusCode}" +
$"\nResponse Error: {ex.Response.ErrorMessage}" +
$"\nLobby Error Status: {error.status}" +
$"\nLobby Error Title: {error.title}");
}
else
{
// For error we can't deserialize, log the exception + body for debugging
Debug.Log($"Lobby service error; Http Status {ex.Response.StatusCode}" +
$"\nResponse Error: {ex.Response.ErrorMessage}" +
$"\nBody: {Encoding.UTF8.GetString(ex.Response.Data)}");
Debug.LogException(ex);
}
}
return null;
}
// Try to join a specific lobby
static async Task<Lobby> JoinLobbyAsync(string lobbyId, Player player = null)
{
Debug.Log($"Attempting to join lobby {lobbyId} ...");
Response<Lobby> response = await LobbyService.LobbyApiClient.JoinLobbyByIdAsync(
new JoinLobbyByIdRequest(lobbyId, player));
Debug.Log($"Joined lobby {response.Result.Id}");
return response.Result;
}
// Try to join a specific lobby; use a lobbyCode to join instead of a LobbyId
static async Task<Lobby> JoinLobbyWithCodeAsync(string lobbyCode, Player player = null)
{
Debug.Log($"Attempting to join lobby with lobby code {lobbyCode} ...");
Response<Lobby> response = await LobbyService.LobbyApiClient.JoinLobbyByCodeAsync(
new JoinLobbyByCodeRequest(new JoinByCodeRequest(lobbyCode, player)));
Debug.Log($"Joined lobby {response.Result.Id}");
return response.Result;
}
// Get details about a specific lobby
static async Task<Lobby> GetLobbyAsync(string lobbyId)
{
Debug.Log($"Getting lobby {lobbyId} ...");
Response<Lobby> response = await LobbyService.LobbyApiClient.GetLobbyAsync(
new GetLobbyRequest(lobbyId));
return response.Result;
}
// Delete an existing lobby; see API docs for access restrictions
static async Task DeleteLobbyAsync(string lobbyId)
{
Debug.Log($"Deleting lobby {lobbyId} ...");
Response response = await LobbyService.LobbyApiClient.DeleteLobbyAsync(
new DeleteLobbyRequest(lobbyId));
Debug.Log($"Lobby {lobbyId} deleted");
}
// Remove a player from a lobby; see API docs for access restrictions
static async Task RemovePlayerFromLobbyAsync(string lobbyId, string playerId)
{
Debug.Log($"Removing {playerId} from lobby {lobbyId} ...");
var request = new RemovePlayerRequest(lobbyId, playerId);
Response response = await LobbyService.LobbyApiClient.RemovePlayerAsync(request);
Debug.Log($"Player {playerId} removed from lobby {lobbyId}");
}
// Set lobby data; see API docs for access restrictions
static async Task<Lobby> UpdateLobbyDataAsync(Lobby lobby)
{
Debug.Log($"Updating lobby data for lobby {lobby.Id} ...");
UpdateRequest updatedState = new UpdateRequest(
maxPlayers: lobby.MaxPlayers,
isPrivate: lobby.IsPrivate,
data: lobby.Data,
hostId: lobby.HostId,
name: lobby.Name);
var updateReq = new UpdateLobbyRequest(lobby.Id, updatedState);
Response<Lobby> response = await LobbyService.LobbyApiClient.UpdateLobbyAsync(updateReq);
Debug.Log($"Lobby data for lobby {lobby.Id} updated");
return response.Result;
}
// Set player data in a lobby; see API docs for access restrictions
static async Task<Lobby> UpdateLobbyPlayerDataAsync(string lobbyId, Player player)
{
Debug.Log($"Updating player data for player {player.Id} in lobby {lobbyId} ...");
var newPlayerState = new PlayerUpdateRequest(
connectionInfo: player.ConnectionInfo,
data: player.Data,
allocationId: player.AllocationId);
var updateReq = new UpdatePlayerRequest(lobbyId, player.Id, newPlayerState);
Response<Lobby> response = await LobbyService.LobbyApiClient.UpdatePlayerAsync(updateReq);
Debug.Log($"Player data for player {player.Id} in lobby {lobbyId} updated");
return response.Result;
}
// A class for errors returned from the service on failures (4xx errors, etc.)
class LobbyError
{
public int status { get; set; }
public string title { get; set; }
public Detail[] details { get; set; }
}
class Detail
{
public string message { get; set; }
public string errorType { get; set; }
}
static bool TryGetErrorFromResponse(HttpClientResponse response, out LobbyError error)
{
var decodedJsonString = Encoding.UTF8.GetString(response.Data);
var success = true;
var settings = new JsonSerializerSettings
{
Error = (sender, args) =>
{
success = false;
args.ErrorContext.Handled = true;
},
MissingMemberHandling = MissingMemberHandling.Ignore
};
error = JsonConvert.DeserializeObject<LobbyError>(decodedJsonString, settings);
return success;
}
}

11
Packages/com.unity.services.lobby/Samples~/HelloWorld/LobbyHelloWorld.cs.meta


fileFormatVersion: 2
guid: 36b1cdc3d10416a44ac98753d781b1c5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

8
Packages/com.unity.services.lobby/Runtime/Apis.meta


fileFormatVersion: 2
guid: 0281d305333c1488b9b2bc3c4f3c26c5
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

313
Packages/com.unity.services.lobby/Runtime/Apis/LobbyApi.cs


using System.Threading.Tasks;
using System.Collections.Generic;
using Unity.Services.Lobbies.Models;
using Unity.Services.Lobbies.Http;
using TaskScheduler = Unity.Services.Lobbies.Scheduler.TaskScheduler;
using Unity.Services.Authentication;
using Unity.Services.Lobbies;
namespace Unity.Services.Lobbies.Apis
{
public interface ILobbyApiClient
{
/// <summary>
/// Async Operation.
/// Create a lobby
/// </summary>
/// <param name="request">Request object for CreateLobby</param>
/// <returns>Task for a Response object containing status code, headers, and Lobby object</returns>
/// <exception cref="Unity.Services.Lobbies.Http.HttpException">An exception containing the HttpClientResponse with headers, response code, and string of error.</exception>
Task<Response<Lobby>> CreateLobbyAsync(CreateLobbyRequest request, Configuration operationConfiguration = null);
/// <summary>
/// Async Operation.
/// Delete a lobby
/// </summary>
/// <param name="request">Request object for DeleteLobby</param>
/// <returns>Task for a Response object containing status code, headers</returns>
/// <exception cref="Unity.Services.Lobbies.Http.HttpException">An exception containing the HttpClientResponse with headers, response code, and string of error.</exception>
Task<Response> DeleteLobbyAsync(DeleteLobbyRequest request, Configuration operationConfiguration = null);
/// <summary>
/// Async Operation.
/// Get lobby details
/// </summary>
/// <param name="request">Request object for GetLobby</param>
/// <returns>Task for a Response object containing status code, headers, and Lobby object</returns>
/// <exception cref="Unity.Services.Lobbies.Http.HttpException">An exception containing the HttpClientResponse with headers, response code, and string of error.</exception>
Task<Response<Lobby>> GetLobbyAsync(GetLobbyRequest request, Configuration operationConfiguration = null);
/// <summary>
/// Async Operation.
/// Join a lobby with lobby code
/// </summary>
/// <param name="request">Request object for JoinLobbyByCode</param>
/// <returns>Task for a Response object containing status code, headers, and Lobby object</returns>
/// <exception cref="Unity.Services.Lobbies.Http.HttpException">An exception containing the HttpClientResponse with headers, response code, and string of error.</exception>
Task<Response<Lobby>> JoinLobbyByCodeAsync(JoinLobbyByCodeRequest request, Configuration operationConfiguration = null);
/// <summary>
/// Async Operation.
/// Join a lobby with lobby ID
/// </summary>
/// <param name="request">Request object for JoinLobbyById</param>
/// <returns>Task for a Response object containing status code, headers, and Lobby object</returns>
/// <exception cref="Unity.Services.Lobbies.Http.HttpException">An exception containing the HttpClientResponse with headers, response code, and string of error.</exception>
Task<Response<Lobby>> JoinLobbyByIdAsync(JoinLobbyByIdRequest request, Configuration operationConfiguration = null);
/// <summary>
/// Async Operation.
/// Query public lobbies
/// </summary>
/// <param name="request">Request object for QueryLobbies</param>
/// <returns>Task for a Response object containing status code, headers, and QueryResponse object</returns>
/// <exception cref="Unity.Services.Lobbies.Http.HttpException">An exception containing the HttpClientResponse with headers, response code, and string of error.</exception>
Task<Response<QueryResponse>> QueryLobbiesAsync(QueryLobbiesRequest request, Configuration operationConfiguration = null);
/// <summary>
/// Async Operation.
/// Query available lobbies and join a random one
/// </summary>
/// <param name="request">Request object for QuickJoinLobby</param>
/// <returns>Task for a Response object containing status code, headers, and Lobby object</returns>
/// <exception cref="Unity.Services.Lobbies.Http.HttpException">An exception containing the HttpClientResponse with headers, response code, and string of error.</exception>
Task<Response<Lobby>> QuickJoinLobbyAsync(QuickJoinLobbyRequest request, Configuration operationConfiguration = null);
/// <summary>
/// Async Operation.
/// Remove a player
/// </summary>
/// <param name="request">Request object for RemovePlayer</param>
/// <returns>Task for a Response object containing status code, headers</returns>
/// <exception cref="Unity.Services.Lobbies.Http.HttpException">An exception containing the HttpClientResponse with headers, response code, and string of error.</exception>
Task<Response> RemovePlayerAsync(RemovePlayerRequest request, Configuration operationConfiguration = null);
/// <summary>
/// Async Operation.
/// Update lobby data
/// </summary>
/// <param name="request">Request object for UpdateLobby</param>
/// <returns>Task for a Response object containing status code, headers, and Lobby object</returns>
/// <exception cref="Unity.Services.Lobbies.Http.HttpException">An exception containing the HttpClientResponse with headers, response code, and string of error.</exception>
Task<Response<Lobby>> UpdateLobbyAsync(UpdateLobbyRequest request, Configuration operationConfiguration = null);
/// <summary>
/// Async Operation.
/// Update player data
/// </summary>
/// <param name="request">Request object for UpdatePlayer</param>
/// <returns>Task for a Response object containing status code, headers, and Lobby object</returns>
/// <exception cref="Unity.Services.Lobbies.Http.HttpException">An exception containing the HttpClientResponse with headers, response code, and string of error.</exception>
Task<Response<Lobby>> UpdatePlayerAsync(UpdatePlayerRequest request, Configuration operationConfiguration = null);
}
///<inheritdoc cref="ILobbyApiClient"/>
public class LobbyApiClient : BaseApiClient, ILobbyApiClient
{
private IAccessToken _accessToken;
private Configuration _configuration;
public Configuration Configuration
{
get {
// We return a merge between the current configuration and the
// global configuration to ensure we have the correct
// combination of headers and a base path (if it is set).
return Configuration.MergeConfigurations(_configuration, LobbyService.Configuration);
}
}
public LobbyApiClient(IHttpClient httpClient,
TaskScheduler taskScheduler,
IAccessToken accessToken,
Configuration configuration = null) : base(httpClient, taskScheduler)
{
// We don't need to worry about the configuration being null at
// this stage, we will check this in the accessor.
_configuration = configuration;
_accessToken = accessToken;
}
public async Task<Response<Lobby>> CreateLobbyAsync(CreateLobbyRequest request,
Configuration operationConfiguration = null)
{
var statusCodeToTypeMap = new Dictionary<string, System.Type>() { { "201", typeof(Lobby) },{ "400", typeof(ErrorStatus) },{ "403", typeof(ErrorStatus) } };
// Merge the operation/request level configuration with the client level configuration.
var finalConfiguration = Configuration.MergeConfigurations(operationConfiguration, Configuration);
var response = await HttpClient.MakeRequestAsync("POST",
request.ConstructUrl(finalConfiguration.BasePath),
request.ConstructBody(),
request.ConstructHeaders(_accessToken, finalConfiguration),
finalConfiguration.RequestTimeout);
var handledResponse = ResponseHandler.HandleAsyncResponse<Lobby>(response, statusCodeToTypeMap);
return new Response<Lobby>(response, handledResponse);
}
public async Task<Response> DeleteLobbyAsync(DeleteLobbyRequest request,
Configuration operationConfiguration = null)
{
var statusCodeToTypeMap = new Dictionary<string, System.Type>() { { "204", null },{ "400", typeof(ErrorStatus) },{ "403", typeof(ErrorStatus) },{ "404", typeof(ErrorStatus) } };
// Merge the operation/request level configuration with the client level configuration.
var finalConfiguration = Configuration.MergeConfigurations(operationConfiguration, Configuration);
var response = await HttpClient.MakeRequestAsync("DELETE",
request.ConstructUrl(finalConfiguration.BasePath),
request.ConstructBody(),
request.ConstructHeaders(_accessToken, finalConfiguration),
finalConfiguration.RequestTimeout);
ResponseHandler.HandleAsyncResponse(response, statusCodeToTypeMap);
return new Response(response);
}
public async Task<Response<Lobby>> GetLobbyAsync(GetLobbyRequest request,
Configuration operationConfiguration = null)
{
var statusCodeToTypeMap = new Dictionary<string, System.Type>() { { "200", typeof(Lobby) },{ "403", typeof(ErrorStatus) },{ "404", typeof(ErrorStatus) } };
// Merge the operation/request level configuration with the client level configuration.
var finalConfiguration = Configuration.MergeConfigurations(operationConfiguration, Configuration);
var response = await HttpClient.MakeRequestAsync("GET",
request.ConstructUrl(finalConfiguration.BasePath),
request.ConstructBody(),
request.ConstructHeaders(_accessToken, finalConfiguration),
finalConfiguration.RequestTimeout);
var handledResponse = ResponseHandler.HandleAsyncResponse<Lobby>(response, statusCodeToTypeMap);
return new Response<Lobby>(response, handledResponse);
}
public async Task<Response<Lobby>> JoinLobbyByCodeAsync(JoinLobbyByCodeRequest request,
Configuration operationConfiguration = null)
{
var statusCodeToTypeMap = new Dictionary<string, System.Type>() { { "200", typeof(Lobby) },{ "400", typeof(ErrorStatus) },{ "403", typeof(ErrorStatus) },{ "409", typeof(ErrorStatus) } };
// Merge the operation/request level configuration with the client level configuration.
var finalConfiguration = Configuration.MergeConfigurations(operationConfiguration, Configuration);
var response = await HttpClient.MakeRequestAsync("POST",
request.ConstructUrl(finalConfiguration.BasePath),
request.ConstructBody(),
request.ConstructHeaders(_accessToken, finalConfiguration),
finalConfiguration.RequestTimeout);
var handledResponse = ResponseHandler.HandleAsyncResponse<Lobby>(response, statusCodeToTypeMap);
return new Response<Lobby>(response, handledResponse);
}
public async Task<Response<Lobby>> JoinLobbyByIdAsync(JoinLobbyByIdRequest request,
Configuration operationConfiguration = null)
{
var statusCodeToTypeMap = new Dictionary<string, System.Type>() { { "200", typeof(Lobby) },{ "400", typeof(ErrorStatus) },{ "403", typeof(ErrorStatus) },{ "404", typeof(ErrorStatus) },{ "409", typeof(ErrorStatus) } };
// Merge the operation/request level configuration with the client level configuration.
var finalConfiguration = Configuration.MergeConfigurations(operationConfiguration, Configuration);
var response = await HttpClient.MakeRequestAsync("POST",
request.ConstructUrl(finalConfiguration.BasePath),
request.ConstructBody(),
request.ConstructHeaders(_accessToken, finalConfiguration),
finalConfiguration.RequestTimeout);
var handledResponse = ResponseHandler.HandleAsyncResponse<Lobby>(response, statusCodeToTypeMap);
return new Response<Lobby>(response, handledResponse);
}
public async Task<Response<QueryResponse>> QueryLobbiesAsync(QueryLobbiesRequest request,
Configuration operationConfiguration = null)
{
var statusCodeToTypeMap = new Dictionary<string, System.Type>() { { "200", typeof(QueryResponse) },{ "400", typeof(ErrorStatus) },{ "403", typeof(ErrorStatus) } };
// Merge the operation/request level configuration with the client level configuration.
var finalConfiguration = Configuration.MergeConfigurations(operationConfiguration, Configuration);
var response = await HttpClient.MakeRequestAsync("POST",
request.ConstructUrl(finalConfiguration.BasePath),
request.ConstructBody(),
request.ConstructHeaders(_accessToken, finalConfiguration),
finalConfiguration.RequestTimeout);
var handledResponse = ResponseHandler.HandleAsyncResponse<QueryResponse>(response, statusCodeToTypeMap);
return new Response<QueryResponse>(response, handledResponse);
}
public async Task<Response<Lobby>> QuickJoinLobbyAsync(QuickJoinLobbyRequest request,
Configuration operationConfiguration = null)
{
var statusCodeToTypeMap = new Dictionary<string, System.Type>() { { "200", typeof(Lobby) },{ "400", typeof(ErrorStatus) },{ "403", typeof(ErrorStatus) },{ "404", typeof(ErrorStatus) },{ "409", typeof(ErrorStatus) } };
// Merge the operation/request level configuration with the client level configuration.
var finalConfiguration = Configuration.MergeConfigurations(operationConfiguration, Configuration);
var response = await HttpClient.MakeRequestAsync("POST",
request.ConstructUrl(finalConfiguration.BasePath),
request.ConstructBody(),
request.ConstructHeaders(_accessToken, finalConfiguration),
finalConfiguration.RequestTimeout);
var handledResponse = ResponseHandler.HandleAsyncResponse<Lobby>(response, statusCodeToTypeMap);
return new Response<Lobby>(response, handledResponse);
}
public async Task<Response> RemovePlayerAsync(RemovePlayerRequest request,
Configuration operationConfiguration = null)
{
var statusCodeToTypeMap = new Dictionary<string, System.Type>() { { "204", null },{ "400", typeof(ErrorStatus) },{ "403", typeof(ErrorStatus) },{ "404", typeof(ErrorStatus) } };
// Merge the operation/request level configuration with the client level configuration.
var finalConfiguration = Configuration.MergeConfigurations(operationConfiguration, Configuration);
var response = await HttpClient.MakeRequestAsync("DELETE",
request.ConstructUrl(finalConfiguration.BasePath),
request.ConstructBody(),
request.ConstructHeaders(_accessToken, finalConfiguration),
finalConfiguration.RequestTimeout);
ResponseHandler.HandleAsyncResponse(response, statusCodeToTypeMap);
return new Response(response);
}
public async Task<Response<Lobby>> UpdateLobbyAsync(UpdateLobbyRequest request,
Configuration operationConfiguration = null)
{
var statusCodeToTypeMap = new Dictionary<string, System.Type>() { { "200", typeof(Lobby) },{ "400", typeof(ErrorStatus) },{ "403", typeof(ErrorStatus) },{ "404", typeof(ErrorStatus) } };
// Merge the operation/request level configuration with the client level configuration.
var finalConfiguration = Configuration.MergeConfigurations(operationConfiguration, Configuration);
var response = await HttpClient.MakeRequestAsync("POST",
request.ConstructUrl(finalConfiguration.BasePath),
request.ConstructBody(),
request.ConstructHeaders(_accessToken, finalConfiguration),
finalConfiguration.RequestTimeout);
var handledResponse = ResponseHandler.HandleAsyncResponse<Lobby>(response, statusCodeToTypeMap);
return new Response<Lobby>(response, handledResponse);
}
public async Task<Response<Lobby>> UpdatePlayerAsync(UpdatePlayerRequest request,
Configuration operationConfiguration = null)
{
var statusCodeToTypeMap = new Dictionary<string, System.Type>() { { "200", typeof(Lobby) },{ "400", typeof(ErrorStatus) },{ "403", typeof(ErrorStatus) },{ "404", typeof(ErrorStatus) } };
// Merge the operation/request level configuration with the client level configuration.
var finalConfiguration = Configuration.MergeConfigurations(operationConfiguration, Configuration);
var response = await HttpClient.MakeRequestAsync("POST",
request.ConstructUrl(finalConfiguration.BasePath),
request.ConstructBody(),
request.ConstructHeaders(_accessToken, finalConfiguration),
finalConfiguration.RequestTimeout);
var handledResponse = ResponseHandler.HandleAsyncResponse<Lobby>(response, statusCodeToTypeMap);
return new Response<Lobby>(response, handledResponse);
}
}
}

11
Packages/com.unity.services.lobby/Runtime/Apis/LobbyApi.cs.meta


fileFormatVersion: 2
guid: c7af8c5a320294bc1af77f2e55c05745
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

975
Packages/com.unity.services.lobby/Runtime/Apis/LobbyApiRequests.cs


using System.Collections.Generic;
using UnityEngine.Scripting;
using System.Text;
using System.Text.RegularExpressions;
using Newtonsoft.Json;
using Unity.Services.Lobbies.Http;
using UnityEngine;
using UnityEngine.Networking;
using Unity.Services.Lobbies.Models;
using Unity.Services.Authentication;
namespace Unity.Services.Lobbies
{
internal static class JsonSerialization
{
public static byte[] Serialize<T>(T obj)
{
return Encoding.UTF8.GetBytes(SerializeToString(obj));
}
public static string SerializeToString<T>(T obj)
{
return JsonConvert.SerializeObject(obj);
}
}
[Preserve]
public class LobbyApiBaseRequest
{
[Preserve]
public List<string> AddParamsToQueryParams(List<string> queryParams, string key, string value)
{
key = UnityWebRequest.EscapeURL(key);
value = UnityWebRequest.EscapeURL(value);
queryParams.Add($"{key}={value}");
return queryParams;
}
[Preserve]
public List<string> AddParamsToQueryParams(List<string> queryParams, string key, List<string> values)
{
foreach(var value in values)
{
string escapedValue = UnityWebRequest.EscapeURL(value);
queryParams.Add($"{UnityWebRequest.EscapeURL(key)}[]={escapedValue}");
}
return queryParams;
}
[Preserve]
public List<string> AddParamsToQueryParams<T>(List<string> queryParams, string key, T value)
{
key = UnityWebRequest.EscapeURL(key);
string valueString = UnityWebRequest.EscapeURL(value.ToString());
queryParams.Add($"{key}={valueString}");
return queryParams;
}
public byte[] ConstructBody(System.IO.Stream stream)
{
if (stream != null)
{
using (System.IO.MemoryStream ms = new System.IO.MemoryStream())
{
stream.CopyTo(ms);
return ms.ToArray();
}
}
return null;
}
public byte[] ConstructBody(string s)
{
return System.Text.Encoding.UTF8.GetBytes(s);
}
public byte[] ConstructBody(object o)
{
return JsonSerialization.Serialize(o);
}
public string GenerateAcceptHeader(string[] accepts)
{
if (accepts.Length == 0)
{
return null;
}
for (int i = 0; i < accepts.Length; ++i)
{
if (string.Equals(accepts[i], "application/json", System.StringComparison.OrdinalIgnoreCase))
{
return "application/json";
}
}
return string.Join(", ", accepts);
}
private static readonly Regex JsonRegex = new Regex(@"application\/json(;\s)?((charset=utf8|q=[0-1]\.\d)(\s)?)*");
public string GenerateContentTypeHeader(string[] contentTypes)
{
if (contentTypes.Length == 0)
{
return null;
}
for(int i = 0; i < contentTypes.Length; ++i)
{
if (!string.IsNullOrWhiteSpace(contentTypes[i]) && JsonRegex.IsMatch(contentTypes[i]))
{
return contentTypes[i];
}
}
return contentTypes[0];
}
public IMultipartFormSection GenerateMultipartFormFileSection(string paramName, System.IO.Stream stream, string contentType)
{
if (stream is System.IO.FileStream)
{
System.IO.FileStream fileStream = (System.IO.FileStream) stream;
return new MultipartFormFileSection(paramName, ConstructBody(fileStream), GetFileName(fileStream.Name), contentType);
}
return new MultipartFormDataSection(paramName, ConstructBody(stream));
}
private string GetFileName(string filePath)
{
return System.IO.Path.GetFileName(filePath);
}
}
[Preserve]
public class CreateLobbyRequest : LobbyApiBaseRequest
{
[Preserve]
public CreateRequest CreateRequest { get; }
string PathAndQueryParams;
/// <summary>
/// CreateLobby Request Object.
/// Create a lobby
/// </summary>
/// <param name="CreateRequest">CreateRequest param</param>
/// <returns>A CreateLobby request object.</returns>
[Preserve]
public CreateLobbyRequest(CreateRequest createRequest = default(CreateRequest))
{
CreateRequest = createRequest;
PathAndQueryParams = $"/create";
List<string> queryParams = new List<string>();
if (queryParams.Count > 0)
{
PathAndQueryParams = $"{PathAndQueryParams}?{string.Join("&", queryParams)}";
}
}
public string ConstructUrl(string requestBasePath)
{
return requestBasePath + PathAndQueryParams;
}
public byte[] ConstructBody()
{
if(CreateRequest != null)
{
return ConstructBody(CreateRequest);
}
return null;
}
public Dictionary<string, string> ConstructHeaders(IAccessToken accessToken,
Configuration operationConfiguration = null)
{
var headers = new Dictionary<string, string>();
if(!string.IsNullOrEmpty(accessToken.AccessToken))
{
headers.Add("authorization", "Bearer " + accessToken.AccessToken);
}
string[] contentTypes = {
"application/json"
};
string[] accepts = {
"application/json",
"application/problem+json"
};
var acceptHeader = GenerateAcceptHeader(accepts);
if (!string.IsNullOrEmpty(acceptHeader))
{
headers.Add("Accept", acceptHeader);
}
var contentTypeHeader = GenerateContentTypeHeader(contentTypes);
if (!string.IsNullOrEmpty(contentTypeHeader))
{
headers.Add("Content-Type", contentTypeHeader);
}
// We also check if there are headers that are defined as part of
// the request configuration.
if (operationConfiguration != null && operationConfiguration.Headers != null)
{
foreach (var pair in operationConfiguration.Headers)
{
headers[pair.Key] = pair.Value;
}
}
return headers;
}
}
[Preserve]
public class DeleteLobbyRequest : LobbyApiBaseRequest
{
[Preserve]
public string LobbyId { get; }
string PathAndQueryParams;
/// <summary>
/// DeleteLobby Request Object.
/// Delete a lobby
/// </summary>
/// <param name="lobbyId">The id of the lobby to execute the request against.</param>
/// <returns>A DeleteLobby request object.</returns>
[Preserve]
public DeleteLobbyRequest(string lobbyId)
{
LobbyId = lobbyId;
PathAndQueryParams = $"/{lobbyId}";
List<string> queryParams = new List<string>();
if (queryParams.Count > 0)
{
PathAndQueryParams = $"{PathAndQueryParams}?{string.Join("&", queryParams)}";
}
}
public string ConstructUrl(string requestBasePath)
{
return requestBasePath + PathAndQueryParams;
}
public byte[] ConstructBody()
{
return null;
}
public Dictionary<string, string> ConstructHeaders(IAccessToken accessToken,
Configuration operationConfiguration = null)
{
var headers = new Dictionary<string, string>();
if(!string.IsNullOrEmpty(accessToken.AccessToken))
{
headers.Add("authorization", "Bearer " + accessToken.AccessToken);
}
string[] contentTypes = {
};
string[] accepts = {
"application/problem+json"
};
var acceptHeader = GenerateAcceptHeader(accepts);
if (!string.IsNullOrEmpty(acceptHeader))
{
headers.Add("Accept", acceptHeader);
}
var contentTypeHeader = GenerateContentTypeHeader(contentTypes);
if (!string.IsNullOrEmpty(contentTypeHeader))
{
headers.Add("Content-Type", contentTypeHeader);
}
// We also check if there are headers that are defined as part of
// the request configuration.
if (operationConfiguration != null && operationConfiguration.Headers != null)
{
foreach (var pair in operationConfiguration.Headers)
{
headers[pair.Key] = pair.Value;
}
}
return headers;
}
}
[Preserve]
public class GetLobbyRequest : LobbyApiBaseRequest
{
[Preserve]
public string LobbyId { get; }
string PathAndQueryParams;
/// <summary>
/// GetLobby Request Object.
/// Get lobby details
/// </summary>
/// <param name="lobbyId">The id of the lobby to execute the request against.</param>
/// <returns>A GetLobby request object.</returns>
[Preserve]
public GetLobbyRequest(string lobbyId)
{
LobbyId = lobbyId;
PathAndQueryParams = $"/{lobbyId}";
List<string> queryParams = new List<string>();
if (queryParams.Count > 0)
{
PathAndQueryParams = $"{PathAndQueryParams}?{string.Join("&", queryParams)}";
}
}
public string ConstructUrl(string requestBasePath)
{
return requestBasePath + PathAndQueryParams;
}
public byte[] ConstructBody()
{
return null;
}
public Dictionary<string, string> ConstructHeaders(IAccessToken accessToken,
Configuration operationConfiguration = null)
{
var headers = new Dictionary<string, string>();
if(!string.IsNullOrEmpty(accessToken.AccessToken))
{
headers.Add("authorization", "Bearer " + accessToken.AccessToken);
}
string[] contentTypes = {
};
string[] accepts = {
"application/json",
"application/problem+json"
};
var acceptHeader = GenerateAcceptHeader(accepts);
if (!string.IsNullOrEmpty(acceptHeader))
{
headers.Add("Accept", acceptHeader);
}
var contentTypeHeader = GenerateContentTypeHeader(contentTypes);
if (!string.IsNullOrEmpty(contentTypeHeader))
{
headers.Add("Content-Type", contentTypeHeader);
}
// We also check if there are headers that are defined as part of
// the request configuration.
if (operationConfiguration != null && operationConfiguration.Headers != null)
{
foreach (var pair in operationConfiguration.Headers)
{
headers[pair.Key] = pair.Value;
}
}
return headers;
}
}
[Preserve]
public class JoinLobbyByCodeRequest : LobbyApiBaseRequest
{
[Preserve]
public JoinByCodeRequest JoinByCodeRequest { get; }
string PathAndQueryParams;
/// <summary>
/// JoinLobbyByCode Request Object.
/// Join a lobby with lobby code
/// </summary>
/// <param name="JoinByCodeRequest">JoinByCodeRequest param</param>
/// <returns>A JoinLobbyByCode request object.</returns>
[Preserve]
public JoinLobbyByCodeRequest(JoinByCodeRequest joinByCodeRequest = default(JoinByCodeRequest))
{
JoinByCodeRequest = joinByCodeRequest;
PathAndQueryParams = $"/joinbycode";
List<string> queryParams = new List<string>();
if (queryParams.Count > 0)
{
PathAndQueryParams = $"{PathAndQueryParams}?{string.Join("&", queryParams)}";
}
}
public string ConstructUrl(string requestBasePath)
{
return requestBasePath + PathAndQueryParams;
}
public byte[] ConstructBody()
{
if(JoinByCodeRequest != null)
{
return ConstructBody(JoinByCodeRequest);
}
return null;
}
public Dictionary<string, string> ConstructHeaders(IAccessToken accessToken,
Configuration operationConfiguration = null)
{
var headers = new Dictionary<string, string>();
if(!string.IsNullOrEmpty(accessToken.AccessToken))
{
headers.Add("authorization", "Bearer " + accessToken.AccessToken);
}
string[] contentTypes = {
"application/json"
};
string[] accepts = {
"application/json",
"application/problem+json"
};
var acceptHeader = GenerateAcceptHeader(accepts);
if (!string.IsNullOrEmpty(acceptHeader))
{
headers.Add("Accept", acceptHeader);
}
var contentTypeHeader = GenerateContentTypeHeader(contentTypes);
if (!string.IsNullOrEmpty(contentTypeHeader))
{
headers.Add("Content-Type", contentTypeHeader);
}
// We also check if there are headers that are defined as part of
// the request configuration.
if (operationConfiguration != null && operationConfiguration.Headers != null)
{
foreach (var pair in operationConfiguration.Headers)
{
headers[pair.Key] = pair.Value;
}
}
return headers;
}
}
[Preserve]
public class JoinLobbyByIdRequest : LobbyApiBaseRequest
{
[Preserve]
public string LobbyId { get; }
[Preserve]
public Player Player { get; }
string PathAndQueryParams;
/// <summary>
/// JoinLobbyById Request Object.
/// Join a lobby with lobby ID
/// </summary>
/// <param name="lobbyId">The id of the lobby to execute the request against.</param>
/// <param name="Player">Player param</param>
/// <returns>A JoinLobbyById request object.</returns>
[Preserve]
public JoinLobbyByIdRequest(string lobbyId, Player player = default(Player))
{
LobbyId = lobbyId;
Player = player;
PathAndQueryParams = $"/{lobbyId}/join";
List<string> queryParams = new List<string>();
if (queryParams.Count > 0)
{
PathAndQueryParams = $"{PathAndQueryParams}?{string.Join("&", queryParams)}";
}
}
public string ConstructUrl(string requestBasePath)
{
return requestBasePath + PathAndQueryParams;
}
public byte[] ConstructBody()
{
if(Player != null)
{
return ConstructBody(Player);
}
return null;
}
public Dictionary<string, string> ConstructHeaders(IAccessToken accessToken,
Configuration operationConfiguration = null)
{
var headers = new Dictionary<string, string>();
if(!string.IsNullOrEmpty(accessToken.AccessToken))
{
headers.Add("authorization", "Bearer " + accessToken.AccessToken);
}
string[] contentTypes = {
"application/json"
};
string[] accepts = {
"application/json",
"application/problem+json"
};
var acceptHeader = GenerateAcceptHeader(accepts);
if (!string.IsNullOrEmpty(acceptHeader))
{
headers.Add("Accept", acceptHeader);
}
var contentTypeHeader = GenerateContentTypeHeader(contentTypes);
if (!string.IsNullOrEmpty(contentTypeHeader))
{
headers.Add("Content-Type", contentTypeHeader);
}
// We also check if there are headers that are defined as part of
// the request configuration.
if (operationConfiguration != null && operationConfiguration.Headers != null)
{
foreach (var pair in operationConfiguration.Headers)
{
headers[pair.Key] = pair.Value;
}
}
return headers;
}
}
[Preserve]
public class QueryLobbiesRequest : LobbyApiBaseRequest
{
[Preserve]
public QueryRequest QueryRequest { get; }
string PathAndQueryParams;
/// <summary>
/// QueryLobbies Request Object.
/// Query public lobbies
/// </summary>
/// <param name="QueryRequest">QueryRequest param</param>
/// <returns>A QueryLobbies request object.</returns>
[Preserve]
public QueryLobbiesRequest(QueryRequest queryRequest = default(QueryRequest))
{
QueryRequest = queryRequest;
PathAndQueryParams = $"/query";
List<string> queryParams = new List<string>();
if (queryParams.Count > 0)
{
PathAndQueryParams = $"{PathAndQueryParams}?{string.Join("&", queryParams)}";
}
}
public string ConstructUrl(string requestBasePath)
{
return requestBasePath + PathAndQueryParams;
}
public byte[] ConstructBody()
{
if(QueryRequest != null)
{
return ConstructBody(QueryRequest);
}
return null;
}
public Dictionary<string, string> ConstructHeaders(IAccessToken accessToken,
Configuration operationConfiguration = null)
{
var headers = new Dictionary<string, string>();
if(!string.IsNullOrEmpty(accessToken.AccessToken))
{
headers.Add("authorization", "Bearer " + accessToken.AccessToken);
}
string[] contentTypes = {
"application/json"
};
string[] accepts = {
"application/json",
"application/problem+json"
};
var acceptHeader = GenerateAcceptHeader(accepts);
if (!string.IsNullOrEmpty(acceptHeader))
{
headers.Add("Accept", acceptHeader);
}
var contentTypeHeader = GenerateContentTypeHeader(contentTypes);
if (!string.IsNullOrEmpty(contentTypeHeader))
{
headers.Add("Content-Type", contentTypeHeader);
}
// We also check if there are headers that are defined as part of
// the request configuration.
if (operationConfiguration != null && operationConfiguration.Headers != null)
{
foreach (var pair in operationConfiguration.Headers)
{
headers[pair.Key] = pair.Value;
}
}
return headers;
}
}
[Preserve]
public class QuickJoinLobbyRequest : LobbyApiBaseRequest
{
[Preserve]
public QuickJoinRequest QuickJoinRequest { get; }
string PathAndQueryParams;
/// <summary>
/// QuickJoinLobby Request Object.
/// Query available lobbies and join a random one
/// </summary>
/// <param name="QuickJoinRequest">QuickJoinRequest param</param>
/// <returns>A QuickJoinLobby request object.</returns>
[Preserve]
public QuickJoinLobbyRequest(QuickJoinRequest quickJoinRequest = default(QuickJoinRequest))
{
QuickJoinRequest = quickJoinRequest;
PathAndQueryParams = $"/quickjoin";
List<string> queryParams = new List<string>();
if (queryParams.Count > 0)
{
PathAndQueryParams = $"{PathAndQueryParams}?{string.Join("&", queryParams)}";
}
}
public string ConstructUrl(string requestBasePath)
{
return requestBasePath + PathAndQueryParams;
}
public byte[] ConstructBody()
{
if(QuickJoinRequest != null)
{
return ConstructBody(QuickJoinRequest);
}
return null;
}
public Dictionary<string, string> ConstructHeaders(IAccessToken accessToken,
Configuration operationConfiguration = null)
{
var headers = new Dictionary<string, string>();
if(!string.IsNullOrEmpty(accessToken.AccessToken))
{
headers.Add("authorization", "Bearer " + accessToken.AccessToken);
}
string[] contentTypes = {
"application/json"
};
string[] accepts = {
"application/json",
"application/problem+json"
};
var acceptHeader = GenerateAcceptHeader(accepts);
if (!string.IsNullOrEmpty(acceptHeader))
{
headers.Add("Accept", acceptHeader);
}
var contentTypeHeader = GenerateContentTypeHeader(contentTypes);
if (!string.IsNullOrEmpty(contentTypeHeader))
{
headers.Add("Content-Type", contentTypeHeader);
}
// We also check if there are headers that are defined as part of
// the request configuration.
if (operationConfiguration != null && operationConfiguration.Headers != null)
{
foreach (var pair in operationConfiguration.Headers)
{
headers[pair.Key] = pair.Value;
}
}
return headers;
}
}
[Preserve]
public class RemovePlayerRequest : LobbyApiBaseRequest
{
[Preserve]
public string LobbyId { get; }
[Preserve]
public string PlayerId { get; }
string PathAndQueryParams;
/// <summary>
/// RemovePlayer Request Object.
/// Remove a player
/// </summary>
/// <param name="lobbyId">The id of the lobby to execute the request against.</param>
/// <param name="playerId">The id of the player to execute the request against.</param>
/// <returns>A RemovePlayer request object.</returns>
[Preserve]
public RemovePlayerRequest(string lobbyId, string playerId)
{
LobbyId = lobbyId;
PlayerId = playerId;
PathAndQueryParams = $"/{lobbyId}/players/{playerId}";
List<string> queryParams = new List<string>();
if (queryParams.Count > 0)
{
PathAndQueryParams = $"{PathAndQueryParams}?{string.Join("&", queryParams)}";
}
}
public string ConstructUrl(string requestBasePath)
{
return requestBasePath + PathAndQueryParams;
}
public byte[] ConstructBody()
{
return null;
}
public Dictionary<string, string> ConstructHeaders(IAccessToken accessToken,
Configuration operationConfiguration = null)
{
var headers = new Dictionary<string, string>();
if(!string.IsNullOrEmpty(accessToken.AccessToken))
{
headers.Add("authorization", "Bearer " + accessToken.AccessToken);
}
string[] contentTypes = {
};
string[] accepts = {
"application/problem+json"
};
var acceptHeader = GenerateAcceptHeader(accepts);
if (!string.IsNullOrEmpty(acceptHeader))
{
headers.Add("Accept", acceptHeader);
}
var contentTypeHeader = GenerateContentTypeHeader(contentTypes);
if (!string.IsNullOrEmpty(contentTypeHeader))
{
headers.Add("Content-Type", contentTypeHeader);
}
// We also check if there are headers that are defined as part of
// the request configuration.
if (operationConfiguration != null && operationConfiguration.Headers != null)
{
foreach (var pair in operationConfiguration.Headers)
{
headers[pair.Key] = pair.Value;
}
}
return headers;
}
}
[Preserve]
public class UpdateLobbyRequest : LobbyApiBaseRequest
{
[Preserve]
public string LobbyId { get; }
[Preserve]
public UpdateRequest UpdateRequest { get; }
string PathAndQueryParams;
/// <summary>
/// UpdateLobby Request Object.
/// Update lobby data
/// </summary>
/// <param name="lobbyId">The id of the lobby to execute the request against.</param>
/// <param name="UpdateRequest">UpdateRequest param</param>
/// <returns>A UpdateLobby request object.</returns>
[Preserve]
public UpdateLobbyRequest(string lobbyId, UpdateRequest updateRequest = default(UpdateRequest))
{
LobbyId = lobbyId;
UpdateRequest = updateRequest;
PathAndQueryParams = $"/{lobbyId}";
List<string> queryParams = new List<string>();
if (queryParams.Count > 0)
{
PathAndQueryParams = $"{PathAndQueryParams}?{string.Join("&", queryParams)}";
}
}
public string ConstructUrl(string requestBasePath)
{
return requestBasePath + PathAndQueryParams;
}
public byte[] ConstructBody()
{
if(UpdateRequest != null)
{
return ConstructBody(UpdateRequest);
}
return null;
}
public Dictionary<string, string> ConstructHeaders(IAccessToken accessToken,
Configuration operationConfiguration = null)
{
var headers = new Dictionary<string, string>();
if(!string.IsNullOrEmpty(accessToken.AccessToken))
{
headers.Add("authorization", "Bearer " + accessToken.AccessToken);
}
string[] contentTypes = {
"application/json"
};
string[] accepts = {
"application/json",
"application/problem+json"
};
var acceptHeader = GenerateAcceptHeader(accepts);
if (!string.IsNullOrEmpty(acceptHeader))
{
headers.Add("Accept", acceptHeader);
}
var contentTypeHeader = GenerateContentTypeHeader(contentTypes);
if (!string.IsNullOrEmpty(contentTypeHeader))
{
headers.Add("Content-Type", contentTypeHeader);
}
// We also check if there are headers that are defined as part of
// the request configuration.
if (operationConfiguration != null && operationConfiguration.Headers != null)
{
foreach (var pair in operationConfiguration.Headers)
{
headers[pair.Key] = pair.Value;
}
}
return headers;
}
}
[Preserve]
public class UpdatePlayerRequest : LobbyApiBaseRequest
{
[Preserve]
public string LobbyId { get; }
[Preserve]
public string PlayerId { get; }
[Preserve]
public PlayerUpdateRequest PlayerUpdateRequest { get; }
string PathAndQueryParams;
/// <summary>
/// UpdatePlayer Request Object.
/// Update player data
/// </summary>
/// <param name="lobbyId">The id of the lobby to execute the request against.</param>
/// <param name="playerId">The id of the player to execute the request against.</param>
/// <param name="PlayerUpdateRequest">PlayerUpdateRequest param</param>
/// <returns>A UpdatePlayer request object.</returns>
[Preserve]
public UpdatePlayerRequest(string lobbyId, string playerId, PlayerUpdateRequest playerUpdateRequest = default(PlayerUpdateRequest))
{
LobbyId = lobbyId;
PlayerId = playerId;
PlayerUpdateRequest = playerUpdateRequest;
PathAndQueryParams = $"/{lobbyId}/players/{playerId}";
List<string> queryParams = new List<string>();
if (queryParams.Count > 0)
{
PathAndQueryParams = $"{PathAndQueryParams}?{string.Join("&", queryParams)}";
}
}
public string ConstructUrl(string requestBasePath)
{
return requestBasePath + PathAndQueryParams;
}
public byte[] ConstructBody()
{
if(PlayerUpdateRequest != null)
{
return ConstructBody(PlayerUpdateRequest);
}
return null;
}
public Dictionary<string, string> ConstructHeaders(IAccessToken accessToken,
Configuration operationConfiguration = null)
{
var headers = new Dictionary<string, string>();
if(!string.IsNullOrEmpty(accessToken.AccessToken))
{
headers.Add("authorization", "Bearer " + accessToken.AccessToken);
}
string[] contentTypes = {
"application/json"
};
string[] accepts = {
"application/json",
"application/problem+json"
};
var acceptHeader = GenerateAcceptHeader(accepts);
if (!string.IsNullOrEmpty(acceptHeader))
{
headers.Add("Accept", acceptHeader);
}
var contentTypeHeader = GenerateContentTypeHeader(contentTypes);
if (!string.IsNullOrEmpty(contentTypeHeader))
{
headers.Add("Content-Type", contentTypeHeader);
}
// We also check if there are headers that are defined as part of
// the request configuration.
if (operationConfiguration != null && operationConfiguration.Headers != null)
{
foreach (var pair in operationConfiguration.Headers)
{
headers[pair.Key] = pair.Value;
}
}
return headers;
}
}
}

11
Packages/com.unity.services.lobby/Runtime/Apis/LobbyApiRequests.cs.meta


fileFormatVersion: 2
guid: 64b9cb702300a4c4daaba9fbaf481895
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

8
Packages/com.unity.services.lobby/Runtime/Configuration.meta


fileFormatVersion: 2
guid: 8378769f08eee49db8d248bce33da040
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

69
Packages/com.unity.services.lobby/Runtime/Configuration/Configuration.cs


using System.Collections.Generic;
namespace Unity.Services.Lobbies
{
/// <summary>
/// Represents a set of configuration settings
/// </summary>
public class Configuration
{
public string BasePath;
public int RequestTimeout;
public int NumberOfRetries;
public IDictionary<string, string> Headers;
public Configuration(string basePath, int requestTimeout, int numRetries, IDictionary<string, string> headers)
{
BasePath = basePath;
RequestTimeout = requestTimeout;
NumberOfRetries = numRetries;
Headers = headers;
}
// Helper function for merging two configurations. Configuration `a` is
// considered the base configuration if it is a valid object. Certain
// values will be overridden if they are set to null within this
// configuration by configuration `b` and the headers will be merged.
public static Configuration MergeConfigurations(Configuration a, Configuration b)
{
// Check if either inputs are `null`, if they are, we return
// whichever is not `null`, if both are `null`, we return `b` which
// will be `null`.
if(a == null || b == null)
{
return a ?? b;
}
Configuration mergedConfig = a;
if(mergedConfig.BasePath == null)
{
mergedConfig.BasePath = b.BasePath;
}
var headers = new Dictionary<string, string>();
if (b.Headers != null)
{
foreach (var pair in b.Headers)
{
headers[pair.Key] = pair.Value;
}
}
if (mergedConfig.Headers != null)
{
foreach (var pair in mergedConfig.Headers)
{
headers[pair.Key] = pair.Value;
}
}
mergedConfig.Headers = headers;
return mergedConfig;
}
}
}

11
Packages/com.unity.services.lobby/Runtime/Configuration/Configuration.cs.meta


fileFormatVersion: 2
guid: 9988cff83b7ea44829092d70024c5abb
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

8
Packages/com.unity.services.lobby/Runtime/Http.meta


fileFormatVersion: 2
guid: cf706965f45104f979462ef65d1f4db8
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

109
Packages/com.unity.services.lobby/Runtime/Http/AsyncOpRetry.cs


using System;
using System.Collections;
using UnityEngine;
namespace Unity.Services.Lobbies.Helpers
{
internal static class AsyncOpRetry
{
public static AsyncOpRetry<T> FromCreateAsync<T>(Func<int, T> op)
{
return AsyncOpRetry<T>.FromCreateAsync(op);
}
}
internal class AsyncOpRetry<T>
{
private uint MaxRetries { get; set; } = 4;
private float JitterMagnitude { get; set; } = 1.0f;
private float DelayScale { get; set; } = 1.0f;
private float MaxDelayTime { get; set; } = 8.0f;
private Func<int, T> CreateOperation { get; set; }
private Func<T, bool> RetryCondition { get; set; }
private Action<T> OnComplete { get; set; }
private AsyncOpRetry(Func<int, T> createAsyncOp)
{
CreateOperation = createAsyncOp;
}
private static float AddJitter(float number, float magnitude)
{
return number + (UnityEngine.Random.value * magnitude);
}
private static float Pow2(float exponent, float scale)
{
return (float) (Math.Pow(2.0f, exponent) * scale);
}
private static float CalculateDelay(int attemptNumber, float maxDelayTime, float delayScale,
float jitterMagnitude)
{
float delayTime = Pow2(attemptNumber, delayScale);
delayTime = AddJitter(delayTime, jitterMagnitude);
delayTime = Math.Min(delayTime, maxDelayTime);
return delayTime;
}
public AsyncOpRetry<T> WithJitterMagnitude(float magnitude)
{
JitterMagnitude = Mathf.Clamp(magnitude, 0.001f, 1.0f);
return this;
}
public AsyncOpRetry<T> WithDelayScale(float scale)
{
DelayScale = Mathf.Clamp(scale, 0.05f, 1.0f);
return this;
}
public AsyncOpRetry<T> WithMaxDelayTime(float time)
{
MaxDelayTime = Mathf.Clamp(time, 0.1f, 60.0f);
return this;
}
public static AsyncOpRetry<T> FromCreateAsync(Func<int, T> op)
{
return new AsyncOpRetry<T>(op);
}
public AsyncOpRetry<T> WithRetryCondition(Func<T, bool> shouldRetry)
{
RetryCondition = shouldRetry;
return this;
}
public AsyncOpRetry<T> WhenComplete(Action<T> onComplete)
{
OnComplete = onComplete;
return this;
}
public AsyncOpRetry<T> UptoMaximumRetries(uint amount)
{
MaxRetries = amount;
return this;
}
public IEnumerator Run()
{
T asyncOp = default;
for (var attempt = 0; attempt <= MaxRetries; ++attempt)
{
asyncOp = CreateOperation(attempt + 1);
yield return asyncOp;
if ((!RetryCondition?.Invoke(asyncOp) ?? false))
{
break;
}
var delayTime = CalculateDelay(attempt, MaxDelayTime, DelayScale, JitterMagnitude);
yield return new WaitForSecondsRealtime(delayTime);
}
OnComplete?.Invoke(asyncOp);
}
}
}

11
Packages/com.unity.services.lobby/Runtime/Http/AsyncOpRetry.cs.meta


fileFormatVersion: 2
guid: 37b7bcef9963d48188ca7b0038055962
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

15
Packages/com.unity.services.lobby/Runtime/Http/BaseApiClient.cs


using System;
using Unity.Services.Lobbies.Scheduler;
namespace Unity.Services.Lobbies.Http
{
public abstract class BaseApiClient
{
protected readonly IHttpClient HttpClient;
public BaseApiClient(IHttpClient httpClient, TaskScheduler scheduler)
{
HttpClient = httpClient ?? new HttpClient(scheduler);
}
}
}

11
Packages/com.unity.services.lobby/Runtime/Http/BaseApiClient.cs.meta


fileFormatVersion: 2
guid: 03b4179fd44124cd588f07100556556e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

35
Packages/com.unity.services.lobby/Runtime/Http/BasicError.cs


using Newtonsoft.Json;
using UnityEngine.Scripting;
namespace Unity.Services.Lobbies.Http
{
[Preserve]
public class BasicError: IError
{
[Preserve]
public string Type { get; }
[Preserve]
public string Title { get; }
[Preserve]
public int? Status { get; }
[Preserve]
public int Code { get; }
[Preserve]
public string Detail { get; }
[Preserve]
public BasicError(string type, string title, int? status, int code, string detail)
{
Type = type;
Title = title;
Status = status;
Code = code;
Detail = detail;
}
public override string ToString()
{
return JsonConvert.SerializeObject(this);
}
}
}

11
Packages/com.unity.services.lobby/Runtime/Http/BasicError.cs.meta


fileFormatVersion: 2
guid: f672b4837a01948d79e2e762cf3d2fcc
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

35
Packages/com.unity.services.lobby/Runtime/Http/CommonErrors.cs


namespace Unity.Services.Lobbies.Http
{
static internal class CommonErrors
{
private const string ErrorPrefix = "com.unity.services.lobby";
public static IError CreateUnspecifiedHttpError(string details)
{
return new BasicError(
$"{ErrorPrefix}http.httperror",
"Unspecified HTTP error",
null,
0,
details
);
}
public static IError RequestOnSuccessNull => new BasicError(
$"{ErrorPrefix}onsuccessnullerror",
"Request must have an onSuccess callback",
null,
0, //TODO: define a code space for SDK side errors so all errors can be identified by a code
"");
public static IError HttpNetworkError => new BasicError(
$"{ErrorPrefix}httpclient.networkerror",
"Network Error",
null,
0,
""
);
}
}

11
Packages/com.unity.services.lobby/Runtime/Http/CommonErrors.cs.meta


fileFormatVersion: 2
guid: d6100b420dfec472389e264a9e0879d4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

34
Packages/com.unity.services.lobby/Runtime/Http/DeserializationException.cs


using System;
namespace Unity.Services.Lobbies.Http
{
[Serializable]
public class DeserializationException : Exception
{
public HttpClientResponse response;
public DeserializationException() : base()
{
}
public DeserializationException(string message) : base(message)
{
}
DeserializationException(string message, Exception inner) : base(message, inner)
{
}
public DeserializationException(HttpClientResponse httpClientResponse) : base(
"Unable to Deserialize Http Client Response")
{
response = httpClientResponse;
}
public DeserializationException(HttpClientResponse httpClientResponse, string message) : base(
message)
{
response = httpClientResponse;
}
}
}

11
Packages/com.unity.services.lobby/Runtime/Http/DeserializationException.cs.meta


fileFormatVersion: 2
guid: 7794414098b5f4262a2e32e5aba969fd
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

239
Packages/com.unity.services.lobby/Runtime/Http/HttpClient.cs


using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using UnityEngine.Networking;
using System.Threading.Tasks;
using Unity.Services.Lobbies.Helpers;
using Unity.Services.Lobbies.Scheduler;
using TaskScheduler = Unity.Services.Lobbies.Scheduler.TaskScheduler;
namespace Unity.Services.Lobbies.Http
{
public class HttpClient : IHttpClient
{
private static readonly HashSet<string> DisallowedHeaders = new HashSet<string>
{
"accept-charset", "access-control-request-headers", "access-control-request-method", "connection", "date",
"dnt", "expect", "host", "keep-alive", "origin", "referer", "te", "trailer", "transfer-encoding", "upgrade",
"via", "content-length", "x-unity-version", "user-agent", "cookie", "cookie2"
};
private static readonly List<int> ErrorCodes = new List<int> {408, 500, 502, 503, 504};
private TaskScheduler _scheduler;
public HttpClient(TaskScheduler scheduler)
{
_scheduler = scheduler;
}
public void Get(string url, Dictionary<string, string> headers, Action<HttpClientResponse> onCompleted,
int requestTimeout = 10)
{
_scheduler.ScheduleMainThreadTask(() =>
{
_scheduler.StartCoroutine(ProcessRequest(UnityWebRequest.kHttpVerbGET, url, headers, null,
requestTimeout, onCompleted));
});
}
public void Delete(string url, Dictionary<string, string> headers, Action<HttpClientResponse> onCompleted,
int requestTimeout = 10)
{
_scheduler.ScheduleMainThreadTask(() =>
{
_scheduler.StartCoroutine(ProcessRequest(UnityWebRequest.kHttpVerbDELETE, url, headers, null,
requestTimeout, onCompleted));
});
}
public void Post(string url, byte[] body, Dictionary<string, string> headers,
Action<HttpClientResponse> onCompleted, int requestTimeout = 10)
{
_scheduler.ScheduleMainThreadTask(() =>
{
_scheduler.StartCoroutine(ProcessRequest(UnityWebRequest.kHttpVerbPOST, url, headers, body,
requestTimeout, onCompleted));
});
}
public void Put(string url, byte[] body, Dictionary<string, string> headers,
Action<HttpClientResponse> onCompleted, int requestTimeout = 10)
{
_scheduler.ScheduleMainThreadTask(() =>
{
_scheduler.StartCoroutine(ProcessRequest(UnityWebRequest.kHttpVerbPUT, url, headers, body,
requestTimeout, onCompleted));
});
}
public void MakeRequest(string method, string url, byte[] body, Dictionary<string, string> headers,
Action<HttpClientResponse> onCompleted, int requestTimeout = 10)
{
_scheduler.ScheduleMainThreadTask(() =>
{
_scheduler.StartCoroutine(ProcessRequest(method.ToUpper(), url, headers, body, requestTimeout,
onCompleted));
});
}
public async Task<HttpClientResponse> MakeRequestAsync(string method, string url, byte[] body,
Dictionary<string, string> headers, int requestTimeout)
{
return await CreateWebRequestAsync(method.ToUpper(), url, body, headers, requestTimeout);
}
public async Task<HttpClientResponse> MakeRequestAsync(string method, string url,
List<IMultipartFormSection> body,
Dictionary<string, string> headers, int requestTimeout, string boundary = null)
{
return await CreateWebRequestAsync(method.ToUpper(), url, body, headers, requestTimeout, boundary);
}
private IEnumerator ProcessRequest(string method, string url, IDictionary<string, string> headers, byte[] body,
int requestTimeout, Action<HttpClientResponse> onCompleted)
{
UnityWebRequestAsyncOperation SetupRequest(int attempt)
{
var webRequest = CreateWebRequest(method, url, body, headers, requestTimeout);
return webRequest.SendWebRequest();
}
bool ShouldRetry(UnityWebRequestAsyncOperation request)
{
var responseCode = (int) request.webRequest.responseCode;
return ErrorCodes.Contains(responseCode);
}
void AsyncOpCompleted(UnityWebRequestAsyncOperation request)
{
var internalResponse = UnityWebRequestHelpers.CreateHttpClientResponse(request);
onCompleted(internalResponse);
}
yield return AsyncOpRetry.FromCreateAsync(SetupRequest)
.WithRetryCondition(ShouldRetry)
.WhenComplete(AsyncOpCompleted)
.Run();
}
private UnityWebRequest CreateWebRequest(string method, string url, byte[] body,
IDictionary<string, string> headers, int requestTimeout = 10)
{
using (var request = new UnityWebRequest(url, method))
{
foreach (var header in headers)
{
if (DisallowedHeaders.Contains(header.Key.ToLower()))
{
continue;
}
request.SetRequestHeader(header.Key, header.Value);
}
request.timeout = requestTimeout;
if (body != null && (method == UnityWebRequest.kHttpVerbPOST || method == UnityWebRequest.kHttpVerbPUT ||
method == "PATCH"))
{
request.uploadHandler = new UploadHandlerRaw(body);
}
request.downloadHandler = new DownloadHandlerBuffer();
return request;
}
}
private async Task<HttpClientResponse> CreateWebRequestAsync(string method, string url, byte[] body,
IDictionary<string, string> headers, int requestTimeout)
{
var result = await await Task.Factory.StartNew(async () =>
{
using (var request = new UnityWebRequest(url, method))
{
foreach (var header in headers)
{
request.SetRequestHeader(header.Key, header.Value);
}
request.timeout = requestTimeout;
if (body != null && (method == UnityWebRequest.kHttpVerbPOST ||
method == UnityWebRequest.kHttpVerbPUT ||
method == "PATCH"))
{
request.uploadHandler = new UploadHandlerRaw(body);
}
request.downloadHandler = new DownloadHandlerBuffer();
return await request.SendWebRequest();
}
}, CancellationToken.None, TaskCreationOptions.None,
Scheduler.ThreadHelper.TaskScheduler);
return result;
}
private async Task<HttpClientResponse> CreateWebRequestAsync(string method, string url,
List<IMultipartFormSection> body,
IDictionary<string, string> headers, int requestTimeout, string boundary = null)
{
var result = await await Task.Factory.StartNew(async () =>
{
byte[] boundaryBytes = string.IsNullOrEmpty(boundary)
? UnityWebRequest.GenerateBoundary()
: Encoding.Default.GetBytes(boundary);
var request = new UnityWebRequest(url, method);
foreach (var header in headers)
{
request.SetRequestHeader(header.Key, header.Value);
}
request.timeout = requestTimeout;
request = SetupMultipartRequest(request, body, boundaryBytes);
request.downloadHandler = new DownloadHandlerBuffer();
return await request.SendWebRequest();
}, CancellationToken.None, TaskCreationOptions.None,
Scheduler.ThreadHelper.TaskScheduler);
return result;
}
private static UnityWebRequest SetupMultipartRequest(UnityWebRequest request,
List<IMultipartFormSection> multipartFormSections, byte[] boundary)
{
byte[] data = (byte[]) null;
if (multipartFormSections != null && (uint) multipartFormSections.Count > 0U)
{
data = UnityWebRequest.SerializeFormSections(multipartFormSections, boundary);
}
UploadHandler uploadHandler = (UploadHandler) new UploadHandlerRaw(data);
uploadHandler.contentType =
"multipart/form-data; boundary=" + Encoding.UTF8.GetString(boundary, 0, boundary.Length);
request.uploadHandler = uploadHandler;
request.downloadHandler = (DownloadHandler) new DownloadHandlerBuffer();
return request;
}
internal static HttpClientResponse CreateHttpClientResponse(UnityWebRequestAsyncOperation unityResponse)
{
var response = unityResponse.webRequest;
var result = new HttpClientResponse(
response.GetResponseHeaders(),
response.responseCode,
#if UNITY_2020_1_OR_NEWER
response.result == UnityWebRequest.Result.ProtocolError,
response.result == UnityWebRequest.Result.ConnectionError,
#else
response.isHttpError,
response.isNetworkError,
#endif
response.downloadHandler.data,
response.error);
return result;
}
}
}

11
Packages/com.unity.services.lobby/Runtime/Http/HttpClient.cs.meta


fileFormatVersion: 2
guid: dbca5ac37bded4161be07ed40f927cf4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

26
Packages/com.unity.services.lobby/Runtime/Http/HttpClientResponse.cs


using System;
using System.Collections;
using System.Collections.Generic;
namespace Unity.Services.Lobbies.Http
{
public class HttpClientResponse
{
public HttpClientResponse(Dictionary<string, string> headers, long statusCode, bool isHttpError, bool isNetworkError, byte[] data, string errorMessage)
{
Headers = headers;
StatusCode = statusCode;
IsHttpError = isHttpError;
IsNetworkError = isNetworkError;
Data = data;
ErrorMessage = errorMessage;
}
public Dictionary<string, string> Headers { get; }
public long StatusCode { get; }
public bool IsHttpError { get; }
public bool IsNetworkError { get; }
public byte[] Data { get;}
public string ErrorMessage { get; }
}
}

11
Packages/com.unity.services.lobby/Runtime/Http/HttpClientResponse.cs.meta


fileFormatVersion: 2
guid: a4910ef67265c45e5ac52936c11bf247
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

51
Packages/com.unity.services.lobby/Runtime/Http/HttpException.cs


using System;
using Unity.Services.Lobbies;
namespace Unity.Services.Lobbies.Http
{
[Serializable]
public class HttpException : Exception
{
public HttpClientResponse Response;
public HttpException() : base()
{
}
public HttpException(string message) : base(message)
{
}
public HttpException(string message, Exception inner) : base(message, inner)
{
}
public HttpException(HttpClientResponse response) : base(response.ErrorMessage)
{
Response = response;
}
}
[Serializable]
public class HttpException<T> : HttpException
{
public T ActualError;
public HttpException() : base()
{
}
public HttpException(string message) : base(message)
{
}
public HttpException(string message, Exception inner) : base(message, inner)
{
}
public HttpException(HttpClientResponse response, T actualError) : base(response)
{
ActualError = actualError;
}
}
}

11
Packages/com.unity.services.lobby/Runtime/Http/HttpException.cs.meta


fileFormatVersion: 2
guid: 58232edbf38ad44249a2514728630186
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

11
Packages/com.unity.services.lobby/Runtime/Http/IError.cs


namespace Unity.Services.Lobbies.Http
{
public interface IError
{
string Type { get; }
string Title { get; }
int? Status { get; }
int Code { get; }
string Detail { get; }
}
}

11
Packages/com.unity.services.lobby/Runtime/Http/IError.cs.meta


fileFormatVersion: 2
guid: 1da59228ebaaf46f597413704aba8f6a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

18
Packages/com.unity.services.lobby/Runtime/Http/IHttpClient.cs


using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using UnityEngine.Networking;
namespace Unity.Services.Lobbies.Http
{
public interface IHttpClient
{
void Get(string url, Dictionary<string, string> headers, Action<HttpClientResponse> onCompleted, int requestTimeout = 10);
void Delete(string url, Dictionary<string, string> headers, Action<HttpClientResponse> onCompleted, int requestTimeout = 10);
void Post(string url, byte[] body, Dictionary<string, string> headers, Action<HttpClientResponse> onCompleted, int requestTimeout = 10);
void Put(string url, byte[] body, Dictionary<string, string> headers, Action<HttpClientResponse> onCompleted, int requestTimeout = 10);
void MakeRequest(string method, string url, byte[] body, Dictionary<string, string> headers, Action<HttpClientResponse> onCompleted, int requestTimeout = 10);
Task<HttpClientResponse> MakeRequestAsync(string method, string url, byte[] body, Dictionary<string, string> headers, int requestTimeout);
Task<HttpClientResponse> MakeRequestAsync(string method, string url, List<IMultipartFormSection> body, Dictionary<string, string> headers, int requestTimeout, string boundary = null);
}
}

11
Packages/com.unity.services.lobby/Runtime/Http/IHttpClient.cs.meta


fileFormatVersion: 2
guid: 0b093dfcc222c458cbf885b998b67d67
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

32
Packages/com.unity.services.lobby/Runtime/Http/JsonHelpers.cs


using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Utilities;
using UnityEngine;
namespace Unity.Services.Lobbies.Http
{
internal static class JsonHelpers
{
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSplashScreen)]
internal static void RegisterTypesForAOT()
{
AotHelper.EnsureType<StringEnumConverter>();
}
internal static bool TryParseJson<T>(this string @this, out T result)
{
var success = true;
var settings = new JsonSerializerSettings
{
Error = (sender, args) =>
{
success = false;
args.ErrorContext.Handled = true;
},
MissingMemberHandling = MissingMemberHandling.Ignore
};
result = JsonConvert.DeserializeObject<T>(@this, settings);
return success;
}
}
}

11
Packages/com.unity.services.lobby/Runtime/Http/JsonHelpers.cs.meta


fileFormatVersion: 2
guid: 053cb354ae0a64ab491a3ef376706de8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

168
Packages/com.unity.services.lobby/Runtime/Http/ResponseHandler.cs


using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using Newtonsoft.Json;
using Unity.Services.Lobbies.Models;
namespace Unity.Services.Lobbies.Http
{
public static class ResponseHandler
{
public static T TryDeserializeResponse<T>(HttpClientResponse response)
{
var settings = new JsonSerializerSettings
{
MissingMemberHandling = MissingMemberHandling.Ignore
};
return JsonConvert.DeserializeObject<T>(GetDeserializardJson(response.Data), settings);
}
public static object TryDeserializeResponse(HttpClientResponse response, Type type)
{
var settings = new JsonSerializerSettings
{
MissingMemberHandling = MissingMemberHandling.Ignore
};
return JsonConvert.DeserializeObject(GetDeserializardJson(response.Data), type, settings);
}
private static string GetDeserializardJson(byte[] data)
{
return Encoding.UTF8.GetString(data);
}
public static void HandleAsyncResponse(HttpClientResponse response, Dictionary<string, Type> statusCodeToTypeMap)
{
if (statusCodeToTypeMap.ContainsKey(response.StatusCode.ToString()))
{
Type responseType = statusCodeToTypeMap[response.StatusCode.ToString()];
if (responseType != null && response.IsHttpError || response.IsNetworkError)
{
if (typeof(IOneOf).IsAssignableFrom(responseType))
{
var instance = CreateOneOfException(response, responseType);
throw instance;
}
else
{
var instance = CreateHttpException(response, responseType);
throw instance;
}
}
}
else
{
throw new HttpException(response);
}
}
private static HttpException CreateOneOfException(HttpClientResponse response, Type responseType)
{
try
{
var dataObject = ResponseHandler.TryDeserializeResponse(response, responseType);
return CreateHttpException(response, ((IOneOf) dataObject).Type);
}
catch (ArgumentException e)
{
throw new DeserializationException(response, e.Message);
}
catch (MissingFieldException)
{
throw new DeserializationException(response,
"Discriminator field not found in the parsed json response.");
}
catch (DeserializationException e) when (e.response == null)
{
throw new DeserializationException(response, e.Message);
}
catch (DeserializationException)
{
throw;
}
catch (Exception)
{
throw new DeserializationException(response);
}
}
private static HttpException CreateHttpException(HttpClientResponse response, Type responseType)
{
Type exceptionType = typeof(HttpException<>);
var genericException = exceptionType.MakeGenericType(responseType);
try
{
if (responseType == typeof(System.IO.Stream))
{
var streamObject = (object)(response.Data == null ? new MemoryStream() : new MemoryStream(response.Data));
var streamObjectInstance = Activator.CreateInstance(genericException, new object[] {response, streamObject});
return (HttpException) streamObjectInstance;
}
var dataObject = ResponseHandler.TryDeserializeResponse(response, responseType);
var instance = Activator.CreateInstance(genericException, new object[] {response, dataObject});
return (HttpException) instance;
}
catch (ArgumentException e)
{
throw new DeserializationException(response, e.Message);
}
catch (MissingFieldException)
{
throw new DeserializationException(response,
"Discriminator field not found in the parsed json response.");
}
catch (DeserializationException e) when (e.response == null)
{
throw new DeserializationException(response, e.Message);
}
catch (DeserializationException)
{
throw;
}
catch (Exception)
{
throw new DeserializationException(response);
}
}
public static T HandleAsyncResponse<T>(HttpClientResponse response, Dictionary<string, Type> statusCodeToTypeMap) where T : class
{
HandleAsyncResponse(response, statusCodeToTypeMap);
try
{
if (statusCodeToTypeMap[response.StatusCode.ToString()] == typeof(System.IO.Stream))
{
return (response.Data == null ? new MemoryStream() : new MemoryStream(response.Data)) as T;
}
return ResponseHandler.TryDeserializeResponse<T>(response);
}
catch (ArgumentException e)
{
throw new DeserializationException(response, e.Message);
}
catch (MissingFieldException)
{
throw new DeserializationException(response,
"Discriminator field not found in the parsed json response.");
}
catch (DeserializationException e) when (e.response == null)
{
throw new DeserializationException(response, e.Message);
}
catch (DeserializationException)
{
throw;
}
catch (Exception)
{
throw new DeserializationException(response);
}
}
}
}

11
Packages/com.unity.services.lobby/Runtime/Http/ResponseHandler.cs.meta


fileFormatVersion: 2
guid: d4ffd438c7fc249c3b17e41609970c50
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

27
Packages/com.unity.services.lobby/Runtime/Http/Responses.cs


using System;
using System.Collections.Generic;
using Unity.Services.Lobbies.Http;
namespace Unity.Services.Lobbies
{
public class Response {
public Dictionary<string, string> Headers { get; }
public long Status { get; set; }
public Response(HttpClientResponse httpResponse)
{
this.Headers = httpResponse.Headers;
this.Status = httpResponse.StatusCode;
}
}
public class Response<T> : Response
{
public T Result { get; }
public Response(HttpClientResponse httpResponse, T result): base(httpResponse)
{
this.Result = result;
}
}
}

11
Packages/com.unity.services.lobby/Runtime/Http/Responses.cs.meta


fileFormatVersion: 2
guid: 18ede7f294fc742fe93636c4e007a689
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

39
Packages/com.unity.services.lobby/Runtime/Http/UnityWebRequestHelpers.cs


using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using UnityEngine.Networking;
namespace Unity.Services.Lobbies.Http
{
public static class UnityWebRequestHelpers
{
public static TaskAwaiter<HttpClientResponse> GetAwaiter(this UnityWebRequestAsyncOperation asyncOp)
{
var tcs = new TaskCompletionSource<HttpClientResponse>();
asyncOp.completed += obj =>
{
var result = CreateHttpClientResponse((UnityWebRequestAsyncOperation) obj);
tcs.SetResult(result);
};
return tcs.Task.GetAwaiter();
}
internal static HttpClientResponse CreateHttpClientResponse(UnityWebRequestAsyncOperation unityResponse)
{
var response = unityResponse.webRequest;
var result = new HttpClientResponse(
response.GetResponseHeaders(),
response.responseCode,
#if UNITY_2020_1_OR_NEWER
response.result == UnityWebRequest.Result.ProtocolError,
response.result == UnityWebRequest.Result.ConnectionError,
#else
response.isHttpError,
response.isNetworkError,
#endif
response.downloadHandler.data,
response.error);
return result;
}
}
}

11
Packages/com.unity.services.lobby/Runtime/Http/UnityWebRequestHelpers.cs.meta


fileFormatVersion: 2
guid: dfc22921885c841cdbbd0f2ecac02c55
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

15
Packages/com.unity.services.lobby/Runtime/LobbyService.cs


using Unity.Services.Lobbies.Apis;
namespace Unity.Services.Lobbies
{
public static class LobbyService
{
/// <summary>
/// Static accessor for LobbyApi methods.
/// </summary>
public static ILobbyApiClient LobbyApiClient { get; internal set; }
public static Configuration Configuration = new Configuration("https://lobby.cloud.unity3d.com/v1", 10, 4, null);
}
}

11
Packages/com.unity.services.lobby/Runtime/LobbyService.cs.meta


fileFormatVersion: 2
guid: e252044ff978b47cc8c06ec6e59b31bf
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

45
Packages/com.unity.services.lobby/Runtime/LobbyServiceProvider.cs


using UnityEngine;
using System.Threading.Tasks;
using Unity.Services.Lobbies.Apis;
using Unity.Services.Lobbies.Http;
using Unity.Services.Lobbies.Scheduler;
using TaskScheduler = Unity.Services.Lobbies.Scheduler.TaskScheduler;
using Unity.Services.Core;
using Unity.Services.Authentication;
namespace Unity.Services.Lobbies
{
internal class LobbyServiceProvider : IInitializablePackage
{
private static GameObject _gameObjectFactory;
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
static void Register()
{
// Pass an instance of this class to Core
var generatedPackageRegistry =
CoreRegistry.Instance.RegisterPackage(new LobbyServiceProvider());
// And specify what components it requires, or provides.
generatedPackageRegistry.DependsOn<IAccessToken>();
;
}
public Task Initialize(CoreRegistry registry)
{
_gameObjectFactory = GameObjectFactory.CreateCoreSdkGameObject();
var scheduler = _gameObjectFactory.GetComponent<TaskScheduler>();
var httpClient = new HttpClient(scheduler);
var accessTokenLobbyApi = registry.GetServiceComponent<IAccessToken>();
if (accessTokenLobbyApi != null)
{
LobbyService.LobbyApiClient = new LobbyApiClient(httpClient, scheduler, accessTokenLobbyApi);
}
return Task.CompletedTask;
}
}
}

11
Packages/com.unity.services.lobby/Runtime/LobbyServiceProvider.cs.meta


fileFormatVersion: 2
guid: 812e6cc46cfdb48b5b4bf47b8cb1bd49
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

8
Packages/com.unity.services.lobby/Runtime/Models.meta


fileFormatVersion: 2
guid: 1e4788f1c450f4bca8d1ffa54541afd2
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

74
Packages/com.unity.services.lobby/Runtime/Models/CreateRequest.cs


using System;
using System.Collections.Generic;
using UnityEngine.Scripting;
using System.Runtime.Serialization;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
namespace Unity.Services.Lobbies.Models
{
/// <summary>
/// The body of a Create Lobby request.
/// </summary>
[Preserve]
[DataContract(Name = "CreateRequest")]
public class CreateRequest
{
/// <summary>
/// The body of a Create Lobby request.
/// </summary>
/// <param name="name">The name of the lobby that should be displayed to users. All whitespace will be trimmed from name.</param>
/// <param name="maxPlayers">The maximum number of players allowed in the lobby.</param>
/// <param name="isPrivate">Indicates whether or not the lobby is publicly visible and will show up in query results. If the lobby is not publicly visible, the creator can share the &#x60;lobbyCode&#x60; with other users who can use it to join this lobby.</param>
/// <param name="player">player param</param>
/// <param name="data">Custom game-specific properties that apply to the lobby (e.g. &#x60;mapName&#x60; or &#x60;gameType&#x60;).</param>
[Preserve]
public CreateRequest(string name, int maxPlayers, bool? isPrivate = null, Player player = default(Player), Dictionary<string, DataObject> data = null)
{
Name = name;
MaxPlayers = maxPlayers;
IsPrivate = isPrivate;
Player = player;
Data = data;
}
/// <summary>
/// The name of the lobby that should be displayed to users. All whitespace will be trimmed from name.
/// </summary>
[Preserve]
[DataMember(Name = "name", IsRequired = true, EmitDefaultValue = true)]
public string Name{ get; }
/// <summary>
/// The maximum number of players allowed in the lobby.
/// </summary>
[Preserve]
[DataMember(Name = "maxPlayers", IsRequired = true, EmitDefaultValue = true)]
public int MaxPlayers{ get; }
/// <summary>
/// Indicates whether or not the lobby is publicly visible and will show up in query results. If the lobby is not publicly visible, the creator can share the &#x60;lobbyCode&#x60; with other users who can use it to join this lobby.
/// </summary>
[Preserve]
[DataMember(Name = "isPrivate", EmitDefaultValue = true)]
public bool? IsPrivate{ get; }
/// <summary>
/// player param
/// </summary>
[Preserve]
[DataMember(Name = "player", EmitDefaultValue = false)]
public Player Player{ get; }
/// <summary>
/// Custom game-specific properties that apply to the lobby (e.g. &#x60;mapName&#x60; or &#x60;gameType&#x60;).
/// </summary>
[Preserve]
[DataMember(Name = "data", EmitDefaultValue = false)]
public Dictionary<string, DataObject> Data{ get; }
}
}

11
Packages/com.unity.services.lobby/Runtime/Models/CreateRequest.cs.meta


fileFormatVersion: 2
guid: 9483a3c0aae5e49abb35865aa4e0b834
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

155
Packages/com.unity.services.lobby/Runtime/Models/DataObject.cs


using System;
using System.Collections.Generic;
using UnityEngine.Scripting;
using System.Runtime.Serialization;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
namespace Unity.Services.Lobbies.Models
{
/// <summary>
/// Custom data property for a lobby.
/// </summary>
[Preserve]
[DataContract(Name = "DataObject")]
public class DataObject
{
/// <summary>
/// Custom data property for a lobby.
/// </summary>
/// <param name="visibility">Indicates for whom the property should be visible. If &#x60;public&#x60;, the property will be visible to everyone and will be included in query results. If &#x60;member&#x60; the data will only be visible to users who are members of the lobby (i.e. those who have successfully joined). If &#x60;private&#x60;, the metadata will only be visible to the host.</param>
/// <param name="value">The value of the custom property. This property can be set to null or empty string. If this property is indexed (by setting the &#x60;index&#x60; field) then the length of the value must be less than 128 bytes.</param>
/// <param name="index">The name of the column to index this property value under, either &#x60;S#&#x60; for strings or &#x60;N#&#x60; for numeric values. If an index is specified on a property, then you can use that index name in a &#x60;QueryFilter&#x60; to filter results by that property. If You will not be prevented from indexing multiple objects having properties different with names but the same the same index, but you will likely receive unexpected results from a query.</param>
[Preserve]
public DataObject(VisibilityOptions visibility, string value = null, IndexOptions index = default)
{
Visibility = visibility;
Value = value;
Index = index;
}
/// <summary>
/// Indicates for whom the property should be visible. If &#x60;public&#x60;, the property will be visible to everyone and will be included in query results. If &#x60;member&#x60; the data will only be visible to users who are members of the lobby (i.e. those who have successfully joined). If &#x60;private&#x60;, the metadata will only be visible to the host.
/// </summary>
[Preserve]
[JsonConverter(typeof(StringEnumConverter))]
[DataMember(Name = "visibility", IsRequired = true, EmitDefaultValue = true)]
public VisibilityOptions Visibility{ get; }
/// <summary>
/// The value of the custom property. This property can be set to null or empty string. If this property is indexed (by setting the &#x60;index&#x60; field) then the length of the value must be less than 128 bytes.
/// </summary>
[Preserve]
[DataMember(Name = "value", EmitDefaultValue = false)]
public string Value{ get; }
/// <summary>
/// The name of the column to index this property value under, either &#x60;S#&#x60; for strings or &#x60;N#&#x60; for numeric values. If an index is specified on a property, then you can use that index name in a &#x60;QueryFilter&#x60; to filter results by that property. If You will not be prevented from indexing multiple objects having properties different with names but the same the same index, but you will likely receive unexpected results from a query.
/// </summary>
[Preserve]
[JsonConverter(typeof(StringEnumConverter))]
[DataMember(Name = "index", EmitDefaultValue = false)]
public IndexOptions Index{ get; }
/// <summary>
/// Indicates for whom the property should be visible. If &#x60;public&#x60;, the property will be visible to everyone and will be included in query results. If &#x60;member&#x60; the data will only be visible to users who are members of the lobby (i.e. those who have successfully joined). If &#x60;private&#x60;, the metadata will only be visible to the host.
/// </summary>
/// <value>Indicates for whom the property should be visible. If &#x60;public&#x60;, the property will be visible to everyone and will be included in query results. If &#x60;member&#x60; the data will only be visible to users who are members of the lobby (i.e. those who have successfully joined). If &#x60;private&#x60;, the metadata will only be visible to the host.</value>
[JsonConverter(typeof(StringEnumConverter))]
public enum VisibilityOptions
{
/// <summary>
/// Enum Public for value: public
/// </summary>
[EnumMember(Value = "public")]
Public = 1,
/// <summary>
/// Enum Member for value: member
/// </summary>
[EnumMember(Value = "member")]
Member = 2,
/// <summary>
/// Enum Private for value: private
/// </summary>
[EnumMember(Value = "private")]
Private = 3
}
/// <summary>
/// The name of the column to index this property value under, either &#x60;S#&#x60; for strings or &#x60;N#&#x60; for numeric values. If an index is specified on a property, then you can use that index name in a &#x60;QueryFilter&#x60; to filter results by that property. If You will not be prevented from indexing multiple objects having properties different with names but the same the same index, but you will likely receive unexpected results from a query.
/// </summary>
/// <value>The name of the column to index this property value under, either &#x60;S#&#x60; for strings or &#x60;N#&#x60; for numeric values. If an index is specified on a property, then you can use that index name in a &#x60;QueryFilter&#x60; to filter results by that property. If You will not be prevented from indexing multiple objects having properties different with names but the same the same index, but you will likely receive unexpected results from a query.</value>
[JsonConverter(typeof(StringEnumConverter))]
public enum IndexOptions
{
/// <summary>
/// Enum S1 for value: S1
/// </summary>
[EnumMember(Value = "S1")]
S1 = 1,
/// <summary>
/// Enum S2 for value: S2
/// </summary>
[EnumMember(Value = "S2")]
S2 = 2,
/// <summary>
/// Enum S3 for value: S3
/// </summary>
[EnumMember(Value = "S3")]
S3 = 3,
/// <summary>
/// Enum S4 for value: S4
/// </summary>
[EnumMember(Value = "S4")]
S4 = 4,
/// <summary>
/// Enum S5 for value: S5
/// </summary>
[EnumMember(Value = "S5")]
S5 = 5,
/// <summary>
/// Enum N1 for value: N1
/// </summary>
[EnumMember(Value = "N1")]
N1 = 6,
/// <summary>
/// Enum N2 for value: N2
/// </summary>
[EnumMember(Value = "N2")]
N2 = 7,
/// <summary>
/// Enum N3 for value: N3
/// </summary>
[EnumMember(Value = "N3")]
N3 = 8,
/// <summary>
/// Enum N4 for value: N4
/// </summary>
[EnumMember(Value = "N4")]
N4 = 9,
/// <summary>
/// Enum N5 for value: N5
/// </summary>
[EnumMember(Value = "N5")]
N5 = 10
}
}
}

11
Packages/com.unity.services.lobby/Runtime/Models/DataObject.cs.meta


fileFormatVersion: 2
guid: 62d95d51b6b604296bec8133022e88ae
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

47
Packages/com.unity.services.lobby/Runtime/Models/Detail.cs


using System;
using System.Collections.Generic;
using UnityEngine.Scripting;
using System.Runtime.Serialization;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
namespace Unity.Services.Lobbies.Models
{
/// <summary>
/// Additional detail about an error. This may include detailed validation failure messages, debugging information, troubleshooting steps, or more.
/// </summary>
[Preserve]
[DataContract(Name = "Detail")]
public class Detail
{
/// <summary>
/// Additional detail about an error. This may include detailed validation failure messages, debugging information, troubleshooting steps, or more.
/// </summary>
/// <param name="errorType">errorType param</param>
/// <param name="message">message param</param>
[Preserve]
public Detail(string errorType = default(string), string message = default(string))
{
ErrorType = errorType;
Message = message;
}
/// <summary>
/// errorType param
/// </summary>
[Preserve]
[DataMember(Name = "errorType", EmitDefaultValue = false)]
public string ErrorType{ get; }
/// <summary>
/// message param
/// </summary>
[Preserve]
[DataMember(Name = "message", EmitDefaultValue = false)]
public string Message{ get; }
}
}

11
Packages/com.unity.services.lobby/Runtime/Models/Detail.cs.meta


fileFormatVersion: 2
guid: d5dd79820f9e34f8f9a67c52fb75585f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

56
Packages/com.unity.services.lobby/Runtime/Models/ErrorStatus.cs


using System;
using System.Collections.Generic;
using UnityEngine.Scripting;
using System.Runtime.Serialization;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
namespace Unity.Services.Lobbies.Models
{
/// <summary>
/// The body that will be returned for any failing request. We are using the [RFC 7807 Error Format](https://www.rfc-editor.org/rfc/rfc7807.html#section-3.1).
/// </summary>
[Preserve]
[DataContract(Name = "ErrorStatus")]
public class ErrorStatus
{
/// <summary>
/// The body that will be returned for any failing request. We are using the [RFC 7807 Error Format](https://www.rfc-editor.org/rfc/rfc7807.html#section-3.1).
/// </summary>
/// <param name="status">status param</param>
/// <param name="title">title param</param>
/// <param name="details">details param</param>
[Preserve]
public ErrorStatus(int status = default(int), string title = default(string), List<Detail> details = default(List<Detail>))
{
Status = status;
Title = title;
Details = details;
}
/// <summary>
/// status param
/// </summary>
[Preserve]
[DataMember(Name = "status", EmitDefaultValue = false)]
public int Status{ get; }
/// <summary>
/// title param
/// </summary>
[Preserve]
[DataMember(Name = "title", EmitDefaultValue = false)]
public string Title{ get; }
/// <summary>
/// details param
/// </summary>
[Preserve]
[DataMember(Name = "details", EmitDefaultValue = false)]
public List<Detail> Details{ get; }
}
}

11
Packages/com.unity.services.lobby/Runtime/Models/ErrorStatus.cs.meta


fileFormatVersion: 2
guid: a24b83f22e6c34e7997f74c83582802b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

47
Packages/com.unity.services.lobby/Runtime/Models/JoinByCodeRequest.cs


using System;
using System.Collections.Generic;
using UnityEngine.Scripting;
using System.Runtime.Serialization;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
namespace Unity.Services.Lobbies.Models
{
/// <summary>
/// The body of a Join Lobby request using lobby code.
/// </summary>
[Preserve]
[DataContract(Name = "JoinByCodeRequest")]
public class JoinByCodeRequest
{
/// <summary>
/// The body of a Join Lobby request using lobby code.
/// </summary>
/// <param name="lobbyCode">The lobby code of the lobby the join. Mutually exclusive with &#x60;id&#x60;. This is used to join a private lobby where the lobby code was shared to other users manually.</param>
/// <param name="player">player param</param>
[Preserve]
public JoinByCodeRequest(string lobbyCode, Player player = default(Player))
{
LobbyCode = lobbyCode;
Player = player;
}
/// <summary>
/// The lobby code of the lobby the join. Mutually exclusive with &#x60;id&#x60;. This is used to join a private lobby where the lobby code was shared to other users manually.
/// </summary>
[Preserve]
[DataMember(Name = "lobbyCode", IsRequired = true, EmitDefaultValue = true)]
public string LobbyCode{ get; }
/// <summary>
/// player param
/// </summary>
[Preserve]
[DataMember(Name = "player", EmitDefaultValue = false)]
public Player Player{ get; }
}
}

11
Packages/com.unity.services.lobby/Runtime/Models/JoinByCodeRequest.cs.meta


fileFormatVersion: 2
guid: 2f965fa0ec2754442a37dc72f66d91a4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

137
Packages/com.unity.services.lobby/Runtime/Models/Lobby.cs


using System;
using System.Collections.Generic;
using UnityEngine.Scripting;
using System.Runtime.Serialization;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
namespace Unity.Services.Lobbies.Models
{
/// <summary>
/// Data about an individual lobby.
/// </summary>
[Preserve]
[DataContract(Name = "Lobby")]
public class Lobby
{
/// <summary>
/// Data about an individual lobby.
/// </summary>
/// <param name="id">id param</param>
/// <param name="lobbyCode">A short code that be used to join a lobby. This is only visible to lobby members. Typically this is displayed to the user so they can share it with other players out of game. Users with the code can join the lobby even when it is private.</param>
/// <param name="upid">The Unity project ID of the game.</param>
/// <param name="name">The name of the lobby. Typically this shown in game UI to represent the lobby.</param>
/// <param name="maxPlayers">The maximum number of players that can be members of the lobby.</param>
/// <param name="availableSlots">The number of remaining open slots for players before the lobby becomes full.</param>
/// <param name="isPrivate">Whether the lobby is private or not. Private lobbies do not appear in query results.</param>
/// <param name="players">The members of the lobby.</param>
/// <param name="data">Properties of the lobby set by the host.</param>
/// <param name="hostId">The ID of the player that is the lobby host.</param>
/// <param name="created">When the lobby was created. The timestamp is in UTC and conforms to ISO 8601.</param>
/// <param name="lastUpdated">When the lobby was last updated. The timestamp is in UTC and conforms to ISO 8601.</param>
[Preserve]
public Lobby(string id = default(string), string lobbyCode = null, string upid = default(string), string name = null, int maxPlayers = default(int), int availableSlots = default(int), bool isPrivate = default(bool), List<Player> players = default(List<Player>), Dictionary<string, DataObject> data = null, string hostId = default(string), DateTime created = default(DateTime), DateTime lastUpdated = default(DateTime))
{
Id = id;
LobbyCode = lobbyCode;
Upid = upid;
Name = name;
MaxPlayers = maxPlayers;
AvailableSlots = availableSlots;
IsPrivate = isPrivate;
Players = players;
Data = data;
HostId = hostId;
Created = created;
LastUpdated = lastUpdated;
}
/// <summary>
/// id param
/// </summary>
[Preserve]
[DataMember(Name = "id", EmitDefaultValue = false)]
public string Id{ get; }
/// <summary>
/// A short code that be used to join a lobby. This is only visible to lobby members. Typically this is displayed to the user so they can share it with other players out of game. Users with the code can join the lobby even when it is private.
/// </summary>
[Preserve]
[DataMember(Name = "lobbyCode", EmitDefaultValue = false)]
public string LobbyCode{ get; }
/// <summary>
/// The Unity project ID of the game.
/// </summary>
[Preserve]
[DataMember(Name = "upid", EmitDefaultValue = false)]
public string Upid{ get; }
/// <summary>
/// The name of the lobby. Typically this shown in game UI to represent the lobby.
/// </summary>
[Preserve]
[DataMember(Name = "name", EmitDefaultValue = false)]
public string Name{ get; }
/// <summary>
/// The maximum number of players that can be members of the lobby.
/// </summary>
[Preserve]
[DataMember(Name = "maxPlayers", EmitDefaultValue = false)]
public int MaxPlayers{ get; }
/// <summary>
/// The number of remaining open slots for players before the lobby becomes full.
/// </summary>
[Preserve]
[DataMember(Name = "availableSlots", EmitDefaultValue = false)]
public int AvailableSlots{ get; }
/// <summary>
/// Whether the lobby is private or not. Private lobbies do not appear in query results.
/// </summary>
[Preserve]
[DataMember(Name = "isPrivate", EmitDefaultValue = true)]
public bool IsPrivate{ get; }
/// <summary>
/// The members of the lobby.
/// </summary>
[Preserve]
[DataMember(Name = "players", EmitDefaultValue = false)]
public List<Player> Players{ get; }
/// <summary>
/// Properties of the lobby set by the host.
/// </summary>
[Preserve]
[DataMember(Name = "data", EmitDefaultValue = false)]
public Dictionary<string, DataObject> Data{ get; }
/// <summary>
/// The ID of the player that is the lobby host.
/// </summary>
[Preserve]
[DataMember(Name = "hostId", EmitDefaultValue = false)]
public string HostId{ get; }
/// <summary>
/// When the lobby was created. The timestamp is in UTC and conforms to ISO 8601.
/// </summary>
[Preserve]
[DataMember(Name = "created", EmitDefaultValue = false)]
public DateTime Created{ get; }
/// <summary>
/// When the lobby was last updated. The timestamp is in UTC and conforms to ISO 8601.
/// </summary>
[Preserve]
[DataMember(Name = "lastUpdated", EmitDefaultValue = false)]
public DateTime LastUpdated{ get; }
}
}

11
Packages/com.unity.services.lobby/Runtime/Models/Lobby.cs.meta


fileFormatVersion: 2
guid: d514f234f15fa4c27b49e4e258e19a60
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

10
Packages/com.unity.services.lobby/Runtime/Models/LobbyIOneOf.cs


using System;
namespace Unity.Services.Lobbies.Models
{
public interface IOneOf
{
Type Type { get; }
object Value { get; }
}
}

11
Packages/com.unity.services.lobby/Runtime/Models/LobbyIOneOf.cs.meta


fileFormatVersion: 2
guid: 1286c7fd235c44e8689081ade5dc4e23
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

83
Packages/com.unity.services.lobby/Runtime/Models/Player.cs


using System;
using System.Collections.Generic;
using UnityEngine.Scripting;
using System.Runtime.Serialization;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
namespace Unity.Services.Lobbies.Models
{
/// <summary>
/// Information about a specific player creating, joining, or already in a lobby.
/// </summary>
[Preserve]
[DataContract(Name = "Player")]
public class Player
{
/// <summary>
/// Information about a specific player creating, joining, or already in a lobby.
/// </summary>
/// <param name="id">The unique identifier for the player. If not provided for a create or join request it will be set to the id of the caller.</param>
/// <param name="connectionInfo">(TBD) Connection information for connecting to a relay with this player.</param>
/// <param name="data">Custom game-specific properties that apply to an individual player (e.g. &#x60;role&#x60; or &#x60;skill&#x60;).</param>
/// <param name="allocationId">An id that associates this player in this lobby with a persistent connection. When a disconnect notification is recevied, this value is used to identify the associated player in a lobby to mark them as disconnected.</param>
/// <param name="joined">The time at which the player joined the lobby.</param>
/// <param name="lastUpdated">The last time the metadata for this player was updated.</param>
[Preserve]
public Player(string id = null, string connectionInfo = null, Dictionary<string, PlayerDataObject> data = null, string allocationId = null, DateTime joined = default(DateTime), DateTime lastUpdated = default(DateTime))
{
Id = id;
ConnectionInfo = connectionInfo;
Data = data;
AllocationId = allocationId;
Joined = joined;
LastUpdated = lastUpdated;
}
/// <summary>
/// The unique identifier for the player. If not provided for a create or join request it will be set to the id of the caller.
/// </summary>
[Preserve]
[DataMember(Name = "id", EmitDefaultValue = false)]
public string Id{ get; }
/// <summary>
/// (TBD) Connection information for connecting to a relay with this player.
/// </summary>
[Preserve]
[DataMember(Name = "connectionInfo", EmitDefaultValue = false)]
public string ConnectionInfo{ get; }
/// <summary>
/// Custom game-specific properties that apply to an individual player (e.g. &#x60;role&#x60; or &#x60;skill&#x60;).
/// </summary>
[Preserve]
[DataMember(Name = "data", EmitDefaultValue = false)]
public Dictionary<string, PlayerDataObject> Data{ get; }
/// <summary>
/// An id that associates this player in this lobby with a persistent connection. When a disconnect notification is recevied, this value is used to identify the associated player in a lobby to mark them as disconnected.
/// </summary>
[Preserve]
[DataMember(Name = "allocationId", EmitDefaultValue = false)]
public string AllocationId{ get; }
/// <summary>
/// The time at which the player joined the lobby.
/// </summary>
[Preserve]
[DataMember(Name = "joined", EmitDefaultValue = false)]
public DateTime Joined{ get; }
/// <summary>
/// The last time the metadata for this player was updated.
/// </summary>
[Preserve]
[DataMember(Name = "lastUpdated", EmitDefaultValue = false)]
public DateTime LastUpdated{ get; }
}
}

11
Packages/com.unity.services.lobby/Runtime/Models/Player.cs.meta


fileFormatVersion: 2
guid: 3101ac2026071440c8600b70a6ca23d3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

76
Packages/com.unity.services.lobby/Runtime/Models/PlayerDataObject.cs


using System;
using System.Collections.Generic;
using UnityEngine.Scripting;
using System.Runtime.Serialization;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
namespace Unity.Services.Lobbies.Models
{
/// <summary>
/// Custom data property for a player.
/// </summary>
[Preserve]
[DataContract(Name = "PlayerDataObject")]
public class PlayerDataObject
{
/// <summary>
/// Custom data property for a player.
/// </summary>
/// <param name="visibility">Indicates for whom the property should be visible. If &#x60;public&#x60;, the property will be visible to everyone and will be included in query results. If &#x60;member&#x60; the data will only be visible to users who are members of the lobby (i.e. those who have successfully joined). If &#x60;private&#x60;, the metadata will only be visible to the the player.</param>
/// <param name="value">The value of the custom property. This property can be set to null or empty string.</param>
[Preserve]
public PlayerDataObject(VisibilityOptions visibility, string value = null)
{
Visibility = visibility;
Value = value;
}
/// <summary>
/// Indicates for whom the property should be visible. If &#x60;public&#x60;, the property will be visible to everyone and will be included in query results. If &#x60;member&#x60; the data will only be visible to users who are members of the lobby (i.e. those who have successfully joined). If &#x60;private&#x60;, the metadata will only be visible to the the player.
/// </summary>
[Preserve]
[JsonConverter(typeof(StringEnumConverter))]
[DataMember(Name = "visibility", IsRequired = true, EmitDefaultValue = true)]
public VisibilityOptions Visibility{ get; }
/// <summary>
/// The value of the custom property. This property can be set to null or empty string.
/// </summary>
[Preserve]
[DataMember(Name = "value", EmitDefaultValue = false)]
public string Value{ get; }
/// <summary>
/// Indicates for whom the property should be visible. If &#x60;public&#x60;, the property will be visible to everyone and will be included in query results. If &#x60;member&#x60; the data will only be visible to users who are members of the lobby (i.e. those who have successfully joined). If &#x60;private&#x60;, the metadata will only be visible to the the player.
/// </summary>
/// <value>Indicates for whom the property should be visible. If &#x60;public&#x60;, the property will be visible to everyone and will be included in query results. If &#x60;member&#x60; the data will only be visible to users who are members of the lobby (i.e. those who have successfully joined). If &#x60;private&#x60;, the metadata will only be visible to the the player.</value>
[JsonConverter(typeof(StringEnumConverter))]
public enum VisibilityOptions
{
/// <summary>
/// Enum Public for value: public
/// </summary>
[EnumMember(Value = "public")]
Public = 1,
/// <summary>
/// Enum Member for value: member
/// </summary>
[EnumMember(Value = "member")]
Member = 2,
/// <summary>
/// Enum Private for value: private
/// </summary>
[EnumMember(Value = "private")]
Private = 3
}
}
}

11
Packages/com.unity.services.lobby/Runtime/Models/PlayerDataObject.cs.meta


fileFormatVersion: 2
guid: 4b3471f8a040c47eab149048fa65e3f4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

56
Packages/com.unity.services.lobby/Runtime/Models/PlayerUpdateRequest.cs


using System;
using System.Collections.Generic;
using UnityEngine.Scripting;
using System.Runtime.Serialization;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
namespace Unity.Services.Lobbies.Models
{
/// <summary>
/// The body of an Update Player Data request.
/// </summary>
[Preserve]
[DataContract(Name = "PlayerUpdateRequest")]
public class PlayerUpdateRequest
{
/// <summary>
/// The body of an Update Player Data request.
/// </summary>
/// <param name="connectionInfo">(TBD) Connection information for connecting to a relay with this player.</param>
/// <param name="data">Custom game-specific properties to add, update, or remove from the player (e.g. &#x60;role&#x60; or &#x60;skill&#x60;). To remove an existing property, include it in &#x60;data&#x60; but set the property object to &#x60;null&#x60;. To update the value to &#x60;null&#x60;, set the &#x60;value&#x60; property of the object to &#x60;null&#x60;.</param>
/// <param name="allocationId">An id that associates this player in this lobby with a persistent connection. When a disconnect notification is recevied, this value is used to identify the associated player in a lobby to mark them as disconnected.</param>
[Preserve]
public PlayerUpdateRequest(string connectionInfo = null, Dictionary<string, PlayerDataObject> data = null, string allocationId = null)
{
ConnectionInfo = connectionInfo;
Data = data;
AllocationId = allocationId;
}
/// <summary>
/// (TBD) Connection information for connecting to a relay with this player.
/// </summary>
[Preserve]
[DataMember(Name = "connectionInfo", EmitDefaultValue = false)]
public string ConnectionInfo{ get; }
/// <summary>
/// Custom game-specific properties to add, update, or remove from the player (e.g. &#x60;role&#x60; or &#x60;skill&#x60;). To remove an existing property, include it in &#x60;data&#x60; but set the property object to &#x60;null&#x60;. To update the value to &#x60;null&#x60;, set the &#x60;value&#x60; property of the object to &#x60;null&#x60;.
/// </summary>
[Preserve]
[DataMember(Name = "data", EmitDefaultValue = false)]
public Dictionary<string, PlayerDataObject> Data{ get; }
/// <summary>
/// An id that associates this player in this lobby with a persistent connection. When a disconnect notification is recevied, this value is used to identify the associated player in a lobby to mark them as disconnected.
/// </summary>
[Preserve]
[DataMember(Name = "allocationId", EmitDefaultValue = false)]
public string AllocationId{ get; }
}
}

11
Packages/com.unity.services.lobby/Runtime/Models/PlayerUpdateRequest.cs.meta


fileFormatVersion: 2
guid: 6cbd6e214eb8c4c7bbf8ec61356c1b22
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

210
Packages/com.unity.services.lobby/Runtime/Models/QueryFilter.cs


using System;
using System.Collections.Generic;
using UnityEngine.Scripting;
using System.Runtime.Serialization;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
namespace Unity.Services.Lobbies.Models
{
/// <summary>
/// A filter for an individual field that is applied to a query.
/// </summary>
[Preserve]
[DataContract(Name = "QueryFilter")]
public class QueryFilter
{
/// <summary>
/// A filter for an individual field that is applied to a query.
/// </summary>
/// <param name="field">The name of the field to filter on. For custom data fields, the name of the index must be used instead of the field name.</param>
/// <param name="value">The value to compare to the field being filtered. This value must be a string and it must be parsable as the same type as &#x60;field&#x60; (e.g. &#x60;integer&#x60; for MaxPlayers, &#x60;datetime&#x60; for Created, etc.). The value for &#x60;datetime&#x60; fields (Created, LastUpdated) must be in RFC3339 format. For example, in C# this can be achieved using the \&quot;o\&quot; format specifier: &#x60;return dateTime.ToString(\&quot;o\&quot;, DateTimeFormatInfo.InvariantInfo);&#x60;. Refer to your language documentation for other methods to generate RFC3339-compatible datetime strings.</param>
/// <param name="op">The operator used to compare the field to the filter value. Supports &#x60;CONTAINS&#x60; (only on the &#x60;Name&#x60; field), &#x60;EQ&#x60; (Equal), &#x60;NE&#x60; (Not Equal), &#x60;LT&#x60; (Less Than), &#x60;LE&#x60; (Less Than or Equal), &#x60;GT&#x60; (Greater Than), or &#x60;GE&#x60; (Greater Than or Equal).</param>
[Preserve]
public QueryFilter(FieldOptions field, string value, OpOptions op)
{
Field = field;
Value = value;
Op = op;
}
/// <summary>
/// The name of the field to filter on. For custom data fields, the name of the index must be used instead of the field name.
/// </summary>
[Preserve]
[JsonConverter(typeof(StringEnumConverter))]
[DataMember(Name = "field", IsRequired = true, EmitDefaultValue = true)]
public FieldOptions Field{ get; }
/// <summary>
/// The value to compare to the field being filtered. This value must be a string and it must be parsable as the same type as &#x60;field&#x60; (e.g. &#x60;integer&#x60; for MaxPlayers, &#x60;datetime&#x60; for Created, etc.). The value for &#x60;datetime&#x60; fields (Created, LastUpdated) must be in RFC3339 format. For example, in C# this can be achieved using the \&quot;o\&quot; format specifier: &#x60;return dateTime.ToString(\&quot;o\&quot;, DateTimeFormatInfo.InvariantInfo);&#x60;. Refer to your language documentation for other methods to generate RFC3339-compatible datetime strings.
/// </summary>
[Preserve]
[DataMember(Name = "value", IsRequired = true, EmitDefaultValue = true)]
public string Value{ get; }
/// <summary>
/// The operator used to compare the field to the filter value. Supports &#x60;CONTAINS&#x60; (only on the &#x60;Name&#x60; field), &#x60;EQ&#x60; (Equal), &#x60;NE&#x60; (Not Equal), &#x60;LT&#x60; (Less Than), &#x60;LE&#x60; (Less Than or Equal), &#x60;GT&#x60; (Greater Than), or &#x60;GE&#x60; (Greater Than or Equal).
/// </summary>
[Preserve]
[JsonConverter(typeof(StringEnumConverter))]
[DataMember(Name = "op", IsRequired = true, EmitDefaultValue = true)]
public OpOptions Op{ get; }
/// <summary>
/// The name of the field to filter on. For custom data fields, the name of the index must be used instead of the field name.
/// </summary>
/// <value>The name of the field to filter on. For custom data fields, the name of the index must be used instead of the field name.</value>
[JsonConverter(typeof(StringEnumConverter))]
public enum FieldOptions
{
/// <summary>
/// Enum MaxPlayers for value: MaxPlayers
/// </summary>
[EnumMember(Value = "MaxPlayers")]
MaxPlayers = 1,
/// <summary>
/// Enum AvailableSlots for value: AvailableSlots
/// </summary>
[EnumMember(Value = "AvailableSlots")]
AvailableSlots = 2,
/// <summary>
/// Enum Name for value: Name
/// </summary>
[EnumMember(Value = "Name")]
Name = 3,
/// <summary>
/// Enum Created for value: Created
/// </summary>
[EnumMember(Value = "Created")]
Created = 4,
/// <summary>
/// Enum LastUpdated for value: LastUpdated
/// </summary>
[EnumMember(Value = "LastUpdated")]
LastUpdated = 5,
/// <summary>
/// Enum S1 for value: S1
/// </summary>
[EnumMember(Value = "S1")]
S1 = 6,
/// <summary>
/// Enum S2 for value: S2
/// </summary>
[EnumMember(Value = "S2")]
S2 = 7,
/// <summary>
/// Enum S3 for value: S3
/// </summary>
[EnumMember(Value = "S3")]
S3 = 8,
/// <summary>
/// Enum S4 for value: S4
/// </summary>
[EnumMember(Value = "S4")]
S4 = 9,
/// <summary>
/// Enum S5 for value: S5
/// </summary>
[EnumMember(Value = "S5")]
S5 = 10,
/// <summary>
/// Enum N1 for value: N1
/// </summary>
[EnumMember(Value = "N1")]
N1 = 11,
/// <summary>
/// Enum N2 for value: N2
/// </summary>
[EnumMember(Value = "N2")]
N2 = 12,
/// <summary>
/// Enum N3 for value: N3
/// </summary>
[EnumMember(Value = "N3")]
N3 = 13,
/// <summary>
/// Enum N4 for value: N4
/// </summary>
[EnumMember(Value = "N4")]
N4 = 14,
/// <summary>
/// Enum N5 for value: N5
/// </summary>
[EnumMember(Value = "N5")]
N5 = 15
}
/// <summary>
/// The operator used to compare the field to the filter value. Supports &#x60;CONTAINS&#x60; (only on the &#x60;Name&#x60; field), &#x60;EQ&#x60; (Equal), &#x60;NE&#x60; (Not Equal), &#x60;LT&#x60; (Less Than), &#x60;LE&#x60; (Less Than or Equal), &#x60;GT&#x60; (Greater Than), or &#x60;GE&#x60; (Greater Than or Equal).
/// </summary>
/// <value>The operator used to compare the field to the filter value. Supports &#x60;CONTAINS&#x60; (only on the &#x60;Name&#x60; field), &#x60;EQ&#x60; (Equal), &#x60;NE&#x60; (Not Equal), &#x60;LT&#x60; (Less Than), &#x60;LE&#x60; (Less Than or Equal), &#x60;GT&#x60; (Greater Than), or &#x60;GE&#x60; (Greater Than or Equal).</value>
[JsonConverter(typeof(StringEnumConverter))]
public enum OpOptions
{
/// <summary>
/// Enum CONTAINS for value: CONTAINS
/// </summary>
[EnumMember(Value = "CONTAINS")]
CONTAINS = 1,
/// <summary>
/// Enum EQ for value: EQ
/// </summary>
[EnumMember(Value = "EQ")]
EQ = 2,
/// <summary>
/// Enum NE for value: NE
/// </summary>
[EnumMember(Value = "NE")]
NE = 3,
/// <summary>
/// Enum LT for value: LT
/// </summary>
[EnumMember(Value = "LT")]
LT = 4,
/// <summary>
/// Enum LE for value: LE
/// </summary>
[EnumMember(Value = "LE")]
LE = 5,
/// <summary>
/// Enum GT for value: GT
/// </summary>
[EnumMember(Value = "GT")]
GT = 6,
/// <summary>
/// Enum GE for value: GE
/// </summary>
[EnumMember(Value = "GE")]
GE = 7
}
}
}

11
Packages/com.unity.services.lobby/Runtime/Models/QueryFilter.cs.meta


fileFormatVersion: 2
guid: 57811e6f3eb004081be3a7d2ae4ec9ac
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

154
Packages/com.unity.services.lobby/Runtime/Models/QueryOrder.cs


using System;
using System.Collections.Generic;
using UnityEngine.Scripting;
using System.Runtime.Serialization;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
namespace Unity.Services.Lobbies.Models
{
/// <summary>
/// An order for an individual field that is applied to a query.
/// </summary>
[Preserve]
[DataContract(Name = "QueryOrder")]
public class QueryOrder
{
/// <summary>
/// An order for an individual field that is applied to a query.
/// </summary>
/// <param name="asc">Whether to sort in ascending or descending order.</param>
/// <param name="field">The name of the field to order on.</param>
[Preserve]
public QueryOrder(bool asc = default(bool), FieldOptions field = default)
{
Asc = asc;
Field = field;
}
/// <summary>
/// Whether to sort in ascending or descending order.
/// </summary>
[Preserve]
[DataMember(Name = "asc", EmitDefaultValue = true)]
public bool Asc{ get; }
/// <summary>
/// The name of the field to order on.
/// </summary>
[Preserve]
[JsonConverter(typeof(StringEnumConverter))]
[DataMember(Name = "field", EmitDefaultValue = false)]
public FieldOptions Field{ get; }
/// <summary>
/// The name of the field to order on.
/// </summary>
/// <value>The name of the field to order on.</value>
[JsonConverter(typeof(StringEnumConverter))]
public enum FieldOptions
{
/// <summary>
/// Enum Name for value: Name
/// </summary>
[EnumMember(Value = "Name")]
Name = 1,
/// <summary>
/// Enum MaxPlayers for value: MaxPlayers
/// </summary>
[EnumMember(Value = "MaxPlayers")]
MaxPlayers = 2,
/// <summary>
/// Enum AvailableSlots for value: AvailableSlots
/// </summary>
[EnumMember(Value = "AvailableSlots")]
AvailableSlots = 3,
/// <summary>
/// Enum Created for value: Created
/// </summary>
[EnumMember(Value = "Created")]
Created = 4,
/// <summary>
/// Enum LastUpdated for value: LastUpdated
/// </summary>
[EnumMember(Value = "LastUpdated")]
LastUpdated = 5,
/// <summary>
/// Enum ID for value: ID
/// </summary>
[EnumMember(Value = "ID")]
ID = 6,
/// <summary>
/// Enum S1 for value: S1
/// </summary>
[EnumMember(Value = "S1")]
S1 = 7,
/// <summary>
/// Enum S2 for value: S2
/// </summary>
[EnumMember(Value = "S2")]
S2 = 8,
/// <summary>
/// Enum S3 for value: S3
/// </summary>
[EnumMember(Value = "S3")]
S3 = 9,
/// <summary>
/// Enum S4 for value: S4
/// </summary>
[EnumMember(Value = "S4")]
S4 = 10,
/// <summary>
/// Enum S5 for value: S5
/// </summary>
[EnumMember(Value = "S5")]
S5 = 11,
/// <summary>
/// Enum N1 for value: N1
/// </summary>
[EnumMember(Value = "N1")]
N1 = 12,
/// <summary>
/// Enum N2 for value: N2
/// </summary>
[EnumMember(Value = "N2")]
N2 = 13,
/// <summary>
/// Enum N3 for value: N3
/// </summary>
[EnumMember(Value = "N3")]
N3 = 14,
/// <summary>
/// Enum N4 for value: N4
/// </summary>
[EnumMember(Value = "N4")]
N4 = 15,
/// <summary>
/// Enum N5 for value: N5
/// </summary>
[EnumMember(Value = "N5")]
N5 = 16
}
}
}

11
Packages/com.unity.services.lobby/Runtime/Models/QueryOrder.cs.meta


fileFormatVersion: 2
guid: 13dd81cf4377f4067abf8c45b64aa8a9
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

83
Packages/com.unity.services.lobby/Runtime/Models/QueryRequest.cs


using System;
using System.Collections.Generic;
using UnityEngine.Scripting;
using System.Runtime.Serialization;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
namespace Unity.Services.Lobbies.Models
{
/// <summary>
/// The body of a Query request which defines how to sort and filter results, how many results to return, etc.
/// </summary>
[Preserve]
[DataContract(Name = "QueryRequest")]
public class QueryRequest
{
/// <summary>
/// The body of a Query request which defines how to sort and filter results, how many results to return, etc.
/// </summary>
/// <param name="count">The number of results to return.</param>
/// <param name="skip">The number of results to skip before selecting results to return.</param>
/// <param name="sampleResults">Whether a random sample of results that match the search filter should be returned.</param>
/// <param name="filter">A list of filters which can be used to narrow down which lobbies to return.</param>
/// <param name="order">A list of orders which define how the results should be ordered in the response.</param>
/// <param name="continuationToken">A continuation token that can be passed to subsequent query requests to fetch the next page of results.</param>
[Preserve]
public QueryRequest(int? count = null, int? skip = null, bool sampleResults = false, List<QueryFilter> filter = default(List<QueryFilter>), List<QueryOrder> order = default(List<QueryOrder>), string continuationToken = null)
{
Count = count;
Skip = skip;
SampleResults = sampleResults;
Filter = filter;
Order = order;
ContinuationToken = continuationToken;
}
/// <summary>
/// The number of results to return.
/// </summary>
[Preserve]
[DataMember(Name = "count", EmitDefaultValue = false)]
public int? Count{ get; }
/// <summary>
/// The number of results to skip before selecting results to return.
/// </summary>
[Preserve]
[DataMember(Name = "skip", EmitDefaultValue = false)]
public int? Skip{ get; }
/// <summary>
/// Whether a random sample of results that match the search filter should be returned.
/// </summary>
[Preserve]
[DataMember(Name = "sampleResults", EmitDefaultValue = true)]
public bool SampleResults{ get; }
/// <summary>
/// A list of filters which can be used to narrow down which lobbies to return.
/// </summary>
[Preserve]
[DataMember(Name = "filter", EmitDefaultValue = false)]
public List<QueryFilter> Filter{ get; }
/// <summary>
/// A list of orders which define how the results should be ordered in the response.
/// </summary>
[Preserve]
[DataMember(Name = "order", EmitDefaultValue = false)]
public List<QueryOrder> Order{ get; }
/// <summary>
/// A continuation token that can be passed to subsequent query requests to fetch the next page of results.
/// </summary>
[Preserve]
[DataMember(Name = "continuationToken", EmitDefaultValue = false)]
public string ContinuationToken{ get; }
}
}

11
Packages/com.unity.services.lobby/Runtime/Models/QueryRequest.cs.meta


fileFormatVersion: 2
guid: 8e9681add0b7c4690abb80579eed3a78
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

47
Packages/com.unity.services.lobby/Runtime/Models/QueryResponse.cs


using System;
using System.Collections.Generic;
using UnityEngine.Scripting;
using System.Runtime.Serialization;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
namespace Unity.Services.Lobbies.Models
{
/// <summary>
/// A list of lobbies that matched the specified lobbies query. Only the public top level, data, and player data properties are returned.
/// </summary>
[Preserve]
[DataContract(Name = "QueryResponse")]
public class QueryResponse
{
/// <summary>
/// A list of lobbies that matched the specified lobbies query. Only the public top level, data, and player data properties are returned.
/// </summary>
/// <param name="results">results param</param>
/// <param name="continuationToken">continuationToken param</param>
[Preserve]
public QueryResponse(List<Lobby> results = default(List<Lobby>), string continuationToken = null)
{
Results = results;
ContinuationToken = continuationToken;
}
/// <summary>
/// results param
/// </summary>
[Preserve]
[DataMember(Name = "results", EmitDefaultValue = false)]
public List<Lobby> Results{ get; }
/// <summary>
/// continuationToken param
/// </summary>
[Preserve]
[DataMember(Name = "continuationToken", EmitDefaultValue = false)]
public string ContinuationToken{ get; }
}
}

11
Packages/com.unity.services.lobby/Runtime/Models/QueryResponse.cs.meta


fileFormatVersion: 2
guid: dc2b6c2759084442883482161a87370a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

47
Packages/com.unity.services.lobby/Runtime/Models/QuickJoinRequest.cs


using System;
using System.Collections.Generic;
using UnityEngine.Scripting;
using System.Runtime.Serialization;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
namespace Unity.Services.Lobbies.Models
{
/// <summary>
/// The body of a QuickJoin request.
/// </summary>
[Preserve]
[DataContract(Name = "QuickJoinRequest")]
public class QuickJoinRequest
{
/// <summary>
/// The body of a QuickJoin request.
/// </summary>
/// <param name="filter">A list of filters which can be used to narrow down which lobbies to attempt to join..</param>
/// <param name="player">player param</param>
[Preserve]
public QuickJoinRequest(List<QueryFilter> filter = default(List<QueryFilter>), Player player = default(Player))
{
Filter = filter;
Player = player;
}
/// <summary>
/// A list of filters which can be used to narrow down which lobbies to attempt to join..
/// </summary>
[Preserve]
[DataMember(Name = "filter", EmitDefaultValue = false)]
public List<QueryFilter> Filter{ get; }
/// <summary>
/// player param
/// </summary>
[Preserve]
[DataMember(Name = "player", EmitDefaultValue = false)]
public Player Player{ get; }
}
}

11
Packages/com.unity.services.lobby/Runtime/Models/QuickJoinRequest.cs.meta


fileFormatVersion: 2
guid: 6a5c71bcafd784dcc88bbc76d2db823a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

74
Packages/com.unity.services.lobby/Runtime/Models/UpdateRequest.cs


using System;
using System.Collections.Generic;
using UnityEngine.Scripting;
using System.Runtime.Serialization;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
namespace Unity.Services.Lobbies.Models
{
/// <summary>
/// The body of an Update Lobby request.
/// </summary>
[Preserve]
[DataContract(Name = "UpdateRequest")]
public class UpdateRequest
{
/// <summary>
/// The body of an Update Lobby request.
/// </summary>
/// <param name="name">The name of the lobby that should be displayed to users. All whitespace will be trimmed from name.</param>
/// <param name="maxPlayers">The maximum number of players allowed in the lobby. Must be greater than or equal to the current number of players in the lobby.</param>
/// <param name="isPrivate">Indicates whether or not the lobby is publicly visible and will show up in query results. If the lobby is not publicly visible, the creator can share the &#x60;lobbyCode&#x60; with other users who can use it to join this lobby.</param>
/// <param name="data">Custom game-specific properties to add, update, or remove from the lobby (e.g. &#x60;mapName&#x60; or &#x60;gameType&#x60;). To remove an existing property, include it in &#x60;data&#x60; but set the property object to &#x60;null&#x60;. To update the value to &#x60;null&#x60;, set the &#x60;value&#x60; property of the object to &#x60;null&#x60;.</param>
/// <param name="hostId">The id of the player to make the host of the lobby. As soon as this is updated the current host will no longer have permission to modify the lobby.</param>
[Preserve]
public UpdateRequest(string name = null, int? maxPlayers = null, bool? isPrivate = null, Dictionary<string, DataObject> data = null, string hostId = null)
{
Name = name;
MaxPlayers = maxPlayers;
IsPrivate = isPrivate;
Data = data;
HostId = hostId;
}
/// <summary>
/// The name of the lobby that should be displayed to users. All whitespace will be trimmed from name.
/// </summary>
[Preserve]
[DataMember(Name = "name", EmitDefaultValue = false)]
public string Name{ get; }
/// <summary>
/// The maximum number of players allowed in the lobby. Must be greater than or equal to the current number of players in the lobby.
/// </summary>
[Preserve]
[DataMember(Name = "maxPlayers", EmitDefaultValue = false)]
public int? MaxPlayers{ get; }
/// <summary>
/// Indicates whether or not the lobby is publicly visible and will show up in query results. If the lobby is not publicly visible, the creator can share the &#x60;lobbyCode&#x60; with other users who can use it to join this lobby.
/// </summary>
[Preserve]
[DataMember(Name = "isPrivate", EmitDefaultValue = true)]
public bool? IsPrivate{ get; }
/// <summary>
/// Custom game-specific properties to add, update, or remove from the lobby (e.g. &#x60;mapName&#x60; or &#x60;gameType&#x60;). To remove an existing property, include it in &#x60;data&#x60; but set the property object to &#x60;null&#x60;. To update the value to &#x60;null&#x60;, set the &#x60;value&#x60; property of the object to &#x60;null&#x60;.
/// </summary>
[Preserve]
[DataMember(Name = "data", EmitDefaultValue = false)]
public Dictionary<string, DataObject> Data{ get; }
/// <summary>
/// The id of the player to make the host of the lobby. As soon as this is updated the current host will no longer have permission to modify the lobby.
/// </summary>
[Preserve]
[DataMember(Name = "hostId", EmitDefaultValue = false)]
public string HostId{ get; }
}
}

11
Packages/com.unity.services.lobby/Runtime/Models/UpdateRequest.cs.meta


fileFormatVersion: 2
guid: c50951a05f90d4ecba6fd8c11bf9769b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

8
Packages/com.unity.services.lobby/Runtime/Scheduler.meta


fileFormatVersion: 2
guid: bc8ad623ce34c4ce887fd09acbfdf978
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

37
Packages/com.unity.services.lobby/Runtime/Scheduler/GameObjectFactory.cs


using System;
using UnityEngine;
namespace Unity.Services.Lobbies.Scheduler
{
/// <summary>
/// <para>A convenience class for creating GameObjects for the SdkCore.</para>
///
/// <para>As this uses the Unity API it is not thread-safe and must be called
/// from the main thread.</para>
/// </summary>
public static class GameObjectFactory
{
/// <summary>
/// Creates a CoreSdk game object, which will contain all components required
/// by the SDK.
/// </summary>
/// <returns>The CoreSdk game object.</returns>
public static GameObject CreateCoreSdkGameObject()
{
var random = new System.Random();
string objectName = "_SdkCore-" + random.Next(0, Int32.MaxValue);
var gameObject = new GameObject(objectName);
#if UNITY_WEBGL
gameObject.AddComponent<TaskSchedulerWebGL>();
#else
gameObject.AddComponent<TaskSchedulerThreaded>();
#endif
UnityEngine.Object.DontDestroyOnLoad(gameObject);
return gameObject;
}
}
}

11
Packages/com.unity.services.lobby/Runtime/Scheduler/GameObjectFactory.cs.meta


fileFormatVersion: 2
guid: f59c56c187fee4085bad6908534f21ba
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

59
Packages/com.unity.services.lobby/Runtime/Scheduler/TaskScheduler.cs


using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
using UnityEngine;
using System.Diagnostics;
namespace Unity.Services.Lobbies.Scheduler
{
/// <summary>
/// <para>Provides the means to schedule tasks on a background thread or the
/// main thread. Also allows for creation of co-routines from classes that do
/// not inherit from MonoBehaviour.</para>
///
/// <para>This is thread safe, through it must be constructed on the main thread.
/// </para>
/// </summary>
public abstract class TaskScheduler : MonoBehaviour
{
/// <summary>
/// Schedules a new task on a background thread.
/// </summary>
///
/// <param name="task">The task that should be executed on a background thread.</param>
public abstract void ScheduleBackgroundTask(Action task);
/// <summary>
/// Determines whether the current thread is the main thread.
/// </summary>
///
/// <returns>Whether or not this thread is the main thread.</returns>
public abstract bool IsMainThread();
/// <summary>
/// Schedules a new task on the main thread. The task will be executed during the
/// next update.
/// </summary>
///
/// <param name="task">The task that should be executed on the main thread.</param>
public abstract void ScheduleMainThreadTask(Action task);
/// <summary>
/// Executes immediately if on main thread else queue on main thread for next update.
/// </summary>
///
/// <param name="action">The task that should be executed on the main thread.</param>
public void ScheduleOrExecuteOnMain(Action action)
{
if (IsMainThread())
{
action?.Invoke();
}
else
{
ScheduleMainThreadTask(action);
}
}
}
}

11
Packages/com.unity.services.lobby/Runtime/Scheduler/TaskScheduler.cs.meta


fileFormatVersion: 2
guid: 7ce941913fb8b445daf0c8bb307cd646
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

90
Packages/com.unity.services.lobby/Runtime/Scheduler/TaskSchedulerThreaded.cs


using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
using UnityEngine;
using System.Diagnostics;
namespace Unity.Services.Lobbies.Scheduler
{
/// <summary>
/// <para>Provides the means to schedule tasks on a background thread or the
/// main thread. Also allows for creation of co-routines from classes that do
/// not inherit from MonoBehaviour.</para>
///
/// <para>This is thread safe, through it must be constructed on the main thread.
/// </para>
/// </summary>
public sealed class TaskSchedulerThreaded : TaskScheduler
{
private Queue<Action> m_mainThreadTaskQueue = new Queue<Action>();
private object m_lock = new object();
private Thread m_mainThread = null;
/// <summary>
/// Constructs a new instances of the Task Scheduler. This must be on the main
/// thread as a reference to the thread is captured.
/// </summary>
void Start()
{
m_mainThread = System.Threading.Thread.CurrentThread;
}
/// <summary>
/// Determines whether the current thread is the main thread.
/// </summary>
///
/// <returns>Whether or not this thread is the main thread.</returns>
public override bool IsMainThread()
{
return (m_mainThread == System.Threading.Thread.CurrentThread);
}
/// <summary>
/// Schedules a new task on a background thread.
/// </summary>
///
/// <param name="task">The task that should be executed on a background thread.</param>
public override void ScheduleBackgroundTask(Action task)
{
ThreadPool.QueueUserWorkItem((object state) =>
{
task();
});
}
/// <summary>
/// Schedules a new task on the main thread. The task will be executed during the
/// next update.
/// </summary>
///
/// <param name="task">The task that should be executed on the main thread.</param>
public override void ScheduleMainThreadTask(Action task)
{
lock (m_lock)
{
m_mainThreadTaskQueue.Enqueue(task);
}
}
/// <summary>
/// The update method which is called every frame. This executes any queued main
/// thread tasks.
/// </summary>
void Update()
{
Queue<Action> taskQueue = null;
lock (m_lock)
{
taskQueue = new Queue<Action>(m_mainThreadTaskQueue);
m_mainThreadTaskQueue.Clear();
}
foreach (Action action in taskQueue)
{
action();
}
}
}
}

11
Packages/com.unity.services.lobby/Runtime/Scheduler/TaskSchedulerThreaded.cs.meta


fileFormatVersion: 2
guid: 33e5c5e12d6584f5db8791f8d6f7c90c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

65
Packages/com.unity.services.lobby/Runtime/Scheduler/TaskSchedulerWebGL.cs


using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
using UnityEngine;
using System.Diagnostics;
namespace Unity.Services.Lobbies.Scheduler
{
/// <summary>
/// <para>Provides the means to schedule tasks on a background thread or the
/// main thread. Also allows for creation of co-routines from classes that do
/// not inherit from MonoBehaviour.</para>
///
/// <para>This is thread safe, through it must be constructed on the main thread.
/// </para>
/// </summary>
public sealed class TaskSchedulerWebGL : TaskScheduler
{
private Queue<Action> m_mainThreadTaskQueue = new Queue<Action>();
/// <summary>
/// Schedules a new task on a background thread.
/// NOTE: In WebGL, multi-threading isn't supported, so this will be scheduled on main thread instead.
/// </summary>
///
/// <param name="task">The task that should be executed on a background thread.</param>
public override void ScheduleBackgroundTask(Action task)
{
ScheduleMainThreadTask(task);
}
/// <summary>
/// Determines whether the current thread is the main thread.
/// WebGL currently runs on a single thread, so this will always be false.
/// </summary>
///
/// <returns>Whether or not this thread is the main thread.</returns>
public override bool IsMainThread()
{
return false;
}
/// <summary>
/// Schedules a new task on the main thread. The task will be executed during the
/// next update.
/// </summary>
///
/// <param name="task">The task that should be executed on the main thread.</param>
public override void ScheduleMainThreadTask(Action task)
{
m_mainThreadTaskQueue.Enqueue(task);
}
/// <summary>
/// The update method which is called every frame. This executes any queued main
/// thread tasks.
/// </summary>
void Update()
{
var action = m_mainThreadTaskQueue.Count > 0 ? m_mainThreadTaskQueue.Dequeue() : null;
action?.Invoke();
}
}
}

11
Packages/com.unity.services.lobby/Runtime/Scheduler/TaskSchedulerWebGL.cs.meta


fileFormatVersion: 2
guid: 77393f2539e724091a1bc1c7bee2ac20
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

部分文件因为文件数量过多而无法显示

正在加载...
取消
保存