[U] add PlayFab SDK and SNS login improvements
- Add PlayFabSDK as local package dependency - Add PlayFabTool.cs for PlayFab API integration - Implement LoginBySns method in TYSdkFacade - Add Android SNS login support in SDKManager and UnityBridgeFunc - Add Build Android With Debug menu option - Improve exception handling and timeout management 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8d731e8907f844532878b81596fe3852
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
userData:
|
||||
@@ -0,0 +1,21 @@
|
||||
#if UNITY_2017_1_OR_NEWER
|
||||
using PlayFab.PfEditor;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
public class MakeScriptableObject
|
||||
{
|
||||
[MenuItem("PlayFab/MakePlayFabSharedSettings")]
|
||||
public static void MakePlayFabSharedSettings()
|
||||
{
|
||||
PlayFabSharedSettings asset = ScriptableObject.CreateInstance<PlayFabSharedSettings>();
|
||||
|
||||
AssetDatabase.CreateAsset(asset, "Assets/PlayFabSdk/Shared/Public/Resources/PlayFabSharedSettings.asset"); // TODO: Path should not be hard coded
|
||||
AssetDatabase.SaveAssets();
|
||||
|
||||
EditorUtility.FocusProjectWindow();
|
||||
|
||||
Selection.activeObject = asset;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3e92542860dab28489c3d9cc0baa1ebd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,38 @@
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace PlayFab.PfEditor
|
||||
{
|
||||
public static class PlayFabHelp
|
||||
{
|
||||
[MenuItem("PlayFab/GettingStarted")]
|
||||
private static void GettingStarted()
|
||||
{
|
||||
Application.OpenURL("https://docs.microsoft.com/en-us/gaming/playfab/index#pivot=documentation&panel=quickstarts");
|
||||
}
|
||||
|
||||
[MenuItem("PlayFab/Docs")]
|
||||
private static void Documentation()
|
||||
{
|
||||
Application.OpenURL("https://docs.microsoft.com/en-us/gaming/playfab/api-references/");
|
||||
}
|
||||
|
||||
[MenuItem("PlayFab/Dashboard")]
|
||||
private static void Dashboard()
|
||||
{
|
||||
Application.OpenURL("https://developer.playfab.com/");
|
||||
}
|
||||
|
||||
[MenuItem("PlayFab/Forum")]
|
||||
private static void Forum()
|
||||
{
|
||||
Application.OpenURL("https://community.playfab.com/index.html");
|
||||
}
|
||||
|
||||
[MenuItem("PlayFab/Provide Feedback")]
|
||||
private static void Feedback()
|
||||
{
|
||||
Application.OpenURL("https://playfab.com/contact/");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e51e733dabbc847fa839b19c01bc577c
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"name": "PlayFabSDKEditor",
|
||||
"references": [
|
||||
"PlayFab"
|
||||
],
|
||||
"includePlatforms": [
|
||||
"Editor"
|
||||
],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": []
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8aa8a8085039f0e4ba1c8d6480d45262
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 3.4 KiB |
@@ -0,0 +1,91 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ec8f5065b10fb4f04bebf82a992c442e
|
||||
TextureImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 10
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 1
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: -1
|
||||
maxTextureSize: 1024
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: -1
|
||||
aniso: 16
|
||||
mipBias: -100
|
||||
wrapU: -1
|
||||
wrapV: -1
|
||||
wrapW: -1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 1
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 3
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 1024
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID: 5e97eb03825dee720800000000000000
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
spritePackingTag:
|
||||
pSDRemoveMatte: 0
|
||||
pSDShowRemoveMatteOption: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 91910e31dc88043ea918915ee9d665d9
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
userData:
|
||||
@@ -0,0 +1,108 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using PlayFab.Internal;
|
||||
|
||||
namespace PlayFab.Json
|
||||
{
|
||||
public class SimpleJsonInstance : ISerializerPlugin
|
||||
{
|
||||
/// <summary>
|
||||
/// Most users shouldn't access this
|
||||
/// JsonWrapper.Serialize, and JsonWrapper.Deserialize will always use it automatically (Unless you deliberately mess with them)
|
||||
/// Any Serialization of an object in the PlayFab namespace should just use JsonWrapper
|
||||
/// </summary>
|
||||
public static PlayFabSimpleJsonCuztomization ApiSerializerStrategy = new PlayFabSimpleJsonCuztomization();
|
||||
public class PlayFabSimpleJsonCuztomization : PocoJsonSerializerStrategy
|
||||
{
|
||||
/// <summary>
|
||||
/// Convert the json value into the destination field/property
|
||||
/// </summary>
|
||||
public override object DeserializeObject(object value, Type type)
|
||||
{
|
||||
var valueStr = value as string;
|
||||
if (valueStr == null) // For all of our custom conversions, value is a string
|
||||
return base.DeserializeObject(value, type);
|
||||
|
||||
var underType = Nullable.GetUnderlyingType(type);
|
||||
if (underType != null)
|
||||
return DeserializeObject(value, underType);
|
||||
else if (type.GetTypeInfo().IsEnum)
|
||||
return Enum.Parse(type, (string)value, true);
|
||||
else if (type == typeof(DateTime))
|
||||
{
|
||||
DateTime output;
|
||||
var result = DateTime.TryParseExact(valueStr, PlayFabUtil._defaultDateTimeFormats, CultureInfo.InvariantCulture, PlayFabUtil.DateTimeStyles, out output);
|
||||
if (result)
|
||||
return output;
|
||||
}
|
||||
else if (type == typeof(DateTimeOffset))
|
||||
{
|
||||
DateTimeOffset output;
|
||||
var result = DateTimeOffset.TryParseExact(valueStr, PlayFabUtil._defaultDateTimeFormats, CultureInfo.InvariantCulture, PlayFabUtil.DateTimeStyles, out output);
|
||||
if (result)
|
||||
return output;
|
||||
}
|
||||
else if (type == typeof(TimeSpan))
|
||||
{
|
||||
double seconds;
|
||||
if (double.TryParse(valueStr, out seconds))
|
||||
return TimeSpan.FromSeconds(seconds);
|
||||
}
|
||||
return base.DeserializeObject(value, type);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set output to a string that represents the input object
|
||||
/// </summary>
|
||||
protected override bool TrySerializeKnownTypes(object input, out object output)
|
||||
{
|
||||
if (input.GetType().GetTypeInfo().IsEnum)
|
||||
{
|
||||
output = input.ToString();
|
||||
return true;
|
||||
}
|
||||
else if (input is DateTime)
|
||||
{
|
||||
output = ((DateTime)input).ToString(PlayFabUtil._defaultDateTimeFormats[PlayFabUtil.DEFAULT_UTC_OUTPUT_INDEX], CultureInfo.InvariantCulture);
|
||||
return true;
|
||||
}
|
||||
else if (input is DateTimeOffset)
|
||||
{
|
||||
output = ((DateTimeOffset)input).ToString(PlayFabUtil._defaultDateTimeFormats[PlayFabUtil.DEFAULT_UTC_OUTPUT_INDEX], CultureInfo.InvariantCulture);
|
||||
return true;
|
||||
}
|
||||
else if (input is TimeSpan)
|
||||
{
|
||||
output = ((TimeSpan)input).TotalSeconds;
|
||||
return true;
|
||||
}
|
||||
return base.TrySerializeKnownTypes(input, out output);
|
||||
}
|
||||
}
|
||||
|
||||
public T DeserializeObject<T>(string json)
|
||||
{
|
||||
return PlayFabSimpleJson.DeserializeObject<T>(json, ApiSerializerStrategy);
|
||||
}
|
||||
|
||||
public T DeserializeObject<T>(string json, object jsonSerializerStrategy)
|
||||
{
|
||||
return PlayFabSimpleJson.DeserializeObject<T>(json, (IJsonSerializerStrategy)jsonSerializerStrategy);
|
||||
}
|
||||
|
||||
public object DeserializeObject(string json)
|
||||
{
|
||||
return PlayFabSimpleJson.DeserializeObject(json, typeof(object), ApiSerializerStrategy);
|
||||
}
|
||||
|
||||
public string SerializeObject(object json)
|
||||
{
|
||||
return PlayFabSimpleJson.SerializeObject(json, ApiSerializerStrategy);
|
||||
}
|
||||
|
||||
public string SerializeObject(object json, object jsonSerializerStrategy)
|
||||
{
|
||||
return PlayFabSimpleJson.SerializeObject(json, (IJsonSerializerStrategy)jsonSerializerStrategy);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1337f8c156b41834691b131f3b6774f9
|
||||
timeCreated: 1462682372
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,44 @@
|
||||
using System;
|
||||
|
||||
namespace PlayFab.Internal
|
||||
{
|
||||
[Obsolete("This logging utility has been deprecated. Use UnityEngine.Debug.Log")]
|
||||
public static class Log
|
||||
{
|
||||
[Obsolete("Debug is deprecated.")]
|
||||
public static void Debug(string text, params object[] args)
|
||||
{
|
||||
if ((PlayFabSettings.LogLevel & PlayFabLogLevel.Debug) != 0)
|
||||
{
|
||||
UnityEngine.Debug.Log(PlayFabUtil.timeStamp + " DEBUG: " + PlayFabUtil.Format(text, args));
|
||||
}
|
||||
}
|
||||
|
||||
[Obsolete("Info is deprecated.")]
|
||||
public static void Info(string text, params object[] args)
|
||||
{
|
||||
if ((PlayFabSettings.LogLevel & PlayFabLogLevel.Info) != 0)
|
||||
{
|
||||
UnityEngine.Debug.Log(PlayFabUtil.timeStamp + " INFO: " + PlayFabUtil.Format(text, args));
|
||||
}
|
||||
}
|
||||
|
||||
[Obsolete("Warning is deprecated.")]
|
||||
public static void Warning(string text, params object[] args)
|
||||
{
|
||||
if ((PlayFabSettings.LogLevel & PlayFabLogLevel.Warning) != 0)
|
||||
{
|
||||
UnityEngine.Debug.LogWarning(PlayFabUtil.timeStamp + " WARNING: " + PlayFabUtil.Format(text, args));
|
||||
}
|
||||
}
|
||||
|
||||
[Obsolete("Error is deprecated.")]
|
||||
public static void Error(string text, params object[] args)
|
||||
{
|
||||
if ((PlayFabSettings.LogLevel & PlayFabLogLevel.Error) != 0)
|
||||
{
|
||||
UnityEngine.Debug.LogError(PlayFabUtil.timeStamp + " ERROR: " + PlayFabUtil.Format(text, args));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5b55790eeab1b3c41a4f1381cbea1213
|
||||
timeCreated: 1462682372
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,808 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace PlayFab
|
||||
{
|
||||
/// <summary>
|
||||
/// Error codes returned by PlayFabAPIs
|
||||
/// </summary>
|
||||
public enum PlayFabErrorCode
|
||||
{
|
||||
Unknown = 1,
|
||||
ConnectionError = 2,
|
||||
JsonParseError = 3,
|
||||
Success = 0,
|
||||
UnkownError = 500,
|
||||
InvalidParams = 1000,
|
||||
AccountNotFound = 1001,
|
||||
AccountBanned = 1002,
|
||||
InvalidUsernameOrPassword = 1003,
|
||||
InvalidTitleId = 1004,
|
||||
InvalidEmailAddress = 1005,
|
||||
EmailAddressNotAvailable = 1006,
|
||||
InvalidUsername = 1007,
|
||||
InvalidPassword = 1008,
|
||||
UsernameNotAvailable = 1009,
|
||||
InvalidSteamTicket = 1010,
|
||||
AccountAlreadyLinked = 1011,
|
||||
LinkedAccountAlreadyClaimed = 1012,
|
||||
InvalidFacebookToken = 1013,
|
||||
AccountNotLinked = 1014,
|
||||
FailedByPaymentProvider = 1015,
|
||||
CouponCodeNotFound = 1016,
|
||||
InvalidContainerItem = 1017,
|
||||
ContainerNotOwned = 1018,
|
||||
KeyNotOwned = 1019,
|
||||
InvalidItemIdInTable = 1020,
|
||||
InvalidReceipt = 1021,
|
||||
ReceiptAlreadyUsed = 1022,
|
||||
ReceiptCancelled = 1023,
|
||||
GameNotFound = 1024,
|
||||
GameModeNotFound = 1025,
|
||||
InvalidGoogleToken = 1026,
|
||||
UserIsNotPartOfDeveloper = 1027,
|
||||
InvalidTitleForDeveloper = 1028,
|
||||
TitleNameConflicts = 1029,
|
||||
UserisNotValid = 1030,
|
||||
ValueAlreadyExists = 1031,
|
||||
BuildNotFound = 1032,
|
||||
PlayerNotInGame = 1033,
|
||||
InvalidTicket = 1034,
|
||||
InvalidDeveloper = 1035,
|
||||
InvalidOrderInfo = 1036,
|
||||
RegistrationIncomplete = 1037,
|
||||
InvalidPlatform = 1038,
|
||||
UnknownError = 1039,
|
||||
SteamApplicationNotOwned = 1040,
|
||||
WrongSteamAccount = 1041,
|
||||
TitleNotActivated = 1042,
|
||||
RegistrationSessionNotFound = 1043,
|
||||
NoSuchMod = 1044,
|
||||
FileNotFound = 1045,
|
||||
DuplicateEmail = 1046,
|
||||
ItemNotFound = 1047,
|
||||
ItemNotOwned = 1048,
|
||||
ItemNotRecycleable = 1049,
|
||||
ItemNotAffordable = 1050,
|
||||
InvalidVirtualCurrency = 1051,
|
||||
WrongVirtualCurrency = 1052,
|
||||
WrongPrice = 1053,
|
||||
NonPositiveValue = 1054,
|
||||
InvalidRegion = 1055,
|
||||
RegionAtCapacity = 1056,
|
||||
ServerFailedToStart = 1057,
|
||||
NameNotAvailable = 1058,
|
||||
InsufficientFunds = 1059,
|
||||
InvalidDeviceID = 1060,
|
||||
InvalidPushNotificationToken = 1061,
|
||||
NoRemainingUses = 1062,
|
||||
InvalidPaymentProvider = 1063,
|
||||
PurchaseInitializationFailure = 1064,
|
||||
DuplicateUsername = 1065,
|
||||
InvalidBuyerInfo = 1066,
|
||||
NoGameModeParamsSet = 1067,
|
||||
BodyTooLarge = 1068,
|
||||
ReservedWordInBody = 1069,
|
||||
InvalidTypeInBody = 1070,
|
||||
InvalidRequest = 1071,
|
||||
ReservedEventName = 1072,
|
||||
InvalidUserStatistics = 1073,
|
||||
NotAuthenticated = 1074,
|
||||
StreamAlreadyExists = 1075,
|
||||
ErrorCreatingStream = 1076,
|
||||
StreamNotFound = 1077,
|
||||
InvalidAccount = 1078,
|
||||
PurchaseDoesNotExist = 1080,
|
||||
InvalidPurchaseTransactionStatus = 1081,
|
||||
APINotEnabledForGameClientAccess = 1082,
|
||||
NoPushNotificationARNForTitle = 1083,
|
||||
BuildAlreadyExists = 1084,
|
||||
BuildPackageDoesNotExist = 1085,
|
||||
CustomAnalyticsEventsNotEnabledForTitle = 1087,
|
||||
InvalidSharedGroupId = 1088,
|
||||
NotAuthorized = 1089,
|
||||
MissingTitleGoogleProperties = 1090,
|
||||
InvalidItemProperties = 1091,
|
||||
InvalidPSNAuthCode = 1092,
|
||||
InvalidItemId = 1093,
|
||||
PushNotEnabledForAccount = 1094,
|
||||
PushServiceError = 1095,
|
||||
ReceiptDoesNotContainInAppItems = 1096,
|
||||
ReceiptContainsMultipleInAppItems = 1097,
|
||||
InvalidBundleID = 1098,
|
||||
JavascriptException = 1099,
|
||||
InvalidSessionTicket = 1100,
|
||||
UnableToConnectToDatabase = 1101,
|
||||
InternalServerError = 1110,
|
||||
InvalidReportDate = 1111,
|
||||
ReportNotAvailable = 1112,
|
||||
DatabaseThroughputExceeded = 1113,
|
||||
InvalidGameTicket = 1115,
|
||||
ExpiredGameTicket = 1116,
|
||||
GameTicketDoesNotMatchLobby = 1117,
|
||||
LinkedDeviceAlreadyClaimed = 1118,
|
||||
DeviceAlreadyLinked = 1119,
|
||||
DeviceNotLinked = 1120,
|
||||
PartialFailure = 1121,
|
||||
PublisherNotSet = 1122,
|
||||
ServiceUnavailable = 1123,
|
||||
VersionNotFound = 1124,
|
||||
RevisionNotFound = 1125,
|
||||
InvalidPublisherId = 1126,
|
||||
DownstreamServiceUnavailable = 1127,
|
||||
APINotIncludedInTitleUsageTier = 1128,
|
||||
DAULimitExceeded = 1129,
|
||||
APIRequestLimitExceeded = 1130,
|
||||
InvalidAPIEndpoint = 1131,
|
||||
BuildNotAvailable = 1132,
|
||||
ConcurrentEditError = 1133,
|
||||
ContentNotFound = 1134,
|
||||
CharacterNotFound = 1135,
|
||||
CloudScriptNotFound = 1136,
|
||||
ContentQuotaExceeded = 1137,
|
||||
InvalidCharacterStatistics = 1138,
|
||||
PhotonNotEnabledForTitle = 1139,
|
||||
PhotonApplicationNotFound = 1140,
|
||||
PhotonApplicationNotAssociatedWithTitle = 1141,
|
||||
InvalidEmailOrPassword = 1142,
|
||||
FacebookAPIError = 1143,
|
||||
InvalidContentType = 1144,
|
||||
KeyLengthExceeded = 1145,
|
||||
DataLengthExceeded = 1146,
|
||||
TooManyKeys = 1147,
|
||||
FreeTierCannotHaveVirtualCurrency = 1148,
|
||||
MissingAmazonSharedKey = 1149,
|
||||
AmazonValidationError = 1150,
|
||||
InvalidPSNIssuerId = 1151,
|
||||
PSNInaccessible = 1152,
|
||||
ExpiredAuthToken = 1153,
|
||||
FailedToGetEntitlements = 1154,
|
||||
FailedToConsumeEntitlement = 1155,
|
||||
TradeAcceptingUserNotAllowed = 1156,
|
||||
TradeInventoryItemIsAssignedToCharacter = 1157,
|
||||
TradeInventoryItemIsBundle = 1158,
|
||||
TradeStatusNotValidForCancelling = 1159,
|
||||
TradeStatusNotValidForAccepting = 1160,
|
||||
TradeDoesNotExist = 1161,
|
||||
TradeCancelled = 1162,
|
||||
TradeAlreadyFilled = 1163,
|
||||
TradeWaitForStatusTimeout = 1164,
|
||||
TradeInventoryItemExpired = 1165,
|
||||
TradeMissingOfferedAndAcceptedItems = 1166,
|
||||
TradeAcceptedItemIsBundle = 1167,
|
||||
TradeAcceptedItemIsStackable = 1168,
|
||||
TradeInventoryItemInvalidStatus = 1169,
|
||||
TradeAcceptedCatalogItemInvalid = 1170,
|
||||
TradeAllowedUsersInvalid = 1171,
|
||||
TradeInventoryItemDoesNotExist = 1172,
|
||||
TradeInventoryItemIsConsumed = 1173,
|
||||
TradeInventoryItemIsStackable = 1174,
|
||||
TradeAcceptedItemsMismatch = 1175,
|
||||
InvalidKongregateToken = 1176,
|
||||
FeatureNotConfiguredForTitle = 1177,
|
||||
NoMatchingCatalogItemForReceipt = 1178,
|
||||
InvalidCurrencyCode = 1179,
|
||||
NoRealMoneyPriceForCatalogItem = 1180,
|
||||
TradeInventoryItemIsNotTradable = 1181,
|
||||
TradeAcceptedCatalogItemIsNotTradable = 1182,
|
||||
UsersAlreadyFriends = 1183,
|
||||
LinkedIdentifierAlreadyClaimed = 1184,
|
||||
CustomIdNotLinked = 1185,
|
||||
TotalDataSizeExceeded = 1186,
|
||||
DeleteKeyConflict = 1187,
|
||||
InvalidXboxLiveToken = 1188,
|
||||
ExpiredXboxLiveToken = 1189,
|
||||
ResettableStatisticVersionRequired = 1190,
|
||||
NotAuthorizedByTitle = 1191,
|
||||
NoPartnerEnabled = 1192,
|
||||
InvalidPartnerResponse = 1193,
|
||||
APINotEnabledForGameServerAccess = 1194,
|
||||
StatisticNotFound = 1195,
|
||||
StatisticNameConflict = 1196,
|
||||
StatisticVersionClosedForWrites = 1197,
|
||||
StatisticVersionInvalid = 1198,
|
||||
APIClientRequestRateLimitExceeded = 1199,
|
||||
InvalidJSONContent = 1200,
|
||||
InvalidDropTable = 1201,
|
||||
StatisticVersionAlreadyIncrementedForScheduledInterval = 1202,
|
||||
StatisticCountLimitExceeded = 1203,
|
||||
StatisticVersionIncrementRateExceeded = 1204,
|
||||
ContainerKeyInvalid = 1205,
|
||||
CloudScriptExecutionTimeLimitExceeded = 1206,
|
||||
NoWritePermissionsForEvent = 1207,
|
||||
CloudScriptFunctionArgumentSizeExceeded = 1208,
|
||||
CloudScriptAPIRequestCountExceeded = 1209,
|
||||
CloudScriptAPIRequestError = 1210,
|
||||
CloudScriptHTTPRequestError = 1211,
|
||||
InsufficientGuildRole = 1212,
|
||||
GuildNotFound = 1213,
|
||||
OverLimit = 1214,
|
||||
EventNotFound = 1215,
|
||||
InvalidEventField = 1216,
|
||||
InvalidEventName = 1217,
|
||||
CatalogNotConfigured = 1218,
|
||||
OperationNotSupportedForPlatform = 1219,
|
||||
SegmentNotFound = 1220,
|
||||
StoreNotFound = 1221,
|
||||
InvalidStatisticName = 1222,
|
||||
TitleNotQualifiedForLimit = 1223,
|
||||
InvalidServiceLimitLevel = 1224,
|
||||
ServiceLimitLevelInTransition = 1225,
|
||||
CouponAlreadyRedeemed = 1226,
|
||||
GameServerBuildSizeLimitExceeded = 1227,
|
||||
GameServerBuildCountLimitExceeded = 1228,
|
||||
VirtualCurrencyCountLimitExceeded = 1229,
|
||||
VirtualCurrencyCodeExists = 1230,
|
||||
TitleNewsItemCountLimitExceeded = 1231,
|
||||
InvalidTwitchToken = 1232,
|
||||
TwitchResponseError = 1233,
|
||||
ProfaneDisplayName = 1234,
|
||||
UserAlreadyAdded = 1235,
|
||||
InvalidVirtualCurrencyCode = 1236,
|
||||
VirtualCurrencyCannotBeDeleted = 1237,
|
||||
IdentifierAlreadyClaimed = 1238,
|
||||
IdentifierNotLinked = 1239,
|
||||
InvalidContinuationToken = 1240,
|
||||
ExpiredContinuationToken = 1241,
|
||||
InvalidSegment = 1242,
|
||||
InvalidSessionId = 1243,
|
||||
SessionLogNotFound = 1244,
|
||||
InvalidSearchTerm = 1245,
|
||||
TwoFactorAuthenticationTokenRequired = 1246,
|
||||
GameServerHostCountLimitExceeded = 1247,
|
||||
PlayerTagCountLimitExceeded = 1248,
|
||||
RequestAlreadyRunning = 1249,
|
||||
ActionGroupNotFound = 1250,
|
||||
MaximumSegmentBulkActionJobsRunning = 1251,
|
||||
NoActionsOnPlayersInSegmentJob = 1252,
|
||||
DuplicateStatisticName = 1253,
|
||||
ScheduledTaskNameConflict = 1254,
|
||||
ScheduledTaskCreateConflict = 1255,
|
||||
InvalidScheduledTaskName = 1256,
|
||||
InvalidTaskSchedule = 1257,
|
||||
SteamNotEnabledForTitle = 1258,
|
||||
LimitNotAnUpgradeOption = 1259,
|
||||
NoSecretKeyEnabledForCloudScript = 1260,
|
||||
TaskNotFound = 1261,
|
||||
TaskInstanceNotFound = 1262,
|
||||
InvalidIdentityProviderId = 1263,
|
||||
MisconfiguredIdentityProvider = 1264,
|
||||
InvalidScheduledTaskType = 1265,
|
||||
BillingInformationRequired = 1266,
|
||||
LimitedEditionItemUnavailable = 1267,
|
||||
InvalidAdPlacementAndReward = 1268,
|
||||
AllAdPlacementViewsAlreadyConsumed = 1269,
|
||||
GoogleOAuthNotConfiguredForTitle = 1270,
|
||||
GoogleOAuthError = 1271,
|
||||
UserNotFriend = 1272,
|
||||
InvalidSignature = 1273,
|
||||
InvalidPublicKey = 1274,
|
||||
GoogleOAuthNoIdTokenIncludedInResponse = 1275,
|
||||
StatisticUpdateInProgress = 1276,
|
||||
LeaderboardVersionNotAvailable = 1277,
|
||||
StatisticAlreadyHasPrizeTable = 1279,
|
||||
PrizeTableHasOverlappingRanks = 1280,
|
||||
PrizeTableHasMissingRanks = 1281,
|
||||
PrizeTableRankStartsAtZero = 1282,
|
||||
InvalidStatistic = 1283,
|
||||
ExpressionParseFailure = 1284,
|
||||
ExpressionInvokeFailure = 1285,
|
||||
ExpressionTooLong = 1286,
|
||||
DataUpdateRateExceeded = 1287,
|
||||
RestrictedEmailDomain = 1288,
|
||||
EncryptionKeyDisabled = 1289,
|
||||
EncryptionKeyMissing = 1290,
|
||||
EncryptionKeyBroken = 1291,
|
||||
NoSharedSecretKeyConfigured = 1292,
|
||||
SecretKeyNotFound = 1293,
|
||||
PlayerSecretAlreadyConfigured = 1294,
|
||||
APIRequestsDisabledForTitle = 1295,
|
||||
InvalidSharedSecretKey = 1296,
|
||||
PrizeTableHasNoRanks = 1297,
|
||||
ProfileDoesNotExist = 1298,
|
||||
ContentS3OriginBucketNotConfigured = 1299,
|
||||
InvalidEnvironmentForReceipt = 1300,
|
||||
EncryptedRequestNotAllowed = 1301,
|
||||
SignedRequestNotAllowed = 1302,
|
||||
RequestViewConstraintParamsNotAllowed = 1303,
|
||||
BadPartnerConfiguration = 1304,
|
||||
XboxBPCertificateFailure = 1305,
|
||||
XboxXASSExchangeFailure = 1306,
|
||||
InvalidEntityId = 1307,
|
||||
StatisticValueAggregationOverflow = 1308,
|
||||
EmailMessageFromAddressIsMissing = 1309,
|
||||
EmailMessageToAddressIsMissing = 1310,
|
||||
SmtpServerAuthenticationError = 1311,
|
||||
SmtpServerLimitExceeded = 1312,
|
||||
SmtpServerInsufficientStorage = 1313,
|
||||
SmtpServerCommunicationError = 1314,
|
||||
SmtpServerGeneralFailure = 1315,
|
||||
EmailClientTimeout = 1316,
|
||||
EmailClientCanceledTask = 1317,
|
||||
EmailTemplateMissing = 1318,
|
||||
InvalidHostForTitleId = 1319,
|
||||
EmailConfirmationTokenDoesNotExist = 1320,
|
||||
EmailConfirmationTokenExpired = 1321,
|
||||
AccountDeleted = 1322,
|
||||
PlayerSecretNotConfigured = 1323,
|
||||
InvalidSignatureTime = 1324,
|
||||
NoContactEmailAddressFound = 1325,
|
||||
InvalidAuthToken = 1326,
|
||||
AuthTokenDoesNotExist = 1327,
|
||||
AuthTokenExpired = 1328,
|
||||
AuthTokenAlreadyUsedToResetPassword = 1329,
|
||||
MembershipNameTooLong = 1330,
|
||||
MembershipNotFound = 1331,
|
||||
GoogleServiceAccountInvalid = 1332,
|
||||
GoogleServiceAccountParseFailure = 1333,
|
||||
EntityTokenMissing = 1334,
|
||||
EntityTokenInvalid = 1335,
|
||||
EntityTokenExpired = 1336,
|
||||
EntityTokenRevoked = 1337,
|
||||
InvalidProductForSubscription = 1338,
|
||||
XboxInaccessible = 1339,
|
||||
SubscriptionAlreadyTaken = 1340,
|
||||
SmtpAddonNotEnabled = 1341,
|
||||
APIConcurrentRequestLimitExceeded = 1342,
|
||||
XboxRejectedXSTSExchangeRequest = 1343,
|
||||
VariableNotDefined = 1344,
|
||||
TemplateVersionNotDefined = 1345,
|
||||
FileTooLarge = 1346,
|
||||
TitleDeleted = 1347,
|
||||
TitleContainsUserAccounts = 1348,
|
||||
TitleDeletionPlayerCleanupFailure = 1349,
|
||||
EntityFileOperationPending = 1350,
|
||||
NoEntityFileOperationPending = 1351,
|
||||
EntityProfileVersionMismatch = 1352,
|
||||
TemplateVersionTooOld = 1353,
|
||||
MembershipDefinitionInUse = 1354,
|
||||
PaymentPageNotConfigured = 1355,
|
||||
FailedLoginAttemptRateLimitExceeded = 1356,
|
||||
EntityBlockedByGroup = 1357,
|
||||
RoleDoesNotExist = 1358,
|
||||
EntityIsAlreadyMember = 1359,
|
||||
DuplicateRoleId = 1360,
|
||||
GroupInvitationNotFound = 1361,
|
||||
GroupApplicationNotFound = 1362,
|
||||
OutstandingInvitationAcceptedInstead = 1363,
|
||||
OutstandingApplicationAcceptedInstead = 1364,
|
||||
RoleIsGroupDefaultMember = 1365,
|
||||
RoleIsGroupAdmin = 1366,
|
||||
RoleNameNotAvailable = 1367,
|
||||
GroupNameNotAvailable = 1368,
|
||||
EmailReportAlreadySent = 1369,
|
||||
EmailReportRecipientBlacklisted = 1370,
|
||||
EventNamespaceNotAllowed = 1371,
|
||||
EventEntityNotAllowed = 1372,
|
||||
InvalidEntityType = 1373,
|
||||
NullTokenResultFromAad = 1374,
|
||||
InvalidTokenResultFromAad = 1375,
|
||||
NoValidCertificateForAad = 1376,
|
||||
InvalidCertificateForAad = 1377,
|
||||
DuplicateDropTableId = 1378,
|
||||
MultiplayerServerError = 1379,
|
||||
MultiplayerServerTooManyRequests = 1380,
|
||||
MultiplayerServerNoContent = 1381,
|
||||
MultiplayerServerBadRequest = 1382,
|
||||
MultiplayerServerUnauthorized = 1383,
|
||||
MultiplayerServerForbidden = 1384,
|
||||
MultiplayerServerNotFound = 1385,
|
||||
MultiplayerServerConflict = 1386,
|
||||
MultiplayerServerInternalServerError = 1387,
|
||||
MultiplayerServerUnavailable = 1388,
|
||||
ExplicitContentDetected = 1389,
|
||||
PIIContentDetected = 1390,
|
||||
InvalidScheduledTaskParameter = 1391,
|
||||
PerEntityEventRateLimitExceeded = 1392,
|
||||
TitleDefaultLanguageNotSet = 1393,
|
||||
EmailTemplateMissingDefaultVersion = 1394,
|
||||
FacebookInstantGamesIdNotLinked = 1395,
|
||||
InvalidFacebookInstantGamesSignature = 1396,
|
||||
FacebookInstantGamesAuthNotConfiguredForTitle = 1397,
|
||||
EntityProfileConstraintValidationFailed = 1398,
|
||||
TelemetryIngestionKeyPending = 1399,
|
||||
TelemetryIngestionKeyNotFound = 1400,
|
||||
StatisticChildNameInvalid = 1402,
|
||||
DataIntegrityError = 1403,
|
||||
VirtualCurrencyCannotBeSetToOlderVersion = 1404,
|
||||
VirtualCurrencyMustBeWithinIntegerRange = 1405,
|
||||
EmailTemplateInvalidSyntax = 1406,
|
||||
EmailTemplateMissingCallback = 1407,
|
||||
PushNotificationTemplateInvalidPayload = 1408,
|
||||
InvalidLocalizedPushNotificationLanguage = 1409,
|
||||
MissingLocalizedPushNotificationMessage = 1410,
|
||||
PushNotificationTemplateMissingPlatformPayload = 1411,
|
||||
PushNotificationTemplatePayloadContainsInvalidJson = 1412,
|
||||
PushNotificationTemplateContainsInvalidIosPayload = 1413,
|
||||
PushNotificationTemplateContainsInvalidAndroidPayload = 1414,
|
||||
PushNotificationTemplateIosPayloadMissingNotificationBody = 1415,
|
||||
PushNotificationTemplateAndroidPayloadMissingNotificationBody = 1416,
|
||||
PushNotificationTemplateNotFound = 1417,
|
||||
PushNotificationTemplateMissingDefaultVersion = 1418,
|
||||
PushNotificationTemplateInvalidSyntax = 1419,
|
||||
PushNotificationTemplateNoCustomPayloadForV1 = 1420,
|
||||
NoLeaderboardForStatistic = 1421,
|
||||
TitleNewsMissingDefaultLanguage = 1422,
|
||||
TitleNewsNotFound = 1423,
|
||||
TitleNewsDuplicateLanguage = 1424,
|
||||
TitleNewsMissingTitleOrBody = 1425,
|
||||
TitleNewsInvalidLanguage = 1426,
|
||||
EmailRecipientBlacklisted = 1427,
|
||||
InvalidGameCenterAuthRequest = 1428,
|
||||
GameCenterAuthenticationFailed = 1429,
|
||||
CannotEnablePartiesForTitle = 1430,
|
||||
PartyError = 1431,
|
||||
PartyRequests = 1432,
|
||||
PartyNoContent = 1433,
|
||||
PartyBadRequest = 1434,
|
||||
PartyUnauthorized = 1435,
|
||||
PartyForbidden = 1436,
|
||||
PartyNotFound = 1437,
|
||||
PartyConflict = 1438,
|
||||
PartyInternalServerError = 1439,
|
||||
PartyUnavailable = 1440,
|
||||
PartyTooManyRequests = 1441,
|
||||
PushNotificationTemplateMissingName = 1442,
|
||||
CannotEnableMultiplayerServersForTitle = 1443,
|
||||
WriteAttemptedDuringExport = 1444,
|
||||
MultiplayerServerTitleQuotaCoresExceeded = 1445,
|
||||
AutomationRuleNotFound = 1446,
|
||||
EntityAPIKeyLimitExceeded = 1447,
|
||||
EntityAPIKeyNotFound = 1448,
|
||||
EntityAPIKeyOrSecretInvalid = 1449,
|
||||
EconomyServiceUnavailable = 1450,
|
||||
EconomyServiceInternalError = 1451,
|
||||
QueryRateLimitExceeded = 1452,
|
||||
EntityAPIKeyCreationDisabledForEntity = 1453,
|
||||
ForbiddenByEntityPolicy = 1454,
|
||||
UpdateInventoryRateLimitExceeded = 1455,
|
||||
StudioCreationRateLimited = 1456,
|
||||
StudioCreationInProgress = 1457,
|
||||
DuplicateStudioName = 1458,
|
||||
StudioNotFound = 1459,
|
||||
StudioDeleted = 1460,
|
||||
StudioDeactivated = 1461,
|
||||
StudioActivated = 1462,
|
||||
TitleCreationRateLimited = 1463,
|
||||
TitleCreationInProgress = 1464,
|
||||
DuplicateTitleName = 1465,
|
||||
TitleActivationRateLimited = 1466,
|
||||
TitleActivationInProgress = 1467,
|
||||
TitleDeactivated = 1468,
|
||||
TitleActivated = 1469,
|
||||
CloudScriptAzureFunctionsExecutionTimeLimitExceeded = 1470,
|
||||
CloudScriptAzureFunctionsArgumentSizeExceeded = 1471,
|
||||
CloudScriptAzureFunctionsReturnSizeExceeded = 1472,
|
||||
CloudScriptAzureFunctionsHTTPRequestError = 1473,
|
||||
VirtualCurrencyBetaGetError = 1474,
|
||||
VirtualCurrencyBetaCreateError = 1475,
|
||||
VirtualCurrencyBetaInitialDepositSaveError = 1476,
|
||||
VirtualCurrencyBetaSaveError = 1477,
|
||||
VirtualCurrencyBetaDeleteError = 1478,
|
||||
VirtualCurrencyBetaRestoreError = 1479,
|
||||
VirtualCurrencyBetaSaveConflict = 1480,
|
||||
VirtualCurrencyBetaUpdateError = 1481,
|
||||
InsightsManagementDatabaseNotFound = 1482,
|
||||
InsightsManagementOperationNotFound = 1483,
|
||||
InsightsManagementErrorPendingOperationExists = 1484,
|
||||
InsightsManagementSetPerformanceLevelInvalidParameter = 1485,
|
||||
InsightsManagementSetStorageRetentionInvalidParameter = 1486,
|
||||
InsightsManagementGetStorageUsageInvalidParameter = 1487,
|
||||
InsightsManagementGetOperationStatusInvalidParameter = 1488,
|
||||
DuplicatePurchaseTransactionId = 1489,
|
||||
EvaluationModePlayerCountExceeded = 1490,
|
||||
GetPlayersInSegmentRateLimitExceeded = 1491,
|
||||
CloudScriptFunctionNameSizeExceeded = 1492,
|
||||
PaidInsightsFeaturesNotEnabled = 1493,
|
||||
CloudScriptAzureFunctionsQueueRequestError = 1494,
|
||||
EvaluationModeTitleCountExceeded = 1495,
|
||||
InsightsManagementTitleNotInFlight = 1496,
|
||||
LimitNotFound = 1497,
|
||||
LimitNotAvailableViaAPI = 1498,
|
||||
InsightsManagementSetStorageRetentionBelowMinimum = 1499,
|
||||
InsightsManagementSetStorageRetentionAboveMaximum = 1500,
|
||||
AppleNotEnabledForTitle = 1501,
|
||||
InsightsManagementNewActiveEventExportLimitInvalid = 1502,
|
||||
InsightsManagementSetPerformanceRateLimited = 1503,
|
||||
PartyRequestsThrottledFromRateLimiter = 1504,
|
||||
XboxServiceTooManyRequests = 1505,
|
||||
NintendoSwitchNotEnabledForTitle = 1506,
|
||||
RequestMultiplayerServersThrottledFromRateLimiter = 1507,
|
||||
TitleDataOverrideNotFound = 1508,
|
||||
DuplicateKeys = 1509,
|
||||
WasNotCreatedWithCloudRoot = 1510,
|
||||
LegacyMultiplayerServersDeprecated = 1511,
|
||||
VirtualCurrencyCurrentlyUnavailable = 1512,
|
||||
SteamUserNotFound = 1513,
|
||||
ElasticSearchOperationFailed = 1514,
|
||||
NotImplemented = 1515,
|
||||
PublisherNotFound = 1516,
|
||||
PublisherDeleted = 1517,
|
||||
ApiDisabledForMigration = 1518,
|
||||
ResourceNameUpdateNotAllowed = 1519,
|
||||
ApiNotEnabledForTitle = 1520,
|
||||
DuplicateTitleNameForPublisher = 1521,
|
||||
AzureTitleCreationInProgress = 1522,
|
||||
TitleConstraintsPublisherDeletion = 1524,
|
||||
InvalidPlayerAccountPoolId = 1525,
|
||||
PlayerAccountPoolNotFound = 1526,
|
||||
PlayerAccountPoolDeleted = 1527,
|
||||
TitleCleanupInProgress = 1528,
|
||||
AzureResourceConcurrentOperationInProgress = 1529,
|
||||
TitlePublisherUpdateNotAllowed = 1530,
|
||||
AzureResourceManagerNotSupportedInStamp = 1531,
|
||||
ApiNotIncludedInAzurePlayFabFeatureSet = 1532,
|
||||
GoogleServiceAccountFailedAuth = 1533,
|
||||
GoogleAPIServiceUnavailable = 1534,
|
||||
GoogleAPIServiceUnknownError = 1535,
|
||||
NoValidIdentityForAad = 1536,
|
||||
PlayerIdentityLinkNotFound = 1537,
|
||||
PhotonApplicationIdAlreadyInUse = 1538,
|
||||
CloudScriptUnableToDeleteProductionRevision = 1539,
|
||||
CustomIdNotFound = 1540,
|
||||
AutomationInvalidInput = 1541,
|
||||
AutomationInvalidRuleName = 1542,
|
||||
AutomationRuleAlreadyExists = 1543,
|
||||
AutomationRuleLimitExceeded = 1544,
|
||||
InvalidGooglePlayGamesServerAuthCode = 1545,
|
||||
PlayStreamConnectionFailed = 1547,
|
||||
InvalidEventContents = 1548,
|
||||
InsightsV1Deprecated = 1549,
|
||||
AnalysisSubscriptionNotFound = 1550,
|
||||
AnalysisSubscriptionFailed = 1551,
|
||||
AnalysisSubscriptionFoundAlready = 1552,
|
||||
AnalysisSubscriptionManagementInvalidInput = 1553,
|
||||
InvalidGameCenterId = 1554,
|
||||
InvalidNintendoSwitchAccountId = 1555,
|
||||
EntityAPIKeysNotSupported = 1556,
|
||||
IpAddressBanned = 1557,
|
||||
EntityLineageBanned = 1558,
|
||||
NamespaceMismatch = 1559,
|
||||
InvalidServiceConfiguration = 1560,
|
||||
InvalidNamespaceMismatch = 1561,
|
||||
MatchmakingEntityInvalid = 2001,
|
||||
MatchmakingPlayerAttributesInvalid = 2002,
|
||||
MatchmakingQueueNotFound = 2016,
|
||||
MatchmakingMatchNotFound = 2017,
|
||||
MatchmakingTicketNotFound = 2018,
|
||||
MatchmakingAlreadyJoinedTicket = 2028,
|
||||
MatchmakingTicketAlreadyCompleted = 2029,
|
||||
MatchmakingQueueConfigInvalid = 2031,
|
||||
MatchmakingMemberProfileInvalid = 2032,
|
||||
NintendoSwitchDeviceIdNotLinked = 2034,
|
||||
MatchmakingNotEnabled = 2035,
|
||||
MatchmakingPlayerAttributesTooLarge = 2043,
|
||||
MatchmakingNumberOfPlayersInTicketTooLarge = 2044,
|
||||
MatchmakingAttributeInvalid = 2046,
|
||||
MatchmakingPlayerHasNotJoinedTicket = 2053,
|
||||
MatchmakingRateLimitExceeded = 2054,
|
||||
MatchmakingTicketMembershipLimitExceeded = 2055,
|
||||
MatchmakingUnauthorized = 2056,
|
||||
MatchmakingQueueLimitExceeded = 2057,
|
||||
MatchmakingRequestTypeMismatch = 2058,
|
||||
MatchmakingBadRequest = 2059,
|
||||
PubSubFeatureNotEnabledForTitle = 2500,
|
||||
PubSubTooManyRequests = 2501,
|
||||
PubSubConnectionNotFoundForEntity = 2502,
|
||||
PubSubConnectionHandleInvalid = 2503,
|
||||
PubSubSubscriptionLimitExceeded = 2504,
|
||||
TitleConfigNotFound = 3001,
|
||||
TitleConfigUpdateConflict = 3002,
|
||||
TitleConfigSerializationError = 3003,
|
||||
CatalogApiNotImplemented = 4000,
|
||||
CatalogEntityInvalid = 4001,
|
||||
CatalogTitleIdMissing = 4002,
|
||||
CatalogPlayerIdMissing = 4003,
|
||||
CatalogClientIdentityInvalid = 4004,
|
||||
CatalogOneOrMoreFilesInvalid = 4005,
|
||||
CatalogItemMetadataInvalid = 4006,
|
||||
CatalogItemIdInvalid = 4007,
|
||||
CatalogSearchParameterInvalid = 4008,
|
||||
CatalogFeatureDisabled = 4009,
|
||||
CatalogConfigInvalid = 4010,
|
||||
CatalogItemTypeInvalid = 4012,
|
||||
CatalogBadRequest = 4013,
|
||||
CatalogTooManyRequests = 4014,
|
||||
ExportInvalidStatusUpdate = 5000,
|
||||
ExportInvalidPrefix = 5001,
|
||||
ExportBlobContainerDoesNotExist = 5002,
|
||||
ExportNotFound = 5004,
|
||||
ExportCouldNotUpdate = 5005,
|
||||
ExportInvalidStorageType = 5006,
|
||||
ExportAmazonBucketDoesNotExist = 5007,
|
||||
ExportInvalidBlobStorage = 5008,
|
||||
ExportKustoException = 5009,
|
||||
ExportKustoConnectionFailed = 5012,
|
||||
ExportUnknownError = 5013,
|
||||
ExportCantEditPendingExport = 5014,
|
||||
ExportLimitExports = 5015,
|
||||
ExportLimitEvents = 5016,
|
||||
ExportInvalidPartitionStatusModification = 5017,
|
||||
ExportCouldNotCreate = 5018,
|
||||
ExportNoBackingDatabaseFound = 5019,
|
||||
ExportCouldNotDelete = 5020,
|
||||
ExportCannotDetermineEventQuery = 5021,
|
||||
ExportInvalidQuerySchemaModification = 5022,
|
||||
ExportQuerySchemaMissingRequiredColumns = 5023,
|
||||
ExportCannotParseQuery = 5024,
|
||||
ExportControlCommandsNotAllowed = 5025,
|
||||
ExportQueryMissingTableReference = 5026,
|
||||
ExportInsightsV1Deprecated = 5027,
|
||||
ExplorerBasicInvalidQueryName = 5100,
|
||||
ExplorerBasicInvalidQueryDescription = 5101,
|
||||
ExplorerBasicInvalidQueryConditions = 5102,
|
||||
ExplorerBasicInvalidQueryStartDate = 5103,
|
||||
ExplorerBasicInvalidQueryEndDate = 5104,
|
||||
ExplorerBasicInvalidQueryGroupBy = 5105,
|
||||
ExplorerBasicInvalidQueryAggregateType = 5106,
|
||||
ExplorerBasicInvalidQueryAggregateProperty = 5107,
|
||||
ExplorerBasicLoadQueriesError = 5108,
|
||||
ExplorerBasicLoadQueryError = 5109,
|
||||
ExplorerBasicCreateQueryError = 5110,
|
||||
ExplorerBasicDeleteQueryError = 5111,
|
||||
ExplorerBasicUpdateQueryError = 5112,
|
||||
ExplorerBasicSavedQueriesLimit = 5113,
|
||||
ExplorerBasicSavedQueryNotFound = 5114,
|
||||
TenantShardMapperShardNotFound = 5500,
|
||||
TitleNotEnabledForParty = 6000,
|
||||
PartyVersionNotFound = 6001,
|
||||
MultiplayerServerBuildReferencedByMatchmakingQueue = 6002,
|
||||
MultiplayerServerBuildReferencedByBuildAlias = 6003,
|
||||
MultiplayerServerBuildAliasReferencedByMatchmakingQueue = 6004,
|
||||
ExperimentationExperimentStopped = 7000,
|
||||
ExperimentationExperimentRunning = 7001,
|
||||
ExperimentationExperimentNotFound = 7002,
|
||||
ExperimentationExperimentNeverStarted = 7003,
|
||||
ExperimentationExperimentDeleted = 7004,
|
||||
ExperimentationClientTimeout = 7005,
|
||||
ExperimentationInvalidVariantConfiguration = 7006,
|
||||
ExperimentationInvalidVariableConfiguration = 7007,
|
||||
ExperimentInvalidId = 7008,
|
||||
ExperimentationNoScorecard = 7009,
|
||||
ExperimentationTreatmentAssignmentFailed = 7010,
|
||||
ExperimentationTreatmentAssignmentDisabled = 7011,
|
||||
ExperimentationInvalidDuration = 7012,
|
||||
ExperimentationMaxExperimentsReached = 7013,
|
||||
ExperimentationExperimentSchedulingInProgress = 7014,
|
||||
ExperimentationInvalidEndDate = 7015,
|
||||
ExperimentationInvalidStartDate = 7016,
|
||||
ExperimentationMaxDurationExceeded = 7017,
|
||||
ExperimentationExclusionGroupNotFound = 7018,
|
||||
ExperimentationExclusionGroupInsufficientCapacity = 7019,
|
||||
ExperimentationExclusionGroupCannotDelete = 7020,
|
||||
ExperimentationExclusionGroupInvalidTrafficAllocation = 7021,
|
||||
ExperimentationExclusionGroupInvalidName = 7022,
|
||||
MaxActionDepthExceeded = 8000,
|
||||
TitleNotOnUpdatedPricingPlan = 9000,
|
||||
SegmentManagementTitleNotInFlight = 10000,
|
||||
SegmentManagementNoExpressionTree = 10001,
|
||||
SegmentManagementTriggerActionCountOverLimit = 10002,
|
||||
SegmentManagementSegmentCountOverLimit = 10003,
|
||||
SegmentManagementInvalidSegmentId = 10004,
|
||||
SegmentManagementInvalidInput = 10005,
|
||||
SegmentManagementInvalidSegmentName = 10006,
|
||||
DeleteSegmentRateLimitExceeded = 10007,
|
||||
CreateSegmentRateLimitExceeded = 10008,
|
||||
UpdateSegmentRateLimitExceeded = 10009,
|
||||
GetSegmentsRateLimitExceeded = 10010,
|
||||
AsyncExportNotInFlight = 10011,
|
||||
AsyncExportNotFound = 10012,
|
||||
AsyncExportRateLimitExceeded = 10013,
|
||||
AnalyticsSegmentCountOverLimit = 10014,
|
||||
SnapshotNotFound = 11000,
|
||||
InventoryApiNotImplemented = 12000,
|
||||
LobbyDoesNotExist = 13000,
|
||||
LobbyRateLimitExceeded = 13001,
|
||||
LobbyPlayerAlreadyJoined = 13002,
|
||||
LobbyNotJoinable = 13003,
|
||||
LobbyMemberCannotRejoin = 13004,
|
||||
LobbyCurrentPlayersMoreThanMaxPlayers = 13005,
|
||||
LobbyPlayerNotPresent = 13006,
|
||||
LobbyBadRequest = 13007,
|
||||
LobbyPlayerMaxLobbyLimitExceeded = 13008,
|
||||
LobbyNewOwnerMustBeConnected = 13009,
|
||||
LobbyCurrentOwnerStillConnected = 13010,
|
||||
LobbyMemberIsNotOwner = 13011,
|
||||
EventSamplingInvalidRatio = 14000,
|
||||
EventSamplingInvalidEventNamespace = 14001,
|
||||
EventSamplingInvalidEventName = 14002,
|
||||
EventSamplingRatioNotFound = 14003,
|
||||
TelemetryKeyNotFound = 14200,
|
||||
TelemetryKeyInvalidName = 14201,
|
||||
TelemetryKeyAlreadyExists = 14202,
|
||||
TelemetryKeyInvalid = 14203,
|
||||
TelemetryKeyCountOverLimit = 14204,
|
||||
TelemetryKeyDeactivated = 14205,
|
||||
TelemetryKeyLongInsightsRetentionNotAllowed = 14206,
|
||||
EventSinkConnectionInvalid = 15000,
|
||||
EventSinkConnectionUnauthorized = 15001,
|
||||
EventSinkRegionInvalid = 15002,
|
||||
EventSinkLimitExceeded = 15003,
|
||||
EventSinkSasTokenInvalid = 15004,
|
||||
EventSinkNotFound = 15005,
|
||||
EventSinkNameInvalid = 15006,
|
||||
EventSinkSasTokenPermissionInvalid = 15007,
|
||||
EventSinkSecretInvalid = 15008,
|
||||
EventSinkTenantNotFound = 15009,
|
||||
EventSinkAadNotFound = 15010,
|
||||
EventSinkDatabaseNotFound = 15011,
|
||||
OperationCanceled = 16000,
|
||||
InvalidDisplayNameRandomSuffixLength = 17000,
|
||||
AllowNonUniquePlayerDisplayNamesDisableNotAllowed = 17001,
|
||||
PartitionedEventInvalid = 18000,
|
||||
PartitionedEventCountOverLimit = 18001,
|
||||
PlayerCustomPropertiesPropertyNameTooLong = 19000,
|
||||
PlayerCustomPropertiesPropertyNameIsInvalid = 19001,
|
||||
PlayerCustomPropertiesStringPropertyValueTooLong = 19002,
|
||||
PlayerCustomPropertiesValueIsInvalidType = 19003,
|
||||
PlayerCustomPropertiesVersionMismatch = 19004,
|
||||
PlayerCustomPropertiesPropertyCountTooHigh = 19005,
|
||||
PlayerCustomPropertiesDuplicatePropertyName = 19006,
|
||||
PlayerCustomPropertiesPropertyDoesNotExist = 19007
|
||||
}
|
||||
|
||||
public class PlayFabError
|
||||
{
|
||||
public string ApiEndpoint;
|
||||
public int HttpCode;
|
||||
public string HttpStatus;
|
||||
public PlayFabErrorCode Error;
|
||||
public string ErrorMessage;
|
||||
public Dictionary<string, List<string>> ErrorDetails;
|
||||
public object CustomData;
|
||||
public uint? RetryAfterSeconds = null;
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return GenerateErrorReport();
|
||||
}
|
||||
|
||||
[ThreadStatic]
|
||||
private static StringBuilder _tempSb;
|
||||
/// <summary>
|
||||
/// This converts the PlayFabError into a human readable string describing the error.
|
||||
/// If error is not found, it will return the http code, status, and error
|
||||
/// </summary>
|
||||
/// <returns>A description of the error that we just incur.</returns>
|
||||
public string GenerateErrorReport()
|
||||
{
|
||||
if (_tempSb == null)
|
||||
_tempSb = new StringBuilder();
|
||||
_tempSb.Length = 0;
|
||||
if (String.IsNullOrEmpty(ErrorMessage))
|
||||
{
|
||||
_tempSb.Append(ApiEndpoint).Append(": ").Append("Http Code: ").Append(HttpCode.ToString()).Append("\nHttp Status: ").Append(HttpStatus).Append("\nError: ").Append(Error.ToString()).Append("\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
_tempSb.Append(ApiEndpoint).Append(": ").Append(ErrorMessage);
|
||||
}
|
||||
|
||||
if (ErrorDetails != null)
|
||||
foreach (var pair in ErrorDetails)
|
||||
foreach (var msg in pair.Value)
|
||||
_tempSb.Append("\n").Append(pair.Key).Append(": ").Append(msg);
|
||||
return _tempSb.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
public class PlayFabException : Exception
|
||||
{
|
||||
public readonly PlayFabExceptionCode Code;
|
||||
public PlayFabException(PlayFabExceptionCode code, string message) : base(message)
|
||||
{
|
||||
Code = code;
|
||||
}
|
||||
}
|
||||
|
||||
public enum PlayFabExceptionCode
|
||||
{
|
||||
AuthContextRequired,
|
||||
BuildError,
|
||||
DeveloperKeyNotSet,
|
||||
EntityTokenNotSet,
|
||||
NotLoggedIn,
|
||||
TitleNotSet,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ed146f2193bb8ef49ad1200eefdab503
|
||||
timeCreated: 1468524876
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6de758a294727f04c82bf319fdd54c60
|
||||
folderAsset: yes
|
||||
timeCreated: 1462746198
|
||||
licenseType: Pro
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,60 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using PlayFab.SharedModels;
|
||||
|
||||
namespace PlayFab.Internal
|
||||
{
|
||||
public enum AuthType
|
||||
{
|
||||
None,
|
||||
PreLoginSession, // Not yet defined
|
||||
LoginSession, // "X-Authorization"
|
||||
DevSecretKey, // "X-SecretKey"
|
||||
EntityToken, // "X-EntityToken"
|
||||
}
|
||||
|
||||
public enum HttpRequestState
|
||||
{
|
||||
Sent,
|
||||
Received,
|
||||
Idle,
|
||||
Error
|
||||
}
|
||||
|
||||
public class CallRequestContainer
|
||||
{
|
||||
#if !UNITY_WSA && !UNITY_WP8
|
||||
public HttpRequestState HttpState = HttpRequestState.Idle;
|
||||
public System.Net.HttpWebRequest HttpRequest = null;
|
||||
#endif
|
||||
#if PLAYFAB_REQUEST_TIMING
|
||||
public PlayFabHttp.RequestTiming Timing;
|
||||
public System.Diagnostics.Stopwatch Stopwatch;
|
||||
#endif
|
||||
|
||||
// This class stores the state of the request and all associated data
|
||||
public string ApiEndpoint = null;
|
||||
public string FullUrl = null;
|
||||
public byte[] Payload = null;
|
||||
public string JsonResponse = null;
|
||||
public PlayFabRequestCommon ApiRequest;
|
||||
public Dictionary<string, string> RequestHeaders;
|
||||
public PlayFabResultCommon ApiResult;
|
||||
public PlayFabError Error;
|
||||
public Action DeserializeResultJson;
|
||||
public Action InvokeSuccessCallback;
|
||||
public Action<PlayFabError> ErrorCallback;
|
||||
public object CustomData = null;
|
||||
public PlayFabApiSettings settings;
|
||||
public PlayFabAuthenticationContext context;
|
||||
public IPlayFabInstanceApi instanceApi;
|
||||
public bool CalledGetResponse = false;
|
||||
|
||||
public CallRequestContainer()
|
||||
{
|
||||
#if PLAYFAB_REQUEST_TIMING
|
||||
Stopwatch = System.Diagnostics.Stopwatch.StartNew();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: aeac58284b4b1cd4ab93ab0e71ba8540
|
||||
timeCreated: 1462745280
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,500 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using PlayFab.Public;
|
||||
using PlayFab.SharedModels;
|
||||
using UnityEngine;
|
||||
|
||||
namespace PlayFab.Internal
|
||||
{
|
||||
/// <summary>
|
||||
/// This is a wrapper for Http So we can better separate the functionaity of Http Requests delegated to WWW or HttpWebRequest
|
||||
/// </summary>
|
||||
public class PlayFabHttp : SingletonMonoBehaviour<PlayFabHttp>
|
||||
{
|
||||
private static List<CallRequestContainer> _apiCallQueue = new List<CallRequestContainer>(); // Starts initialized, and is nulled when it's flushed
|
||||
|
||||
public delegate void ApiProcessingEvent<in TEventArgs>(TEventArgs e);
|
||||
public delegate void ApiProcessErrorEvent(PlayFabRequestCommon request, PlayFabError error);
|
||||
public static event ApiProcessingEvent<ApiProcessingEventArgs> ApiProcessingEventHandler;
|
||||
public static event ApiProcessErrorEvent ApiProcessingErrorEventHandler;
|
||||
public static readonly Dictionary<string, string> GlobalHeaderInjection = new Dictionary<string, string>();
|
||||
|
||||
private static IPlayFabLogger _logger;
|
||||
#if !DISABLE_PLAYFABENTITY_API && !DISABLE_PLAYFABCLIENT_API
|
||||
private static IScreenTimeTracker screenTimeTracker = new ScreenTimeTracker();
|
||||
private const float delayBetweenBatches = 5.0f;
|
||||
#endif
|
||||
|
||||
#if PLAYFAB_REQUEST_TIMING
|
||||
public struct RequestTiming
|
||||
{
|
||||
public DateTime StartTimeUtc;
|
||||
public string ApiEndpoint;
|
||||
public int WorkerRequestMs;
|
||||
public int MainThreadRequestMs;
|
||||
}
|
||||
|
||||
public delegate void ApiRequestTimingEvent(RequestTiming time);
|
||||
public static event ApiRequestTimingEvent ApiRequestTimingEventHandler;
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Return the number of api calls that are waiting for results from the server
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static int GetPendingMessages()
|
||||
{
|
||||
var transport = PluginManager.GetPlugin<ITransportPlugin>(PluginContract.PlayFab_Transport);
|
||||
return transport.IsInitialized ? transport.GetPendingMessages() : 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This initializes the GameObject and ensures it is in the scene.
|
||||
/// </summary>
|
||||
public static void InitializeHttp()
|
||||
{
|
||||
if (string.IsNullOrEmpty(PlayFabSettings.TitleId))
|
||||
throw new PlayFabException(PlayFabExceptionCode.TitleNotSet, "You must set PlayFabSettings.TitleId before making API Calls.");
|
||||
var transport = PluginManager.GetPlugin<ITransportPlugin>(PluginContract.PlayFab_Transport);
|
||||
if (transport.IsInitialized)
|
||||
return;
|
||||
|
||||
transport.Initialize();
|
||||
CreateInstance(); // Invoke the SingletonMonoBehaviour
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This initializes the GameObject and ensures it is in the scene.
|
||||
/// </summary>
|
||||
public static void InitializeLogger(IPlayFabLogger setLogger = null)
|
||||
{
|
||||
if (_logger != null)
|
||||
throw new InvalidOperationException("Once initialized, the logger cannot be reset.");
|
||||
if (setLogger == null)
|
||||
setLogger = new PlayFabLogger();
|
||||
_logger = setLogger;
|
||||
}
|
||||
|
||||
#if !DISABLE_PLAYFABENTITY_API && !DISABLE_PLAYFABCLIENT_API
|
||||
/// <summary>
|
||||
/// This initializes ScreenTimeTracker object and notifying it to start sending info.
|
||||
/// </summary>
|
||||
/// <param name="playFabUserId">Result of the user's login, represent user ID</param>
|
||||
public static void InitializeScreenTimeTracker(string entityId, string entityType, string playFabUserId)
|
||||
{
|
||||
screenTimeTracker.ClientSessionStart(entityId, entityType, playFabUserId);
|
||||
instance.StartCoroutine(SendScreenTimeEvents(delayBetweenBatches));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This function will send Screen Time events on a periodic basis.
|
||||
/// </summary>
|
||||
/// <param name="secondsBetweenBatches">Delay between batches, in seconds</param>
|
||||
private static IEnumerator SendScreenTimeEvents(float secondsBetweenBatches)
|
||||
{
|
||||
WaitForSeconds delay = new WaitForSeconds(secondsBetweenBatches);
|
||||
|
||||
while (!PlayFabSettings.DisableFocusTimeCollection)
|
||||
{
|
||||
screenTimeTracker.Send();
|
||||
yield return delay;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
public static void SimpleGetCall(string fullUrl, Action<byte[]> successCallback, Action<string> errorCallback)
|
||||
{
|
||||
InitializeHttp();
|
||||
PluginManager.GetPlugin<ITransportPlugin>(PluginContract.PlayFab_Transport).SimpleGetCall(fullUrl, successCallback, errorCallback);
|
||||
}
|
||||
|
||||
|
||||
public static void SimplePutCall(string fullUrl, byte[] payload, Action<byte[]> successCallback, Action<string> errorCallback)
|
||||
{
|
||||
InitializeHttp();
|
||||
PluginManager.GetPlugin<ITransportPlugin>(PluginContract.PlayFab_Transport).SimplePutCall(fullUrl, payload, successCallback, errorCallback);
|
||||
}
|
||||
|
||||
public static void SimplePostCall(string fullUrl, byte[] payload, Action<byte[]> successCallback, Action<string> errorCallback)
|
||||
{
|
||||
InitializeHttp();
|
||||
PluginManager.GetPlugin<ITransportPlugin>(PluginContract.PlayFab_Transport).SimplePostCall(fullUrl, payload, successCallback, errorCallback);
|
||||
}
|
||||
|
||||
protected internal static void MakeApiCall<TResult>(string apiEndpoint,
|
||||
PlayFabRequestCommon request, AuthType authType, Action<TResult> resultCallback,
|
||||
Action<PlayFabError> errorCallback, object customData = null, Dictionary<string, string> extraHeaders = null, PlayFabAuthenticationContext authenticationContext = null, PlayFabApiSettings apiSettings = null, IPlayFabInstanceApi instanceApi = null)
|
||||
where TResult : PlayFabResultCommon
|
||||
{
|
||||
apiSettings = apiSettings ?? PlayFabSettings.staticSettings;
|
||||
var fullUrl = apiSettings.GetFullUrl(apiEndpoint, apiSettings.RequestGetParams);
|
||||
_MakeApiCall(apiEndpoint, fullUrl, request, authType, resultCallback, errorCallback, customData, extraHeaders, false, authenticationContext, apiSettings, instanceApi);
|
||||
}
|
||||
|
||||
protected internal static void MakeApiCallWithFullUri<TResult>(string fullUri,
|
||||
PlayFabRequestCommon request, AuthType authType, Action<TResult> resultCallback,
|
||||
Action<PlayFabError> errorCallback, object customData = null, Dictionary<string, string> extraHeaders = null, PlayFabAuthenticationContext authenticationContext = null, PlayFabApiSettings apiSettings = null, IPlayFabInstanceApi instanceApi = null)
|
||||
where TResult : PlayFabResultCommon
|
||||
{
|
||||
apiSettings = apiSettings ?? PlayFabSettings.staticSettings;
|
||||
// This will not be called if environment file does not exist or does not contain property the debugging URI
|
||||
_MakeApiCall(null, fullUri, request, authType, resultCallback, errorCallback, customData, extraHeaders, false, authenticationContext, apiSettings, instanceApi);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Internal method for Make API Calls
|
||||
/// </summary>
|
||||
private static void _MakeApiCall<TResult>(string apiEndpoint, string fullUrl,
|
||||
PlayFabRequestCommon request, AuthType authType, Action<TResult> resultCallback,
|
||||
Action<PlayFabError> errorCallback, object customData, Dictionary<string, string> extraHeaders, bool allowQueueing, PlayFabAuthenticationContext authenticationContext, PlayFabApiSettings apiSettings, IPlayFabInstanceApi instanceApi)
|
||||
where TResult : PlayFabResultCommon
|
||||
{
|
||||
InitializeHttp();
|
||||
SendEvent(apiEndpoint, request, null, ApiProcessingEventType.Pre);
|
||||
|
||||
var serializer = PluginManager.GetPlugin<ISerializerPlugin>(PluginContract.PlayFab_Serializer);
|
||||
var reqContainer = new CallRequestContainer
|
||||
{
|
||||
ApiEndpoint = apiEndpoint,
|
||||
FullUrl = fullUrl,
|
||||
settings = apiSettings,
|
||||
context = authenticationContext,
|
||||
CustomData = customData,
|
||||
Payload = Encoding.UTF8.GetBytes(serializer.SerializeObject(request)),
|
||||
ApiRequest = request,
|
||||
ErrorCallback = errorCallback,
|
||||
RequestHeaders = extraHeaders ?? new Dictionary<string, string>(), // Use any headers provided by the customer
|
||||
instanceApi = instanceApi
|
||||
};
|
||||
// Append any additional headers
|
||||
foreach (var pair in GlobalHeaderInjection)
|
||||
if (!reqContainer.RequestHeaders.ContainsKey(pair.Key))
|
||||
reqContainer.RequestHeaders[pair.Key] = pair.Value;
|
||||
|
||||
#if PLAYFAB_REQUEST_TIMING
|
||||
reqContainer.Timing.StartTimeUtc = DateTime.UtcNow;
|
||||
reqContainer.Timing.ApiEndpoint = apiEndpoint;
|
||||
#endif
|
||||
|
||||
// Add PlayFab Headers
|
||||
var transport = PluginManager.GetPlugin<ITransportPlugin>(PluginContract.PlayFab_Transport);
|
||||
reqContainer.RequestHeaders["X-ReportErrorAsSuccess"] = "true"; // Makes processing PlayFab errors a little easier
|
||||
reqContainer.RequestHeaders["X-PlayFabSDK"] = PlayFabSettings.VersionString; // Tell PlayFab which SDK this is
|
||||
switch (authType)
|
||||
{
|
||||
#if ENABLE_PLAYFABSERVER_API || ENABLE_PLAYFABADMIN_API || UNITY_EDITOR || ENABLE_PLAYFAB_SECRETKEY
|
||||
case AuthType.DevSecretKey:
|
||||
if (apiSettings.DeveloperSecretKey == null) throw new PlayFabException(PlayFabExceptionCode.DeveloperKeyNotSet, "DeveloperSecretKey is not found in Request, Server Instance or PlayFabSettings");
|
||||
reqContainer.RequestHeaders["X-SecretKey"] = apiSettings.DeveloperSecretKey; break;
|
||||
#endif
|
||||
#if !DISABLE_PLAYFABCLIENT_API
|
||||
case AuthType.LoginSession:
|
||||
if (authenticationContext != null)
|
||||
reqContainer.RequestHeaders["X-Authorization"] = authenticationContext.ClientSessionTicket;
|
||||
break;
|
||||
#endif
|
||||
#if !DISABLE_PLAYFABENTITY_API
|
||||
case AuthType.EntityToken:
|
||||
if (authenticationContext != null)
|
||||
reqContainer.RequestHeaders["X-EntityToken"] = authenticationContext.EntityToken;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
// These closures preserve the TResult generic information in a way that's safe for all the devices
|
||||
reqContainer.DeserializeResultJson = () =>
|
||||
{
|
||||
reqContainer.ApiResult = serializer.DeserializeObject<TResult>(reqContainer.JsonResponse);
|
||||
};
|
||||
reqContainer.InvokeSuccessCallback = () =>
|
||||
{
|
||||
if (resultCallback != null)
|
||||
{
|
||||
resultCallback((TResult)reqContainer.ApiResult);
|
||||
}
|
||||
};
|
||||
|
||||
if (allowQueueing && _apiCallQueue != null)
|
||||
{
|
||||
for (var i = _apiCallQueue.Count - 1; i >= 0; i--)
|
||||
if (_apiCallQueue[i].ApiEndpoint == apiEndpoint)
|
||||
_apiCallQueue.RemoveAt(i);
|
||||
_apiCallQueue.Add(reqContainer);
|
||||
}
|
||||
else
|
||||
{
|
||||
transport.MakeApiCall(reqContainer);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Internal code shared by IPlayFabHTTP implementations
|
||||
/// </summary>
|
||||
internal void OnPlayFabApiResult(CallRequestContainer reqContainer)
|
||||
{
|
||||
var result = reqContainer.ApiResult;
|
||||
|
||||
#if !DISABLE_PLAYFABENTITY_API
|
||||
|
||||
var entRes = result as AuthenticationModels.GetEntityTokenResponse;
|
||||
if (entRes != null)
|
||||
{
|
||||
PlayFabSettings.staticPlayer.EntityToken = entRes.EntityToken;
|
||||
}
|
||||
|
||||
#endif
|
||||
#if !DISABLE_PLAYFABCLIENT_API
|
||||
var logRes = result as ClientModels.LoginResult;
|
||||
var regRes = result as ClientModels.RegisterPlayFabUserResult;
|
||||
if (logRes != null)
|
||||
{
|
||||
logRes.AuthenticationContext = new PlayFabAuthenticationContext(logRes.SessionTicket, logRes.EntityToken.EntityToken, logRes.PlayFabId, logRes.EntityToken.Entity.Id, logRes.EntityToken.Entity.Type);
|
||||
if (reqContainer.context != null)
|
||||
reqContainer.context.CopyFrom(logRes.AuthenticationContext);
|
||||
}
|
||||
else if (regRes != null)
|
||||
{
|
||||
regRes.AuthenticationContext = new PlayFabAuthenticationContext(regRes.SessionTicket, regRes.EntityToken.EntityToken, regRes.PlayFabId, regRes.EntityToken.Entity.Id, regRes.EntityToken.Entity.Type);
|
||||
if (reqContainer.context != null)
|
||||
reqContainer.context.CopyFrom(regRes.AuthenticationContext);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// MonoBehaviour OnEnable Method
|
||||
/// </summary>
|
||||
private void OnEnable()
|
||||
{
|
||||
if (_logger != null)
|
||||
{
|
||||
_logger.OnEnable();
|
||||
}
|
||||
|
||||
#if !DISABLE_PLAYFABENTITY_API && !DISABLE_PLAYFABCLIENT_API
|
||||
if ((screenTimeTracker != null) && !PlayFabSettings.DisableFocusTimeCollection)
|
||||
{
|
||||
screenTimeTracker.OnEnable();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// MonoBehaviour OnDisable
|
||||
/// </summary>
|
||||
private void OnDisable()
|
||||
{
|
||||
if (_logger != null)
|
||||
{
|
||||
_logger.OnDisable();
|
||||
}
|
||||
|
||||
#if !DISABLE_PLAYFABENTITY_API && !DISABLE_PLAYFABCLIENT_API
|
||||
if ((screenTimeTracker != null) && !PlayFabSettings.DisableFocusTimeCollection)
|
||||
{
|
||||
screenTimeTracker.OnDisable();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// MonoBehaviour OnDestroy
|
||||
/// </summary>
|
||||
private void OnDestroy()
|
||||
{
|
||||
var transport = PluginManager.GetPlugin<ITransportPlugin>(PluginContract.PlayFab_Transport);
|
||||
if (transport.IsInitialized)
|
||||
{
|
||||
transport.OnDestroy();
|
||||
}
|
||||
|
||||
if (_logger != null)
|
||||
{
|
||||
_logger.OnDestroy();
|
||||
}
|
||||
|
||||
#if !DISABLE_PLAYFABENTITY_API && !DISABLE_PLAYFABCLIENT_API
|
||||
if ((screenTimeTracker != null) && !PlayFabSettings.DisableFocusTimeCollection)
|
||||
{
|
||||
screenTimeTracker.OnDestroy();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// MonoBehaviour OnApplicationFocus
|
||||
/// </summary>
|
||||
public void OnApplicationFocus(bool isFocused)
|
||||
{
|
||||
#if !DISABLE_PLAYFABENTITY_API && !DISABLE_PLAYFABCLIENT_API
|
||||
if ((screenTimeTracker != null) && !PlayFabSettings.DisableFocusTimeCollection)
|
||||
{
|
||||
screenTimeTracker.OnApplicationFocus(isFocused);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// MonoBehaviour OnApplicationQuit
|
||||
/// </summary>
|
||||
public void OnApplicationQuit()
|
||||
{
|
||||
#if !DISABLE_PLAYFABENTITY_API && !DISABLE_PLAYFABCLIENT_API
|
||||
if ((screenTimeTracker != null) && !PlayFabSettings.DisableFocusTimeCollection)
|
||||
{
|
||||
screenTimeTracker.OnApplicationQuit();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// MonoBehaviour Update
|
||||
/// </summary>
|
||||
private void Update()
|
||||
{
|
||||
var transport = PluginManager.GetPlugin<ITransportPlugin>(PluginContract.PlayFab_Transport);
|
||||
if (transport.IsInitialized)
|
||||
{
|
||||
if (_apiCallQueue != null)
|
||||
{
|
||||
foreach (var eachRequest in _apiCallQueue)
|
||||
transport.MakeApiCall(eachRequest); // Flush the queue
|
||||
_apiCallQueue = null; // null this after it's flushed
|
||||
}
|
||||
transport.Update();
|
||||
}
|
||||
|
||||
while (_injectedCoroutines.Count > 0)
|
||||
StartCoroutine(_injectedCoroutines.Dequeue());
|
||||
|
||||
while (_injectedAction.Count > 0)
|
||||
{
|
||||
var action = _injectedAction.Dequeue();
|
||||
if (action != null)
|
||||
{
|
||||
action.Invoke();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#region Helpers
|
||||
protected internal static PlayFabError GeneratePlayFabError(string apiEndpoint, string json, object customData)
|
||||
{
|
||||
Dictionary<string, object> errorDict = null;
|
||||
Dictionary<string, List<string>> errorDetails = null;
|
||||
var serializer = PluginManager.GetPlugin<ISerializerPlugin>(PluginContract.PlayFab_Serializer);
|
||||
try
|
||||
{
|
||||
// Deserialize the error
|
||||
errorDict = serializer.DeserializeObject<Dictionary<string, object>>(json);
|
||||
}
|
||||
catch (Exception) { /* Unusual, but shouldn't actually matter */ }
|
||||
try
|
||||
{
|
||||
object errorDetailsString;
|
||||
if (errorDict != null && errorDict.TryGetValue("errorDetails", out errorDetailsString))
|
||||
errorDetails = serializer.DeserializeObject<Dictionary<string, List<string>>>(errorDetailsString.ToString());
|
||||
}
|
||||
catch (Exception) { /* Unusual, but shouldn't actually matter */ }
|
||||
|
||||
return new PlayFabError
|
||||
{
|
||||
ApiEndpoint = apiEndpoint,
|
||||
HttpCode = errorDict != null && errorDict.ContainsKey("code") ? Convert.ToInt32(errorDict["code"]) : 400,
|
||||
HttpStatus = errorDict != null && errorDict.ContainsKey("status") ? (string)errorDict["status"] : "BadRequest",
|
||||
Error = errorDict != null && errorDict.ContainsKey("errorCode") ? (PlayFabErrorCode)Convert.ToInt32(errorDict["errorCode"]) : PlayFabErrorCode.ServiceUnavailable,
|
||||
ErrorMessage = errorDict != null && errorDict.ContainsKey("errorMessage") ? (string)errorDict["errorMessage"] : json,
|
||||
ErrorDetails = errorDetails,
|
||||
CustomData = customData,
|
||||
RetryAfterSeconds = errorDict != null && errorDict.ContainsKey("retryAfterSeconds") ? Convert.ToUInt32(errorDict["retryAfterSeconds"]) : (uint?)null,
|
||||
};
|
||||
}
|
||||
|
||||
protected internal static void SendErrorEvent(PlayFabRequestCommon request, PlayFabError error)
|
||||
{
|
||||
if (ApiProcessingErrorEventHandler == null)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
ApiProcessingErrorEventHandler(request, error);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogException(e);
|
||||
}
|
||||
}
|
||||
|
||||
protected internal static void SendEvent(string apiEndpoint, PlayFabRequestCommon request, PlayFabResultCommon result, ApiProcessingEventType eventType)
|
||||
{
|
||||
if (ApiProcessingEventHandler == null)
|
||||
return;
|
||||
try
|
||||
{
|
||||
ApiProcessingEventHandler(new ApiProcessingEventArgs
|
||||
{
|
||||
ApiEndpoint = apiEndpoint,
|
||||
EventType = eventType,
|
||||
Request = request,
|
||||
Result = result
|
||||
});
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void ClearAllEvents()
|
||||
{
|
||||
ApiProcessingEventHandler = null;
|
||||
ApiProcessingErrorEventHandler = null;
|
||||
}
|
||||
|
||||
#if PLAYFAB_REQUEST_TIMING
|
||||
protected internal static void SendRequestTiming(RequestTiming rt)
|
||||
{
|
||||
if (ApiRequestTimingEventHandler != null)
|
||||
{
|
||||
ApiRequestTimingEventHandler(rt);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endregion
|
||||
private readonly Queue<IEnumerator> _injectedCoroutines = new Queue<IEnumerator>();
|
||||
private readonly Queue<Action> _injectedAction = new Queue<Action>();
|
||||
|
||||
public void InjectInUnityThread(IEnumerator x)
|
||||
{
|
||||
_injectedCoroutines.Enqueue(x);
|
||||
}
|
||||
|
||||
public void InjectInUnityThread(Action action)
|
||||
{
|
||||
_injectedAction.Enqueue(action);
|
||||
}
|
||||
}
|
||||
|
||||
#region Event Classes
|
||||
public enum ApiProcessingEventType
|
||||
{
|
||||
Pre,
|
||||
Post
|
||||
}
|
||||
|
||||
public class ApiProcessingEventArgs
|
||||
{
|
||||
public string ApiEndpoint;
|
||||
public ApiProcessingEventType EventType;
|
||||
public PlayFabRequestCommon Request;
|
||||
public PlayFabResultCommon Result;
|
||||
|
||||
public TRequest GetRequest<TRequest>() where TRequest : PlayFabRequestCommon
|
||||
{
|
||||
return Request as TRequest;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 97a8a3caac8b73541aa8a9a1e330f479
|
||||
timeCreated: 1462575707
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,244 @@
|
||||
#if UNITY_2017_2_OR_NEWER
|
||||
|
||||
using PlayFab.SharedModels;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Networking;
|
||||
|
||||
namespace PlayFab.Internal
|
||||
{
|
||||
public class PlayFabUnityHttp : ITransportPlugin
|
||||
{
|
||||
private bool _isInitialized = false;
|
||||
private readonly int _pendingWwwMessages = 0;
|
||||
|
||||
public bool IsInitialized { get { return _isInitialized; } }
|
||||
|
||||
public void Initialize() { _isInitialized = true; }
|
||||
|
||||
public void Update() { }
|
||||
|
||||
public void OnDestroy() { }
|
||||
|
||||
public void SimpleGetCall(string fullUrl, Action<byte[]> successCallback, Action<string> errorCallback)
|
||||
{
|
||||
PlayFabHttp.instance.StartCoroutine(SimpleCallCoroutine("get", fullUrl, null, successCallback, errorCallback));
|
||||
}
|
||||
|
||||
public void SimplePutCall(string fullUrl, byte[] payload, Action<byte[]> successCallback, Action<string> errorCallback)
|
||||
{
|
||||
PlayFabHttp.instance.StartCoroutine(SimpleCallCoroutine("put", fullUrl, payload, successCallback, errorCallback));
|
||||
}
|
||||
|
||||
public void SimplePostCall(string fullUrl, byte[] payload, Action<byte[]> successCallback, Action<string> errorCallback)
|
||||
{
|
||||
PlayFabHttp.instance.StartCoroutine(SimpleCallCoroutine("post", fullUrl, payload, successCallback, errorCallback));
|
||||
}
|
||||
|
||||
private static IEnumerator SimpleCallCoroutine(string method, string fullUrl, byte[] payload, Action<byte[]> successCallback, Action<string> errorCallback)
|
||||
{
|
||||
if (payload == null)
|
||||
{
|
||||
using (UnityWebRequest www = UnityWebRequest.Get(fullUrl))
|
||||
{
|
||||
#if UNITY_2017_2_OR_NEWER
|
||||
www.timeout = PlayFabSettings.RequestTimeout / 1000;
|
||||
yield return www.SendWebRequest();
|
||||
#else
|
||||
yield return www.Send();
|
||||
#endif
|
||||
|
||||
if (!string.IsNullOrEmpty(www.error))
|
||||
errorCallback(www.error);
|
||||
else
|
||||
successCallback(www.downloadHandler.data);
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
UnityWebRequest request;
|
||||
if (method == "put")
|
||||
{
|
||||
request = UnityWebRequest.Put(fullUrl, payload);
|
||||
}
|
||||
else
|
||||
{
|
||||
request = new UnityWebRequest(fullUrl, "POST");
|
||||
request.uploadHandler = (UploadHandler)new UploadHandlerRaw(payload);
|
||||
request.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer();
|
||||
request.SetRequestHeader("Content-Type", "application/json");
|
||||
}
|
||||
|
||||
|
||||
#if UNITY_2017_2_OR_NEWER
|
||||
#if !UNITY_2019_1_OR_NEWER
|
||||
request.chunkedTransfer = false; // can be removed after Unity's PUT will be more stable
|
||||
#endif
|
||||
yield return request.SendWebRequest();
|
||||
#else
|
||||
yield return request.Send();
|
||||
#endif
|
||||
|
||||
#if UNITY_2020_1_OR_NEWER
|
||||
if (request.result == UnityWebRequest.Result.ConnectionError || request.result == UnityWebRequest.Result.ProtocolError)
|
||||
#else
|
||||
if (request.isNetworkError || request.isHttpError)
|
||||
#endif
|
||||
{
|
||||
errorCallback(request.error);
|
||||
}
|
||||
else
|
||||
{
|
||||
successCallback(request.downloadHandler.data);
|
||||
}
|
||||
|
||||
request.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
public void MakeApiCall(object reqContainerObj)
|
||||
{
|
||||
CallRequestContainer reqContainer = (CallRequestContainer)reqContainerObj;
|
||||
reqContainer.RequestHeaders["Content-Type"] = "application/json";
|
||||
|
||||
// Start the www corouting to Post, and get a response or error which is then passed to the callbacks.
|
||||
PlayFabHttp.instance.StartCoroutine(Post(reqContainer));
|
||||
}
|
||||
|
||||
private IEnumerator Post(CallRequestContainer reqContainer)
|
||||
{
|
||||
#if PLAYFAB_REQUEST_TIMING
|
||||
var stopwatch = System.Diagnostics.Stopwatch.StartNew();
|
||||
var startTime = DateTime.UtcNow;
|
||||
#endif
|
||||
|
||||
using var www = new UnityWebRequest(reqContainer.FullUrl)
|
||||
{
|
||||
uploadHandler = new UploadHandlerRaw(reqContainer.Payload),
|
||||
downloadHandler = new DownloadHandlerBuffer(),
|
||||
method = "POST"
|
||||
};
|
||||
|
||||
foreach (var headerPair in reqContainer.RequestHeaders)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(headerPair.Key) && !string.IsNullOrEmpty(headerPair.Value))
|
||||
www.SetRequestHeader(headerPair.Key, headerPair.Value);
|
||||
else
|
||||
Debug.LogWarning("Null header: " + headerPair.Key + " = " + headerPair.Value);
|
||||
}
|
||||
|
||||
#if UNITY_2017_2_OR_NEWER
|
||||
yield return www.SendWebRequest();
|
||||
#else
|
||||
yield return www.Send();
|
||||
#endif
|
||||
|
||||
#if PLAYFAB_REQUEST_TIMING
|
||||
stopwatch.Stop();
|
||||
var timing = new PlayFabHttp.RequestTiming {
|
||||
StartTimeUtc = startTime,
|
||||
ApiEndpoint = reqContainer.ApiEndpoint,
|
||||
WorkerRequestMs = (int)stopwatch.ElapsedMilliseconds,
|
||||
MainThreadRequestMs = (int)stopwatch.ElapsedMilliseconds
|
||||
};
|
||||
PlayFabHttp.SendRequestTiming(timing);
|
||||
#endif
|
||||
|
||||
if (!string.IsNullOrEmpty(www.error))
|
||||
{
|
||||
OnError(www.error, reqContainer);
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
byte[] responseBytes = www.downloadHandler.data;
|
||||
string responseText = System.Text.Encoding.UTF8.GetString(responseBytes, 0, responseBytes.Length);
|
||||
OnResponse(responseText, reqContainer);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
OnError("Unhandled error in PlayFabUnityHttp: " + e, reqContainer);
|
||||
}
|
||||
}
|
||||
www.Dispose();
|
||||
}
|
||||
|
||||
public int GetPendingMessages()
|
||||
{
|
||||
return _pendingWwwMessages;
|
||||
}
|
||||
|
||||
public void OnResponse(string response, CallRequestContainer reqContainer)
|
||||
{
|
||||
try
|
||||
{
|
||||
#if PLAYFAB_REQUEST_TIMING
|
||||
var startTime = DateTime.UtcNow;
|
||||
#endif
|
||||
var serializer = PluginManager.GetPlugin<ISerializerPlugin>(PluginContract.PlayFab_Serializer);
|
||||
var httpResult = serializer.DeserializeObject<HttpResponseObject>(response);
|
||||
|
||||
if (httpResult.code == 200)
|
||||
{
|
||||
// We have a good response from the server
|
||||
reqContainer.JsonResponse = serializer.SerializeObject(httpResult.data);
|
||||
reqContainer.DeserializeResultJson();
|
||||
reqContainer.ApiResult.Request = reqContainer.ApiRequest;
|
||||
reqContainer.ApiResult.CustomData = reqContainer.CustomData;
|
||||
|
||||
PlayFabHttp.instance.OnPlayFabApiResult(reqContainer);
|
||||
#if !DISABLE_PLAYFABCLIENT_API
|
||||
PlayFabDeviceUtil.OnPlayFabLogin(reqContainer.ApiResult, reqContainer.settings, reqContainer.instanceApi);
|
||||
#endif
|
||||
try
|
||||
{
|
||||
PlayFabHttp.SendEvent(reqContainer.ApiEndpoint, reqContainer.ApiRequest, reqContainer.ApiResult, ApiProcessingEventType.Post);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogException(e);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
reqContainer.InvokeSuccessCallback();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogException(e);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (reqContainer.ErrorCallback != null)
|
||||
{
|
||||
reqContainer.Error = PlayFabHttp.GeneratePlayFabError(reqContainer.ApiEndpoint, response, reqContainer.CustomData);
|
||||
PlayFabHttp.SendErrorEvent(reqContainer.ApiRequest, reqContainer.Error);
|
||||
reqContainer.ErrorCallback(reqContainer.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void OnError(string error, CallRequestContainer reqContainer)
|
||||
{
|
||||
reqContainer.JsonResponse = error;
|
||||
if (reqContainer.ErrorCallback != null)
|
||||
{
|
||||
reqContainer.Error = PlayFabHttp.GeneratePlayFabError(reqContainer.ApiEndpoint, reqContainer.JsonResponse, reqContainer.CustomData);
|
||||
PlayFabHttp.SendErrorEvent(reqContainer.ApiRequest, reqContainer.Error);
|
||||
reqContainer.ErrorCallback(reqContainer.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,13 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fdda21a9c6bb5c74d85422afab113b0f
|
||||
timeCreated: 1512617003
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,219 @@
|
||||
#if !UNITY_2018_2_OR_NEWER // Unity has deprecated Www
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
using PlayFab.Json;
|
||||
using PlayFab.SharedModels;
|
||||
using UnityEngine;
|
||||
#if UNITY_5_4_OR_NEWER
|
||||
using UnityEngine.Networking;
|
||||
#else
|
||||
using UnityEngine.Experimental.Networking;
|
||||
#endif
|
||||
|
||||
namespace PlayFab.Internal
|
||||
{
|
||||
public class PlayFabWww : ITransportPlugin
|
||||
{
|
||||
private bool _isInitialized = false;
|
||||
private int _pendingWwwMessages = 0;
|
||||
|
||||
public bool IsInitialized { get { return _isInitialized; } }
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
_isInitialized = true;
|
||||
}
|
||||
|
||||
public void Update() { }
|
||||
public void OnDestroy() { }
|
||||
|
||||
public void SimpleGetCall(string fullUrl, Action<byte[]> successCallback, Action<string> errorCallback)
|
||||
{
|
||||
PlayFabHttp.instance.StartCoroutine(SimpleCallCoroutine("get", fullUrl, null, successCallback, errorCallback));
|
||||
}
|
||||
|
||||
public void SimplePutCall(string fullUrl, byte[] payload, Action<byte[]> successCallback, Action<string> errorCallback)
|
||||
{
|
||||
PlayFabHttp.instance.StartCoroutine(SimpleCallCoroutine("put", fullUrl, payload, successCallback, errorCallback));
|
||||
}
|
||||
|
||||
public void SimplePostCall(string fullUrl, byte[] payload, Action<byte[]> successCallback, Action<string> errorCallback)
|
||||
{
|
||||
PlayFabHttp.instance.StartCoroutine(SimpleCallCoroutine("post", fullUrl, payload, successCallback, errorCallback));
|
||||
}
|
||||
|
||||
private static IEnumerator SimpleCallCoroutine(string method, string fullUrl, byte[] payload, Action<byte[]> successCallback, Action<string> errorCallback)
|
||||
{
|
||||
if (payload == null)
|
||||
{
|
||||
var www = new WWW(fullUrl);
|
||||
yield return www;
|
||||
if (!string.IsNullOrEmpty(www.error))
|
||||
errorCallback(www.error);
|
||||
else
|
||||
successCallback(www.bytes);
|
||||
}
|
||||
else
|
||||
{
|
||||
UnityWebRequest request;
|
||||
if (method == "put")
|
||||
{
|
||||
request = UnityWebRequest.Put(fullUrl, payload);
|
||||
}
|
||||
else
|
||||
{
|
||||
var strPayload = System.Text.Encoding.UTF8.GetString(payload, 0, payload.Length);
|
||||
request = UnityWebRequest.Post(fullUrl, strPayload);
|
||||
}
|
||||
|
||||
#if UNITY_2017_2_OR_NEWER
|
||||
request.chunkedTransfer = false; // can be removed after Unity's PUT will be more stable
|
||||
request.SendWebRequest();
|
||||
#else
|
||||
request.Send();
|
||||
#endif
|
||||
|
||||
#if !UNITY_WEBGL
|
||||
while (request.uploadProgress < 1 || request.downloadProgress < 1)
|
||||
{
|
||||
yield return 1;
|
||||
}
|
||||
#else
|
||||
while (!request.isDone)
|
||||
{
|
||||
yield return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!string.IsNullOrEmpty(request.error))
|
||||
errorCallback(request.error);
|
||||
else
|
||||
successCallback(request.downloadHandler.data);
|
||||
}
|
||||
}
|
||||
|
||||
public void MakeApiCall(object reqContainerObj)
|
||||
{
|
||||
CallRequestContainer reqContainer = (CallRequestContainer)reqContainerObj;
|
||||
reqContainer.RequestHeaders["Content-Type"] = "application/json";
|
||||
|
||||
//Debug.LogFormat("Posting {0} to Url: {1}", req.Trim(), url);
|
||||
var www = new WWW(reqContainer.FullUrl, reqContainer.Payload, reqContainer.RequestHeaders);
|
||||
|
||||
#if PLAYFAB_REQUEST_TIMING
|
||||
var stopwatch = System.Diagnostics.Stopwatch.StartNew();
|
||||
#endif
|
||||
|
||||
// Start the www corouting to Post, and get a response or error which is then passed to the callbacks.
|
||||
Action<string> wwwSuccessCallback = (response) =>
|
||||
{
|
||||
try
|
||||
{
|
||||
#if PLAYFAB_REQUEST_TIMING
|
||||
var startTime = DateTime.UtcNow;
|
||||
#endif
|
||||
var serializer = PluginManager.GetPlugin<ISerializerPlugin>(PluginContract.PlayFab_Serializer);
|
||||
var httpResult = serializer.DeserializeObject<HttpResponseObject>(response);
|
||||
|
||||
if (httpResult.code == 200)
|
||||
{
|
||||
// We have a good response from the server
|
||||
reqContainer.JsonResponse = serializer.SerializeObject(httpResult.data);
|
||||
reqContainer.DeserializeResultJson();
|
||||
reqContainer.ApiResult.Request = reqContainer.ApiRequest;
|
||||
reqContainer.ApiResult.CustomData = reqContainer.CustomData;
|
||||
|
||||
PlayFabHttp.instance.OnPlayFabApiResult(reqContainer);
|
||||
#if !DISABLE_PLAYFABCLIENT_API
|
||||
PlayFabDeviceUtil.OnPlayFabLogin(reqContainer.ApiResult, reqContainer.settings, reqContainer.instanceApi);
|
||||
#endif
|
||||
|
||||
try
|
||||
{
|
||||
PlayFabHttp.SendEvent(reqContainer.ApiEndpoint, reqContainer.ApiRequest, reqContainer.ApiResult, ApiProcessingEventType.Post);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogException(e);
|
||||
}
|
||||
|
||||
#if PLAYFAB_REQUEST_TIMING
|
||||
stopwatch.Stop();
|
||||
var timing = new PlayFabHttp.RequestTiming {
|
||||
StartTimeUtc = startTime,
|
||||
ApiEndpoint = reqContainer.ApiEndpoint,
|
||||
WorkerRequestMs = (int)stopwatch.ElapsedMilliseconds,
|
||||
MainThreadRequestMs = (int)stopwatch.ElapsedMilliseconds
|
||||
};
|
||||
PlayFabHttp.SendRequestTiming(timing);
|
||||
#endif
|
||||
try
|
||||
{
|
||||
reqContainer.InvokeSuccessCallback();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogException(e);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (reqContainer.ErrorCallback != null)
|
||||
{
|
||||
reqContainer.Error = PlayFabHttp.GeneratePlayFabError(reqContainer.ApiEndpoint, response, reqContainer.CustomData);
|
||||
PlayFabHttp.SendErrorEvent(reqContainer.ApiRequest, reqContainer.Error);
|
||||
reqContainer.ErrorCallback(reqContainer.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogException(e);
|
||||
}
|
||||
};
|
||||
|
||||
Action<string> wwwErrorCallback = (errorCb) =>
|
||||
{
|
||||
reqContainer.JsonResponse = errorCb;
|
||||
if (reqContainer.ErrorCallback != null)
|
||||
{
|
||||
reqContainer.Error = PlayFabHttp.GeneratePlayFabError(reqContainer.ApiEndpoint, reqContainer.JsonResponse, reqContainer.CustomData);
|
||||
PlayFabHttp.SendErrorEvent(reqContainer.ApiRequest, reqContainer.Error);
|
||||
reqContainer.ErrorCallback(reqContainer.Error);
|
||||
}
|
||||
};
|
||||
|
||||
PlayFabHttp.instance.StartCoroutine(PostPlayFabApiCall(www, wwwSuccessCallback, wwwErrorCallback));
|
||||
}
|
||||
|
||||
private IEnumerator PostPlayFabApiCall(WWW www, Action<string> wwwSuccessCallback, Action<string> wwwErrorCallback)
|
||||
{
|
||||
yield return www;
|
||||
if (!string.IsNullOrEmpty(www.error))
|
||||
{
|
||||
wwwErrorCallback(www.error);
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
byte[] responseBytes = www.bytes;
|
||||
string responseText = System.Text.Encoding.UTF8.GetString(responseBytes, 0, responseBytes.Length);
|
||||
wwwSuccessCallback(responseText);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
wwwErrorCallback("Unhandled error in PlayFabWWW: " + e);
|
||||
}
|
||||
}
|
||||
www.Dispose();
|
||||
}
|
||||
|
||||
public int GetPendingMessages()
|
||||
{
|
||||
return _pendingWwwMessages;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 71ae810a641b9644187c8824db5ff1fe
|
||||
timeCreated: 1462745593
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,544 @@
|
||||
#if !UNITY_WSA && !UNITY_WP8
|
||||
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Threading;
|
||||
using PlayFab.SharedModels;
|
||||
#if !DISABLE_PLAYFABCLIENT_API
|
||||
using PlayFab.ClientModels;
|
||||
#endif
|
||||
|
||||
namespace PlayFab.Internal
|
||||
{
|
||||
public class PlayFabWebRequest : ITransportPlugin
|
||||
{
|
||||
/// <summary>
|
||||
/// Disable encryption certificate validation within PlayFabWebRequest using this request.
|
||||
/// This is not generally recommended.
|
||||
/// As of early 2018:
|
||||
/// None of the built-in Unity mechanisms validate the certificate, using .Net 3.5 equivalent runtime
|
||||
/// It is also not currently feasible to provide a single cross platform solution that will correctly validate a certificate.
|
||||
/// The Risk:
|
||||
/// All Unity HTTPS mechanisms are vulnerable to Man-In-The-Middle attacks.
|
||||
/// The only more-secure option is to define a custom CustomCertValidationHook, specifically tailored to the platforms you support,
|
||||
/// which validate the cert based on a list of trusted certificate providers. This list of providers must be able to update itself, as the
|
||||
/// base certificates for those providers will also expire and need updating on a regular basis.
|
||||
/// </summary>
|
||||
public static void SkipCertificateValidation()
|
||||
{
|
||||
var rcvc = new System.Net.Security.RemoteCertificateValidationCallback(AcceptAllCertifications); //(sender, cert, chain, ssl) => true
|
||||
ServicePointManager.ServerCertificateValidationCallback = rcvc;
|
||||
certValidationSet = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Provide PlayFabWebRequest with a custom ServerCertificateValidationCallback which can be used to validate the PlayFab encryption certificate.
|
||||
/// Please do not:
|
||||
/// - Hard code the current PlayFab certificate information - The PlayFab certificate updates itself on a regular schedule, and your game will fail and require a republish to fix
|
||||
/// - Hard code a list of static certificate authorities - Any single exported list of certificate authorities will become out of date, and have the same problem when the CA cert expires
|
||||
/// Real solution:
|
||||
/// - A mechanism where a valid certificate authority list can be securely downloaded and updated without republishing the client when existing certificates expire.
|
||||
/// </summary>
|
||||
public static System.Net.Security.RemoteCertificateValidationCallback CustomCertValidationHook
|
||||
{
|
||||
set
|
||||
{
|
||||
ServicePointManager.ServerCertificateValidationCallback = value;
|
||||
certValidationSet = true;
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly Queue<Action> ResultQueueTransferThread = new Queue<Action>();
|
||||
private static readonly Queue<Action> ResultQueueMainThread = new Queue<Action>();
|
||||
private static readonly List<CallRequestContainer> ActiveRequests = new List<CallRequestContainer>();
|
||||
|
||||
private static bool certValidationSet = false;
|
||||
private static Thread _requestQueueThread;
|
||||
private static readonly object _ThreadLock = new object();
|
||||
private static readonly TimeSpan ThreadKillTimeout = TimeSpan.FromSeconds(60);
|
||||
private static DateTime _threadKillTime = DateTime.UtcNow + ThreadKillTimeout; // Kill the thread after 1 minute of inactivity
|
||||
private static bool _isApplicationPlaying;
|
||||
private static int _activeCallCount;
|
||||
|
||||
private static string _unityVersion;
|
||||
|
||||
private bool _isInitialized = false;
|
||||
|
||||
public bool IsInitialized { get { return _isInitialized; } }
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
SetupCertificates();
|
||||
_isApplicationPlaying = true;
|
||||
_unityVersion = Application.unityVersion;
|
||||
_isInitialized = true;
|
||||
}
|
||||
|
||||
public void OnDestroy()
|
||||
{
|
||||
_isApplicationPlaying = false;
|
||||
lock (ResultQueueTransferThread)
|
||||
{
|
||||
ResultQueueTransferThread.Clear();
|
||||
}
|
||||
lock (ActiveRequests)
|
||||
{
|
||||
ActiveRequests.Clear();
|
||||
}
|
||||
lock (_ThreadLock)
|
||||
{
|
||||
_requestQueueThread = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void SetupCertificates()
|
||||
{
|
||||
// These are performance Optimizations for HttpWebRequests.
|
||||
ServicePointManager.DefaultConnectionLimit = 10;
|
||||
ServicePointManager.Expect100Continue = false;
|
||||
|
||||
if (!certValidationSet)
|
||||
{
|
||||
Debug.LogWarning("PlayFab API calls will likely fail because you have not set up a HttpWebRequest certificate validation mechanism");
|
||||
Debug.LogWarning("Please set a validation callback into PlayFab.Internal.PlayFabWebRequest.CustomCertValidationHook, or set PlayFab.Internal.PlayFabWebRequest.SkipCertificateValidation()");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This disables certificate validation, if it's been activated by a customer via SkipCertificateValidation()
|
||||
/// </summary>
|
||||
private static bool AcceptAllCertifications(object sender, System.Security.Cryptography.X509Certificates.X509Certificate certificate, System.Security.Cryptography.X509Certificates.X509Chain chain, System.Net.Security.SslPolicyErrors sslPolicyErrors)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public void SimpleGetCall(string fullUrl, Action<byte[]> successCallback, Action<string> errorCallback)
|
||||
{
|
||||
// This needs to be improved to use a decent thread-pool, but it can be improved invisibly later
|
||||
var newThread = new Thread(() => SimpleHttpsWorker("GET", fullUrl, null, successCallback, errorCallback));
|
||||
newThread.Start();
|
||||
}
|
||||
|
||||
public void SimplePutCall(string fullUrl, byte[] payload, Action<byte[]> successCallback, Action<string> errorCallback)
|
||||
{
|
||||
// This needs to be improved to use a decent thread-pool, but it can be improved invisibly later
|
||||
var newThread = new Thread(() => SimpleHttpsWorker("PUT", fullUrl, payload, successCallback, errorCallback));
|
||||
newThread.Start();
|
||||
}
|
||||
|
||||
public void SimplePostCall(string fullUrl, byte[] payload, Action<byte[]> successCallback, Action<string> errorCallback)
|
||||
{
|
||||
// This needs to be improved to use a decent thread-pool, but it can be improved invisibly later
|
||||
var newThread = new Thread(() => SimpleHttpsWorker("POST", fullUrl, payload, successCallback, errorCallback));
|
||||
newThread.Start();
|
||||
}
|
||||
|
||||
|
||||
private void SimpleHttpsWorker(string httpMethod, string fullUrl, byte[] payload, Action<byte[]> successCallback, Action<string> errorCallback)
|
||||
{
|
||||
// This should also use a pooled HttpWebRequest object, but that too can be improved invisibly later
|
||||
var httpRequest = (HttpWebRequest)WebRequest.Create(fullUrl);
|
||||
httpRequest.UserAgent = "UnityEngine-Unity; Version: " + _unityVersion;
|
||||
httpRequest.Method = httpMethod;
|
||||
httpRequest.KeepAlive = PlayFabSettings.RequestKeepAlive;
|
||||
httpRequest.Timeout = PlayFabSettings.RequestTimeout;
|
||||
httpRequest.AllowWriteStreamBuffering = false;
|
||||
httpRequest.ReadWriteTimeout = PlayFabSettings.RequestTimeout;
|
||||
|
||||
if (payload != null)
|
||||
{
|
||||
httpRequest.ContentLength = payload.LongLength;
|
||||
using (var stream = httpRequest.GetRequestStream())
|
||||
{
|
||||
stream.Write(payload, 0, payload.Length);
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var response = httpRequest.GetResponse();
|
||||
byte[] output = null;
|
||||
using (var responseStream = response.GetResponseStream())
|
||||
{
|
||||
if (responseStream != null)
|
||||
{
|
||||
output = new byte[response.ContentLength];
|
||||
responseStream.Read(output, 0, output.Length);
|
||||
}
|
||||
}
|
||||
successCallback(output);
|
||||
}
|
||||
catch (WebException webException)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var responseStream = webException.Response.GetResponseStream())
|
||||
{
|
||||
if (responseStream != null)
|
||||
using (var stream = new StreamReader(responseStream))
|
||||
errorCallback(stream.ReadToEnd());
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogException(e);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void MakeApiCall(object reqContainerObj)
|
||||
{
|
||||
CallRequestContainer reqContainer = (CallRequestContainer)reqContainerObj;
|
||||
reqContainer.HttpState = HttpRequestState.Idle;
|
||||
|
||||
lock (ActiveRequests)
|
||||
{
|
||||
ActiveRequests.Insert(0, reqContainer);
|
||||
}
|
||||
|
||||
ActivateThreadWorker();
|
||||
}
|
||||
|
||||
private static void ActivateThreadWorker()
|
||||
{
|
||||
lock (_ThreadLock)
|
||||
{
|
||||
if (_requestQueueThread != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
_requestQueueThread = new Thread(WorkerThreadMainLoop);
|
||||
_requestQueueThread.Start();
|
||||
}
|
||||
}
|
||||
|
||||
private static void WorkerThreadMainLoop()
|
||||
{
|
||||
try
|
||||
{
|
||||
bool active;
|
||||
lock (_ThreadLock)
|
||||
{
|
||||
// Kill the thread after 1 minute of inactivity
|
||||
_threadKillTime = DateTime.UtcNow + ThreadKillTimeout;
|
||||
}
|
||||
|
||||
List<CallRequestContainer> localActiveRequests = new List<CallRequestContainer>();
|
||||
do
|
||||
{
|
||||
//process active requests
|
||||
lock (ActiveRequests)
|
||||
{
|
||||
localActiveRequests.AddRange(ActiveRequests);
|
||||
ActiveRequests.Clear();
|
||||
_activeCallCount = localActiveRequests.Count;
|
||||
}
|
||||
|
||||
var activeCalls = localActiveRequests.Count;
|
||||
for (var i = activeCalls - 1; i >= 0; i--) // We must iterate backwards, because we remove at index i in some cases
|
||||
{
|
||||
switch (localActiveRequests[i].HttpState)
|
||||
{
|
||||
case HttpRequestState.Error:
|
||||
localActiveRequests.RemoveAt(i); break;
|
||||
case HttpRequestState.Idle:
|
||||
Post(localActiveRequests[i]); break;
|
||||
case HttpRequestState.Sent:
|
||||
if (!localActiveRequests[i].CalledGetResponse) { // Else we'll GetResponse try again next tick
|
||||
localActiveRequests[i].HttpRequest.GetResponseAsync();
|
||||
localActiveRequests[i].CalledGetResponse = true;
|
||||
}
|
||||
else if (localActiveRequests[i].HttpRequest.HaveResponse)
|
||||
ProcessHttpResponse(localActiveRequests[i]);
|
||||
break;
|
||||
case HttpRequestState.Received:
|
||||
ProcessJsonResponse(localActiveRequests[i]);
|
||||
localActiveRequests.RemoveAt(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#region Expire Thread.
|
||||
// Check if we've been inactive
|
||||
lock (_ThreadLock)
|
||||
{
|
||||
var now = DateTime.UtcNow;
|
||||
if (activeCalls > 0 && _isApplicationPlaying)
|
||||
{
|
||||
// Still active, reset the _threadKillTime
|
||||
_threadKillTime = now + ThreadKillTimeout;
|
||||
}
|
||||
// Kill the thread after 1 minute of inactivity
|
||||
active = now <= _threadKillTime;
|
||||
if (!active)
|
||||
{
|
||||
_requestQueueThread = null;
|
||||
}
|
||||
// This thread will be stopped, so null this now, inside lock (_threadLock)
|
||||
}
|
||||
#endregion
|
||||
|
||||
Thread.Sleep(1);
|
||||
} while (active);
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogException(e);
|
||||
_requestQueueThread = null;
|
||||
}
|
||||
}
|
||||
|
||||
private static void Post(CallRequestContainer reqContainer)
|
||||
{
|
||||
try
|
||||
{
|
||||
reqContainer.HttpRequest = (HttpWebRequest)WebRequest.Create(reqContainer.FullUrl);
|
||||
reqContainer.HttpRequest.UserAgent = "UnityEngine-Unity; Version: " + _unityVersion;
|
||||
reqContainer.HttpRequest.SendChunked = false;
|
||||
// Prevents hitting a proxy if no proxy is available. TODO: Add support for proxy's.
|
||||
reqContainer.HttpRequest.Proxy = null;
|
||||
|
||||
foreach (var pair in reqContainer.RequestHeaders)
|
||||
reqContainer.HttpRequest.Headers.Add(pair.Key, pair.Value);
|
||||
|
||||
reqContainer.HttpRequest.ContentType = "application/json";
|
||||
reqContainer.HttpRequest.Method = "POST";
|
||||
reqContainer.HttpRequest.KeepAlive = PlayFabSettings.RequestKeepAlive;
|
||||
reqContainer.HttpRequest.Timeout = PlayFabSettings.RequestTimeout;
|
||||
reqContainer.HttpRequest.AllowWriteStreamBuffering = false;
|
||||
reqContainer.HttpRequest.Proxy = null;
|
||||
reqContainer.HttpRequest.ContentLength = reqContainer.Payload.LongLength;
|
||||
reqContainer.HttpRequest.ReadWriteTimeout = PlayFabSettings.RequestTimeout;
|
||||
|
||||
//Debug.Log("Get Stream");
|
||||
// Get Request Stream and send data in the body.
|
||||
using (var stream = reqContainer.HttpRequest.GetRequestStream())
|
||||
{
|
||||
//Debug.Log("Post Stream");
|
||||
stream.Write(reqContainer.Payload, 0, reqContainer.Payload.Length);
|
||||
//Debug.Log("After Post stream");
|
||||
}
|
||||
|
||||
reqContainer.HttpState = HttpRequestState.Sent;
|
||||
}
|
||||
catch (WebException e)
|
||||
{
|
||||
reqContainer.JsonResponse = ResponseToString(e.Response) ?? e.Status + ": WebException making http request to: " + reqContainer.FullUrl;
|
||||
var enhancedError = new WebException(reqContainer.JsonResponse, e);
|
||||
Debug.LogException(enhancedError);
|
||||
QueueRequestError(reqContainer);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
reqContainer.JsonResponse = "Unhandled exception in Post : " + reqContainer.FullUrl;
|
||||
var enhancedError = new Exception(reqContainer.JsonResponse, e);
|
||||
Debug.LogException(enhancedError);
|
||||
QueueRequestError(reqContainer);
|
||||
}
|
||||
}
|
||||
|
||||
private static void ProcessHttpResponse(CallRequestContainer reqContainer)
|
||||
{
|
||||
try
|
||||
{
|
||||
#if PLAYFAB_REQUEST_TIMING
|
||||
reqContainer.Timing.WorkerRequestMs = (int)reqContainer.Stopwatch.ElapsedMilliseconds;
|
||||
#endif
|
||||
// Get and check the response
|
||||
var httpResponse = (HttpWebResponse)reqContainer.HttpRequest.GetResponse();
|
||||
if (httpResponse.StatusCode == HttpStatusCode.OK)
|
||||
{
|
||||
reqContainer.JsonResponse = ResponseToString(httpResponse);
|
||||
}
|
||||
|
||||
if (httpResponse.StatusCode != HttpStatusCode.OK || string.IsNullOrEmpty(reqContainer.JsonResponse))
|
||||
{
|
||||
reqContainer.JsonResponse = reqContainer.JsonResponse ?? "No response from server";
|
||||
QueueRequestError(reqContainer);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Response Recieved Successfully, now process.
|
||||
}
|
||||
|
||||
reqContainer.HttpState = HttpRequestState.Received;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
var msg = "Unhandled exception in ProcessHttpResponse : " + reqContainer.FullUrl;
|
||||
reqContainer.JsonResponse = reqContainer.JsonResponse ?? msg;
|
||||
var enhancedError = new Exception(msg, e);
|
||||
Debug.LogException(enhancedError);
|
||||
QueueRequestError(reqContainer);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the reqContainer into an error state, and queue it to invoke the ErrorCallback for that request
|
||||
/// </summary>
|
||||
private static void QueueRequestError(CallRequestContainer reqContainer)
|
||||
{
|
||||
reqContainer.Error = PlayFabHttp.GeneratePlayFabError(reqContainer.ApiEndpoint, reqContainer.JsonResponse, reqContainer.CustomData); // Decode the server-json error
|
||||
reqContainer.HttpState = HttpRequestState.Error;
|
||||
lock (ResultQueueTransferThread)
|
||||
{
|
||||
//Queue The result callbacks to run on the main thread.
|
||||
ResultQueueTransferThread.Enqueue(() =>
|
||||
{
|
||||
PlayFabHttp.SendErrorEvent(reqContainer.ApiRequest, reqContainer.Error);
|
||||
if (reqContainer.ErrorCallback != null)
|
||||
reqContainer.ErrorCallback(reqContainer.Error);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private static void ProcessJsonResponse(CallRequestContainer reqContainer)
|
||||
{
|
||||
try
|
||||
{
|
||||
var serializer = PluginManager.GetPlugin<ISerializerPlugin>(PluginContract.PlayFab_Serializer);
|
||||
var httpResult = serializer.DeserializeObject<HttpResponseObject>(reqContainer.JsonResponse);
|
||||
|
||||
#if PLAYFAB_REQUEST_TIMING
|
||||
reqContainer.Timing.WorkerRequestMs = (int)reqContainer.Stopwatch.ElapsedMilliseconds;
|
||||
#endif
|
||||
|
||||
//This would happen if playfab returned a 500 internal server error or a bad json response.
|
||||
if (httpResult == null || httpResult.code != 200)
|
||||
{
|
||||
QueueRequestError(reqContainer);
|
||||
return;
|
||||
}
|
||||
|
||||
reqContainer.JsonResponse = serializer.SerializeObject(httpResult.data);
|
||||
reqContainer.DeserializeResultJson(); // Assigns Result with a properly typed object
|
||||
reqContainer.ApiResult.Request = reqContainer.ApiRequest;
|
||||
reqContainer.ApiResult.CustomData = reqContainer.CustomData;
|
||||
|
||||
if(_isApplicationPlaying)
|
||||
{
|
||||
PlayFabHttp.instance.OnPlayFabApiResult(reqContainer);
|
||||
}
|
||||
|
||||
#if !DISABLE_PLAYFABCLIENT_API
|
||||
lock (ResultQueueTransferThread)
|
||||
{
|
||||
ResultQueueTransferThread.Enqueue(() => { PlayFabDeviceUtil.OnPlayFabLogin(reqContainer.ApiResult, reqContainer.settings, reqContainer.instanceApi); });
|
||||
}
|
||||
#endif
|
||||
lock (ResultQueueTransferThread)
|
||||
{
|
||||
//Queue The result callbacks to run on the main thread.
|
||||
ResultQueueTransferThread.Enqueue(() =>
|
||||
{
|
||||
#if PLAYFAB_REQUEST_TIMING
|
||||
reqContainer.Stopwatch.Stop();
|
||||
reqContainer.Timing.MainThreadRequestMs = (int)reqContainer.Stopwatch.ElapsedMilliseconds;
|
||||
PlayFabHttp.SendRequestTiming(reqContainer.Timing);
|
||||
#endif
|
||||
try
|
||||
{
|
||||
PlayFabHttp.SendEvent(reqContainer.ApiEndpoint, reqContainer.ApiRequest, reqContainer.ApiResult, ApiProcessingEventType.Post);
|
||||
reqContainer.InvokeSuccessCallback();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogException(e); // Log the user's callback exception back to them without halting PlayFabHttp
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
var msg = "Unhandled exception in ProcessJsonResponse : " + reqContainer.FullUrl;
|
||||
reqContainer.JsonResponse = reqContainer.JsonResponse ?? msg;
|
||||
var enhancedError = new Exception(msg, e);
|
||||
Debug.LogException(enhancedError);
|
||||
QueueRequestError(reqContainer);
|
||||
}
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
lock (ResultQueueTransferThread)
|
||||
{
|
||||
while (ResultQueueTransferThread.Count > 0)
|
||||
{
|
||||
var actionToQueue = ResultQueueTransferThread.Dequeue();
|
||||
ResultQueueMainThread.Enqueue(actionToQueue);
|
||||
}
|
||||
}
|
||||
|
||||
while (ResultQueueMainThread.Count > 0)
|
||||
{
|
||||
var finishedRequest = ResultQueueMainThread.Dequeue();
|
||||
finishedRequest();
|
||||
}
|
||||
}
|
||||
|
||||
private static string ResponseToString(WebResponse webResponse)
|
||||
{
|
||||
if (webResponse == null)
|
||||
return null;
|
||||
|
||||
try
|
||||
{
|
||||
using (var responseStream = webResponse.GetResponseStream())
|
||||
{
|
||||
if (responseStream == null)
|
||||
return null;
|
||||
using (var stream = new StreamReader(responseStream))
|
||||
{
|
||||
return stream.ReadToEnd();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (WebException webException)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var responseStream = webException.Response.GetResponseStream())
|
||||
{
|
||||
if (responseStream == null)
|
||||
return null;
|
||||
using (var stream = new StreamReader(responseStream))
|
||||
{
|
||||
return stream.ReadToEnd();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogException(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogException(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public int GetPendingMessages()
|
||||
{
|
||||
var count = 0;
|
||||
lock (ActiveRequests)
|
||||
count += ActiveRequests.Count + _activeCallCount;
|
||||
lock (ResultQueueTransferThread)
|
||||
count += ResultQueueTransferThread.Count;
|
||||
return count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 18fd1a0daadd68d45aebf8c19cac2bda
|
||||
timeCreated: 1466016486
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bce6184794650f24fa8ac244b25edc17
|
||||
timeCreated: 1462682372
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,58 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace PlayFab.Internal
|
||||
{
|
||||
//public to be accessible by Unity engine
|
||||
public class SingletonMonoBehaviour<T> : MonoBehaviour where T : SingletonMonoBehaviour<T>
|
||||
{
|
||||
private static T _instance;
|
||||
|
||||
public static T instance
|
||||
{
|
||||
get
|
||||
{
|
||||
CreateInstance();
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
|
||||
public static void CreateInstance()
|
||||
{
|
||||
if (_instance == null)
|
||||
{
|
||||
//find existing instance
|
||||
_instance = FindObjectOfType<T>();
|
||||
if (_instance == null)
|
||||
{
|
||||
//create new instance
|
||||
var go = new GameObject(typeof(T).Name);
|
||||
_instance = go.AddComponent<T>();
|
||||
}
|
||||
//initialize instance if necessary
|
||||
if (!_instance.initialized)
|
||||
{
|
||||
_instance.Initialize();
|
||||
_instance.initialized = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void Awake ()
|
||||
{
|
||||
if (Application.isPlaying)
|
||||
{
|
||||
DontDestroyOnLoad(this);
|
||||
}
|
||||
|
||||
//check if instance already exists when reloading original scene
|
||||
if (_instance != null)
|
||||
{
|
||||
DestroyImmediate (gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
protected bool initialized;
|
||||
|
||||
protected virtual void Initialize() { }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f6a51fa1ed684497db153f40961979c4
|
||||
timeCreated: 1462682373
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,157 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
#if NETFX_CORE
|
||||
using System.Reflection;
|
||||
#endif
|
||||
|
||||
namespace PlayFab.Internal
|
||||
{
|
||||
public static class PlayFabUtil
|
||||
{
|
||||
static PlayFabUtil() { }
|
||||
|
||||
private static string _localSettingsFileName = "playfab.local.settings.json";
|
||||
public static readonly string[] _defaultDateTimeFormats = new string[]{ // All parseable ISO 8601 formats for DateTime.[Try]ParseExact - Lets us deserialize any legacy timestamps in one of these formats
|
||||
// These are the standard format with ISO 8601 UTC markers (T/Z)
|
||||
"yyyy-MM-ddTHH:mm:ss.FFFFFFZ",
|
||||
"yyyy-MM-ddTHH:mm:ss.FFFFZ",
|
||||
"yyyy-MM-ddTHH:mm:ss.FFFZ", // DEFAULT_UTC_OUTPUT_INDEX
|
||||
"yyyy-MM-ddTHH:mm:ss.FFZ",
|
||||
"yyyy-MM-ddTHH:mm:ssZ",
|
||||
"yyyy-MM-dd HH:mm:ssZ", // Added for Android Push Plugin
|
||||
|
||||
// These are the standard format without ISO 8601 UTC markers (T/Z)
|
||||
"yyyy-MM-dd HH:mm:ss.FFFFFF",
|
||||
"yyyy-MM-dd HH:mm:ss.FFFF",
|
||||
"yyyy-MM-dd HH:mm:ss.FFF",
|
||||
"yyyy-MM-dd HH:mm:ss.FF", // DEFAULT_LOCAL_OUTPUT_INDEX
|
||||
"yyyy-MM-dd HH:mm:ss",
|
||||
|
||||
// These are the result of an input bug, which we now have to support as long as the db has entries formatted like this
|
||||
"yyyy-MM-dd HH:mm.ss.FFFF",
|
||||
"yyyy-MM-dd HH:mm.ss.FFF",
|
||||
"yyyy-MM-dd HH:mm.ss.FF",
|
||||
"yyyy-MM-dd HH:mm.ss",
|
||||
};
|
||||
public const int DEFAULT_UTC_OUTPUT_INDEX = 2; // The default format everybody should use
|
||||
public const int DEFAULT_LOCAL_OUTPUT_INDEX = 9; // The default format if you want to use local time (This doesn't have universal support in all PlayFab code)
|
||||
public static DateTimeStyles DateTimeStyles = DateTimeStyles.RoundtripKind;
|
||||
|
||||
public static string timeStamp
|
||||
{
|
||||
get { return DateTime.Now.ToString(_defaultDateTimeFormats[DEFAULT_LOCAL_OUTPUT_INDEX]); }
|
||||
}
|
||||
|
||||
public static string utcTimeStamp
|
||||
{
|
||||
get { return DateTime.UtcNow.ToString(_defaultDateTimeFormats[DEFAULT_UTC_OUTPUT_INDEX]); }
|
||||
}
|
||||
|
||||
public static string Format(string text, params object[] args)
|
||||
{
|
||||
return args.Length > 0 ? string.Format(text, args) : text;
|
||||
}
|
||||
|
||||
[ThreadStatic]
|
||||
private static StringBuilder _sb;
|
||||
/// <summary>
|
||||
/// A threadsafe way to block and load a text file
|
||||
///
|
||||
/// Load a text file, and return the file as text.
|
||||
/// Used for small (usually json) files.
|
||||
/// </summary>
|
||||
public static string ReadAllFileText(string filename)
|
||||
{
|
||||
if (!File.Exists(filename))
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
if (_sb == null)
|
||||
{
|
||||
_sb = new StringBuilder();
|
||||
}
|
||||
_sb.Length = 0;
|
||||
|
||||
using (var fs = new FileStream(filename, FileMode.Open))
|
||||
{
|
||||
using (var br = new BinaryReader(fs))
|
||||
{
|
||||
while (br.BaseStream.Position != br.BaseStream.Length)
|
||||
{
|
||||
_sb.Append(br.ReadChar());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return _sb.ToString();
|
||||
}
|
||||
|
||||
public static T TryEnumParse<T>(string value, T defaultValue)
|
||||
{
|
||||
try
|
||||
{
|
||||
return (T)Enum.Parse(typeof(T), value);
|
||||
}
|
||||
catch (InvalidCastException)
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
UnityEngine.Debug.LogError("Enum cast failed with unknown error: " + e.Message);
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
#if UNITY_2017_1_OR_NEWER
|
||||
internal static string GetLocalSettingsFileProperty(string propertyKey)
|
||||
{
|
||||
string envFileContent = null;
|
||||
|
||||
string currDir = Directory.GetCurrentDirectory();
|
||||
string currDirEnvFile = Path.Combine(currDir, _localSettingsFileName);
|
||||
|
||||
if (File.Exists(currDirEnvFile))
|
||||
{
|
||||
envFileContent = ReadAllFileText(currDirEnvFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
string tempDir = Path.GetTempPath();
|
||||
string tempDirEnvFile = Path.Combine(tempDir, _localSettingsFileName);
|
||||
|
||||
if (File.Exists(tempDirEnvFile))
|
||||
{
|
||||
envFileContent = ReadAllFileText(tempDirEnvFile);
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(envFileContent))
|
||||
{
|
||||
var serializer = PluginManager.GetPlugin<ISerializerPlugin>(PluginContract.PlayFab_Serializer);
|
||||
var envJson = serializer.DeserializeObject<Dictionary<string, object>>(envFileContent);
|
||||
try
|
||||
{
|
||||
object result;
|
||||
if (envJson.TryGetValue(propertyKey, out result))
|
||||
{
|
||||
return result == null ? null : result.ToString();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
catch (KeyNotFoundException)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
return string.Empty;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b3bfc0fbdbe1a36429699dfc30c9e488
|
||||
timeCreated: 1462682372
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,66 @@
|
||||
#if UNITY_WSA && UNITY_WP8
|
||||
#define NETFX_CORE
|
||||
#endif
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
|
||||
namespace PlayFab
|
||||
{
|
||||
public static class WsaReflectionExtensions
|
||||
{
|
||||
#if !NETFX_CORE
|
||||
public static Delegate CreateDelegate(this MethodInfo methodInfo, Type delegateType, object instance)
|
||||
{
|
||||
return Delegate.CreateDelegate(delegateType, instance, methodInfo);
|
||||
}
|
||||
public static Type GetTypeInfo(this Type type)
|
||||
{
|
||||
return type;
|
||||
}
|
||||
public static Type AsType(this Type type)
|
||||
{
|
||||
return type;
|
||||
}
|
||||
public static string GetDelegateName(this Delegate delegateInstance)
|
||||
{
|
||||
return delegateInstance.Method.Name;
|
||||
}
|
||||
#else
|
||||
public static bool IsInstanceOfType(this Type type, object obj)
|
||||
{
|
||||
return obj != null && type.GetTypeInfo().IsAssignableFrom(obj.GetType().GetTypeInfo());
|
||||
}
|
||||
public static string GetDelegateName(this Delegate delegateInstance)
|
||||
{
|
||||
return delegateInstance.ToString();
|
||||
}
|
||||
public static MethodInfo GetMethod(this Type type, string methodName)
|
||||
{
|
||||
return type.GetTypeInfo().GetDeclaredMethod(methodName);
|
||||
}
|
||||
public static IEnumerable<FieldInfo> GetFields(this TypeInfo typeInfo)
|
||||
{
|
||||
return typeInfo.DeclaredFields;
|
||||
}
|
||||
public static TypeInfo GetTypeInfo(this TypeInfo typeInfo)
|
||||
{
|
||||
return typeInfo;
|
||||
}
|
||||
public static IEnumerable<ConstructorInfo> GetConstructors(this TypeInfo typeInfo)
|
||||
{
|
||||
return typeInfo.DeclaredConstructors;
|
||||
}
|
||||
public static IEnumerable<MethodInfo> GetMethods(this TypeInfo typeInfo, BindingFlags ignored)
|
||||
{
|
||||
return typeInfo.DeclaredMethods;
|
||||
}
|
||||
public static IEnumerable<TypeInfo> GetTypes(this Assembly assembly)
|
||||
{
|
||||
return assembly.DefinedTypes;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1b20d57e2279b3a408268b20c2be2208
|
||||
timeCreated: 1468890373
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 34c5d2725a89d1c40af9b10a9b9dcbc5
|
||||
folderAsset: yes
|
||||
timeCreated: 1467491757
|
||||
licenseType: Pro
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,34 @@
|
||||
using UnityEngine;
|
||||
using PlayFab;
|
||||
|
||||
#if UNITY_5_3_OR_NEWER
|
||||
[CreateAssetMenu(fileName = "PlayFabSharedSettings", menuName = "PlayFab/CreateSharedSettings", order = 1)]
|
||||
#endif
|
||||
public class PlayFabSharedSettings : ScriptableObject
|
||||
{
|
||||
public string TitleId;
|
||||
|
||||
internal string VerticalName = null;
|
||||
#if ENABLE_PLAYFABSERVER_API || ENABLE_PLAYFABADMIN_API || UNITY_EDITOR || ENABLE_PLAYFAB_SECRETKEY
|
||||
public string DeveloperSecretKey;
|
||||
#endif
|
||||
public string ProductionEnvironmentUrl = "";
|
||||
|
||||
#if UNITY_2017_2_OR_NEWER
|
||||
public WebRequestType RequestType = WebRequestType.UnityWebRequest;
|
||||
#else
|
||||
public WebRequestType RequestType = WebRequestType.UnityWww;
|
||||
#endif
|
||||
|
||||
public bool DisableDeviceInfo;
|
||||
public bool DisableFocusTimeCollection;
|
||||
|
||||
public int RequestTimeout = 2000;
|
||||
public bool RequestKeepAlive = true;
|
||||
|
||||
public PlayFabLogLevel LogLevel = PlayFabLogLevel.Warning | PlayFabLogLevel.Error;
|
||||
public string LoggerHost = "";
|
||||
public int LoggerPort = 0;
|
||||
public bool EnableRealTimeLogging = false;
|
||||
public int LogCapLimit = 30;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 093286084a3d1994a9c28281a1c38b1d
|
||||
timeCreated: 1467748518
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,44 @@
|
||||
using PlayFab.Internal;
|
||||
|
||||
namespace PlayFab.SharedModels
|
||||
{
|
||||
public class HttpResponseObject
|
||||
{
|
||||
public int code;
|
||||
public string status;
|
||||
public object data;
|
||||
}
|
||||
|
||||
public class PlayFabBaseModel
|
||||
{
|
||||
public string ToJson()
|
||||
{
|
||||
var json = PluginManager.GetPlugin<ISerializerPlugin>(PluginContract.PlayFab_Serializer);
|
||||
return json.SerializeObject(this);
|
||||
}
|
||||
}
|
||||
|
||||
public interface IPlayFabInstanceApi { }
|
||||
|
||||
public class PlayFabRequestCommon : PlayFabBaseModel
|
||||
{
|
||||
public PlayFabAuthenticationContext AuthenticationContext;
|
||||
}
|
||||
|
||||
public class PlayFabResultCommon : PlayFabBaseModel
|
||||
{
|
||||
public PlayFabRequestCommon Request;
|
||||
public object CustomData;
|
||||
}
|
||||
|
||||
public class PlayFabLoginResultCommon : PlayFabResultCommon
|
||||
{
|
||||
public PlayFabAuthenticationContext AuthenticationContext;
|
||||
}
|
||||
|
||||
public class PlayFabResult<TResult> where TResult : PlayFabResultCommon
|
||||
{
|
||||
public TResult Result;
|
||||
public object CustomData;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8e2ad5324972b434883785ddddf9c851
|
||||
timeCreated: 1467491766
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 85636a5aec9f04e91a75e422c19ff5da
|
||||
folderAsset: yes
|
||||
timeCreated: 1462682372
|
||||
licenseType: Pro
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace PlayFab
|
||||
{
|
||||
/// <summary>
|
||||
/// Base interface of any PlayFab SDK plugin.
|
||||
/// </summary>
|
||||
public interface IPlayFabPlugin
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c515d14de9458ef449d382c41e4943b0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,15 @@
|
||||
namespace PlayFab
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface of any data serializer SDK plugin.
|
||||
/// </summary>
|
||||
public interface ISerializerPlugin : IPlayFabPlugin
|
||||
{
|
||||
T DeserializeObject<T>(string serialized);
|
||||
T DeserializeObject<T>(string serialized, object serializerStrategy);
|
||||
object DeserializeObject(string serialized);
|
||||
|
||||
string SerializeObject(object obj);
|
||||
string SerializeObject(object obj, object serializerStrategy);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d33ec65e8a628fe44a4aa5c55289a16d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,27 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace PlayFab
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface of any transport SDK plugin.
|
||||
/// </summary>
|
||||
public interface ITransportPlugin: IPlayFabPlugin
|
||||
{
|
||||
bool IsInitialized { get; }
|
||||
void Initialize();
|
||||
|
||||
// Mirroring MonoBehaviour - Relayed from PlayFabHTTP
|
||||
void Update();
|
||||
void OnDestroy();
|
||||
|
||||
void SimpleGetCall(string fullUrl, Action<byte[]> successCallback, Action<string> errorCallback);
|
||||
void SimplePutCall(string fullUrl, byte[] payload, Action<byte[]> successCallback, Action<string> errorCallback);
|
||||
|
||||
void SimplePostCall(string fullUrl, byte[] payload, Action<byte[]> successCallback, Action<string> errorCallback);
|
||||
|
||||
void MakeApiCall(object reqContainer);
|
||||
|
||||
int GetPendingMessages();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b97cd56b9c312144bb35f37b431aa18f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,84 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
|
||||
namespace PlayFab
|
||||
{
|
||||
public class PlayFabApiSettings
|
||||
{
|
||||
private string _ProductionEnvironmentUrl = PlayFabSettings.DefaultPlayFabApiUrl;
|
||||
public readonly Dictionary<string, string> _requestGetParams = new Dictionary<string, string> {
|
||||
{ "sdk", PlayFabSettings.VersionString }
|
||||
};
|
||||
|
||||
public virtual Dictionary<string, string> RequestGetParams { get { return _requestGetParams; } }
|
||||
|
||||
/// <summary> This is only for customers running a private cluster. Generally you shouldn't touch this </summary>
|
||||
public virtual string ProductionEnvironmentUrl { get { return _ProductionEnvironmentUrl; } set { _ProductionEnvironmentUrl = value; } }
|
||||
/// <summary> You must set this value for PlayFabSdk to work properly (Found in the Game Manager for your title, at the PlayFab Website) </summary>
|
||||
public virtual string TitleId { get; set; }
|
||||
|
||||
/// <summary> The name of a customer vertical. This is only for customers running a private cluster. Generally you shouldn't touch this </summary>
|
||||
internal virtual string VerticalName { get; set; }
|
||||
#if ENABLE_PLAYFABSERVER_API || ENABLE_PLAYFABADMIN_API || UNITY_EDITOR || ENABLE_PLAYFAB_SECRETKEY
|
||||
/// <summary> You must set this value for PlayFabSdk to work properly (Found in the Game Manager for your title, at the PlayFab Website) </summary>
|
||||
public virtual string DeveloperSecretKey { get; set; }
|
||||
#endif
|
||||
/// <summary> Set this to true to prevent hardware information from leaving the device </summary>
|
||||
public virtual bool DisableDeviceInfo { get; set; }
|
||||
/// <summary> Set this to true to prevent focus change information from leaving the device </summary>
|
||||
public virtual bool DisableFocusTimeCollection { get; set; }
|
||||
|
||||
|
||||
public virtual string GetFullUrl(string apiCall, Dictionary<string, string> getParams)
|
||||
{
|
||||
return PlayFabSettings.GetFullUrl(apiCall, getParams, this);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is only meant for PlayFabSettings to use as a redirect to store values on PlayFabSharedSettings instead of locally
|
||||
/// </summary>
|
||||
internal class PlayFabSettingsRedirect : PlayFabApiSettings
|
||||
{
|
||||
private readonly Func<PlayFabSharedSettings> GetSO;
|
||||
public PlayFabSettingsRedirect(Func<PlayFabSharedSettings> getSO) { GetSO = getSO; }
|
||||
|
||||
public override string ProductionEnvironmentUrl
|
||||
{
|
||||
get { var so = GetSO(); return so == null ? base.ProductionEnvironmentUrl : so.ProductionEnvironmentUrl; }
|
||||
set { var so = GetSO(); if (so != null) so.ProductionEnvironmentUrl = value; base.ProductionEnvironmentUrl = value; }
|
||||
}
|
||||
|
||||
internal override string VerticalName
|
||||
{
|
||||
get { var so = GetSO(); return so == null ? base.VerticalName : so.VerticalName; }
|
||||
set { var so = GetSO(); if (so != null) so.VerticalName = value; base.VerticalName = value; }
|
||||
}
|
||||
|
||||
#if ENABLE_PLAYFABSERVER_API || ENABLE_PLAYFABADMIN_API || UNITY_EDITOR || ENABLE_PLAYFAB_SECRETKEY
|
||||
public override string DeveloperSecretKey
|
||||
{
|
||||
get { var so = GetSO(); return so == null ? base.DeveloperSecretKey : so.DeveloperSecretKey; }
|
||||
set { var so = GetSO(); if (so != null) so.DeveloperSecretKey = value; base.DeveloperSecretKey = value; }
|
||||
}
|
||||
#endif
|
||||
|
||||
public override string TitleId
|
||||
{
|
||||
get { var so = GetSO(); return so == null ? base.TitleId : so.TitleId; }
|
||||
set { var so = GetSO(); if (so != null) so.TitleId = value; base.TitleId = value; }
|
||||
}
|
||||
|
||||
public override bool DisableDeviceInfo
|
||||
{
|
||||
get { var so = GetSO(); return so == null ? base.DisableDeviceInfo : so.DisableDeviceInfo; }
|
||||
set { var so = GetSO(); if (so != null) so.DisableDeviceInfo = value; base.DisableDeviceInfo = value; }
|
||||
}
|
||||
|
||||
public override bool DisableFocusTimeCollection
|
||||
{
|
||||
get { var so = GetSO(); return so == null ? base.DisableFocusTimeCollection : so.DisableFocusTimeCollection; }
|
||||
set { var so = GetSO(); if (so != null) so.DisableFocusTimeCollection = value; base.DisableFocusTimeCollection = value; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 66cd997c6a8b2ed4d8d2b5c2a97b6e22
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,77 @@
|
||||
namespace PlayFab
|
||||
{
|
||||
public sealed class PlayFabAuthenticationContext
|
||||
{
|
||||
public PlayFabAuthenticationContext()
|
||||
{
|
||||
}
|
||||
|
||||
public PlayFabAuthenticationContext(string clientSessionTicket, string entityToken, string playFabId, string entityId, string entityType) : this()
|
||||
{
|
||||
#if !DISABLE_PLAYFABCLIENT_API
|
||||
ClientSessionTicket = clientSessionTicket;
|
||||
PlayFabId = playFabId;
|
||||
#endif
|
||||
#if !DISABLE_PLAYFABENTITY_API
|
||||
EntityToken = entityToken;
|
||||
EntityId = entityId;
|
||||
EntityType = entityType;
|
||||
#endif
|
||||
}
|
||||
|
||||
public void CopyFrom(PlayFabAuthenticationContext other)
|
||||
{
|
||||
#if !DISABLE_PLAYFABCLIENT_API
|
||||
ClientSessionTicket = other.ClientSessionTicket;
|
||||
PlayFabId = other.PlayFabId;
|
||||
#endif
|
||||
#if !DISABLE_PLAYFABENTITY_API
|
||||
EntityToken = other.EntityToken;
|
||||
EntityId = other.EntityId;
|
||||
EntityType = other.EntityType;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !DISABLE_PLAYFABCLIENT_API
|
||||
/// <summary> Allows access to the ClientAPI </summary>
|
||||
public string ClientSessionTicket;
|
||||
/// <summary> The master player entity Id </summary>
|
||||
public string PlayFabId;
|
||||
public bool IsClientLoggedIn()
|
||||
{
|
||||
return !string.IsNullOrEmpty(ClientSessionTicket);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !DISABLE_PLAYFABENTITY_API
|
||||
/// <summary> Allows access to most Entity APIs </summary>
|
||||
public string EntityToken;
|
||||
/// <summary>
|
||||
/// Clients: The title player entity Id (unless replaced with a related entity)
|
||||
/// Servers: The title id (unless replaced with a related entity)
|
||||
/// </summary>
|
||||
public string EntityId;
|
||||
/// <summary>
|
||||
/// Describes the type of entity identified by EntityId
|
||||
/// </summary>
|
||||
public string EntityType;
|
||||
public bool IsEntityLoggedIn()
|
||||
{
|
||||
return !string.IsNullOrEmpty(EntityToken);
|
||||
}
|
||||
#endif
|
||||
|
||||
public void ForgetAllCredentials()
|
||||
{
|
||||
#if !DISABLE_PLAYFABCLIENT_API
|
||||
PlayFabId = null;
|
||||
ClientSessionTicket = null;
|
||||
#endif
|
||||
#if !DISABLE_PLAYFABENTITY_API
|
||||
EntityToken = null;
|
||||
EntityId = null;
|
||||
EntityType = null;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5e4df1f8e07aee2409343554f628ce8b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,138 @@
|
||||
using UnityEngine;
|
||||
using System.Text;
|
||||
using PlayFab.SharedModels;
|
||||
using UnityEngine.Rendering;
|
||||
#if NETFX_CORE
|
||||
using System.Reflection;
|
||||
#endif
|
||||
|
||||
namespace PlayFab
|
||||
{
|
||||
public class PlayFabDataGatherer
|
||||
{
|
||||
#if UNITY_5 || UNITY_5_3_OR_NEWER
|
||||
// UNITY_5 Application info
|
||||
public string ProductName;
|
||||
public string ProductBundle;
|
||||
public string Version;
|
||||
public string Company;
|
||||
public RuntimePlatform Platform;
|
||||
// UNITY_5 Graphics Abilities
|
||||
public bool GraphicsMultiThreaded;
|
||||
#else
|
||||
public enum GraphicsDeviceType
|
||||
{
|
||||
OpenGL2 = 0, Direct3D9 = 1, Direct3D11 = 2, PlayStation3 = 3, Null = 4, Xbox360 = 6, OpenGLES2 = 8, OpenGLES3 = 11, PlayStationVita = 12,
|
||||
PlayStation4 = 13, XboxOne = 14, PlayStationMobile = 15, Metal = 16, OpenGLCore = 17, Direct3D12 = 18, Nintendo3DS = 19
|
||||
}
|
||||
|
||||
// RuntimePlatform Enum info:
|
||||
// OSXEditor = 0, OSXPlayer = 1, WindowsPlayer = 2, OSXWebPlayer = 3, OSXDashboardPlayer = 4, WindowsWebPlayer = 5, WindowsEditor = 7,
|
||||
// IPhonePlayer = 8, PS3 = 9, XBOX360 = 10, Android = 11, LinuxPlayer = 13, FlashPlayer = 15, WebGLPlayer = 17, MetroPlayerX86 = 18,
|
||||
// WSAPlayerX86 = 18, MetroPlayerX64 = 19,WSAPlayerX64 = 19, MetroPlayerARM = 20, WSAPlayerARM = 20, WP8Player = 21,
|
||||
// EditorBrowsable(EditorBrowsableState.Never)] BB10Player = 22, BlackBerryPlayer = 22, TizenPlayer = 23, PSP2 = 24, PS4 = 25,
|
||||
// PSM = 26, XboxOne = 27, SamsungTVPlayer = 28, WiiU = 30, tvOS = 31
|
||||
#endif
|
||||
#if !UNITY_5_0 && (UNITY_5 || UNITY_5_3_OR_NEWER)
|
||||
public GraphicsDeviceType GraphicsType;
|
||||
#endif
|
||||
|
||||
// Application info
|
||||
public string DataPath;
|
||||
public string PersistentDataPath;
|
||||
public string StreamingAssetsPath;
|
||||
public int TargetFrameRate;
|
||||
public string UnityVersion;
|
||||
public bool RunInBackground;
|
||||
|
||||
//DEVICE & OS
|
||||
public string DeviceModel;
|
||||
//public enum DeviceType { Unknown, Handheld, Console, Desktop }
|
||||
public DeviceType DeviceType;
|
||||
public string DeviceUniqueId;
|
||||
public string OperatingSystem;
|
||||
|
||||
//GRAPHICS ABILITIES
|
||||
public int GraphicsDeviceId;
|
||||
public string GraphicsDeviceName;
|
||||
public int GraphicsMemorySize;
|
||||
public int GraphicsShaderLevel;
|
||||
|
||||
//SYSTEM INFO
|
||||
public int SystemMemorySize;
|
||||
public int ProcessorCount;
|
||||
public int ProcessorFrequency;
|
||||
public string ProcessorType;
|
||||
public bool SupportsAccelerometer;
|
||||
public bool SupportsGyroscope;
|
||||
public bool SupportsLocationService;
|
||||
|
||||
public PlayFabDataGatherer()
|
||||
{
|
||||
#if UNITY_5 || UNITY_5_3_OR_NEWER
|
||||
// UNITY_5 Application info
|
||||
ProductName = Application.productName;
|
||||
Version = Application.version;
|
||||
Company = Application.companyName;
|
||||
Platform = Application.platform;
|
||||
// UNITY_5 Graphics Abilities
|
||||
GraphicsMultiThreaded = SystemInfo.graphicsMultiThreaded;
|
||||
#endif
|
||||
#if !UNITY_5_0 && (UNITY_5 || UNITY_5_3_OR_NEWER)
|
||||
GraphicsType = SystemInfo.graphicsDeviceType;
|
||||
#endif
|
||||
|
||||
//Only Used on iOS & Android
|
||||
#if UNITY_5_6_OR_NEWER && (UNITY_ANDROID || UNITY_IOS || UNITY_IPHONE)
|
||||
ProductBundle = Application.identifier;
|
||||
#elif UNITY_ANDROID || UNITY_IOS || UNITY_IPHONE
|
||||
ProductBundle = Application.bundleIdentifier;
|
||||
#endif
|
||||
|
||||
// Application info
|
||||
DataPath = Application.dataPath;
|
||||
#if !UNITY_SWITCH
|
||||
PersistentDataPath = Application.persistentDataPath;
|
||||
#endif
|
||||
StreamingAssetsPath = Application.streamingAssetsPath;
|
||||
TargetFrameRate = Application.targetFrameRate;
|
||||
UnityVersion = Application.unityVersion;
|
||||
|
||||
//DEVICE & OS
|
||||
DeviceModel = SystemInfo.deviceModel;
|
||||
DeviceType = SystemInfo.deviceType;
|
||||
|
||||
DeviceUniqueId = PlayFabSettings.DeviceUniqueIdentifier;
|
||||
OperatingSystem = SystemInfo.operatingSystem;
|
||||
|
||||
//GRAPHICS ABILITIES
|
||||
GraphicsDeviceId = SystemInfo.graphicsDeviceID;
|
||||
GraphicsDeviceName = SystemInfo.graphicsDeviceName;
|
||||
GraphicsMemorySize = SystemInfo.graphicsMemorySize;
|
||||
GraphicsShaderLevel = SystemInfo.graphicsShaderLevel;
|
||||
|
||||
//SYSTEM INFO
|
||||
SystemMemorySize = SystemInfo.systemMemorySize;
|
||||
ProcessorCount = SystemInfo.processorCount;
|
||||
#if UNITY_5_3_OR_NEWER
|
||||
ProcessorFrequency = SystemInfo.processorFrequency; // Not Supported in PRE Unity 5_2
|
||||
#endif
|
||||
ProcessorType = SystemInfo.processorType;
|
||||
SupportsAccelerometer = SystemInfo.supportsAccelerometer;
|
||||
SupportsGyroscope = SystemInfo.supportsGyroscope;
|
||||
SupportsLocationService = SystemInfo.supportsLocationService;
|
||||
}
|
||||
|
||||
public string GenerateReport()
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
sb.Append("Logging System Info: ========================================\n");
|
||||
foreach (var field in GetType().GetTypeInfo().GetFields())
|
||||
{
|
||||
var fld = field.GetValue(this).ToString();
|
||||
sb.AppendFormat("System Info - {0}: {1}\n", field.Name, fld);
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9021fc3e0230b9a4db0f0e1b104b764b
|
||||
timeCreated: 1464569227
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 059603d7e53649849b7f08d3b99af79c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,270 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using PlayFab.Internal;
|
||||
using UnityEngine;
|
||||
|
||||
namespace PlayFab.Public
|
||||
{
|
||||
#if !UNITY_WSA && !UNITY_WP8 && !NETFX_CORE
|
||||
public interface IPlayFabLogger
|
||||
{
|
||||
IPAddress ip { get; set; }
|
||||
int port { get; set; }
|
||||
string url { get; set; }
|
||||
|
||||
// Unity MonoBehaviour callbacks
|
||||
void OnEnable();
|
||||
void OnDisable();
|
||||
void OnDestroy();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is some unity-log capturing logic, and threading tools that allow logging to be caught and processed on another thread
|
||||
/// </summary>
|
||||
public abstract class PlayFabLoggerBase : IPlayFabLogger
|
||||
{
|
||||
private static readonly StringBuilder Sb = new StringBuilder();
|
||||
private readonly Queue<string> LogMessageQueue = new Queue<string>();
|
||||
private const int LOG_CACHE_INTERVAL_MS = 10000;
|
||||
|
||||
private Thread _writeLogThread;
|
||||
private readonly object _threadLock = new object();
|
||||
private static readonly TimeSpan _threadKillTimeout = TimeSpan.FromSeconds(60);
|
||||
private DateTime _threadKillTime = DateTime.UtcNow + _threadKillTimeout; // Kill the thread after 1 minute of inactivity
|
||||
private bool _isApplicationPlaying = true;
|
||||
private int _pendingLogsCount;
|
||||
|
||||
public IPAddress ip { get; set; }
|
||||
public int port { get; set; }
|
||||
public string url { get; set; }
|
||||
|
||||
protected PlayFabLoggerBase()
|
||||
{
|
||||
var gatherer = new PlayFabDataGatherer();
|
||||
var message = gatherer.GenerateReport();
|
||||
lock (LogMessageQueue)
|
||||
{
|
||||
LogMessageQueue.Enqueue(message);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void OnEnable()
|
||||
{
|
||||
PlayFabHttp.instance.StartCoroutine(RegisterLogger()); // Coroutine helper to set up log-callbacks
|
||||
}
|
||||
|
||||
private IEnumerator RegisterLogger()
|
||||
{
|
||||
yield return new WaitForEndOfFrame(); // Effectively just a short wait before activating this registration
|
||||
if (!string.IsNullOrEmpty(PlayFabSettings.LoggerHost))
|
||||
{
|
||||
#if UNITY_5 || UNITY_5_3_OR_NEWER
|
||||
Application.logMessageReceivedThreaded += HandleUnityLog;
|
||||
#else
|
||||
Application.RegisterLogCallback(HandleUnityLog);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void OnDisable()
|
||||
{
|
||||
if (!string.IsNullOrEmpty(PlayFabSettings.LoggerHost))
|
||||
{
|
||||
#if UNITY_5 || UNITY_5_3_OR_NEWER
|
||||
Application.logMessageReceivedThreaded -= HandleUnityLog;
|
||||
#else
|
||||
Application.RegisterLogCallback(null);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void OnDestroy()
|
||||
{
|
||||
_isApplicationPlaying = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Logs are cached and written in bursts
|
||||
/// BeginUploadLog is called at the begining of each burst
|
||||
/// </summary>
|
||||
protected abstract void BeginUploadLog();
|
||||
/// <summary>
|
||||
/// Logs are cached and written in bursts
|
||||
/// UploadLog is called for each cached log, between BeginUploadLog and EndUploadLog
|
||||
/// </summary>
|
||||
protected abstract void UploadLog(string message);
|
||||
/// <summary>
|
||||
/// Logs are cached and written in bursts
|
||||
/// EndUploadLog is called at the end of each burst
|
||||
/// </summary>
|
||||
protected abstract void EndUploadLog();
|
||||
|
||||
/// <summary>
|
||||
/// Handler to process Unity logs into our logging system
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
/// <param name="stacktrace"></param>
|
||||
/// <param name="type"></param>
|
||||
private void HandleUnityLog(string message, string stacktrace, LogType type)
|
||||
{
|
||||
if (!PlayFabSettings.EnableRealTimeLogging)
|
||||
return;
|
||||
|
||||
Sb.Length = 0;
|
||||
if (type == LogType.Log || type == LogType.Warning)
|
||||
{
|
||||
Sb.Append(type).Append(": ").Append(message);
|
||||
message = Sb.ToString();
|
||||
lock (LogMessageQueue)
|
||||
{
|
||||
LogMessageQueue.Enqueue(message);
|
||||
}
|
||||
}
|
||||
else if (type == LogType.Error || type == LogType.Exception)
|
||||
{
|
||||
Sb.Append(type).Append(": ").Append(message).Append("\n").Append(stacktrace).Append(StackTraceUtility.ExtractStackTrace());
|
||||
message = Sb.ToString();
|
||||
lock (LogMessageQueue)
|
||||
{
|
||||
LogMessageQueue.Enqueue(message);
|
||||
}
|
||||
}
|
||||
ActivateThreadWorker();
|
||||
}
|
||||
|
||||
private void ActivateThreadWorker()
|
||||
{
|
||||
lock (_threadLock)
|
||||
{
|
||||
if (_writeLogThread != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
_writeLogThread = new Thread(WriteLogThreadWorker);
|
||||
_writeLogThread.Start();
|
||||
}
|
||||
}
|
||||
|
||||
private void WriteLogThreadWorker()
|
||||
{
|
||||
try
|
||||
{
|
||||
bool active;
|
||||
lock (_threadLock)
|
||||
{
|
||||
// Kill the thread after 1 minute of inactivity
|
||||
_threadKillTime = DateTime.UtcNow + _threadKillTimeout;
|
||||
}
|
||||
|
||||
var localLogQueue = new Queue<string>();
|
||||
do
|
||||
{
|
||||
lock (LogMessageQueue)
|
||||
{
|
||||
_pendingLogsCount = LogMessageQueue.Count;
|
||||
while (LogMessageQueue.Count > 0) // Transfer the messages to the local queue
|
||||
localLogQueue.Enqueue(LogMessageQueue.Dequeue());
|
||||
}
|
||||
|
||||
BeginUploadLog();
|
||||
while (localLogQueue.Count > 0) // Transfer the messages to the local queue
|
||||
UploadLog(localLogQueue.Dequeue());
|
||||
EndUploadLog();
|
||||
|
||||
#region Expire Thread.
|
||||
// Check if we've been inactive
|
||||
lock (_threadLock)
|
||||
{
|
||||
var now = DateTime.UtcNow;
|
||||
if (_pendingLogsCount > 0 && _isApplicationPlaying)
|
||||
{
|
||||
// Still active, reset the _threadKillTime
|
||||
_threadKillTime = now + _threadKillTimeout;
|
||||
}
|
||||
// Kill the thread after 1 minute of inactivity
|
||||
active = now <= _threadKillTime;
|
||||
if (!active)
|
||||
{
|
||||
_writeLogThread = null;
|
||||
}
|
||||
// This thread will be stopped, so null this now, inside lock (_threadLock)
|
||||
}
|
||||
#endregion
|
||||
|
||||
Thread.Sleep(LOG_CACHE_INTERVAL_MS);
|
||||
} while (active);
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogException(e);
|
||||
_writeLogThread = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
public interface IPlayFabLogger
|
||||
{
|
||||
string ip { get; set; }
|
||||
int port { get; set; }
|
||||
string url { get; set; }
|
||||
|
||||
// Unity MonoBehaviour callbacks
|
||||
void OnEnable();
|
||||
void OnDisable();
|
||||
void OnDestroy();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is just a placeholder. WP8 doesn't support direct threading, but instead makes you use the await command.
|
||||
/// </summary>
|
||||
public abstract class PlayFabLoggerBase : IPlayFabLogger
|
||||
{
|
||||
public string ip { get; set; }
|
||||
public int port { get; set; }
|
||||
public string url { get; set; }
|
||||
|
||||
// Unity MonoBehaviour callbacks
|
||||
public void OnEnable() { }
|
||||
public void OnDisable() { }
|
||||
public void OnDestroy() { }
|
||||
|
||||
protected abstract void BeginUploadLog();
|
||||
protected abstract void UploadLog(string message);
|
||||
protected abstract void EndUploadLog();
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// This translates the logs up to the PlayFab service via a PlayFab restful API
|
||||
/// TODO: PLAYFAB - attach these to the PlayFab API
|
||||
/// </summary>
|
||||
public class PlayFabLogger : PlayFabLoggerBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Logs are cached and written in bursts
|
||||
/// BeginUploadLog is called at the begining of each burst
|
||||
/// </summary>
|
||||
protected override void BeginUploadLog()
|
||||
{
|
||||
}
|
||||
/// <summary>
|
||||
/// Logs are cached and written in bursts
|
||||
/// UploadLog is called for each cached log, between BeginUploadLog and EndUploadLog
|
||||
/// </summary>
|
||||
protected override void UploadLog(string message)
|
||||
{
|
||||
}
|
||||
/// <summary>
|
||||
/// Logs are cached and written in bursts
|
||||
/// EndUploadLog is called at the end of each burst
|
||||
/// </summary>
|
||||
protected override void EndUploadLog()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 65702fe1cdebb8e4783afb157a614161
|
||||
timeCreated: 1465847308
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,222 @@
|
||||
using PlayFab.Internal;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
|
||||
namespace PlayFab
|
||||
{
|
||||
public enum WebRequestType
|
||||
{
|
||||
#if !UNITY_2018_2_OR_NEWER // Unity has deprecated Www
|
||||
UnityWww, // High compatability Unity api calls
|
||||
#endif
|
||||
UnityWebRequest, // Modern unity HTTP component
|
||||
HttpWebRequest, // High performance multi-threaded api calls
|
||||
CustomHttp //If this is used, you must set the Http to an IPlayFabHttp object.
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum PlayFabLogLevel
|
||||
{
|
||||
None = 0,
|
||||
Debug = 1 << 0,
|
||||
Info = 1 << 1,
|
||||
Warning = 1 << 2,
|
||||
Error = 1 << 3,
|
||||
All = Debug | Info | Warning | Error,
|
||||
}
|
||||
|
||||
public static class PlayFabSettings
|
||||
{
|
||||
static PlayFabSettings() { }
|
||||
|
||||
private static PlayFabSharedSettings _playFabShared = null;
|
||||
private static PlayFabSharedSettings PlayFabSharedPrivate { get { if (_playFabShared == null) _playFabShared = GetSharedSettingsObjectPrivate(); return _playFabShared; } }
|
||||
|
||||
/// <summary>
|
||||
/// Global settings used by all static API classes, and as the default for all instance API classes
|
||||
/// </summary>
|
||||
public static readonly PlayFabApiSettings staticSettings = new PlayFabSettingsRedirect(() => { return PlayFabSharedPrivate; });
|
||||
/// <summary>
|
||||
/// Global user for all static API classes
|
||||
/// </summary>
|
||||
public static readonly PlayFabAuthenticationContext staticPlayer = new PlayFabAuthenticationContext();
|
||||
|
||||
public const string SdkVersion = "2.167.230529";
|
||||
public const string BuildIdentifier = "adobuild_unitysdk_167";
|
||||
public const string VersionString = "UnitySDK-2.167.230529";
|
||||
|
||||
public const string DefaultPlayFabApiUrl = "playfabapi.com";
|
||||
|
||||
private static PlayFabSharedSettings GetSharedSettingsObjectPrivate()
|
||||
{
|
||||
var settingsList = Resources.LoadAll<PlayFabSharedSettings>("PlayFabSharedSettings");
|
||||
if (settingsList.Length != 1)
|
||||
{
|
||||
Debug.LogWarning("The number of PlayFabSharedSettings objects should be 1: " + settingsList.Length);
|
||||
Debug.LogWarning("If you are upgrading your SDK, you can ignore this warning as PlayFabSharedSettings will be imported soon. If you are not upgrading your SDK and you see this message, you should re-download the latest PlayFab source code.");
|
||||
}
|
||||
return settingsList[0];
|
||||
}
|
||||
|
||||
public static string DeviceUniqueIdentifier
|
||||
{
|
||||
get
|
||||
{
|
||||
var deviceId = "";
|
||||
#if UNITY_ANDROID && !UNITY_EDITOR
|
||||
AndroidJavaClass up = new AndroidJavaClass ("com.unity3d.player.UnityPlayer");
|
||||
AndroidJavaObject currentActivity = up.GetStatic<AndroidJavaObject> ("currentActivity");
|
||||
AndroidJavaObject contentResolver = currentActivity.Call<AndroidJavaObject> ("getContentResolver");
|
||||
AndroidJavaClass secure = new AndroidJavaClass ("android.provider.Settings$Secure");
|
||||
deviceId = secure.CallStatic<string> ("getString", contentResolver, "android_id");
|
||||
#else
|
||||
deviceId = SystemInfo.deviceUniqueIdentifier;
|
||||
#endif
|
||||
return deviceId;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// These are variables which can differ from one PlayFab API Instance to another
|
||||
/// </summary>
|
||||
#region staticSettings Redirects
|
||||
// You must set this value for PlayFabSdk to work properly (Found in the Game Manager for your title, at the PlayFab Website)
|
||||
public static string TitleId { get { return staticSettings.TitleId; } set { staticSettings.TitleId = value; } }
|
||||
|
||||
/// <summary> The name of a customer vertical. This is only for customers running a private cluster. Generally you shouldn't touch this </summary>
|
||||
internal static string VerticalName { get { return staticSettings.VerticalName; } set { staticSettings.VerticalName = value; } }
|
||||
#if ENABLE_PLAYFABSERVER_API || ENABLE_PLAYFABADMIN_API || UNITY_EDITOR || ENABLE_PLAYFAB_SECRETKEY
|
||||
public static string DeveloperSecretKey { get { return staticSettings.DeveloperSecretKey; } set { staticSettings.DeveloperSecretKey = value; } }
|
||||
#endif
|
||||
/// <summary> Set this to true to prevent hardware information from leaving the device </summary>
|
||||
public static bool DisableDeviceInfo { get { return staticSettings.DisableDeviceInfo; } set { staticSettings.DisableDeviceInfo = value; } }
|
||||
/// <summary> Set this to true to prevent focus change information from leaving the device </summary>
|
||||
public static bool DisableFocusTimeCollection { get { return staticSettings.DisableFocusTimeCollection; } set { staticSettings.DisableFocusTimeCollection = value; } }
|
||||
#endregion staticSettings Redirects
|
||||
|
||||
/// <summary>
|
||||
/// These are variables which are always singleton global
|
||||
/// </summary>
|
||||
#region PlayFabSharedSettings Redirects
|
||||
[ObsoleteAttribute("LogLevel has been deprecated, please use UnityEngine.Debug.Log for your logging needs.")]
|
||||
public static PlayFabLogLevel LogLevel { get { return PlayFabSharedPrivate.LogLevel; } set { PlayFabSharedPrivate.LogLevel = value; } }
|
||||
public static WebRequestType RequestType { get { return PlayFabSharedPrivate.RequestType; } set { PlayFabSharedPrivate.RequestType = value; } }
|
||||
public static int RequestTimeout { get { return PlayFabSharedPrivate.RequestTimeout; } set { PlayFabSharedPrivate.RequestTimeout = value; } }
|
||||
public static bool RequestKeepAlive { get { return PlayFabSharedPrivate.RequestKeepAlive; } set { PlayFabSharedPrivate.RequestKeepAlive = value; } }
|
||||
public static string LoggerHost { get { return PlayFabSharedPrivate.LoggerHost; } set { PlayFabSharedPrivate.LoggerHost = value; } }
|
||||
public static int LoggerPort { get { return PlayFabSharedPrivate.LoggerPort; } set { PlayFabSharedPrivate.LoggerPort = value; } }
|
||||
public static bool EnableRealTimeLogging { get { return PlayFabSharedPrivate.EnableRealTimeLogging; } set { PlayFabSharedPrivate.EnableRealTimeLogging = value; } }
|
||||
public static int LogCapLimit { get { return PlayFabSharedPrivate.LogCapLimit; } set { PlayFabSharedPrivate.LogCapLimit = value; } }
|
||||
#endregion PlayFabSharedSettings Redirects
|
||||
|
||||
private static string _localApiServer;
|
||||
public static string LocalApiServer
|
||||
{
|
||||
get
|
||||
{
|
||||
#if UNITY_2017_1_OR_NEWER
|
||||
return _localApiServer ?? PlayFabUtil.GetLocalSettingsFileProperty("LocalApiServer");
|
||||
#else
|
||||
return _localApiServer;
|
||||
#endif
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
_localApiServer = value;
|
||||
}
|
||||
}
|
||||
|
||||
[ThreadStatic]
|
||||
private static StringBuilder _cachedStringBuilder;
|
||||
|
||||
private static StringBuilder AcquireStringBuilder()
|
||||
{
|
||||
if (_cachedStringBuilder == null)
|
||||
{
|
||||
_cachedStringBuilder = new StringBuilder(1000);
|
||||
}
|
||||
|
||||
_cachedStringBuilder.Clear();
|
||||
return _cachedStringBuilder;
|
||||
}
|
||||
|
||||
public static string GetFullUrl(string apiCall, Dictionary<string, string> getParams, PlayFabApiSettings apiSettings = null)
|
||||
{
|
||||
StringBuilder sb = AcquireStringBuilder();
|
||||
|
||||
string productionEnvironmentUrl = null, verticalName = null, titleId = null;
|
||||
|
||||
if (apiSettings != null)
|
||||
{
|
||||
|
||||
if (!string.IsNullOrEmpty(apiSettings.ProductionEnvironmentUrl))
|
||||
{
|
||||
productionEnvironmentUrl = apiSettings.ProductionEnvironmentUrl;
|
||||
}
|
||||
if (!string.IsNullOrEmpty(apiSettings.VerticalName))
|
||||
{
|
||||
verticalName = apiSettings.VerticalName;
|
||||
}
|
||||
if (!string.IsNullOrEmpty(apiSettings.TitleId))
|
||||
{
|
||||
titleId = apiSettings.TitleId;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (productionEnvironmentUrl == null)
|
||||
{
|
||||
productionEnvironmentUrl = !string.IsNullOrEmpty(PlayFabSharedPrivate.ProductionEnvironmentUrl) ? PlayFabSharedPrivate.ProductionEnvironmentUrl : DefaultPlayFabApiUrl;
|
||||
}
|
||||
if (verticalName == null && apiSettings != null && !string.IsNullOrEmpty(apiSettings.VerticalName))
|
||||
{
|
||||
verticalName = apiSettings.VerticalName;
|
||||
}
|
||||
if (titleId == null)
|
||||
{
|
||||
titleId = PlayFabSharedPrivate.TitleId;
|
||||
}
|
||||
|
||||
var baseUrl = productionEnvironmentUrl;
|
||||
if (!baseUrl.StartsWith("http"))
|
||||
{
|
||||
sb.Append("https://");
|
||||
if (!string.IsNullOrEmpty(titleId))
|
||||
{
|
||||
sb.Append(titleId).Append(".");
|
||||
}
|
||||
if (!string.IsNullOrEmpty(verticalName))
|
||||
{
|
||||
sb.Append(verticalName).Append(".");
|
||||
}
|
||||
}
|
||||
|
||||
sb.Append(baseUrl).Append(apiCall);
|
||||
|
||||
if (getParams != null)
|
||||
{
|
||||
bool firstParam = true;
|
||||
foreach (var paramPair in getParams)
|
||||
{
|
||||
if (firstParam)
|
||||
{
|
||||
sb.Append("?");
|
||||
firstParam = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.Append("&");
|
||||
}
|
||||
sb.Append(paramPair.Key).Append("=").Append(paramPair.Value);
|
||||
}
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: aa223f24327e645d39b48f0ca9615e68
|
||||
timeCreated: 1462682372
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace PlayFab
|
||||
{
|
||||
public enum PluginContract
|
||||
{
|
||||
PlayFab_Serializer,
|
||||
PlayFab_Transport
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2e25ec8533eb4fe4fa7d39cc8dcda24c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,23 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace PlayFab
|
||||
{
|
||||
public struct PluginContractKey
|
||||
{
|
||||
public PluginContract _pluginContract;
|
||||
public string _pluginName;
|
||||
}
|
||||
|
||||
public class PluginContractKeyComparator : EqualityComparer<PluginContractKey>
|
||||
{
|
||||
public override bool Equals(PluginContractKey x, PluginContractKey y)
|
||||
{
|
||||
return x._pluginContract == y._pluginContract && x._pluginName.Equals(y._pluginName);
|
||||
}
|
||||
|
||||
public override int GetHashCode(PluginContractKey obj)
|
||||
{
|
||||
return (int)obj._pluginContract + obj._pluginName.GetHashCode();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c74eb9de26e70e7489002fb92b96af0f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,110 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using PlayFab.Internal;
|
||||
|
||||
namespace PlayFab
|
||||
{
|
||||
public class PluginManager
|
||||
{
|
||||
private ConcurrentDictionary<PluginContractKey, IPlayFabPlugin> plugins = new ConcurrentDictionary<PluginContractKey, IPlayFabPlugin>(new PluginContractKeyComparator());
|
||||
|
||||
/// <summary>
|
||||
/// The singleton instance of plugin manager.
|
||||
/// </summary>
|
||||
private static readonly PluginManager Instance = new PluginManager();
|
||||
|
||||
private PluginManager()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a plugin.
|
||||
/// If a plugin with specified contract and optional instance name does not exist, it will create a new one.
|
||||
/// </summary>
|
||||
/// <param name="contract">The plugin contract.</param>
|
||||
/// <param name="instanceName">The optional plugin instance name. Instance names allow to have mulptiple plugins with the same contract.</param>
|
||||
/// <returns>The plugin instance.</returns>
|
||||
public static T GetPlugin<T>(PluginContract contract, string instanceName = "") where T : IPlayFabPlugin
|
||||
{
|
||||
return (T)Instance.GetPluginInternal(contract, instanceName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets a custom plugin.
|
||||
/// If a plugin with specified contract and optional instance name already exists, it will be replaced with specified instance.
|
||||
/// </summary>
|
||||
/// <param name="plugin">The plugin instance.</param>
|
||||
/// <param name="contract">The app contract of plugin.</param>
|
||||
/// <param name="instanceName">The optional plugin instance name. Instance names allow to have mulptiple plugins with the same contract.</param>
|
||||
public static void SetPlugin(IPlayFabPlugin plugin, PluginContract contract, string instanceName = "")
|
||||
{
|
||||
Instance.SetPluginInternal(plugin, contract, instanceName);
|
||||
}
|
||||
|
||||
private IPlayFabPlugin GetPluginInternal(PluginContract contract, string instanceName)
|
||||
{
|
||||
var key = new PluginContractKey { _pluginContract = contract, _pluginName = instanceName };
|
||||
IPlayFabPlugin plugin;
|
||||
if (!this.plugins.TryGetValue(key, out plugin))
|
||||
{
|
||||
// Requested plugin is not in the cache, create the default one
|
||||
switch (contract)
|
||||
{
|
||||
case PluginContract.PlayFab_Serializer:
|
||||
plugin = this.CreatePlugin<PlayFab.Json.SimpleJsonInstance>();
|
||||
break;
|
||||
case PluginContract.PlayFab_Transport:
|
||||
plugin = this.CreatePlayFabTransportPlugin();
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentException("This contract is not supported", "contract");
|
||||
}
|
||||
|
||||
this.plugins[key] = plugin;
|
||||
}
|
||||
|
||||
return plugin;
|
||||
}
|
||||
|
||||
private void SetPluginInternal(IPlayFabPlugin plugin, PluginContract contract, string instanceName)
|
||||
{
|
||||
if (plugin == null)
|
||||
{
|
||||
throw new ArgumentNullException("plugin", "Plugin instance cannot be null");
|
||||
}
|
||||
|
||||
var key = new PluginContractKey { _pluginContract = contract, _pluginName = instanceName };
|
||||
this.plugins[key] = plugin;
|
||||
}
|
||||
|
||||
private IPlayFabPlugin CreatePlugin<T>() where T : IPlayFabPlugin, new()
|
||||
{
|
||||
return (IPlayFabPlugin)System.Activator.CreateInstance(typeof(T));
|
||||
}
|
||||
|
||||
private ITransportPlugin CreatePlayFabTransportPlugin()
|
||||
{
|
||||
ITransportPlugin transport = null;
|
||||
#if !UNITY_WSA && !UNITY_WP8
|
||||
if (PlayFabSettings.RequestType == WebRequestType.HttpWebRequest)
|
||||
transport = new PlayFabWebRequest();
|
||||
#endif
|
||||
|
||||
#if UNITY_2018_2_OR_NEWER // PlayFabWww will throw warnings as Unity has deprecated Www
|
||||
if (transport == null)
|
||||
transport = new PlayFabUnityHttp();
|
||||
#elif UNITY_2017_2_OR_NEWER
|
||||
if (PlayFabSettings.RequestType == WebRequestType.UnityWww)
|
||||
transport = new PlayFabWww();
|
||||
|
||||
if (transport == null)
|
||||
transport = new PlayFabUnityHttp();
|
||||
#else
|
||||
if (transport == null)
|
||||
transport = new PlayFabWww();
|
||||
#endif
|
||||
|
||||
return transport;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 408cd48212db9ae46b9100b1d3fef3b1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c770a70afd8f88f40bb0f25e3b0dbb55
|
||||
folderAsset: yes
|
||||
timeCreated: 1468086149
|
||||
licenseType: Pro
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,27 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 093286084a3d1994a9c28281a1c38b1d, type: 3}
|
||||
m_Name: PlayFabSharedSettings
|
||||
m_EditorClassIdentifier:
|
||||
TitleId: 6DC6D
|
||||
DeveloperSecretKey: P4Y6PXT3ZZTP6N1KPZPSF1DOKJAFYIRK7HMGNZNA687OPKW9Y9
|
||||
ProductionEnvironmentUrl:
|
||||
RequestType: 0
|
||||
DisableDeviceInfo: 0
|
||||
DisableFocusTimeCollection: 0
|
||||
RequestTimeout: 8000
|
||||
RequestKeepAlive: 1
|
||||
LogLevel: 12
|
||||
LoggerHost:
|
||||
LoggerPort: 0
|
||||
EnableRealTimeLogging: 0
|
||||
LogCapLimit: 30
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 698b2db098268c640929a7b8090a31eb
|
||||
timeCreated: 1532637394
|
||||
licenseType: Pro
|
||||
NativeFormatImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user