[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:
2025-12-29 16:12:17 +08:00
parent 638e6a3327
commit aa5ce1ff5a
226 changed files with 64975 additions and 62 deletions

View File

@@ -0,0 +1,5 @@
fileFormatVersion: 2
guid: 8d731e8907f844532878b81596fe3852
folderAsset: yes
DefaultImporter:
userData:

View File

@@ -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

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3e92542860dab28489c3d9cc0baa1ebd
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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/");
}
}
}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: e51e733dabbc847fa839b19c01bc577c
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@@ -0,0 +1,16 @@
{
"name": "PlayFabSDKEditor",
"references": [
"PlayFab"
],
"includePlatforms": [
"Editor"
],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": []
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 8aa8a8085039f0e4ba1c8d6480d45262
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

View File

@@ -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:

View File

@@ -0,0 +1,5 @@
fileFormatVersion: 2
guid: 91910e31dc88043ea918915ee9d665d9
folderAsset: yes
DefaultImporter:
userData:

View File

@@ -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);
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 1337f8c156b41834691b131f3b6774f9
timeCreated: 1462682372
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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));
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 5b55790eeab1b3c41a4f1381cbea1213
timeCreated: 1462682372
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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,
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: ed146f2193bb8ef49ad1200eefdab503
timeCreated: 1468524876
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 6de758a294727f04c82bf319fdd54c60
folderAsset: yes
timeCreated: 1462746198
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: aeac58284b4b1cd4ab93ab0e71ba8540
timeCreated: 1462745280
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 97a8a3caac8b73541aa8a9a1e330f479
timeCreated: 1462575707
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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

View File

@@ -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:

View File

@@ -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

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 71ae810a641b9644187c8824db5ff1fe
timeCreated: 1462745593
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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

View File

@@ -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

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: bce6184794650f24fa8ac244b25edc17
timeCreated: 1462682372
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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() { }
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: f6a51fa1ed684497db153f40961979c4
timeCreated: 1462682373
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: b3bfc0fbdbe1a36429699dfc30c9e488
timeCreated: 1462682372
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 1b20d57e2279b3a408268b20c2be2208
timeCreated: 1468890373
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 34c5d2725a89d1c40af9b10a9b9dcbc5
folderAsset: yes
timeCreated: 1467491757
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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;
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 093286084a3d1994a9c28281a1c38b1d
timeCreated: 1467748518
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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;
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 8e2ad5324972b434883785ddddf9c851
timeCreated: 1467491766
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 85636a5aec9f04e91a75e422c19ff5da
folderAsset: yes
timeCreated: 1462682372
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,9 @@
namespace PlayFab
{
/// <summary>
/// Base interface of any PlayFab SDK plugin.
/// </summary>
public interface IPlayFabPlugin
{
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c515d14de9458ef449d382c41e4943b0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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);
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d33ec65e8a628fe44a4aa5c55289a16d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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();
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b97cd56b9c312144bb35f37b431aa18f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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; }
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 66cd997c6a8b2ed4d8d2b5c2a97b6e22
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5e4df1f8e07aee2409343554f628ce8b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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();
}
}
}

View File

@@ -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

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 059603d7e53649849b7f08d3b99af79c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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()
{
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 65702fe1cdebb8e4783afb157a614161
timeCreated: 1465847308
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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();
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: aa223f24327e645d39b48f0ca9615e68
timeCreated: 1462682372
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
namespace PlayFab
{
public enum PluginContract
{
PlayFab_Serializer,
PlayFab_Transport
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2e25ec8533eb4fe4fa7d39cc8dcda24c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c74eb9de26e70e7489002fb92b96af0f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 408cd48212db9ae46b9100b1d3fef3b1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: c770a70afd8f88f40bb0f25e3b0dbb55
folderAsset: yes
timeCreated: 1468086149
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 698b2db098268c640929a7b8090a31eb
timeCreated: 1532637394
licenseType: Pro
NativeFormatImporter:
userData:
assetBundleName:
assetBundleVariant: