Commit b89e0808 authored by nk161690's avatar nk161690

gg play

parent 6c4cd520
fileFormatVersion: 2 fileFormatVersion: 2
guid: d3c5c5ae093a5c7459a7c2875d753562 guid: 915c158b06079337fb2ca40f56727c1d
folderAsset: yes folderAsset: yes
DefaultImporter: DefaultImporter:
externalObjects: {} externalObjects: {}
......
fileFormatVersion: 2 fileFormatVersion: 2
guid: b7b977ddac702410d9afe830593d49d1 guid: e2b1894e7d784825bf9719c33331fae8
labels:
- gvh
- gvh_version-1.2.169
- gvhp_exportpath-ExternalDependencyManager/Editor/1.2.169/Google.IOSResolver.dll
- gvhp_targets-editor
PluginImporter: PluginImporter:
externalObjects: {} externalObjects: {}
serializedVersion: 2 serializedVersion: 2
......
fileFormatVersion: 2 fileFormatVersion: 2
guid: 8aafe0b0d0d5f4e0eb3476e052977318 guid: 2730c87d98d4480884d11cfb29ff72cb
labels:
- gvh
- gvh_version-1.2.169
- gvhp_exportpath-ExternalDependencyManager/Editor/1.2.169/Google.JarResolver.dll
- gvhp_targets-editor
PluginImporter: PluginImporter:
externalObjects: {} externalObjects: {}
serializedVersion: 2 serializedVersion: 2
......
fileFormatVersion: 2 fileFormatVersion: 2
guid: 55cbe0f2ed59c472ab1f0f3ffdd43d0e guid: 3ed19a202c4b4b439183dc00efee3c4a
labels:
- gvh
- gvh_version-1.2.169
- gvhp_exportpath-ExternalDependencyManager/Editor/1.2.169/Google.PackageManagerResolver.dll
- gvhp_targets-editor
PluginImporter: PluginImporter:
externalObjects: {} externalObjects: {}
serializedVersion: 2 serializedVersion: 2
......
fileFormatVersion: 2 fileFormatVersion: 2
guid: 2910e11bc0de145b7bb6ca10a42a9a40 guid: 14338063180a4626be53643cb2ab5d69
labels:
- gvh
- gvh_version-1.2.169
- gvhp_exportpath-ExternalDependencyManager/Editor/1.2.169/Google.VersionHandlerImpl.dll
- gvhp_targets-editor
PluginImporter: PluginImporter:
externalObjects: {} externalObjects: {}
serializedVersion: 2 serializedVersion: 2
......
# Version 1.2.169 - Jan 20, 2021
* General - Fixes #425 - Change to save `GvhProjectSettings.xml` without
Unicode byte order mark (BoM).
* Android Resolver - Remove reference to `jcenter()`
* iOS Resolver - Force setting `LANG` when executing Cocoapods in shell mode on
Mac.
# Version 1.2.168 - Dec 9, 2021
* All - Fixes #472 by removing the use of `System.Diagnostics.Debug.Assert`
* All - Fixed #477 by properly enabling EDM4U libraries for Unity 2021.2+ when
the package is installed through `.tgz`
# Version 1.2.167 - Oct 6, 2021
* All - Moved versioned `.dll` in EDM4U to a versioned folder and remove their
version postfix in their filename. For instance, `IOSResolver.dll` will be
placed at `ExternalDependencyManager/Editor/1.2.167/Google.IOSResolver.dll`.
* Android Resolver - Fixed #243 by only using the highest version in
`mainTemplate.gradle` when duplicated dependencies are presented.
* Android Resolver - Added supports to x86_64 to ABI list for Android apps on
Chrome OS.
# Version 1.2.166 - Jun 30, 2021 # Version 1.2.166 - Jun 30, 2021
* All - Fixed #440 and fixed #447 by specifying the parameter type while calling * All - Fixed #440 and fixed #447 by specifying the parameter type while calling
`GetApplicationIdentifier()` Unity API using reflection, due to a new `GetApplicationIdentifier()` Unity API using reflection, due to a new
......
fileFormatVersion: 2 fileFormatVersion: 2
guid: d67e36cf70144eeeb62948707545ecfd guid: deafbeef1ed04f639e3195087b6d2e9f
labels: labels:
- gvh - gvh
- gvh_version-1.2.166 - gvh_version-1.2.169
- gvhp_exportpath-ExternalDependencyManager/Editor/CHANGELOG.md - gvhp_exportpath-ExternalDependencyManager/Editor/CHANGELOG.md
timeCreated: 1584567712
licenseType: Pro
TextScriptImporter: TextScriptImporter:
userData: externalObjects: {}
assetBundleName: userData:
assetBundleVariant: assetBundleName:
assetBundleVariant:
fileFormatVersion: 2 fileFormatVersion: 2
guid: bb6999c8a5ce4ba99688ec579babe5b7 guid: 17e39196248d458daa69b514bc09b6a7
labels: labels:
- gvh - gvh
- gvh_version-1.2.166 - gvh_version-1.2.169
- gvhp_exportpath-ExternalDependencyManager/Editor/Google.VersionHandler.dll - gvhp_exportpath-ExternalDependencyManager/Editor/Google.VersionHandler.dll
- gvhp_targets-editor - gvhp_targets-editor
timeCreated: 1480838400
PluginImporter: PluginImporter:
externalObjects: {} externalObjects: {}
serializedVersion: 2 serializedVersion: 2
iconMap: {} iconMap: {}
executionOrder: {} executionOrder: {}
defineConstraints: []
isPreloaded: 0 isPreloaded: 0
isOverridable: 0 isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData: platformData:
- first: - first:
Any: Any:
second: second:
enabled: 0 enabled: 0
settings: {} settings: {}
...@@ -31,6 +33,6 @@ PluginImporter: ...@@ -31,6 +33,6 @@ PluginImporter:
enabled: 0 enabled: 0
settings: settings:
CPU: AnyCPU CPU: AnyCPU
userData: userData:
assetBundleName: assetBundleName:
assetBundleVariant: assetBundleVariant:
fileFormatVersion: 2 fileFormatVersion: 2
guid: 35a6726adf03479eb04b8c082346d551 guid: 61e923e8fff245a9bf5cfcf0774e75df
labels: labels:
- gvh - gvh
- gvh_version-1.2.166 - gvh_version-1.2.169
- gvhp_exportpath-ExternalDependencyManager/Editor/LICENSE - gvhp_exportpath-ExternalDependencyManager/Editor/LICENSE
timeCreated: 1584567712 DefaultImporter:
licenseType: Pro externalObjects: {}
TextScriptImporter: userData:
userData: assetBundleName:
assetBundleName: assetBundleVariant:
assetBundleVariant:
fileFormatVersion: 2 fileFormatVersion: 2
guid: 11eb52f780284fd69194951ac46cb538 guid: 57b5c3f72b65480eba2cc96380835972
labels: labels:
- gvh - gvh
- gvh_version-1.2.166 - gvh_version-1.2.169
- gvhp_exportpath-ExternalDependencyManager/Editor/README.md - gvhp_exportpath-ExternalDependencyManager/Editor/README.md
timeCreated: 1584567712
licenseType: Pro
TextScriptImporter: TextScriptImporter:
userData: externalObjects: {}
assetBundleName: userData:
assetBundleVariant: assetBundleName:
assetBundleVariant:
Assets/ExternalDependencyManager/Editor/1.2.169/Google.IOSResolver.dll
Assets/ExternalDependencyManager/Editor/1.2.169/Google.IOSResolver.dll.mdb
Assets/ExternalDependencyManager/Editor/1.2.169/Google.JarResolver.dll
Assets/ExternalDependencyManager/Editor/1.2.169/Google.JarResolver.dll.mdb
Assets/ExternalDependencyManager/Editor/1.2.169/Google.PackageManagerResolver.dll
Assets/ExternalDependencyManager/Editor/1.2.169/Google.PackageManagerResolver.dll.mdb
Assets/ExternalDependencyManager/Editor/1.2.169/Google.VersionHandlerImpl.dll
Assets/ExternalDependencyManager/Editor/1.2.169/Google.VersionHandlerImpl.dll.mdb
Assets/ExternalDependencyManager/Editor/CHANGELOG.md Assets/ExternalDependencyManager/Editor/CHANGELOG.md
Assets/ExternalDependencyManager/Editor/Google.IOSResolver.dll
Assets/ExternalDependencyManager/Editor/Google.IOSResolver.dll.mdb
Assets/ExternalDependencyManager/Editor/Google.JarResolver.dll
Assets/ExternalDependencyManager/Editor/Google.JarResolver.dll.mdb
Assets/ExternalDependencyManager/Editor/Google.PackageManagerResolver.dll
Assets/ExternalDependencyManager/Editor/Google.PackageManagerResolver.dll.mdb
Assets/ExternalDependencyManager/Editor/Google.VersionHandler.dll Assets/ExternalDependencyManager/Editor/Google.VersionHandler.dll
Assets/ExternalDependencyManager/Editor/Google.VersionHandler.dll.mdb Assets/ExternalDependencyManager/Editor/Google.VersionHandler.dll.mdb
Assets/ExternalDependencyManager/Editor/Google.VersionHandlerImpl.dll
Assets/ExternalDependencyManager/Editor/Google.VersionHandlerImpl.dll.mdb
Assets/ExternalDependencyManager/Editor/LICENSE Assets/ExternalDependencyManager/Editor/LICENSE
Assets/ExternalDependencyManager/Editor/README.md Assets/ExternalDependencyManager/Editor/README.md
fileFormatVersion: 2 fileFormatVersion: 2
guid: 70e37c0d68034f8a953638d978633f87 guid: f0ebd68c0b4541ada7e16bfce4ef4155
labels: labels:
- gvh - gvh
- gvh_manifest - gvh_manifest
- gvh_version-1.2.166 - gvh_version-1.2.169
- gvhp_exportpath-ExternalDependencyManager/Editor/external-dependency-manager_version-1.2.166_manifest.txt - gvhp_exportpath-ExternalDependencyManager/Editor/external-dependency-manager_version-1.2.169_manifest.txt
- gvhp_manifestname-0External Dependency Manager - gvhp_manifestname-0External Dependency Manager
- gvhp_manifestname-play-services-resolver - gvhp_manifestname-play-services-resolver
timeCreated: 1474401009
licenseType: Pro
TextScriptImporter: TextScriptImporter:
userData: externalObjects: {}
assetBundleName: userData:
assetBundleVariant: assetBundleName:
assetBundleVariant:
using GooglePlayGames;
using TMPro;
using UnityEngine;
public class GgPlayLogin : MonoBehaviour
{
[SerializeField] private TextMeshProUGUI message;
}
fileFormatVersion: 2
guid: 3233805e6ce28714fa7e4a9c6aff793a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: be5036f1d701f274ba37e68da140a648
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 07c584f6dabcf1c52bdb6a9f07429cde
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 11083f74e79584f50ad394be94e2caec
folderAsset: yes
timeCreated: 1435699548
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:
// <copyright file="GPGSAndroidSetupUI.cs" company="Google Inc.">
// Copyright (C) Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
namespace GooglePlayGames.Editor
{
using System;
using System.Collections;
using System.IO;
using System.Xml;
using UnityEditor;
using UnityEngine;
/// <summary>
/// Google Play Game Services Setup dialog for Android.
/// </summary>
public class GPGSAndroidSetupUI : EditorWindow
{
/// <summary>
/// The configuration data from the play games console "resource data"
/// </summary>
private string mConfigData = string.Empty;
/// <summary>
/// The name of the class to generate containing the resource constants.
/// </summary>
private string mClassName = "GPGSIds";
/// <summary>
/// The scroll position
/// </summary>
private Vector2 scroll;
/// <summary>
/// The directory for the constants class.
/// </summary>
private string mConstantDirectory = "Assets";
/// <summary>
/// The web client identifier.
/// </summary>
private string mWebClientId = string.Empty;
/// <summary>
/// Menus the item for GPGS android setup.
/// </summary>
[MenuItem("Window/Google Play Games/Setup/Android setup...", false, 1)]
public static void MenuItemFileGPGSAndroidSetup()
{
EditorWindow window = EditorWindow.GetWindow(
typeof(GPGSAndroidSetupUI), true, GPGSStrings.AndroidSetup.Title);
window.minSize = new Vector2(500, 400);
}
[MenuItem("Window/Google Play Games/Setup/Android setup...", true)]
public static bool EnableAndroidMenuItem()
{
#if UNITY_ANDROID
return true;
#else
return false;
#endif
}
/// <summary>
/// Performs setup using the Android resources downloaded XML file
/// from the play console.
/// </summary>
/// <returns><c>true</c>, if setup was performed, <c>false</c> otherwise.</returns>
/// <param name="clientId">The web client id.</param>
/// <param name="classDirectory">the directory to write the constants file to.</param>
/// <param name="className">Fully qualified class name for the resource Ids.</param>
/// <param name="resourceXmlData">Resource xml data.</param>
/// <param name="nearbySvcId">Nearby svc identifier.</param>
/// <param name="requiresGooglePlus">Indicates this app requires G+</param>
public static bool PerformSetup(
string clientId,
string classDirectory,
string className,
string resourceXmlData,
string nearbySvcId)
{
if (string.IsNullOrEmpty(resourceXmlData) &&
!string.IsNullOrEmpty(nearbySvcId))
{
return PerformSetup(
clientId,
GPGSProjectSettings.Instance.Get(GPGSUtil.APPIDKEY),
nearbySvcId);
}
if (ParseResources(classDirectory, className, resourceXmlData))
{
GPGSProjectSettings.Instance.Set(GPGSUtil.CLASSDIRECTORYKEY, classDirectory);
GPGSProjectSettings.Instance.Set(GPGSUtil.CLASSNAMEKEY, className);
GPGSProjectSettings.Instance.Set(GPGSUtil.ANDROIDRESOURCEKEY, resourceXmlData);
// check the bundle id and set it if needed.
CheckBundleId();
GPGSUtil.CheckAndFixDependencies();
GPGSUtil.CheckAndFixVersionedAssestsPaths();
AssetDatabase.Refresh();
Google.VersionHandler.VerboseLoggingEnabled = true;
Google.VersionHandler.UpdateVersionedAssets(forceUpdate: true);
Google.VersionHandler.Enabled = true;
AssetDatabase.Refresh();
Google.VersionHandler.InvokeStaticMethod(
Google.VersionHandler.FindClass(
"Google.JarResolver",
"GooglePlayServices.PlayServicesResolver"),
"MenuResolve", null);
return PerformSetup(
clientId,
GPGSProjectSettings.Instance.Get(GPGSUtil.APPIDKEY),
nearbySvcId);
}
return false;
}
/// <summary>
/// Provide static access to setup for facilitating automated builds.
/// </summary>
/// <param name="webClientId">The oauth2 client id for the game. This is only
/// needed if the ID Token or access token are needed.</param>
/// <param name="appId">App identifier.</param>
/// <param name="nearbySvcId">Optional nearby connection serviceId</param>
/// <param name="requiresGooglePlus">Indicates that GooglePlus should be enabled</param>
/// <returns>true if successful</returns>
public static bool PerformSetup(string webClientId, string appId, string nearbySvcId)
{
if (!string.IsNullOrEmpty(webClientId))
{
if (!GPGSUtil.LooksLikeValidClientId(webClientId))
{
GPGSUtil.Alert(GPGSStrings.Setup.ClientIdError);
return false;
}
string serverAppId = webClientId.Split('-')[0];
if (!serverAppId.Equals(appId))
{
GPGSUtil.Alert(GPGSStrings.Setup.AppIdMismatch);
return false;
}
}
// check for valid app id
if (!GPGSUtil.LooksLikeValidAppId(appId) && string.IsNullOrEmpty(nearbySvcId))
{
GPGSUtil.Alert(GPGSStrings.Setup.AppIdError);
return false;
}
if (nearbySvcId != null)
{
#if UNITY_ANDROID
if (!NearbyConnectionUI.PerformSetup(nearbySvcId, true))
{
return false;
}
#endif
}
GPGSProjectSettings.Instance.Set(GPGSUtil.APPIDKEY, appId);
GPGSProjectSettings.Instance.Set(GPGSUtil.WEBCLIENTIDKEY, webClientId);
GPGSProjectSettings.Instance.Save();
GPGSUtil.UpdateGameInfo();
// check that Android SDK is there
if (!GPGSUtil.HasAndroidSdk())
{
Debug.LogError("Android SDK not found.");
EditorUtility.DisplayDialog(
GPGSStrings.AndroidSetup.SdkNotFound,
GPGSStrings.AndroidSetup.SdkNotFoundBlurb,
GPGSStrings.Ok);
return false;
}
// Generate AndroidManifest.xml
GPGSUtil.GenerateAndroidManifest();
// refresh assets, and we're done
AssetDatabase.Refresh();
GPGSProjectSettings.Instance.Set(GPGSUtil.ANDROIDSETUPDONEKEY, true);
GPGSProjectSettings.Instance.Save();
return true;
}
/// <summary>
/// Called when this object is enabled by Unity editor.
/// </summary>
public void OnEnable()
{
GPGSProjectSettings settings = GPGSProjectSettings.Instance;
mConstantDirectory = settings.Get(GPGSUtil.CLASSDIRECTORYKEY, mConstantDirectory);
mClassName = settings.Get(GPGSUtil.CLASSNAMEKEY, mClassName);
mConfigData = settings.Get(GPGSUtil.ANDROIDRESOURCEKEY);
mWebClientId = settings.Get(GPGSUtil.WEBCLIENTIDKEY);
}
/// <summary>
/// Called when the GUI should be rendered.
/// </summary>
public void OnGUI()
{
GUI.skin.label.wordWrap = true;
GUILayout.BeginVertical();
GUIStyle link = new GUIStyle(GUI.skin.label);
link.normal.textColor = new Color(0f, 0f, 1f);
GUILayout.Space(10);
GUILayout.Label(GPGSStrings.AndroidSetup.Blurb);
if (GUILayout.Button("Open Play Games Console", link, GUILayout.ExpandWidth(false)))
{
Application.OpenURL("https://play.google.com/apps/publish");
}
Rect last = GUILayoutUtility.GetLastRect();
last.y += last.height - 2;
last.x += 3;
last.width -= 6;
last.height = 2;
GUI.Box(last, string.Empty);
GUILayout.Space(15);
GUILayout.Label("Constants class name", EditorStyles.boldLabel);
GUILayout.Label("Enter the fully qualified name of the class to create containing the constants");
GUILayout.Space(10);
mConstantDirectory = EditorGUILayout.TextField(
"Directory to save constants",
mConstantDirectory,
GUILayout.MinWidth(480));
mClassName = EditorGUILayout.TextField(
"Constants class name",
mClassName,
GUILayout.MinWidth(480));
GUILayout.Label("Resources Definition", EditorStyles.boldLabel);
GUILayout.Label("Paste in the Android Resources from the Play Console");
GUILayout.Space(10);
scroll = GUILayout.BeginScrollView(scroll);
mConfigData = EditorGUILayout.TextArea(
mConfigData,
GUILayout.MinWidth(475),
GUILayout.Height(Screen.height));
GUILayout.EndScrollView();
GUILayout.Space(10);
// Client ID field
GUILayout.Label(GPGSStrings.Setup.WebClientIdTitle, EditorStyles.boldLabel);
GUILayout.Label(GPGSStrings.AndroidSetup.WebClientIdBlurb);
mWebClientId = EditorGUILayout.TextField(
GPGSStrings.Setup.ClientId,
mWebClientId,
GUILayout.MinWidth(450));
GUILayout.Space(10);
GUILayout.FlexibleSpace();
GUILayout.BeginHorizontal();
GUILayout.FlexibleSpace();
if (GUILayout.Button(GPGSStrings.Setup.SetupButton, GUILayout.Width(100)))
{
// check that the classname entered is valid
try
{
if (GPGSUtil.LooksLikeValidPackageName(mClassName))
{
DoSetup();
return;
}
}
catch (Exception e)
{
GPGSUtil.Alert(
GPGSStrings.Error,
"Invalid classname: " + e.Message);
}
}
if (GUILayout.Button("Cancel", GUILayout.Width(100)))
{
Close();
}
GUILayout.FlexibleSpace();
GUILayout.EndHorizontal();
GUILayout.Space(20);
GUILayout.EndVertical();
}
/// <summary>
/// Starts the setup process.
/// </summary>
public void DoSetup()
{
if (PerformSetup(mWebClientId, mConstantDirectory, mClassName, mConfigData, null))
{
CheckBundleId();
EditorUtility.DisplayDialog(
GPGSStrings.Success,
GPGSStrings.AndroidSetup.SetupComplete,
GPGSStrings.Ok);
GPGSProjectSettings.Instance.Set(GPGSUtil.ANDROIDSETUPDONEKEY, true);
Close();
}
else
{
GPGSUtil.Alert(
GPGSStrings.Error,
"Invalid or missing XML resource data. Make sure the data is" +
" valid and contains the app_id element");
}
}
/// <summary>
/// Checks the bundle identifier.
/// </summary>
/// <remarks>
/// Check the package id. If one is set the gpgs properties,
/// and the player settings are the default or empty, set it.
/// if the player settings is not the default, then prompt before
/// overwriting.
/// </remarks>
public static void CheckBundleId()
{
string packageName = GPGSProjectSettings.Instance.Get(
GPGSUtil.ANDROIDBUNDLEIDKEY, string.Empty);
string currentId;
#if UNITY_5_6_OR_NEWER
currentId = PlayerSettings.GetApplicationIdentifier(
BuildTargetGroup.Android);
#else
currentId = PlayerSettings.bundleIdentifier;
#endif
if (!string.IsNullOrEmpty(packageName))
{
if (string.IsNullOrEmpty(currentId) ||
currentId == "com.Company.ProductName")
{
#if UNITY_5_6_OR_NEWER
PlayerSettings.SetApplicationIdentifier(
BuildTargetGroup.Android, packageName);
#else
PlayerSettings.bundleIdentifier = packageName;
#endif
}
else if (currentId != packageName)
{
if (EditorUtility.DisplayDialog(
"Set Bundle Identifier?",
"The server configuration is using " +
packageName + ", but the player settings is set to " +
currentId + ".\nSet the Bundle Identifier to " +
packageName + "?",
"OK",
"Cancel"))
{
#if UNITY_5_6_OR_NEWER
PlayerSettings.SetApplicationIdentifier(
BuildTargetGroup.Android, packageName);
#else
PlayerSettings.bundleIdentifier = packageName;
#endif
}
}
}
else
{
Debug.Log("NULL package!!");
}
}
/// <summary>
/// Parses the resources xml and set the properties. Also generates the
/// constants file.
/// </summary>
/// <returns><c>true</c>, if resources was parsed, <c>false</c> otherwise.</returns>
/// <param name="classDirectory">Class directory.</param>
/// <param name="className">Class name.</param>
/// <param name="res">Res. the data to parse.</param>
private static bool ParseResources(string classDirectory, string className, string res)
{
XmlTextReader reader = new XmlTextReader(new StringReader(res));
bool inResource = false;
string lastProp = null;
Hashtable resourceKeys = new Hashtable();
string appId = null;
while (reader.Read())
{
if (reader.Name == "resources")
{
inResource = true;
}
if (inResource && reader.Name == "string")
{
lastProp = reader.GetAttribute("name");
}
else if (inResource && !string.IsNullOrEmpty(lastProp))
{
if (reader.HasValue)
{
if (lastProp == "app_id")
{
appId = reader.Value;
GPGSProjectSettings.Instance.Set(GPGSUtil.APPIDKEY, appId);
}
else if (lastProp == "package_name")
{
GPGSProjectSettings.Instance.Set(GPGSUtil.ANDROIDBUNDLEIDKEY, reader.Value);
}
else
{
resourceKeys[lastProp] = reader.Value;
}
lastProp = null;
}
}
}
reader.Close();
if (resourceKeys.Count > 0)
{
GPGSUtil.WriteResourceIds(classDirectory, className, resourceKeys);
}
return appId != null;
}
}
}
\ No newline at end of file
fileFormatVersion: 2
guid: 41fe658b93aa24c709c540575965fdff
labels:
- gvh
- gvh_version-0.11.01
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
// <copyright file="GPGSDocsUI.cs" company="Google Inc.">
// Copyright (C) 2014 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
namespace GooglePlayGames.Editor
{
using UnityEngine;
using UnityEditor;
public class GPGSDocsUI
{
[MenuItem("Window/Google Play Games/Documentation/Plugin Getting Started Guide...", false, 100)]
public static void MenuItemGettingStartedGuide()
{
Application.OpenURL(GPGSStrings.ExternalLinks.GettingStartedGuideURL);
}
[MenuItem("Window/Google Play Games/Documentation/Google Play Games API...", false, 101)]
public static void MenuItemPlayGamesServicesAPI()
{
Application.OpenURL(GPGSStrings.ExternalLinks.PlayGamesServicesApiURL);
}
[MenuItem("Window/Google Play Games/About/About the Plugin...", false, 300)]
public static void MenuItemAbout()
{
string msg = GPGSStrings.AboutText +
PluginVersion.VersionString + " (" +
string.Format("0x{0:X8}", GooglePlayGames.PluginVersion.VersionInt) + ")";
EditorUtility.DisplayDialog(GPGSStrings.AboutTitle, msg,
GPGSStrings.Ok);
}
[MenuItem("Window/Google Play Games/About/License...", false, 301)]
public static void MenuItemLicense()
{
EditorUtility.DisplayDialog(GPGSStrings.LicenseTitle, GPGSStrings.LicenseText,
GPGSStrings.Ok);
}
}
}
\ No newline at end of file
fileFormatVersion: 2
guid: 73cbcab28a27446ff9e06e06a040814f
labels:
- gvh
- gvh_version-0.11.01
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
// <copyright file="GPGSPostBuild.cs" company="Google Inc.">
// Copyright (C) 2014 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
#if UNITY_ANDROID
namespace GooglePlayGames.Editor
{
using System.Collections.Generic;
using System.IO;
using UnityEditor.Callbacks;
using UnityEditor;
using UnityEngine;
public static class GPGSPostBuild
{
[PostProcessBuild(99999)]
public static void OnPostprocessBuild(BuildTarget target, string pathToBuiltProject)
{
if (!GPGSProjectSettings.Instance.GetBool(GPGSUtil.ANDROIDSETUPDONEKEY, false))
{
EditorUtility.DisplayDialog("Google Play Games not configured!",
"Warning!! Google Play Games was not configured, Game Services will not work correctly.",
"OK");
}
return;
}
}
}
#endif //UNITY_ANDROID
\ No newline at end of file
fileFormatVersion: 2
guid: 1a7b050a8e8214613893df7d81dcc13c
labels:
- gvh
- gvh_version-0.11.01
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
// <copyright file="GPGSProjectSettings.cs" company="Google Inc.">
// Copyright (C) 2014 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
// Keep this file even on unsupported configurations.
namespace GooglePlayGames.Editor
{
using System.Collections.Generic;
using System.IO;
#if UNITY_2017_3_OR_NEWER
using UnityEngine.Networking;
#else
using UnityEngine;
#endif
public class GPGSProjectSettings
{
private static GPGSProjectSettings sInstance = null;
public static GPGSProjectSettings Instance
{
get
{
if (sInstance == null)
{
sInstance = new GPGSProjectSettings();
}
return sInstance;
}
}
private bool mDirty = false;
private readonly string mFile;
private Dictionary<string, string> mDict = new Dictionary<string, string>();
private GPGSProjectSettings()
{
mFile = GPGSUtil.SlashesToPlatformSeparator("ProjectSettings/GooglePlayGameSettings.txt");
StreamReader rd = null;
// read the settings file, this list is all the locations it can be in order of precedence.
string[] fileLocations =
{
mFile,
GPGSUtil.SlashesToPlatformSeparator(Path.Combine(GPGSUtil.RootPath, "Editor/projsettings.txt")),
GPGSUtil.SlashesToPlatformSeparator("Assets/Editor/projsettings.txt")
};
foreach (string f in fileLocations)
{
if (File.Exists(f))
{
// assign the reader and break out of the loop
rd = new StreamReader(f);
break;
}
}
if (rd != null)
{
while (!rd.EndOfStream)
{
string line = rd.ReadLine();
if (line == null || line.Trim().Length == 0)
{
break;
}
line = line.Trim();
string[] p = line.Split(new char[] {'='}, 2);
if (p.Length >= 2)
{
mDict[p[0].Trim()] = p[1].Trim();
}
}
rd.Close();
}
}
public string Get(string key, Dictionary<string, string> overrides)
{
if (overrides.ContainsKey(key))
{
return overrides[key];
}
else if (mDict.ContainsKey(key))
{
#if UNITY_2017_3_OR_NEWER
return UnityWebRequest.UnEscapeURL(mDict[key]);
#else
return WWW.UnEscapeURL(mDict[key]);
#endif
}
else
{
return string.Empty;
}
}
public string Get(string key, string defaultValue)
{
if (mDict.ContainsKey(key))
{
#if UNITY_2017_3_OR_NEWER
return UnityWebRequest.UnEscapeURL(mDict[key]);
#else
return WWW.UnEscapeURL(mDict[key]);
#endif
}
else
{
return defaultValue;
}
}
public string Get(string key)
{
return Get(key, string.Empty);
}
public bool GetBool(string key, bool defaultValue)
{
return Get(key, defaultValue ? "true" : "false").Equals("true");
}
public bool GetBool(string key)
{
return Get(key, "false").Equals("true");
}
public void Set(string key, string val)
{
#if UNITY_2017_3_OR_NEWER
string escaped = UnityWebRequest.EscapeURL(val);
#else
string escaped = WWW.EscapeURL(val);
#endif
mDict[key] = escaped;
mDirty = true;
}
public void Set(string key, bool val)
{
Set(key, val ? "true" : "false");
}
public void Save()
{
// See if we are building the plugin, and don't write the settings file
string[] args = System.Environment.GetCommandLineArgs();
foreach (string a in args)
{
if (a == "-g.building")
{
mDirty = false;
break;
}
}
if (!mDirty)
{
return;
}
StreamWriter wr = new StreamWriter(mFile, false);
foreach (string key in mDict.Keys)
{
wr.WriteLine(key + "=" + mDict[key]);
}
wr.Close();
mDirty = false;
}
public static void Reload()
{
sInstance = new GPGSProjectSettings();
}
}
}
fileFormatVersion: 2
guid: cf234a050ba25433f9386e20578ccf19
labels:
- gvh
- gvh_version-0.11.01
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
// <copyright file="GPGSStrings.cs" company="Google Inc.">
// Copyright (C) 2014 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
// Keep the strings all the time even if on an unsupported configuration.
namespace GooglePlayGames.Editor
{
public class GPGSStrings
{
public const string Error = "Error";
public const string Ok = "OK";
public const string Cancel = "Cancel";
public const string Yes = "Yes";
public const string No = "No";
public const string Success = "Success";
public const string Warning = "Warning";
public class PostInstall
{
public const string Title = "Google Play Games Plugin for Unity";
public const string Text = "The Google Play Games Plugin for Unity version $VERSION " +
"is now ready to use. If this is a new installation or if you have " +
"just upgraded from a previous version, please click the 'Google Play Games' " +
"menu and select 'Android Setup' to set up your project.";
}
public class Setup
{
public const string AppIdTitle = "Google Play Games Application ID";
public const string AppId = "Application ID";
public const string AppIdBlurb = "Enter your application ID below. This is the numeric\n" +
"identifier provided by the Developer Console (for example, 123456789012).";
public const string AppIdError = "The App Id does not appear to be valid. " +
"It must consist solely of digits, usually 10 or more.";
public const string WebClientIdTitle = "Web App Client ID (Optional)";
public const string ClientId = "Client ID";
public const string ClientIdError = "The Client ID does not appear to be valid. " +
"It should end in .apps.googleusercontent.com.";
public const string AppIdMismatch = "Web app client ID not associated with this game!";
public const string NearbyServiceId = "Nearby Connection Service ID";
public const string NearbyServiceBlurb = "Enter the service id that identifies the " +
"nearby connections service scope";
public const string SetupButton = "Setup";
}
public class NearbyConnections
{
public const string Title = "Google Play Games - Nearby Connections Setup";
public const string Blurb = "To configure Nearby Connections in this project,\n" +
"please enter the information below and click on the Setup button.";
public const string SetupComplete = "Nearby connections configured successfully.";
}
public class AndroidSetup
{
public const string Title = "Google Play Games - Android Configuration";
public const string Blurb = "To configure Google Play Games in this project,\n" +
"go to the Play Game console, then enter the information below and click on the Setup button.";
public const string WebClientIdBlurb =
"The web app client ID is needed to access the user's ID token and " +
"call other APIs onbehalf of the user." +
" It is not required for Game Services. Enter your oauth2 client ID below.\nTo obtain this " +
"ID, generate a web linked app in Developer Console. Example:\n" +
"123456789012-abcdefghijklm.apps.googleusercontent.com";
public const string PkgName = "Package name";
public const string PkgNameBlurb = "Enter your application's package name below.\n" +
"(for example, com.example.lorem.ipsum).";
public const string PackageNameError = "The package name does not appear to be valid. " +
"Enter a valid Android package name (for example, com.example.lorem.ipsum).";
public const string SdkNotFound = "Android SDK Not found";
public const string SdkNotFoundBlurb = "The Android SDK path was not found. " +
"Please configure it in the Unity preferences window (under External Tools).";
public const string LibProjNotFound = "Google Play Services Library Project Not Found";
public const string LibProjNotFoundBlurb = "Google Play Services library project " +
"could not be found your SDK installation. Make sure it is installed (open " +
"the SDK manager and go to Extras, and select Google Play Services).";
public const string SupportJarNotFound = "Android Support Library v4 Not Found";
public const string SupportJarNotFoundBlurb = "Android Support Library v4 " +
"could not be found your SDK installation. Make sure it is installed (open " +
"the SDK manager and go to Extras, and select 'Android Support Library').";
public const string LibProjVerNotFound = "The version of your copy of the Google Play " +
"Services Library Project could not be determined. Please make sure it is " +
"at least version {0}. Continue?";
public const string LibProjVerTooOld = "Your copy of the Google Play " +
"Services Library Project is out of date. Please launch the Android SDK manager " +
"and upgrade your Google Play Services bundle to the latest version (your version: " +
"{0}; required version: {1}). Proceeding may cause problems. Proceed anyway?";
public const string SetupComplete = "Google Play Games configured successfully.";
}
public class ExternalLinks
{
public const string GettingStartedGuideURL =
"https://github.com/playgameservices/play-games-plugin-for-unity";
public const string PlayGamesServicesApiURL =
"https://developers.google.com/games/services";
public const string GooglePlayGamesAndroidSdkTitle = "Google Play Games Android SDK Download";
public const string GooglePlayGamesAndroidSdkBlurb = "The Google Play Games SDK for " +
"Android must be downloaded via the Android SDK Manager. Do you wish to " +
"start the SDK manager now?";
public const string GooglePlayGamesAndroidSdkInstructions = "The Android SDK manager " +
"will be launched. Install or upgrade the 'Google Play Services' package, " +
"which can be found under the 'Extras' " +
"category.";
public const string GooglePlayGamesAndroidSdkManagerFailed = "Failed to find the " +
"Android SDK manager executable. Make sure the Android SDK is properly installed " +
"and that its path is correctly configured in the Unity preferences window " +
"(under External Tools).";
}
public const string AboutTitle = "Google Play Games Plugin for Unity";
public const string AboutText = "Copyright (C) 2014 Google Inc.\n\nThis is an open-source " +
"plugin that allows cross-platform integration with Google Play games services. " +
"For more information, visit the official site on Github:\n\n" +
"https://github.com/playgameservices/play-games-plugin-for-unity\n\nPlugin version: ";
public const string LicenseTitle = "Google Play Games Plugin for Unity";
public const string LicenseText = "Copyright (C) 2014 Google Inc. All Rights Reserved.\n\n" +
"Licensed under the Apache License, Version 2.0 (the \"License\"); " +
"you may not use this file except in compliance with the License. " +
"You may obtain a copy of the License at\n\n" +
" http://www.apache.org/licenses/LICENSE-2.0\n\n" +
"Unless required by applicable law or agreed to in writing, software " +
"distributed under the License is distributed on an \"AS IS\" BASIS, " +
"WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. " +
"See the License for the specific language governing permissions and " +
"limitations under the License.";
}
}
\ No newline at end of file
fileFormatVersion: 2
guid: 992ecb564cf02408d9c5a1b44d958334
labels:
- gvh
- gvh_version-0.11.01
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
// <copyright file="GPGSUpgrader.cs" company="Google Inc.">
// Copyright (C) 2014 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
#if UNITY_ANDROID
namespace GooglePlayGames.Editor
{
using System.IO;
using UnityEditor;
using UnityEngine;
/// <summary>
/// GPGS upgrader handles performing and upgrade tasks.
/// </summary>
[InitializeOnLoad]
public class GPGSUpgrader
{
/// <summary>
/// Initializes static members of the <see cref="GooglePlayGames.GPGSUpgrader"/> class.
/// </summary>
static GPGSUpgrader()
{
if (EditorApplication.isPlayingOrWillChangePlaymode)
return;
Debug.Log("GPGSUpgrader start");
GPGSProjectSettings.Instance.Set(GPGSUtil.LASTUPGRADEKEY, PluginVersion.VersionKey);
GPGSProjectSettings.Instance.Set(GPGSUtil.PLUGINVERSIONKEY,
PluginVersion.VersionString);
GPGSProjectSettings.Instance.Save();
bool isChanged = false;
// Check that there is a AndroidManifest.xml file
if (!GPGSUtil.AndroidManifestExists())
{
isChanged = true;
GPGSUtil.GenerateAndroidManifest();
}
if (isChanged)
{
AssetDatabase.Refresh();
}
Debug.Log("GPGSUpgrader done");
}
}
}
#endif
fileFormatVersion: 2
guid: 357a64420a0c44b61a0ed7ca22c7f10f
labels:
- gvh
- gvh_version-0.11.01
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
// <copyright file="GPGSUtil.cs" company="Google Inc.">
// Copyright (C) 2014 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
// Keep this even on unsupported configurations.
namespace GooglePlayGames.Editor
{
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Xml;
using UnityEditor;
using UnityEngine;
/// <summary>
/// Utility class to perform various tasks in the editor.
/// </summary>
public static class GPGSUtil
{
/// <summary>Property key for project settings.</summary>
public const string SERVICEIDKEY = "App.NearbdServiceId";
/// <summary>Property key for project settings.</summary>
public const string APPIDKEY = "proj.AppId";
/// <summary>Property key for project settings.</summary>
public const string CLASSDIRECTORYKEY = "proj.classDir";
/// <summary>Property key for project settings.</summary>
public const string CLASSNAMEKEY = "proj.ConstantsClassName";
/// <summary>Property key for project settings.</summary>
public const string WEBCLIENTIDKEY = "and.ClientId";
/// <summary>Property key for project settings.</summary>
public const string ANDROIDRESOURCEKEY = "and.ResourceData";
/// <summary>Property key for project settings.</summary>
public const string ANDROIDSETUPDONEKEY = "android.SetupDone";
/// <summary>Property key for project settings.</summary>
public const string ANDROIDBUNDLEIDKEY = "and.BundleId";
/// <summary>Property key for plugin version.</summary>
public const string PLUGINVERSIONKEY = "proj.pluginVersion";
/// <summary>Property key for nearby settings done.</summary>
public const string NEARBYSETUPDONEKEY = "android.NearbySetupDone";
/// <summary>Property key for project settings.</summary>
public const string LASTUPGRADEKEY = "lastUpgrade";
/// <summary>Constant for token replacement</summary>
private const string SERVICEIDPLACEHOLDER = "__NEARBY_SERVICE_ID__";
private const string SERVICEID_ELEMENT_PLACEHOLDER = "__NEARBY_SERVICE_ELEMENT__";
private const string NEARBY_PERMISSIONS_PLACEHOLDER = "__NEARBY_PERMISSIONS__";
/// <summary>Constant for token replacement</summary>
private const string APPIDPLACEHOLDER = "__APP_ID__";
/// <summary>Constant for token replacement</summary>
private const string CLASSNAMEPLACEHOLDER = "__Class__";
/// <summary>Constant for token replacement</summary>
private const string WEBCLIENTIDPLACEHOLDER = "__WEB_CLIENTID__";
/// <summary>Constant for token replacement</summary>
private const string PLUGINVERSIONPLACEHOLDER = "__PLUGIN_VERSION__";
/// <summary>Constant for require google plus token replacement</summary>
private const string REQUIREGOOGLEPLUSPLACEHOLDER = "__REQUIRE_GOOGLE_PLUS__";
/// <summary>Property key for project settings.</summary>
private const string TOKENPERMISSIONKEY = "proj.tokenPermissions";
/// <summary>Constant for token replacement</summary>
private const string NAMESPACESTARTPLACEHOLDER = "__NameSpaceStart__";
/// <summary>Constant for token replacement</summary>
private const string NAMESPACEENDPLACEHOLDER = "__NameSpaceEnd__";
/// <summary>Constant for token replacement</summary>
private const string CONSTANTSPLACEHOLDER = "__Constant_Properties__";
/// <summary>
/// The game info file path, relative to the plugin root directory. This is a generated file.
/// </summary>
private const string GameInfoRelativePath = "Runtime/Scripts/GameInfo.cs";
/// <summary>
/// The manifest path, relative to the plugin root directory.
/// </summary>
/// <remarks>The Games SDK requires additional metadata in the AndroidManifest.xml
/// file. </remarks>
private const string ManifestRelativePath =
"../../Plugins/Android/GooglePlayGamesManifest.androidlib/AndroidManifest.xml";
private const string RootFolderName = "com.google.play.games";
/// <summary>
/// The root path of the Google Play Games plugin
/// </summary>
public static string RootPath
{
get
{
if (string.IsNullOrEmpty(mRootPath))
{
#if UNITY_2018_4_OR_NEWER
// Search for root path in plugin locations for both Asset packages and UPM packages
string[] dirs = Directory.GetDirectories("Packages", RootFolderName, SearchOption.AllDirectories);
string[] dir1 = Directory.GetDirectories("Assets", RootFolderName, SearchOption.AllDirectories);
int dirsLength = dirs.Length;
Array.Resize<string>(ref dirs, dirsLength + dir1.Length);
Array.Copy(dir1, 0, dirs, dirsLength, dir1.Length);
#else
string[] dirs = Directory.GetDirectories("Assets", RootFolderName, SearchOption.AllDirectories);
#endif
switch (dirs.Length)
{
case 0:
Alert("Plugin error: com.google.play.games folder was renamed");
throw new Exception("com.google.play.games folder was renamed");
case 1:
mRootPath = SlashesToPlatformSeparator(dirs[0]);
break;
default:
for (int i = 0; i < dirs.Length; i++)
{
if (File.Exists(SlashesToPlatformSeparator(Path.Combine(dirs[i], GameInfoRelativePath)))
)
{
mRootPath = SlashesToPlatformSeparator(dirs[i]);
break;
}
}
if (string.IsNullOrEmpty(mRootPath))
{
Alert("Plugin error: com.google.play.games folder was renamed");
throw new Exception("com.google.play.games folder was renamed");
}
break;
}
}
// UPM package root path is 'Library/PackageCache/com.google.play.games@.*/
// where the suffix can be a version number if installed with URS
// or a hash if from disk or tarball
if (mRootPath.Contains(RootFolderName + '@'))
{
mRootPath = mRootPath.Replace("Packages", "Library/PackageCache");
}
return mRootPath;
}
}
/// <summary>
/// The game info file path. This is a generated file.
/// </summary>
private static string GameInfoPath
{
get { return SlashesToPlatformSeparator(Path.Combine(RootPath, GameInfoRelativePath)); }
}
/// <summary>
/// The manifest path.
/// </summary>
/// <remarks>The Games SDK requires additional metadata in the AndroidManifest.xml
/// file. </remarks>
private static string ManifestPath
{
get { return SlashesToPlatformSeparator(Path.Combine(RootPath, ManifestRelativePath)); }
}
/// <summary>
/// The root path of the Google Play Games plugin
/// </summary>
private static string mRootPath = "";
/// <summary>
/// The map of replacements for filling in code templates. The
/// key is the string that appears in the template as a placeholder,
/// the value is the key into the GPGSProjectSettings.
/// </summary>
private static Dictionary<string, string> replacements =
new Dictionary<string, string>()
{
// Put this element placeholder first, since it has embedded placeholder
{SERVICEID_ELEMENT_PLACEHOLDER, SERVICEID_ELEMENT_PLACEHOLDER},
{SERVICEIDPLACEHOLDER, SERVICEIDKEY},
{APPIDPLACEHOLDER, APPIDKEY},
{CLASSNAMEPLACEHOLDER, CLASSNAMEKEY},
{WEBCLIENTIDPLACEHOLDER, WEBCLIENTIDKEY},
{PLUGINVERSIONPLACEHOLDER, PLUGINVERSIONKEY},
// Causes the placeholder to be replaced with overridden value at runtime.
{NEARBY_PERMISSIONS_PLACEHOLDER, NEARBY_PERMISSIONS_PLACEHOLDER}
};
/// <summary>
/// Replaces / in file path to be the os specific separator.
/// </summary>
/// <returns>The path.</returns>
/// <param name="path">Path with correct separators.</param>
public static string SlashesToPlatformSeparator(string path)
{
return path.Replace("/", System.IO.Path.DirectorySeparatorChar.ToString());
}
/// <summary>
/// Reads the file.
/// </summary>
/// <returns>The file contents. The slashes are corrected.</returns>
/// <param name="filePath">File path.</param>
public static string ReadFile(string filePath)
{
filePath = SlashesToPlatformSeparator(filePath);
if (!File.Exists(filePath))
{
Alert("Plugin error: file not found: " + filePath);
return null;
}
StreamReader sr = new StreamReader(filePath);
string body = sr.ReadToEnd();
sr.Close();
return body;
}
/// <summary>
/// Reads the editor template.
/// </summary>
/// <returns>The editor template contents.</returns>
/// <param name="name">Name of the template in the editor directory.</param>
public static string ReadEditorTemplate(string name)
{
return ReadFile(
Path.Combine(RootPath, string.Format("Editor{0}{1}.txt", Path.DirectorySeparatorChar, name)));
}
/// <summary>
/// Writes the file.
/// </summary>
/// <param name="file">File path - the slashes will be corrected.</param>
/// <param name="body">Body of the file to write.</param>
public static void WriteFile(string file, string body)
{
file = SlashesToPlatformSeparator(file);
DirectoryInfo dir = Directory.GetParent(file);
dir.Create();
using (var wr = new StreamWriter(file, false))
{
wr.Write(body);
}
}
/// <summary>
/// Validates the string to be a valid nearby service id.
/// </summary>
/// <returns><c>true</c>, if like valid service identifier was looksed, <c>false</c> otherwise.</returns>
/// <param name="s">string to test.</param>
public static bool LooksLikeValidServiceId(string s)
{
if (s.Length < 3)
{
return false;
}
foreach (char c in s)
{
if (!char.IsLetterOrDigit(c) && c != '.')
{
return false;
}
}
return true;
}
/// <summary>
/// Looks the like valid app identifier.
/// </summary>
/// <returns><c>true</c>, if valid app identifier, <c>false</c> otherwise.</returns>
/// <param name="s">the string to test.</param>
public static bool LooksLikeValidAppId(string s)
{
if (s.Length < 5)
{
return false;
}
foreach (char c in s)
{
if (c < '0' || c > '9')
{
return false;
}
}
return true;
}
/// <summary>
/// Looks the like valid client identifier.
/// </summary>
/// <returns><c>true</c>, if valid client identifier, <c>false</c> otherwise.</returns>
/// <param name="s">the string to test.</param>
public static bool LooksLikeValidClientId(string s)
{
return s.EndsWith(".googleusercontent.com");
}
/// <summary>
/// Looks the like a valid bundle identifier.
/// </summary>
/// <returns><c>true</c>, if valid bundle identifier, <c>false</c> otherwise.</returns>
/// <param name="s">the string to test.</param>
public static bool LooksLikeValidBundleId(string s)
{
return s.Length > 3;
}
/// <summary>
/// Looks like a valid package.
/// </summary>
/// <returns><c>true</c>, if valid package name, <c>false</c> otherwise.</returns>
/// <param name="s">the string to test.</param>
public static bool LooksLikeValidPackageName(string s)
{
if (string.IsNullOrEmpty(s))
{
throw new Exception("cannot be empty");
}
string[] parts = s.Split(new char[] {'.'});
foreach (string p in parts)
{
char[] bytes = p.ToCharArray();
for (int i = 0; i < bytes.Length; i++)
{
if (i == 0 && !char.IsLetter(bytes[i]))
{
throw new Exception("each part must start with a letter");
}
else if (char.IsWhiteSpace(bytes[i]))
{
throw new Exception("cannot contain spaces");
}
else if (!char.IsLetterOrDigit(bytes[i]) && bytes[i] != '_')
{
throw new Exception("must be alphanumeric or _");
}
}
}
return parts.Length >= 1;
}
/// <summary>
/// Determines if is setup done.
/// </summary>
/// <returns><c>true</c> if is setup done; otherwise, <c>false</c>.</returns>
public static bool IsSetupDone()
{
bool doneSetup = true;
#if UNITY_ANDROID
doneSetup = GPGSProjectSettings.Instance.GetBool(ANDROIDSETUPDONEKEY, false);
// check gameinfo
if (File.Exists(GameInfoPath))
{
string contents = ReadFile(GameInfoPath);
if (contents.Contains(APPIDPLACEHOLDER))
{
Debug.Log("GameInfo not initialized with AppId. " +
"Run Window > Google Play Games > Setup > Android Setup...");
return false;
}
}
else
{
Debug.Log("GameInfo.cs does not exist. Run Window > Google Play Games > Setup > Android Setup...");
return false;
}
#endif
return doneSetup;
}
/// <summary>
/// Makes legal identifier from string.
/// Returns a legal C# identifier from the given string. The transformations are:
/// - spaces => underscore _
/// - punctuation => empty string
/// - leading numbers are prefixed with underscore.
/// </summary>
/// <returns>the id</returns>
/// <param name="key">Key to convert to an identifier.</param>
public static string MakeIdentifier(string key)
{
string s;
string retval = string.Empty;
if (string.IsNullOrEmpty(key))
{
return "_";
}
s = key.Trim().Replace(' ', '_');
foreach (char c in s)
{
if (char.IsLetterOrDigit(c) || c == '_')
{
retval += c;
}
}
return retval;
}
/// <summary>
/// Displays an error dialog.
/// </summary>
/// <param name="s">the message</param>
public static void Alert(string s)
{
Alert(GPGSStrings.Error, s);
}
/// <summary>
/// Displays a dialog with the given title and message.
/// </summary>
/// <param name="title">the title.</param>
/// <param name="message">the message.</param>
public static void Alert(string title, string message)
{
EditorUtility.DisplayDialog(title, message, GPGSStrings.Ok);
}
/// <summary>
/// Gets the android sdk path.
/// </summary>
/// <returns>The android sdk path.</returns>
public static string GetAndroidSdkPath()
{
string sdkPath = EditorPrefs.GetString("AndroidSdkRoot");
#if UNITY_2019_1_OR_NEWER
// Unity 2019.x added installation of the Android SDK in the AndroidPlayer directory
// so fallback to searching for it there.
if (string.IsNullOrEmpty(sdkPath) || EditorPrefs.GetBool("SdkUseEmbedded"))
{
string androidPlayerDir = BuildPipeline.GetPlaybackEngineDirectory(BuildTarget.Android, BuildOptions.None);
if (!string.IsNullOrEmpty(androidPlayerDir))
{
string androidPlayerSdkDir = Path.Combine(androidPlayerDir, "SDK");
if (Directory.Exists(androidPlayerSdkDir))
{
sdkPath = androidPlayerSdkDir;
}
}
}
#endif
if (sdkPath != null && (sdkPath.EndsWith("/") || sdkPath.EndsWith("\\")))
{
sdkPath = sdkPath.Substring(0, sdkPath.Length - 1);
}
return sdkPath;
}
/// <summary>
/// Determines if the android sdk exists.
/// </summary>
/// <returns><c>true</c> if android sdk exists; otherwise, <c>false</c>.</returns>
public static bool HasAndroidSdk()
{
string sdkPath = GetAndroidSdkPath();
return sdkPath != null && sdkPath.Trim() != string.Empty && System.IO.Directory.Exists(sdkPath);
}
/// <summary>
/// Gets the unity major version.
/// </summary>
/// <returns>The unity major version.</returns>
public static int GetUnityMajorVersion()
{
#if UNITY_5
string majorVersion = Application.unityVersion.Split('.')[0];
int ver;
if (!int.TryParse(majorVersion, out ver))
{
ver = 0;
}
return ver;
#elif UNITY_4_6
return 4;
#else
return 0;
#endif
}
/// <summary>
/// Checks for the android manifest file exsistance.
/// </summary>
/// <returns><c>true</c>, if the file exists <c>false</c> otherwise.</returns>
public static bool AndroidManifestExists()
{
string destFilename = ManifestPath;
return File.Exists(destFilename);
}
/// <summary>
/// Generates the android manifest.
/// </summary>
public static void GenerateAndroidManifest()
{
string destFilename = ManifestPath;
// Generate AndroidManifest.xml
string manifestBody = GPGSUtil.ReadEditorTemplate("template-AndroidManifest");
Dictionary<string, string> overrideValues =
new Dictionary<string, string>();
if (!string.IsNullOrEmpty(GPGSProjectSettings.Instance.Get(SERVICEIDKEY)))
{
overrideValues[NEARBY_PERMISSIONS_PLACEHOLDER] =
" <!-- Required for Nearby Connections -->\n" +
" <uses-permission android:name=\"android.permission.BLUETOOTH\" />\n" +
" <uses-permission android:name=\"android.permission.BLUETOOTH_ADMIN\" />\n" +
" <uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\" />\n" +
" <uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\" />\n" +
" <uses-permission android:name=\"android.permission.ACCESS_COARSE_LOCATION\" />\n";
overrideValues[SERVICEID_ELEMENT_PLACEHOLDER] =
" <!-- Required for Nearby Connections API -->\n" +
" <meta-data android:name=\"com.google.android.gms.nearby.connection.SERVICE_ID\"\n" +
" android:value=\"__NEARBY_SERVICE_ID__\" />\n";
}
else
{
overrideValues[NEARBY_PERMISSIONS_PLACEHOLDER] = "";
overrideValues[SERVICEID_ELEMENT_PLACEHOLDER] = "";
}
foreach (KeyValuePair<string, string> ent in replacements)
{
string value =
GPGSProjectSettings.Instance.Get(ent.Value, overrideValues);
manifestBody = manifestBody.Replace(ent.Key, value);
}
GPGSUtil.WriteFile(destFilename, manifestBody);
GPGSUtil.UpdateGameInfo();
}
/// <summary>
/// Writes the resource identifiers file. This file contains the
/// resource ids copied (downloaded?) from the play game app console.
/// </summary>
/// <param name="classDirectory">Class directory.</param>
/// <param name="className">Class name.</param>
/// <param name="resourceKeys">Resource keys.</param>
public static void WriteResourceIds(string classDirectory, string className, Hashtable resourceKeys)
{
string constantsValues = string.Empty;
string[] parts = className.Split('.');
string dirName = classDirectory;
if (string.IsNullOrEmpty(dirName))
{
dirName = "Assets";
}
string nameSpace = string.Empty;
for (int i = 0; i < parts.Length - 1; i++)
{
dirName += "/" + parts[i];
if (nameSpace != string.Empty)
{
nameSpace += ".";
}
nameSpace += parts[i];
}
EnsureDirExists(dirName);
foreach (DictionaryEntry ent in resourceKeys)
{
string key = MakeIdentifier((string) ent.Key);
constantsValues += " public const string " +
key + " = \"" + ent.Value + "\"; // <GPGSID>\n";
}
string fileBody = GPGSUtil.ReadEditorTemplate("template-Constants");
if (nameSpace != string.Empty)
{
fileBody = fileBody.Replace(
NAMESPACESTARTPLACEHOLDER,
"namespace " + nameSpace + "\n{");
}
else
{
fileBody = fileBody.Replace(NAMESPACESTARTPLACEHOLDER, string.Empty);
}
fileBody = fileBody.Replace(CLASSNAMEPLACEHOLDER, parts[parts.Length - 1]);
fileBody = fileBody.Replace(CONSTANTSPLACEHOLDER, constantsValues);
if (nameSpace != string.Empty)
{
fileBody = fileBody.Replace(
NAMESPACEENDPLACEHOLDER,
"}");
}
else
{
fileBody = fileBody.Replace(NAMESPACEENDPLACEHOLDER, string.Empty);
}
WriteFile(Path.Combine(dirName, parts[parts.Length - 1] + ".cs"), fileBody);
}
/// <summary>
/// Updates the game info file. This is a generated file containing the
/// app and client ids.
/// </summary>
public static void UpdateGameInfo()
{
string fileBody = GPGSUtil.ReadEditorTemplate("template-GameInfo");
foreach (KeyValuePair<string, string> ent in replacements)
{
string value =
GPGSProjectSettings.Instance.Get(ent.Value);
fileBody = fileBody.Replace(ent.Key, value);
}
GPGSUtil.WriteFile(GameInfoPath, fileBody);
}
/// <summary>
/// Checks the dependencies file and fixes repository paths
/// if they are incorrect (for example if the user moved plugin
/// into some subdirectory). This is a generated file containing
/// the list of dependencies that are needed for the plugin to work.
/// </summary>
public static void CheckAndFixDependencies()
{
string depPath =
SlashesToPlatformSeparator(Path.Combine(GPGSUtil.RootPath,
"Editor/GooglePlayGamesPluginDependencies.xml"));
XmlDocument doc = new XmlDocument();
doc.Load(depPath);
XmlNodeList repos = doc.SelectNodes("//androidPackage[contains(@spec,'com.google.games')]//repository");
foreach (XmlNode repo in repos)
{
if (!Directory.Exists(repo.InnerText))
{
int pos = repo.InnerText.IndexOf(RootFolderName);
if (pos != -1)
{
repo.InnerText =
Path.Combine(RootPath, repo.InnerText.Substring(pos + RootFolderName.Length + 1))
.Replace("\\", "/");
}
}
}
doc.Save(depPath);
}
/// <summary>
/// Checks the file containing the list of versioned assets and fixes
/// paths to them if they are incorrect (for example if the user moved
/// plugin into some subdirectory). This is a generated file.
/// </summary>
public static void CheckAndFixVersionedAssestsPaths()
{
string[] foundPaths =
Directory.GetFiles(RootPath, "GooglePlayGamesPlugin_v*.txt", SearchOption.AllDirectories);
if (foundPaths.Length == 1)
{
string tmpFilePath = Path.GetTempFileName();
StreamWriter writer = new StreamWriter(tmpFilePath);
using (StreamReader reader = new StreamReader(foundPaths[0]))
{
string assetPath;
while ((assetPath = reader.ReadLine()) != null)
{
int pos = assetPath.IndexOf(RootFolderName);
if (pos != -1)
{
assetPath = Path.Combine(RootPath, assetPath.Substring(pos + RootFolderName.Length + 1))
.Replace("\\", "/");
}
writer.WriteLine(assetPath);
}
}
writer.Flush();
writer.Close();
try
{
File.Copy(tmpFilePath, foundPaths[0], true);
}
finally
{
File.Delete(tmpFilePath);
}
}
}
/// <summary>
/// Ensures the dir exists.
/// </summary>
/// <param name="dir">Directory to check.</param>
public static void EnsureDirExists(string dir)
{
dir = SlashesToPlatformSeparator(dir);
if (!Directory.Exists(dir))
{
Directory.CreateDirectory(dir);
}
}
/// <summary>
/// Deletes the dir if exists.
/// </summary>
/// <param name="dir">Directory to delete.</param>
public static void DeleteDirIfExists(string dir)
{
dir = SlashesToPlatformSeparator(dir);
if (Directory.Exists(dir))
{
Directory.Delete(dir, true);
}
}
/// <summary>
/// Gets the Google Play Services library version. This is only
/// needed for Unity versions less than 5.
/// </summary>
/// <returns>The GPS version.</returns>
/// <param name="libProjPath">Lib proj path.</param>
private static int GetGPSVersion(string libProjPath)
{
string versionFile = libProjPath + "/res/values/version.xml";
XmlTextReader reader = new XmlTextReader(new StreamReader(versionFile));
bool inResource = false;
int version = -1;
while (reader.Read())
{
if (reader.Name == "resources")
{
inResource = true;
}
if (inResource && reader.Name == "integer")
{
if ("google_play_services_version".Equals(
reader.GetAttribute("name")))
{
reader.Read();
Debug.Log("Read version string: " + reader.Value);
version = Convert.ToInt32(reader.Value);
}
}
}
reader.Close();
return version;
}
}
}
fileFormatVersion: 2
guid: fd01714f9ee99447996b878b1ac67540
labels:
- gvh
- gvh_version-0.11.01
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
{
"name": "Google.Play.Games.Editor",
"references": [
"Google.Play.Games"
],
"includePlatforms": [
"Editor"
]
}
fileFormatVersion: 2
guid: 9172e27a923a34eb8b02dc3ab88d3dcd
labels:
- gvh
- gvh_version-0.11.01
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
<?xml version="1.0" encoding="UTF-8" ?>
<dependencies>
<!-- Internal library dependency generated at build time.
It also defines the transitive dependencies on play-services
-->
<androidPackages>
<androidPackage spec="com.google.games:gpgs-plugin-support:0.11.01">
<repositories>
<repository>Packages/com.google.play.games/Editor/m2repository</repository>
</repositories>
</androidPackage>
</androidPackages>
</dependencies>
fileFormatVersion: 2
guid: 56e4f40c267bfa268afda2ea9f4846a0
labels:
- gvh
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
Assets/Plugins/Android/GooglePlayGamesManifest.androidlib/project.properties
Assets/ExternalDependencyManager/Editor/README.md
Assets/ExternalDependencyManager/Editor/Google.VersionHandler.dll.mdb
Assets/ExternalDependencyManager/Editor/external-dependency-manager_version-1.2.169_manifest.txt
Assets/ExternalDependencyManager/Editor/1.2.169/Google.VersionHandlerImpl.dll
Assets/ExternalDependencyManager/Editor/1.2.169/Google.JarResolver.dll.mdb
Assets/ExternalDependencyManager/Editor/1.2.169/Google.VersionHandlerImpl.dll.mdb
Assets/ExternalDependencyManager/Editor/1.2.169/Google.PackageManagerResolver.dll
Assets/ExternalDependencyManager/Editor/1.2.169/Google.IOSResolver.dll
Assets/ExternalDependencyManager/Editor/1.2.169/Google.IOSResolver.dll.mdb
Assets/ExternalDependencyManager/Editor/1.2.169/Google.PackageManagerResolver.dll.mdb
Assets/ExternalDependencyManager/Editor/1.2.169/Google.JarResolver.dll
Assets/ExternalDependencyManager/Editor/Google.VersionHandler.dll
Assets/ExternalDependencyManager/Editor/CHANGELOG.md
Assets/ExternalDependencyManager/Editor/LICENSE
Assets/GooglePlayGames/AssemblyInfo.cs
Assets/GooglePlayGames/com.google.play.games/Editor/m2repository/com/google/games/gpgs-plugin-support/maven-metadata.xml
Assets/GooglePlayGames/com.google.play.games/Editor/m2repository/com/google/games/gpgs-plugin-support/maven-metadata.xml.sha1
Assets/GooglePlayGames/com.google.play.games/Editor/m2repository/com/google/games/gpgs-plugin-support/0.11.01/gpgs-plugin-support-0.11.01.srcaar.sha1
Assets/GooglePlayGames/com.google.play.games/Editor/m2repository/com/google/games/gpgs-plugin-support/0.11.01/gpgs-plugin-support-0.11.01.pom
Assets/GooglePlayGames/com.google.play.games/Editor/m2repository/com/google/games/gpgs-plugin-support/0.11.01/gpgs-plugin-support-0.11.01.srcaar
Assets/GooglePlayGames/com.google.play.games/Editor/m2repository/com/google/games/gpgs-plugin-support/0.11.01/gpgs-plugin-support-0.11.01.pom.md5
Assets/GooglePlayGames/com.google.play.games/Editor/m2repository/com/google/games/gpgs-plugin-support/0.11.01/gpgs-plugin-support-0.11.01.pom.sha1
Assets/GooglePlayGames/com.google.play.games/Editor/m2repository/com/google/games/gpgs-plugin-support/0.11.01/gpgs-plugin-support-0.11.01.srcaar.md5
Assets/GooglePlayGames/com.google.play.games/Editor/m2repository/com/google/games/gpgs-plugin-support/maven-metadata.xml.md5
Assets/GooglePlayGames/com.google.play.games/Editor/template-AndroidManifest.txt
Assets/GooglePlayGames/com.google.play.games/Editor/GPGSUtil.cs
Assets/GooglePlayGames/com.google.play.games/Editor/GPGSStrings.cs
Assets/GooglePlayGames/com.google.play.games/Editor/GooglePlayGamesPluginDependencies.xml
Assets/GooglePlayGames/com.google.play.games/Editor/GPGSPostBuild.cs
Assets/GooglePlayGames/com.google.play.games/Editor/GPGSDocsUI.cs
Assets/GooglePlayGames/com.google.play.games/Editor/Google.Play.Games.Editor.asmdef
Assets/GooglePlayGames/com.google.play.games/Editor/template-GameInfo.txt
Assets/GooglePlayGames/com.google.play.games/Editor/GPGSProjectSettings.cs
Assets/GooglePlayGames/com.google.play.games/Editor/GPGSUpgrader.cs
Assets/GooglePlayGames/com.google.play.games/Editor/NearbyConnectionUI.cs
Assets/GooglePlayGames/com.google.play.games/Editor/GPGSAndroidSetupUI.cs
Assets/GooglePlayGames/com.google.play.games/Editor/template-Constants.txt
Assets/GooglePlayGames/com.google.play.games/package.json
Assets/GooglePlayGames/com.google.play.games/Proguard/games.txt
Assets/GooglePlayGames/com.google.play.games/Runtime/Google.Play.Games.asmdef
Assets/GooglePlayGames/com.google.play.games/Runtime/Scripts/OurUtils/NearbyHelperObject.cs
Assets/GooglePlayGames/com.google.play.games/Runtime/Scripts/OurUtils/PlayGamesHelperObject.cs
Assets/GooglePlayGames/com.google.play.games/Runtime/Scripts/OurUtils/Misc.cs
Assets/GooglePlayGames/com.google.play.games/Runtime/Scripts/OurUtils/PlatformUtils.cs
Assets/GooglePlayGames/com.google.play.games/Runtime/Scripts/OurUtils/Logger.cs
Assets/GooglePlayGames/com.google.play.games/Runtime/Scripts/GameInfo.cs
Assets/GooglePlayGames/com.google.play.games/Runtime/Scripts/Platforms/PlayGamesClientFactory.cs
Assets/GooglePlayGames/com.google.play.games/Runtime/Scripts/Platforms/NearbyConnectionClientFactory.cs
Assets/GooglePlayGames/com.google.play.games/Runtime/Scripts/Platforms/Android/AndroidNearbyConnectionClient.cs
Assets/GooglePlayGames/com.google.play.games/Runtime/Scripts/Platforms/Android/AndroidClient.cs
Assets/GooglePlayGames/com.google.play.games/Runtime/Scripts/Platforms/Android/AndroidJavaConverter.cs
Assets/GooglePlayGames/com.google.play.games/Runtime/Scripts/Platforms/Android/AndroidSnapshotMetadata.cs
Assets/GooglePlayGames/com.google.play.games/Runtime/Scripts/Platforms/Android/AndroidSavedGameClient.cs
Assets/GooglePlayGames/com.google.play.games/Runtime/Scripts/Platforms/Android/AndroidHelperFragment.cs
Assets/GooglePlayGames/com.google.play.games/Runtime/Scripts/Platforms/Android/AndroidEventsClient.cs
Assets/GooglePlayGames/com.google.play.games/Runtime/Scripts/Platforms/Android/AndroidTaskUtils.cs
Assets/GooglePlayGames/com.google.play.games/Runtime/Scripts/ISocialPlatform/PlayGamesPlatform.cs
Assets/GooglePlayGames/com.google.play.games/Runtime/Scripts/ISocialPlatform/PlayGamesAchievement.cs
Assets/GooglePlayGames/com.google.play.games/Runtime/Scripts/ISocialPlatform/PlayGamesLeaderboard.cs
Assets/GooglePlayGames/com.google.play.games/Runtime/Scripts/ISocialPlatform/PlayGamesLocalUser.cs
Assets/GooglePlayGames/com.google.play.games/Runtime/Scripts/ISocialPlatform/PlayGamesUserProfile.cs
Assets/GooglePlayGames/com.google.play.games/Runtime/Scripts/ISocialPlatform/PlayGamesScore.cs
Assets/GooglePlayGames/com.google.play.games/Runtime/Scripts/BasicApi/ScorePageToken.cs
Assets/GooglePlayGames/com.google.play.games/Runtime/Scripts/BasicApi/Player.cs
Assets/GooglePlayGames/com.google.play.games/Runtime/Scripts/BasicApi/LeaderboardScoreData.cs
Assets/GooglePlayGames/com.google.play.games/Runtime/Scripts/BasicApi/Nearby/AdvertisingResult.cs
Assets/GooglePlayGames/com.google.play.games/Runtime/Scripts/BasicApi/Nearby/ConnectionResponse.cs
Assets/GooglePlayGames/com.google.play.games/Runtime/Scripts/BasicApi/Nearby/ConnectionRequest.cs
Assets/GooglePlayGames/com.google.play.games/Runtime/Scripts/BasicApi/Nearby/EndpointDetails.cs
Assets/GooglePlayGames/com.google.play.games/Runtime/Scripts/BasicApi/Nearby/NearbyConnectionConfiguration.cs
Assets/GooglePlayGames/com.google.play.games/Runtime/Scripts/BasicApi/Nearby/INearbyConnectionClient.cs
Assets/GooglePlayGames/com.google.play.games/Runtime/Scripts/BasicApi/Nearby/DummyNearbyConnectionClient.cs
Assets/GooglePlayGames/com.google.play.games/Runtime/Scripts/BasicApi/CommonStatusCodes.cs
Assets/GooglePlayGames/com.google.play.games/Runtime/Scripts/BasicApi/CommonTypes.cs
Assets/GooglePlayGames/com.google.play.games/Runtime/Scripts/BasicApi/SavedGame/ISavedGameClient.cs
Assets/GooglePlayGames/com.google.play.games/Runtime/Scripts/BasicApi/SavedGame/SavedGameMetadataUpdate.cs
Assets/GooglePlayGames/com.google.play.games/Runtime/Scripts/BasicApi/SavedGame/ISavedGameMetadata.cs
Assets/GooglePlayGames/com.google.play.games/Runtime/Scripts/BasicApi/Achievement.cs
Assets/GooglePlayGames/com.google.play.games/Runtime/Scripts/BasicApi/SignInStatus.cs
Assets/GooglePlayGames/com.google.play.games/Runtime/Scripts/BasicApi/Events/Event.cs
Assets/GooglePlayGames/com.google.play.games/Runtime/Scripts/BasicApi/Events/IEvent.cs
Assets/GooglePlayGames/com.google.play.games/Runtime/Scripts/BasicApi/Events/IEventsClient.cs
Assets/GooglePlayGames/com.google.play.games/Runtime/Scripts/BasicApi/PlayerStats.cs
Assets/GooglePlayGames/com.google.play.games/Runtime/Scripts/BasicApi/DummyClient.cs
Assets/GooglePlayGames/com.google.play.games/Runtime/Scripts/BasicApi/SignInInteractivity.cs
Assets/GooglePlayGames/com.google.play.games/Runtime/Scripts/BasicApi/IPlayGamesClient.cs
Assets/GooglePlayGames/com.google.play.games/Runtime/Scripts/BasicApi/PlayerProfile.cs
Assets/GooglePlayGames/com.google.play.games/Runtime/Scripts/PluginVersion.cs
Assets/PlayServicesResolver/Editor/play-services-resolver_v1.2.137.0.txt
fileFormatVersion: 2
guid: 693a823b8f0ad41fe8231a1b1c8a50da
labels:
- gvh
- gvh_manifest
- gvh_version-0.11.01
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
// <copyright file="NearbyConnectionUI.cs" company="Google Inc.">
// Copyright (C) 2014 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
#if UNITY_ANDROID
namespace GooglePlayGames.Editor
{
using UnityEngine;
using UnityEditor;
public class NearbyConnectionUI : EditorWindow
{
private string mNearbyServiceId = string.Empty;
[MenuItem("Window/Google Play Games/Setup/Nearby Connections setup...", false, 3)]
public static void MenuItemNearbySetup()
{
EditorWindow window = EditorWindow.GetWindow(
typeof(NearbyConnectionUI), true, GPGSStrings.NearbyConnections.Title);
window.minSize = new Vector2(400, 200);
}
[MenuItem("Window/Google Play Games/Setup/Nearby Connections setup...", true)]
public static bool EnableNearbyMenuItem()
{
#if UNITY_ANDROID
return true;
#else
return false;
#endif
}
public void OnEnable()
{
mNearbyServiceId = GPGSProjectSettings.Instance.Get(GPGSUtil.SERVICEIDKEY);
}
public void OnGUI()
{
GUI.skin.label.wordWrap = true;
GUILayout.BeginVertical();
GUILayout.Space(10);
GUILayout.Label(GPGSStrings.NearbyConnections.Blurb);
GUILayout.Space(10);
GUILayout.Label(GPGSStrings.Setup.NearbyServiceId, EditorStyles.boldLabel);
GUILayout.Space(10);
GUILayout.Label(GPGSStrings.Setup.NearbyServiceBlurb);
mNearbyServiceId = EditorGUILayout.TextField(GPGSStrings.Setup.NearbyServiceId,
mNearbyServiceId, GUILayout.Width(350));
GUILayout.FlexibleSpace();
GUILayout.BeginHorizontal();
GUILayout.FlexibleSpace();
if (GUILayout.Button(GPGSStrings.Setup.SetupButton,
GUILayout.Width(100)))
{
DoSetup();
}
if (GUILayout.Button("Cancel", GUILayout.Width(100)))
{
this.Close();
}
GUILayout.FlexibleSpace();
GUILayout.EndHorizontal();
GUILayout.Space(20);
GUILayout.EndVertical();
}
private void DoSetup()
{
if (PerformSetup(mNearbyServiceId, true))
{
EditorUtility.DisplayDialog(GPGSStrings.Success,
GPGSStrings.NearbyConnections.SetupComplete, GPGSStrings.Ok);
this.Close();
}
}
/// Provide static access to setup for facilitating automated builds.
/// <param name="nearbyServiceId">The nearby connections service Id</param>
/// <param name="androidBuild">true if building android</param>
public static bool PerformSetup(string nearbyServiceId, bool androidBuild)
{
// check for valid app id
if (!GPGSUtil.LooksLikeValidServiceId(nearbyServiceId))
{
if (EditorUtility.DisplayDialog(
"Remove Nearby connection permissions? ",
"The service Id is invalid. It must follow package naming rules. " +
"Do you want to remove the AndroidManifest entries for Nearby connections?",
"Yes",
"No"))
{
GPGSProjectSettings.Instance.Set(GPGSUtil.SERVICEIDKEY, null);
GPGSProjectSettings.Instance.Save();
}
else
{
return false;
}
}
else
{
GPGSProjectSettings.Instance.Set(GPGSUtil.SERVICEIDKEY, nearbyServiceId);
GPGSProjectSettings.Instance.Save();
}
if (androidBuild)
{
// create needed directories
GPGSUtil.EnsureDirExists("Assets/Plugins");
GPGSUtil.EnsureDirExists("Assets/Plugins/Android");
// Generate AndroidManifest.xml
GPGSUtil.GenerateAndroidManifest();
GPGSProjectSettings.Instance.Set(GPGSUtil.NEARBYSETUPDONEKEY, true);
GPGSProjectSettings.Instance.Save();
// Resolve the dependencies
Google.VersionHandler.VerboseLoggingEnabled = true;
Google.VersionHandler.UpdateVersionedAssets(forceUpdate: true);
Google.VersionHandler.Enabled = true;
AssetDatabase.Refresh();
Google.VersionHandler.InvokeStaticMethod(
Google.VersionHandler.FindClass(
"Google.JarResolver",
"GooglePlayServices.PlayServicesResolver"),
"MenuResolve", null);
}
return true;
}
}
}
#endif
\ No newline at end of file
fileFormatVersion: 2
guid: b64332a502e18436da5652adbf7e24a3
labels:
- gvh
- gvh_version-0.11.01
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: a1aac54589c4640cd89900056af3a094
folderAsset: yes
timeCreated: 1515000812
licenseType: Free
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 6bfd2e0bf6a79efa5a524c758a029a97
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 44f501fdbcc7ecb3a9d935d48385fcd7
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: ab2c8702a5ac8186e833079b0c2b97eb
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 7aad2f859f18616f6b634cecc92785db
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 270a1b374befae139bb007ed9fe42c0a
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<groupId>com.google.games</groupId>
<artifactId>gpgs-plugin-support</artifactId>
<version>0.11.01</version>
<packaging>srcaar</packaging>
<dependencies>
<dependency>
<groupId>com.google.android.gms</groupId>
<artifactId>play-services-games-v2</artifactId>
<version>17.0.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.google.android.gms</groupId>
<artifactId>play-services-nearby</artifactId>
<version>18.0.2</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>
fileFormatVersion: 2
guid: 021d4ecf67ff30875941d1d1d3e4273f
labels:
- gvh
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 3a8de8e589297f83cbf708663d04784d
labels:
- gvh
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 2ace5c923ae5a5e4182561bb8b0e47ad
labels:
- gvh
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 6a5d6cd742873c73f8f0c9a1ac445182
labels:
- gvh
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 8a7a2dcd7d551e040938c69456bd0643
labels:
- gvh
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: b8fc53361999b1f4a830505b47234b73
labels:
- gvh
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
<?xml version="1.0" encoding="UTF-8"?>
<metadata>
<groupId>com.google.games</groupId>
<artifactId>gpgs-plugin-support</artifactId>
<versioning>
<release>0.11.01</release>
<versions>
<version>0.11.01</version>
</versions>
<lastUpdated>20220321142410</lastUpdated>
</versioning>
</metadata>
fileFormatVersion: 2
guid: b99ac5f1bd7ba77d390d8508c2c3b8cc
labels:
- gvh
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: e9ae03af85334796fa074f4f75bd5426
labels:
- gvh
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 75441663f29e7a430af793277d746c7e
labels:
- gvh
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
<?xml version="1.0" encoding="utf-8"?>
<!-- This file was automatically generated by the Google Play Games plugin for Unity
Do not edit. -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.google.example.games.mainlibproj"
android:versionCode="1"
android:versionName="1.0" >
__NEARBY_PERMISSIONS__
<application>
__NEARBY_SERVICE_ELEMENT__
<!-- The space in these forces it to be interpreted as a string vs. int -->
<meta-data android:name="com.google.android.gms.games.APP_ID"
android:value="\u003__APP_ID__" />
<!-- Keep track of which plugin is being used -->
<meta-data android:name="com.google.android.gms.games.unityVersion"
android:value="\u003__PLUGIN_VERSION__" />
<activity android:name="com.google.games.bridge.NativeBridgeActivity"
android:theme="@android:style/Theme.Translucent.NoTitleBar.Fullscreen" />
</application>
</manifest>
fileFormatVersion: 2
guid: 0e1f3c150256848b1ba98702cfb71220
labels:
- gvh
- gvh_version-0.11.01
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
// <copyright file="GPGSIds.cs" company="Google Inc.">
// Copyright (C) 2015 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
///
/// This file is automatically generated DO NOT EDIT!
///
/// These are the constants defined in the Play Games Console for Game Services
/// Resources.
///
__NameSpaceStart__
public static class __Class__
{
__Constant_Properties__
}
__NameSpaceEnd__
fileFormatVersion: 2
guid: 7f2719cb8be514661b7b6aa9986bfe5f
labels:
- gvh
- gvh_version-0.11.01
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
// <copyright file="GameInfo.cs" company="Google Inc.">
// Copyright (C) 2015 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
#if UNITY_ANDROID
namespace GooglePlayGames {
///
/// This file is automatically generated DO NOT EDIT!
///
/// These are the constants defined in the Play Games Console for Game Services
/// Resources.
///
/// <summary>
/// File containing information about the game. This is automatically updated by running the
/// platform-appropriate setup commands in the Unity editor (which does a simple search / replace
/// on the IDs in the form "__ID__"). We can check whether any particular field has been updated
/// by checking whether it still retains its initial value - we prevent the constants from being
/// replaced in the aforementioned search/replace by stripping off the leading and trailing "__".
/// </summary>
public static class GameInfo {
private const string UnescapedApplicationId = "APP_ID";
private const string UnescapedIosClientId = "IOS_CLIENTID";
private const string UnescapedWebClientId = "WEB_CLIENTID";
private const string UnescapedNearbyServiceId = "NEARBY_SERVICE_ID";
public const string ApplicationId = "__APP_ID__"; // Filled in automatically
public const string IosClientId = "__IOS_CLIENTID__"; // Filled in automatically
public const string WebClientId = "__WEB_CLIENTID__"; // Filled in automatically
public const string NearbyConnectionServiceId = "__NEARBY_SERVICE_ID__";
public static bool ApplicationIdInitialized() {
return !string.IsNullOrEmpty(ApplicationId) && !ApplicationId.Equals(ToEscapedToken(UnescapedApplicationId));
}
public static bool IosClientIdInitialized() {
return !string.IsNullOrEmpty(IosClientId) && !IosClientId.Equals(ToEscapedToken(UnescapedIosClientId));
}
public static bool WebClientIdInitialized() {
return !string.IsNullOrEmpty(WebClientId) && !WebClientId.Equals(ToEscapedToken(UnescapedWebClientId));
}
public static bool NearbyConnectionsInitialized() {
return !string.IsNullOrEmpty(NearbyConnectionServiceId) &&
!NearbyConnectionServiceId.Equals(ToEscapedToken(UnescapedNearbyServiceId));
}
/// <summary>
/// Returns an escaped token (i.e. one flanked with "__") for the passed token
/// </summary>
/// <returns>The escaped token.</returns>
/// <param name="token">The Token</param>
private static string ToEscapedToken(string token) {
return string.Format("__{0}__", token);
}
}
}
#endif
fileFormatVersion: 2
guid: c6fa1c0456d174d298bf8dd66f584e9e
labels:
- gvh
- gvh_version-0.11.01
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 484e9bbdd408c50d993232965d92e0cb
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
-keep class com.google.android.gms.games.leaderboard.** { *; }
-keep class com.google.android.gms.games.snapshot.** { *; }
-keep class com.google.android.gms.games.achievement.** { *; }
-keep class com.google.android.gms.games.event.** { *; }
-keep class com.google.android.gms.games.stats.** { *; }
-keep class com.google.android.gms.games.* { *; }
-keep class com.google.android.gms.common.api.ResultCallback { *; }
-keep class com.google.android.gms.signin.** { *; }
-keep class com.google.android.gms.dynamic.** { *; }
-keep class com.google.android.gms.dynamite.** { *; }
-keep class com.google.android.gms.tasks.** { *; }
-keep class com.google.android.gms.security.** { *; }
-keep class com.google.android.gms.base.** { *; }
-keep class com.google.android.gms.actions.** { *; }
-keep class com.google.games.bridge.** { *; }
-keep class com.google.android.gms.common.ConnectionResult { *; }
-keep class com.google.android.gms.common.GooglePlayServicesUtil { *; }
-keep class com.google.android.gms.common.api.** { *; }
-keep class com.google.android.gms.common.data.DataBufferUtils { *; }
-keep class com.google.android.gms.nearby.** { *; }
fileFormatVersion: 2
guid: 4176788a1a4cdec9e8100aceecddd212
labels:
- gvh
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 831a102b513bb304da26f7ca18913f3e
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
{
"name": "Google.Play.Games",
"includePlatforms": [
"Android",
"Editor"
]
}
fileFormatVersion: 2
guid: 1ed07ff861e5f468287b0baef844706d
labels:
- gvh
- gvh_version-0.11.01
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 6ac644c502fda71c8a1a146903d950de
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 0a565e85253b345878939982a360e0b6
folderAsset: yes
DefaultImporter:
userData:
// <copyright file="Achievement.cs" company="Google Inc.">
// Copyright (C) 2014 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
#if UNITY_ANDROID
namespace GooglePlayGames.BasicApi
{
using System;
/// <summary>Data interface for retrieving achievement information.</summary>
/// <remarks>
/// There are 3 states an achievement can be in:
/// <para>
/// Hidden - indicating the name and description of the achievement is
/// not visible to the player.
/// </para><para>
/// Revealed - indicating the name and description of the achievement is
/// visible to the player.
/// Unlocked - indicating the player has unlocked, or achieved, the achievment.
/// </para><para>
/// Achievements has two types, standard which is unlocked in one step,
/// and incremental, which require multiple steps to unlock.
/// </para>
/// </remarks>
public class Achievement
{
static readonly DateTime UnixEpoch =
new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
private string mId = string.Empty;
private bool mIsIncremental = false;
private bool mIsRevealed = false;
private bool mIsUnlocked = false;
private int mCurrentSteps = 0;
private int mTotalSteps = 0;
private string mDescription = string.Empty;
private string mName = string.Empty;
private long mLastModifiedTime = 0;
private ulong mPoints;
private string mRevealedImageUrl;
private string mUnlockedImageUrl;
/// <summary>
/// Returns a <see cref="System.String"/> that represents the current <see cref="GooglePlayGames.BasicApi.Achievement"/>.
/// </summary>
/// <returns>A <see cref="System.String"/> that represents the current <see cref="GooglePlayGames.BasicApi.Achievement"/>.</returns>
public override string ToString()
{
return string.Format(
"[Achievement] id={0}, name={1}, desc={2}, type={3}, revealed={4}, unlocked={5}, steps={6}/{7}",
mId, mName, mDescription, mIsIncremental ? "INCREMENTAL" : "STANDARD",
mIsRevealed, mIsUnlocked, mCurrentSteps, mTotalSteps);
}
public Achievement()
{
}
/// <summary>
/// Indicates whether this achievement is incremental.
/// </summary>
public bool IsIncremental
{
get { return mIsIncremental; }
set { mIsIncremental = value; }
}
/// <summary>
/// The number of steps the user has gone towards unlocking this achievement.
/// </summary>
public int CurrentSteps
{
get { return mCurrentSteps; }
set { mCurrentSteps = value; }
}
/// <summary>
/// The total number of steps needed to unlock this achievement.
/// </summary>
public int TotalSteps
{
get { return mTotalSteps; }
set { mTotalSteps = value; }
}
/// <summary>
/// Indicates whether the achievement is unlocked or not.
/// </summary>
public bool IsUnlocked
{
get { return mIsUnlocked; }
set { mIsUnlocked = value; }
}
/// <summary>
/// Indicates whether the achievement is revealed or not (hidden).
/// </summary>
public bool IsRevealed
{
get { return mIsRevealed; }
set { mIsRevealed = value; }
}
/// <summary>
/// The ID string of this achievement.
/// </summary>
public string Id
{
get { return mId; }
set { mId = value; }
}
/// <summary>
/// The description of this achievement.
/// </summary>
public string Description
{
get { return this.mDescription; }
set { mDescription = value; }
}
/// <summary>
/// The name of this achievement.
/// </summary>
public string Name
{
get { return this.mName; }
set { mName = value; }
}
/// <summary>
/// The date and time the state of the achievement was modified.
/// </summary>
/// <remarks>
/// The value is invalid (-1 long) if the achievement state has
/// never been updated.
/// </remarks>
public DateTime LastModifiedTime
{
get { return UnixEpoch.AddMilliseconds(mLastModifiedTime); }
set
{
TimeSpan ts = value - UnixEpoch;
mLastModifiedTime = (long) ts.TotalMilliseconds;
}
}
/// <summary>
/// The number of experience points earned for unlocking this Achievement.
/// </summary>
public ulong Points
{
get { return mPoints; }
set { mPoints = value; }
}
/// <summary>
/// The URL to the image to display when the achievement is revealed.
/// </summary>
public string RevealedImageUrl
{
get { return mRevealedImageUrl; }
set { mRevealedImageUrl = value; }
}
/// <summary>
/// The URL to the image to display when the achievement is unlocked.
/// </summary>
public string UnlockedImageUrl
{
get { return mUnlockedImageUrl; }
set { mUnlockedImageUrl = value; }
}
}
}
#endif
\ No newline at end of file
fileFormatVersion: 2
guid: b20fc2fda369044ba962d1d9115c4c63
labels:
- gvh
- gvh_version-0.11.01
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
// <copyright file="CommonStatusCodes.cs" company="Google Inc.">
// Copyright (C) 2014 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
#if UNITY_ANDROID
namespace GooglePlayGames.BasicApi
{
/// <summary>
/// Common status codes.
/// See https://developers.google.com/android/reference/com/google/android/gms/common/api/CommonStatusCodes
/// </summary>
public enum CommonStatusCodes
{
/// <summary>The operation was successful, but the device's cache was used.</summary>
SuccessCached = -1,
/// <summary>The operation was successful.</summary>
Success = 0,
/// <summary>Google Play services is missing on this device.</summary>
ServiceMissing = 1,
/// <summary>The installed version of Google Play services is out of date.</summary>
ServiceVersionUpdateRequired = 2,
/// <summary>The installed version of Google Play services has been disabled on this device.</summary>
ServiceDisabled = 3,
/// <summary>The client attempted to connect to the service but the user is not signed in.</summary>
SignInRequired = 4,
/// <summary>The client attempted to connect to the service with an invalid account name specified.</summary>
InvalidAccount = 5,
/// <summary>Completing the operation requires some form of resolution.</summary>
ResolutionRequired = 6,
/// <summary>A network error occurred.</summary>
NetworkError = 7,
/// <summary>An internal error occurred.</summary>
InternalError = 8,
/// <summary>The version of the Google Play services installed on this device is not authentic.</summary>
ServiceInvalid = 9,
/// <summary>The application is misconfigured.</summary>
DeveloperError = 10,
/// <summary>The application is not licensed to the user.</summary>
LicenseCheckFailed = 11,
/// <summary>The operation failed with no more detailed information.</summary>
Error = 13,
/// <summary>A blocking call was interrupted while waiting and did not run to completion.</summary>
Interrupted = 14,
/// <summary>Timed out while awaiting the result.</summary>
Timeout = 15,
/// <summary>The result was canceled either due to client disconnect or cancel().</summary>
Canceled = 16,
/// <summary>The client attempted to call a method from an API that failed to connect.</summary>
ApiNotConnected = 17,
/// <summary>Invalid credentials were provided.</summary>
AuthApiInvalidCredentials = 3000,
/// <summary>Access is forbidden.</summary>
AuthApiAccessForbidden = 3001,
/// <summary>Error related to the client.</summary>
AuthApiClientError = 3002,
/// <summary>Error related to the server.</summary>
AuthApiServerError = 3003,
/// <summary>Error related to token.</summary>
AuthTokenError = 3004,
/// <summary>Error related to auth URL resolution.</summary>
AuthUrlResolution = 3005
}
}
#endif
\ No newline at end of file
fileFormatVersion: 2
guid: cd54f7a2763f74ce191bdd3efa0a44d5
labels:
- gvh
- gvh_version-0.11.01
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
// <copyright file="CommonTypes.cs" company="Google Inc.">
// Copyright (C) 2014 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
namespace GooglePlayGames.BasicApi
{
/// <summary>
/// A enum describing where game data can be fetched from.
/// </summary>
public enum DataSource
{
/// <summary>
/// Allow a read from either a local cache, or the network.
/// </summary>
/// <remarks> Values from the cache may be
/// stale (potentially producing more write conflicts), but reading from cache may still
/// allow reads to succeed if the device does not have internet access and may complete more
/// quickly (as the reads can occur locally rather requiring network roundtrips).
/// </remarks>
ReadCacheOrNetwork,
/// <summary>
/// Only allow reads from network.
/// </summary>
/// <remarks> This guarantees any returned values were current at the time
/// the read succeeded, but prevents reads from succeeding if the network is unavailable for
/// any reason.
/// </remarks>
ReadNetworkOnly
}
/// <summary> Native response status codes</summary>
/// <remarks> These values are returned by the native SDK API.
/// NOTE: These values are different than the CommonStatusCodes.
/// </remarks>
public enum ResponseStatus
{
/// <summary>The operation was successful.</summary>
Success = 1,
/// <summary>The operation was successful, but the device's cache was used.</summary>
SuccessWithStale = 2,
/// <summary>The application is not licensed to the user.</summary>
LicenseCheckFailed = -1,
/// <summary>An internal error occurred.</summary>
InternalError = -2,
/// <summary>The player is not authorized to perform the operation.</summary>
NotAuthorized = -3,
/// <summary>The installed version of Google Play services is out of date.</summary>
VersionUpdateRequired = -4,
/// <summary>Timed out while awaiting the result.</summary>
Timeout = -5,
///< summary>
/// Constant indicating that the developer does not have access to the friends list, but can
/// call the AskForLoadFriendsResolution API to show a consent dialog.
///</summary>
ResolutionRequired = -6,
}
/// <summary> Native response status codes for UI operations.</summary>
/// <remarks> These values are returned by the native SDK API.
/// </remarks>
public enum UIStatus
{
/// <summary>The result is valid.</summary>
Valid = 1,
/// <summary>An internal error occurred.</summary>
InternalError = -2,
/// <summary>The player is not authorized to perform the operation.</summary>
NotAuthorized = -3,
/// <summary>The installed version of Google Play services is out of date.</summary>
VersionUpdateRequired = -4,
/// <summary>Timed out while awaiting the result.</summary>
Timeout = -5,
/// <summary>UI closed by user.</summary>
UserClosedUI = -6,
UiBusy = -12,
/// <summary>An network error occurred.</summary>
NetworkError = -20,
}
/// <summary>Values specifying the start location for fetching scores.</summary>
public enum LeaderboardStart
{
/// <summary>Start fetching scores from the top of the list.</summary>
TopScores = 1,
/// <summary>Start fetching relative to the player's score.</summary>
PlayerCentered = 2,
}
/// <summary>Values specifying which leaderboard timespan to use.</summary>
public enum LeaderboardTimeSpan
{
/// <summary>Daily scores. The day resets at 11:59 PM PST.</summary>
Daily = 1,
/// <summary>Weekly scores. The week resets at 11:59 PM PST on Sunday.</summary>
Weekly = 2,
/// <summary>All time scores.</summary>
AllTime = 3,
}
/// <summary>Values specifying which leaderboard collection to use.</summary>
public enum LeaderboardCollection
{
/// <summary>Public leaderboards contain the scores of players who are sharing their gameplay publicly.</summary>
Public = 1,
/// <summary>Social leaderboards contain the scores of players in the viewing player's circles.</summary>
Social = 2,
}
public enum FriendsListVisibilityStatus
{
///< summary>
/// Constant indicating that currently it's unknown if the friends list is visible to the
/// game, game can ask for permission from user.
///</summary>
Unknown = 0,
/// Constant indicating that the friends list is currently visible to the game.
Visible = 1,
///< summary>
/// Constant indicating that the developer does not have access to the friends list, but can
/// call the AskForLoadFriendsResolution API to show a consent dialog.
///</summary>
ResolutionRequired = 2,
///< summary>
/// Constant indicating that the friends list is currently unavailable for this user, and it
/// is not possible to request access at this time, either because the user has permanently
/// declined or the friends feature is not available to them. In this state, any attempts to
/// request
/// access to the friends list will be unsuccessful.
///</summary>
Unavailable = 3,
/// <summary>An network error occurred.</summary>
NetworkError = -4,
/// <summary>The player is not authorized to perform the operation.</summary>
NotAuthorized = -5,
}
public enum LoadFriendsStatus
{
/// <summary>An unknown value to return when loadFriends is not available.</summary>
Unknown = 0,
/// <summary>All the friends have been loaded.</summary>
Completed = 1,
/// <summary>There are more friends to load.</summary>
LoadMore = 2,
/// <summary>
/// The game doesn't have permission to access the player's friends list. No friends loaded.
/// </summary>
ResolutionRequired = -3,
/// <summary>An internal error occurred.</summary>
InternalError = -4,
/// <summary>The player is not authorized to perform the operation.</summary>
NotAuthorized = -5,
/// <summary>An network error occurred.</summary>
NetworkError = -6,
}
public class CommonTypesUtil
{
public static bool StatusIsSuccess(ResponseStatus status)
{
return ((int) status) > 0;
}
}
}
fileFormatVersion: 2
guid: 1c5d1cb1974d14c0c8b32fcf00089556
labels:
- gvh
- gvh_version-0.11.01
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
// <copyright file="DummyClient.cs" company="Google Inc.">
// Copyright (C) 2014 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
#if UNITY_ANDROID
namespace GooglePlayGames.BasicApi
{
using System;
using GooglePlayGames.OurUtils;
using UnityEngine.SocialPlatforms;
/// <summary>
/// Dummy client used in Editor.
/// </summary>
/// <remarks>Google Play Game Services are not supported in the Editor
/// environment, so this client is used as a placeholder.
/// </remarks>
public class DummyClient : IPlayGamesClient
{
public void Authenticate(Action<SignInStatus> callback)
{
LogUsage();
if (callback != null)
{
callback(SignInStatus.Canceled);
}
}
public void ManuallyAuthenticate(Action<SignInStatus> callback)
{
LogUsage();
if (callback != null)
{
callback(SignInStatus.Canceled);
}
}
public bool IsAuthenticated()
{
LogUsage();
return false;
}
public void RequestServerSideAccess(bool forceRefreshToken, Action<string> callback)
{
LogUsage();
if (callback != null)
{
callback(null);
}
}
public string GetUserId()
{
LogUsage();
return "DummyID";
}
public void GetPlayerStats(Action<CommonStatusCodes, PlayerStats> callback)
{
LogUsage();
callback(CommonStatusCodes.ApiNotConnected, new PlayerStats());
}
public string GetUserDisplayName()
{
LogUsage();
return "Player";
}
public string GetUserImageUrl()
{
LogUsage();
return null;
}
public void LoadUsers(string[] userIds, Action<IUserProfile[]> callback)
{
LogUsage();
if (callback != null)
{
callback.Invoke(null);
}
}
public void LoadAchievements(Action<Achievement[]> callback)
{
LogUsage();
if (callback != null)
{
callback.Invoke(null);
}
}
public void UnlockAchievement(string achId, Action<bool> callback)
{
LogUsage();
if (callback != null)
{
callback.Invoke(false);
}
}
public void RevealAchievement(string achId, Action<bool> callback)
{
LogUsage();
if (callback != null)
{
callback.Invoke(false);
}
}
public void IncrementAchievement(string achId, int steps, Action<bool> callback)
{
LogUsage();
if (callback != null)
{
callback.Invoke(false);
}
}
public void SetStepsAtLeast(string achId, int steps, Action<bool> callback)
{
LogUsage();
if (callback != null)
{
callback.Invoke(false);
}
}
public void ShowAchievementsUI(Action<UIStatus> callback)
{
LogUsage();
if (callback != null)
{
callback.Invoke(UIStatus.VersionUpdateRequired);
}
}
public void AskForLoadFriendsResolution(Action<UIStatus> callback) {
LogUsage();
if (callback != null) {
callback.Invoke(UIStatus.VersionUpdateRequired);
}
}
public LoadFriendsStatus GetLastLoadFriendsStatus() {
LogUsage();
return LoadFriendsStatus.Unknown;
}
public void LoadFriends(int pageSize, bool forceReload,
Action<LoadFriendsStatus> callback) {
LogUsage();
if (callback != null) {
callback.Invoke(LoadFriendsStatus.Unknown);
}
}
public void LoadMoreFriends(int pageSize, Action<LoadFriendsStatus> callback) {
LogUsage();
if (callback != null) {
callback.Invoke(LoadFriendsStatus.Unknown);
}
}
public void ShowCompareProfileWithAlternativeNameHintsUI(string userId,
string otherPlayerInGameName,
string currentPlayerInGameName,
Action<UIStatus> callback) {
LogUsage();
if (callback != null) {
callback.Invoke(UIStatus.VersionUpdateRequired);
}
}
public void GetFriendsListVisibility(bool forceReload,
Action<FriendsListVisibilityStatus> callback) {
LogUsage();
if (callback != null) {
callback.Invoke(FriendsListVisibilityStatus.Unknown);
}
}
public void ShowLeaderboardUI(
string leaderboardId,
LeaderboardTimeSpan span,
Action<UIStatus> callback)
{
LogUsage();
if (callback != null)
{
callback.Invoke(UIStatus.VersionUpdateRequired);
}
}
public int LeaderboardMaxResults()
{
return 25;
}
public void LoadScores(
string leaderboardId,
LeaderboardStart start,
int rowCount,
LeaderboardCollection collection,
LeaderboardTimeSpan timeSpan,
Action<LeaderboardScoreData> callback)
{
LogUsage();
if (callback != null)
{
callback(new LeaderboardScoreData(
leaderboardId,
ResponseStatus.LicenseCheckFailed));
}
}
public void LoadMoreScores(
ScorePageToken token,
int rowCount,
Action<LeaderboardScoreData> callback)
{
LogUsage();
if (callback != null)
{
callback(new LeaderboardScoreData(
token.LeaderboardId,
ResponseStatus.LicenseCheckFailed));
}
}
public void SubmitScore(string leaderboardId, long score, Action<bool> callback)
{
LogUsage();
if (callback != null)
{
callback.Invoke(false);
}
}
public void SubmitScore(
string leaderboardId,
long score,
string metadata,
Action<bool> callback)
{
LogUsage();
if (callback != null)
{
callback.Invoke(false);
}
}
public SavedGame.ISavedGameClient GetSavedGameClient()
{
LogUsage();
return null;
}
public GooglePlayGames.BasicApi.Events.IEventsClient GetEventsClient()
{
LogUsage();
return null;
}
public void LoadFriends(Action<bool> callback)
{
LogUsage();
callback(false);
}
public IUserProfile[] GetFriends()
{
LogUsage();
return new IUserProfile[0];
}
private static void LogUsage()
{
Logger.d("Received method call on DummyClient - using stub implementation.");
}
}
}
#endif
fileFormatVersion: 2
guid: 2c600182c9892457e92f885549bd838a
labels:
- gvh
- gvh_version-0.11.01
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 672ea858ca3b74efb9d0981849563065
folderAsset: yes
timeCreated: 1435699548
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:
namespace GooglePlayGames.BasicApi.Events
{
internal class Event : IEvent
{
private string mId;
private string mName;
private string mDescription;
private string mImageUrl;
private ulong mCurrentCount;
private EventVisibility mVisibility;
internal Event(string id, string name, string description, string imageUrl,
ulong currentCount, EventVisibility visibility)
{
mId = id;
mName = name;
mDescription = description;
mImageUrl = imageUrl;
mCurrentCount = currentCount;
mVisibility = visibility;
}
public string Id
{
get { return mId; }
}
public string Name
{
get { return mName; }
}
public string Description
{
get { return mDescription; }
}
public string ImageUrl
{
get { return mImageUrl; }
}
public ulong CurrentCount
{
get { return mCurrentCount; }
}
public EventVisibility Visibility
{
get { return mVisibility; }
}
}
}
fileFormatVersion: 2
guid: ce7f6801baead4bbda584bb96882e78b
labels:
- gvh
- gvh_version-0.11.01
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
// <copyright file="IEvent.cs" company="Google Inc.">
// Copyright (C) 2014 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
namespace GooglePlayGames.BasicApi.Events
{
public enum EventVisibility
{
Hidden = 1,
Revealed = 2,
}
/// <summary>
/// Data object representing an Event. <see cref="Native.PInvoke.EventManager"/> for more.
/// </summary>
public interface IEvent
{
/// <summary>
/// The ID of the event.
/// </summary>
string Id { get; }
/// <summary>
/// The name of the event.
/// </summary>
string Name { get; }
/// <summary>
/// The description of the event.
/// </summary>
string Description { get; }
/// <summary>
/// The URL of the image for the event. Empty if there is no image for this event.
/// </summary>
/// <value>The image URL.</value>
string ImageUrl { get; }
/// <summary>
/// The current count for this event.
/// </summary>
ulong CurrentCount { get; }
/// <summary>
/// The visibility of the event.
/// </summary>
EventVisibility Visibility { get; }
}
}
fileFormatVersion: 2
guid: 7e4f4f47218d14208a8ae0f676e1bca4
labels:
- gvh
- gvh_version-0.11.01
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
// <copyright file="IEventsClient.cs" company="Google Inc.">
// Copyright (C) 2014 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
#if UNITY_ANDROID
namespace GooglePlayGames.BasicApi.Events
{
using System;
using System.Collections.Generic;
/// <summary>
/// An interface for interacting with events.
///
/// <para>See online <a href="https://developers.google.com/games/services/common/concepts/events">
/// documentation for Events</a> for more information.</para>
///
/// All callbacks in this interface must be invoked on the game thread.
/// </summary>
public interface IEventsClient
{
/// <summary>
/// Fetches all events defined for this game.
/// </summary>
/// <param name="source">The source of the event (i.e. whether we can return stale cached
/// values).</param>
/// <param name="callback">A callback for the results of the request. The passed list will only
/// be non-empty if the request succeeded. This callback will be invoked on the game thread.
/// </param>
void FetchAllEvents(DataSource source, Action<ResponseStatus, List<IEvent>> callback);
/// <summary>
/// Fetchs the event with the specified ID.
/// </summary>
/// <param name="source">The source of the event (i.e. whether we can return stale cached
/// values).</param>
/// <param name="eventId">The ID of the event.</param>
/// <param name="callback">A callback for the result of the event. If the request failed, the
/// passed event will be null. This callback will be invoked on the game thread.</param>
void FetchEvent(DataSource source, string eventId, Action<ResponseStatus, IEvent> callback);
/// <summary>
/// Increments the indicated event.
/// </summary>
/// <param name="eventId">The ID of the event to increment.</param>
/// <param name="stepsToIncrement">The number of steps to increment by.</param>
void IncrementEvent(string eventId, uint stepsToIncrement);
}
}
#endif
fileFormatVersion: 2
guid: da57ba264ec114c57b8352923847ec34
labels:
- gvh
- gvh_version-0.11.01
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
// <copyright file="IPlayGamesClient.cs" company="Google Inc.">
// Copyright (C) 2014 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
#if UNITY_ANDROID
namespace GooglePlayGames.BasicApi
{
using System;
using UnityEngine.SocialPlatforms;
/// <summary>
/// Defines an abstract interface for a Play Games Client.
/// </summary>
/// <remarks>Concrete implementations
/// might be, for example, the client for Android or for iOS. One fundamental concept
/// that implementors of this class must adhere to is stable authentication state.
/// This means that once Authenticate() returns true through its callback, the user is
/// considered to be forever after authenticated while the app is running. The implementation
/// must make sure that this is the case -- for example, it must try to silently
/// re-authenticate the user if authentication is lost or wait for the authentication
/// process to get fixed if it is temporarily in a bad state (such as when the
/// Activity in Android has just been brought to the foreground and the connection to
/// the Games services hasn't yet been established). To the user of this
/// interface, once the user is authenticated, they're forever authenticated.
/// Unless, of course, there is an unusual permanent failure such as the underlying
/// service dying, in which it's acceptable that API method calls will fail.
///
/// <para>All methods can be called from the game thread. The user of this interface
/// DOES NOT NEED to call them from the UI thread of the game. Transferring to the UI
/// thread when necessary is a responsibility of the implementors of this interface.</para>
///
/// <para>CALLBACKS: all callbacks must be invoked in Unity's main thread.
/// Implementors of this interface must guarantee that (suggestion: use
/// <see cref="PlayGamesHelperObject.RunOnGameThread(System.Action)"/>).</para>
/// </remarks>
public interface IPlayGamesClient
{
/// <summary>
/// Returns the result of the automatic sign-in attempt.
/// </summary>
/// <remarks>This returns the result
/// </remarks>
/// <param name="callback">Callback</param>
void Authenticate(Action<SignInStatus> callback);
/// <summary>
/// Manually requests that your game performs sign in with Play Games Services.
/// </summary>
/// <remarks>
/// Note that a sign-in attempt will be made automatically when your game's application
/// started. For this reason most games will not need to manually request to perform sign-in
/// unless the automatic sign-in attempt failed and your game requires access to Play Games
/// Services.
/// </remarks>
/// <param name="callback"></param>
void ManuallyAuthenticate(Action<SignInStatus> callback);
/// <summary>
/// Returns whether or not user is authenticated.
/// </summary>
/// <returns><c>true</c> if the user is authenticated; otherwise, <c>false</c>.</returns>
bool IsAuthenticated();
/// <summary>
/// Requests server-side access to Player Games Services for the currently signed in player.
/// </summary>
/// When requested an authorization code is returned that can be used by your game-server to
/// exchange for an access token and conditionally a refresh token (when {@code forceRefreshToken}
/// is true). The access token may then be used by your game-server to access the Play Games
/// Services web APIs. This is commonly used to complete a sign-in flow by verifying the Play Games
/// Services player id.
///
/// <p>If {@code forceRefreshToken} is true, when exchanging the authorization code a refresh token
/// will be returned in addition to the access token. The refresh token allows the game-server to
/// request additional access tokens, allowing your game-server to continue accesses Play Games
/// Services while the user is not actively playing your app.
/// <remarks>
///
/// </remarks>
/// <param name="forceRefreshToken">If {@code true} when the returned authorization code is exchanged a
/// refresh token will be included in addition to an access token.</param>
/// <param name="callback"></param>
void RequestServerSideAccess(bool forceRefreshToken, Action<string> callback);
/// <summary>
/// Returns the authenticated user's ID. Note that this value may change if a user signs
/// on and signs in with a different account.
/// </summary>
/// <returns>The user's ID, <code>null</code> if the user is not logged in.</returns>
string GetUserId();
/// <summary>
/// Loads friends of the authenticated user. This loads the entire list of friends.
/// </summary>
/// <param name="callback">Callback invoked when complete. bool argument
/// indicates success.</param>
void LoadFriends(Action<bool> callback);
/// <summary>
/// Returns a human readable name for the user, if they are logged in.
/// </summary>
/// <returns>The user's human-readable name. <code>null</code> if they are not logged
/// in</returns>
string GetUserDisplayName();
/// <summary>
/// Returns the user's avatar url, if they are logged in and have an avatar.
/// </summary>
/// <returns>The URL to load the avatar image. <code>null</code> if they are not logged
/// in</returns>
string GetUserImageUrl();
/// <summary>Gets the player stats.</summary>
/// <param name="callback">Callback for response.</param>
void GetPlayerStats(Action<CommonStatusCodes, PlayerStats> callback);
/// <summary>
/// Loads the users specified. This is mainly used by the leaderboard
/// APIs to get the information of a high scorer.
/// </summary>
/// <param name="userIds">User identifiers.</param>
/// <param name="callback">Callback.</param>
void LoadUsers(string[] userIds, Action<IUserProfile[]> callback);
/// <summary>
/// Loads the achievements for the current signed in user and invokes
/// the callback.
/// </summary>
void LoadAchievements(Action<Achievement[]> callback);
/// <summary>
/// Unlocks the achievement with the passed identifier.
/// </summary>
/// <remarks>If the operation succeeds, the callback
/// will be invoked on the game thread with <code>true</code>. If the operation fails, the
/// callback will be invoked with <code>false</code>. This operation will immediately fail if
/// the user is not authenticated (i.e. the callback will immediately be invoked with
/// <code>false</code>). If the achievement is already unlocked, this call will
/// succeed immediately.
/// </remarks>
/// <param name="achievementId">The ID of the achievement to unlock.</param>
/// <param name="successOrFailureCalllback">Callback used to indicate whether the operation
/// succeeded or failed.</param>
void UnlockAchievement(string achievementId, Action<bool> successOrFailureCalllback);
/// <summary>
/// Reveals the achievement with the passed identifier.
/// </summary>
/// <remarks>If the operation succeeds, the callback
/// will be invoked on the game thread with <code>true</code>. If the operation fails, the
/// callback will be invoked with <code>false</code>. This operation will immediately fail if
/// the user is not authenticated (i.e. the callback will immediately be invoked with
/// <code>false</code>). If the achievement is already in a revealed state, this call will
/// succeed immediately.
/// </remarks>
/// <param name="achievementId">The ID of the achievement to reveal.</param>
/// <param name="successOrFailureCalllback">Callback used to indicate whether the operation
/// succeeded or failed.</param>
void RevealAchievement(string achievementId, Action<bool> successOrFailureCalllback);
/// <summary>
/// Increments the achievement with the passed identifier.
/// </summary>
/// <remarks>If the operation succeeds, the
/// callback will be invoked on the game thread with <code>true</code>. If the operation
/// fails, the callback will be invoked with <code>false</code>. This operation will
/// immediately fail if the user is not authenticated (i.e. the callback will immediately be
/// invoked with <code>false</code>).
/// </remarks>
/// <param name="achievementId">The ID of the achievement to increment.</param>
/// <param name="steps">The number of steps to increment by.</param>
/// <param name="successOrFailureCalllback">Callback used to indicate whether the operation
/// succeeded or failed.</param>
void IncrementAchievement(string achievementId, int steps,
Action<bool> successOrFailureCalllback);
/// <summary>
/// Set an achievement to have at least the given number of steps completed.
/// </summary>
/// <remarks>
/// Calling this method while the achievement already has more steps than
/// the provided value is a no-op. Once the achievement reaches the
/// maximum number of steps, the achievement is automatically unlocked,
/// and any further mutation operations are ignored.
/// </remarks>
/// <param name="achId">Ach identifier.</param>
/// <param name="steps">Steps.</param>
/// <param name="callback">Callback.</param>
void SetStepsAtLeast(string achId, int steps, Action<bool> callback);
/// <summary>
/// Shows the appropriate platform-specific achievements UI.
/// <param name="callback">The callback to invoke when complete. If null,
/// no callback is called. </param>
/// </summary>
void ShowAchievementsUI(Action<UIStatus> callback);
/// <summary>
/// Shows the appropriate platform-specific friends sharing UI.
/// <param name="callback">The callback to invoke when complete. If null,
/// no callback is called. </param>
/// </summary>
void AskForLoadFriendsResolution(Action<UIStatus> callback);
/// <summary>
/// Returns the latest LoadFriendsStatus obtained from loading friends.
/// </summary>
LoadFriendsStatus GetLastLoadFriendsStatus();
/// <summary>
/// Shows the Play Games Player Profile UI for a specific user identifier.
/// </summary>
/// <param name="otherUserId">User Identifier.</param>
/// <param name="otherPlayerInGameName">
/// The game's own display name of the player referred to by userId.
/// </param>
/// <param name="currentPlayerInGameName">
/// The game's own display name of the current player.
/// </param>
/// <param name="callback">Callback invoked upon completion.</param>
void ShowCompareProfileWithAlternativeNameHintsUI(
string otherUserId, string otherPlayerInGameName, string currentPlayerInGameName,
Action<UIStatus> callback);
/// <summary>
/// Returns if the user has allowed permission for the game to access the friends list.
/// </summary>
/// <param name="forceReload">If true, this call will clear any locally cached data and
/// attempt to fetch the latest data from the server. Normally, this should be set to {@code
/// false} to gain advantages of data caching.</param> <param name="callback">Callback
/// invoked upon completion.</param>
void GetFriendsListVisibility(bool forceReload, Action<FriendsListVisibilityStatus> callback);
/// <summary>
/// Loads the first page of the user's friends
/// </summary>
/// <param name="pageSize">
/// The number of entries to request for this initial page. Note that if cached
/// data already exists, the returned buffer may contain more than this size, but it is
/// guaranteed to contain at least this many if the collection contains enough records.
/// </param>
/// <param name="forceReload">
/// If true, this call will clear any locally cached data and attempt to
/// fetch the latest data from the server. This would commonly be used for something like a
/// user-initiated refresh. Normally, this should be set to {@code false} to gain advantages
/// of data caching.</param>
/// <param name="callback">Callback invoked upon completion.</param>
void LoadFriends(int pageSize, bool forceReload, Action<LoadFriendsStatus> callback);
/// <summary>
/// Loads the friends list page
/// </summary>
/// <param name="pageSize">
/// The number of entries to request for this page. Note that if cached data already
/// exists, the returned buffer may contain more than this size, but it is guaranteed
/// to contain at least this many if the collection contains enough records.
/// </param>
/// <param name="callback"></param>
void LoadMoreFriends(int pageSize, Action<LoadFriendsStatus> callback);
/// <summary>
/// Shows the leaderboard UI for a specific leaderboard.
/// </summary>
/// <remarks>If the passed ID is <code>null</code>, all leaderboards are displayed.
/// </remarks>
/// <param name="leaderboardId">The leaderboard to display. <code>null</code> to display
/// all.</param>
/// <param name="span">Timespan to display for the leaderboard</param>
/// <param name="callback">If non-null, the callback to invoke when the
/// leaderboard is dismissed.
/// </param>
void ShowLeaderboardUI(string leaderboardId, LeaderboardTimeSpan span,
Action<UIStatus> callback);
/// <summary>
/// Loads the score data for the given leaderboard.
/// </summary>
/// <param name="leaderboardId">Leaderboard identifier.</param>
/// <param name="start">Start indicating the top scores or player centric</param>
/// <param name="rowCount">max number of scores to return. non-positive indicates
/// no rows should be returned. This causes only the summary info to
/// be loaded. This can be limited
/// by the SDK.</param>
/// <param name="collection">leaderboard collection: public or social</param>
/// <param name="timeSpan">leaderboard timespan</param>
/// <param name="callback">callback with the scores, and a page token.
/// The token can be used to load next/prev pages.</param>
void LoadScores(string leaderboardId, LeaderboardStart start, int rowCount,
LeaderboardCollection collection, LeaderboardTimeSpan timeSpan,
Action<LeaderboardScoreData> callback);
/// <summary>
/// Loads the more scores for the leaderboard.
/// </summary>
/// <remarks>The token is accessed
/// by calling LoadScores() with a positive row count.
/// </remarks>
/// <param name="token">Token for tracking the score loading.</param>
/// <param name="rowCount">max number of scores to return.
/// This can be limited by the SDK.</param>
/// <param name="callback">Callback.</param>
void LoadMoreScores(ScorePageToken token, int rowCount,
Action<LeaderboardScoreData> callback);
/// <summary>
/// Returns the max number of scores returned per call.
/// </summary>
/// <returns>The max results.</returns>
int LeaderboardMaxResults();
/// <summary>
/// Submits the passed score to the passed leaderboard.
/// </summary>
/// <remarks>This operation will immediately fail
/// if the user is not authenticated (i.e. the callback will immediately be invoked with
/// <code>false</code>).
/// </remarks>
/// <param name="leaderboardId">Leaderboard identifier.</param>
/// <param name="score">Score.</param>
/// <param name="successOrFailureCalllback">Callback used to indicate whether the operation
/// succeeded or failed.</param>
void SubmitScore(string leaderboardId, long score, Action<bool> successOrFailureCalllback);
/// <summary>
/// Submits the score for the currently signed-in player.
/// </summary>
/// <param name="score">Score.</param>
/// <param name="leaderboardId">leaderboard id.</param>
/// <param name="metadata">metadata about the score.</param>
/// <param name="successOrFailureCalllback">Callback upon completion.</param>
void SubmitScore(string leaderboardId, long score, string metadata,
Action<bool> successOrFailureCalllback);
/// <summary>
/// Gets the saved game client.
/// </summary>
/// <returns>The saved game client.</returns>
SavedGame.ISavedGameClient GetSavedGameClient();
/// <summary>
/// Gets the events client.
/// </summary>
/// <returns>The events client.</returns>
Events.IEventsClient GetEventsClient();
IUserProfile[] GetFriends();
}
}
#endif
fileFormatVersion: 2
guid: 9138e04e4459148c680055b40ad324c0
labels:
- gvh
- gvh_version-0.11.01
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
// <copyright file="LeaderboardScoreData.cs" company="Google Inc.">
// Copyright (C) 2015 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
#if UNITY_ANDROID
namespace GooglePlayGames.BasicApi
{
using System.Collections.Generic;
using UnityEngine.SocialPlatforms;
/// <summary>
/// Leaderboard score data. This is the callback data
/// when loading leaderboard scores. There are several SDK
/// API calls needed to be made to collect all the required data,
/// so this class is used to simplify the response.
/// </summary>
public class LeaderboardScoreData
{
private string mId;
private ResponseStatus mStatus;
private ulong mApproxCount;
private string mTitle;
private IScore mPlayerScore;
private ScorePageToken mPrevPage;
private ScorePageToken mNextPage;
private List<PlayGamesScore> mScores = new List<PlayGamesScore>();
internal LeaderboardScoreData(string leaderboardId)
{
mId = leaderboardId;
}
internal LeaderboardScoreData(string leaderboardId, ResponseStatus status)
{
mId = leaderboardId;
mStatus = status;
}
public bool Valid
{
get
{
return mStatus == ResponseStatus.Success ||
mStatus == ResponseStatus.SuccessWithStale;
}
}
public ResponseStatus Status
{
get { return mStatus; }
internal set { mStatus = value; }
}
public ulong ApproximateCount
{
get { return mApproxCount; }
internal set { mApproxCount = value; }
}
public string Title
{
get { return mTitle; }
internal set { mTitle = value; }
}
public string Id
{
get { return mId; }
internal set { mId = value; }
}
public IScore PlayerScore
{
get { return mPlayerScore; }
internal set { mPlayerScore = value; }
}
public IScore[] Scores
{
get { return mScores.ToArray(); }
}
internal int AddScore(PlayGamesScore score)
{
mScores.Add(score);
return mScores.Count;
}
public ScorePageToken PrevPageToken
{
get { return mPrevPage; }
internal set { mPrevPage = value; }
}
public ScorePageToken NextPageToken
{
get { return mNextPage; }
internal set { mNextPage = value; }
}
public override string ToString()
{
return string.Format("[LeaderboardScoreData: mId={0}, " +
" mStatus={1}, mApproxCount={2}, mTitle={3}]",
mId, mStatus, mApproxCount, mTitle);
}
}
}
#endif
\ No newline at end of file
fileFormatVersion: 2
guid: 8e369c64e8c9f4571a8847f37848c37e
labels:
- gvh
- gvh_version-0.11.01
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: c980790a380df4850b17a208e544d062
folderAsset: yes
timeCreated: 1435699549
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:
// <copyright file="AdvertisingResult.cs" company="Google Inc.">
// Copyright (C) 2014 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
namespace GooglePlayGames.BasicApi.Nearby
{
using System;
using System.Collections.Generic;
using GooglePlayGames.OurUtils;
public struct AdvertisingResult
{
private readonly ResponseStatus mStatus;
private readonly string mLocalEndpointName;
public AdvertisingResult(ResponseStatus status, string localEndpointName)
{
this.mStatus = status;
this.mLocalEndpointName = Misc.CheckNotNull(localEndpointName);
}
public bool Succeeded
{
get { return mStatus == ResponseStatus.Success; }
}
public ResponseStatus Status
{
get { return mStatus; }
}
public string LocalEndpointName
{
get { return mLocalEndpointName; }
}
}
}
\ No newline at end of file
fileFormatVersion: 2
guid: 941324a6338664af6a9faf5b88cad408
labels:
- gvh
- gvh_version-0.11.01
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
// <copyright file="ConnectionRequest.cs" company="Google Inc.">
// Copyright (C) 2014 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
namespace GooglePlayGames.BasicApi.Nearby
{
using GooglePlayGames.OurUtils;
public struct ConnectionRequest
{
private readonly EndpointDetails mRemoteEndpoint;
private readonly byte[] mPayload;
public ConnectionRequest(string remoteEndpointId,
string remoteEndpointName, string serviceId, byte[] payload)
{
Logger.d("Constructing ConnectionRequest");
mRemoteEndpoint = new EndpointDetails(remoteEndpointId, remoteEndpointName, serviceId);
this.mPayload = Misc.CheckNotNull(payload);
}
public EndpointDetails RemoteEndpoint
{
get { return mRemoteEndpoint; }
}
public byte[] Payload
{
get { return mPayload; }
}
}
}
\ No newline at end of file
fileFormatVersion: 2
guid: c7f9bb6b249224f99ad05a87d3e4ee34
labels:
- gvh
- gvh_version-0.11.01
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
// <copyright file="ConnectionResponse.cs" company="Google Inc.">
// Copyright (C) 2014 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
namespace GooglePlayGames.BasicApi.Nearby
{
using GooglePlayGames.OurUtils;
public struct ConnectionResponse
{
private static readonly byte[] EmptyPayload = new byte[0];
public enum Status
{
Accepted,
Rejected,
ErrorInternal,
ErrorNetworkNotConnected,
ErrorEndpointNotConnected,
ErrorAlreadyConnected
}
private readonly long mLocalClientId;
private readonly string mRemoteEndpointId;
private readonly Status mResponseStatus;
private readonly byte[] mPayload;
private ConnectionResponse(long localClientId, string remoteEndpointId, Status code,
byte[] payload)
{
this.mLocalClientId = localClientId;
this.mRemoteEndpointId = Misc.CheckNotNull(remoteEndpointId);
this.mResponseStatus = code;
this.mPayload = Misc.CheckNotNull(payload);
}
public long LocalClientId
{
get { return mLocalClientId; }
}
public string RemoteEndpointId
{
get { return mRemoteEndpointId; }
}
public Status ResponseStatus
{
get { return mResponseStatus; }
}
public byte[] Payload
{
get { return mPayload; }
}
public static ConnectionResponse Rejected(long localClientId, string remoteEndpointId)
{
return new ConnectionResponse(localClientId, remoteEndpointId, Status.Rejected,
EmptyPayload);
}
public static ConnectionResponse NetworkNotConnected(long localClientId, string remoteEndpointId)
{
return new ConnectionResponse(localClientId, remoteEndpointId, Status.ErrorNetworkNotConnected,
EmptyPayload);
}
public static ConnectionResponse InternalError(long localClientId, string remoteEndpointId)
{
return new ConnectionResponse(localClientId, remoteEndpointId, Status.ErrorInternal,
EmptyPayload);
}
public static ConnectionResponse EndpointNotConnected(long localClientId, string remoteEndpointId)
{
return new ConnectionResponse(localClientId, remoteEndpointId, Status.ErrorEndpointNotConnected,
EmptyPayload);
}
public static ConnectionResponse Accepted(long localClientId, string remoteEndpointId,
byte[] payload)
{
return new ConnectionResponse(localClientId, remoteEndpointId, Status.Accepted,
payload);
}
public static ConnectionResponse AlreadyConnected(long localClientId,
string remoteEndpointId)
{
return new ConnectionResponse(localClientId, remoteEndpointId,
Status.ErrorAlreadyConnected,
EmptyPayload);
}
}
}
\ No newline at end of file
fileFormatVersion: 2
guid: ad6611af8d0204d0d8922a327d3d9ec0
labels:
- gvh
- gvh_version-0.11.01
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
// <copyright file="DummyNearbyConnectionClient.cs" company="Google Inc.">
// Copyright (C) 2014 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
#if UNITY_ANDROID
namespace GooglePlayGames.BasicApi.Nearby
{
using UnityEngine;
public class DummyNearbyConnectionClient : INearbyConnectionClient
{
public int MaxUnreliableMessagePayloadLength()
{
return NearbyConnectionConfiguration.MaxUnreliableMessagePayloadLength;
}
public int MaxReliableMessagePayloadLength()
{
return NearbyConnectionConfiguration.MaxReliableMessagePayloadLength;
}
public void SendReliable(System.Collections.Generic.List<string> recipientEndpointIds, byte[] payload)
{
OurUtils.Logger.d("SendReliable called from dummy implementation");
}
public void SendUnreliable(System.Collections.Generic.List<string> recipientEndpointIds, byte[] payload)
{
OurUtils.Logger.d("SendUnreliable called from dummy implementation");
}
public void StartAdvertising(string name, System.Collections.Generic.List<string> appIdentifiers,
System.TimeSpan? advertisingDuration, System.Action<AdvertisingResult> resultCallback,
System.Action<ConnectionRequest> connectionRequestCallback)
{
AdvertisingResult obj = new AdvertisingResult(ResponseStatus.LicenseCheckFailed, string.Empty);
resultCallback.Invoke(obj);
}
public void StopAdvertising()
{
OurUtils.Logger.d("StopAvertising in dummy implementation called");
}
public void SendConnectionRequest(string name, string remoteEndpointId, byte[] payload,
System.Action<ConnectionResponse> responseCallback, IMessageListener listener)
{
OurUtils.Logger.d("SendConnectionRequest called from dummy implementation");
if (responseCallback != null)
{
ConnectionResponse obj = ConnectionResponse.Rejected(0, string.Empty);
responseCallback.Invoke(obj);
}
}
public void AcceptConnectionRequest(string remoteEndpointId, byte[] payload, IMessageListener listener)
{
OurUtils.Logger.d("AcceptConnectionRequest in dummy implementation called");
}
public void StartDiscovery(string serviceId, System.TimeSpan? advertisingTimeout, IDiscoveryListener listener)
{
OurUtils.Logger.d("StartDiscovery in dummy implementation called");
}
public void StopDiscovery(string serviceId)
{
OurUtils.Logger.d("StopDiscovery in dummy implementation called");
}
public void RejectConnectionRequest(string requestingEndpointId)
{
OurUtils.Logger.d("RejectConnectionRequest in dummy implementation called");
}
public void DisconnectFromEndpoint(string remoteEndpointId)
{
OurUtils.Logger.d("DisconnectFromEndpoint in dummy implementation called");
}
public void StopAllConnections()
{
OurUtils.Logger.d("StopAllConnections in dummy implementation called");
}
public string LocalEndpointId()
{
return string.Empty;
}
public string LocalDeviceId()
{
return "DummyDevice";
}
public string GetAppBundleId()
{
return "dummy.bundle.id";
}
public string GetServiceId()
{
return "dummy.service.id";
}
}
}
#endif
\ No newline at end of file
fileFormatVersion: 2
guid: 9b3f34a2bba13428789d02b53fd89a47
labels:
- gvh
- gvh_version-0.11.01
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
// <copyright file="EndpointDetails.cs" company="Google Inc.">
// Copyright (C) 2014 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
namespace GooglePlayGames.BasicApi.Nearby
{
using GooglePlayGames.OurUtils;
public struct EndpointDetails
{
private readonly string mEndpointId;
private readonly string mName;
private readonly string mServiceId;
public EndpointDetails(string endpointId, string name, string serviceId)
{
this.mEndpointId = Misc.CheckNotNull(endpointId);
this.mName = Misc.CheckNotNull(name);
this.mServiceId = Misc.CheckNotNull(serviceId);
}
public string EndpointId
{
get { return mEndpointId; }
}
public string Name
{
get { return mName; }
}
public string ServiceId
{
get { return mServiceId; }
}
}
}
\ No newline at end of file
fileFormatVersion: 2
guid: 9d9a087b0e20d4752b24f33a4a2bf977
labels:
- gvh
- gvh_version-0.11.01
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
// <copyright file="INearbyConnectionClient.cs" company="Google Inc.">
// Copyright (C) 2014 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
namespace GooglePlayGames.BasicApi.Nearby
{
using System;
using System.Collections.Generic;
// move this inside IMessageListener and IDiscoveryListener are always declared.
#if UNITY_ANDROID
public interface INearbyConnectionClient
{
int MaxUnreliableMessagePayloadLength();
int MaxReliableMessagePayloadLength();
void SendReliable(List<string> recipientEndpointIds, byte[] payload);
void SendUnreliable(List<string> recipientEndpointIds, byte[] payload);
void StartAdvertising(string name, List<string> appIdentifiers,
TimeSpan? advertisingDuration, Action<AdvertisingResult> resultCallback,
Action<ConnectionRequest> connectionRequestCallback);
void StopAdvertising();
void SendConnectionRequest(string name, string remoteEndpointId, byte[] payload,
Action<ConnectionResponse> responseCallback, IMessageListener listener);
void AcceptConnectionRequest(string remoteEndpointId, byte[] payload,
IMessageListener listener);
void StartDiscovery(string serviceId, TimeSpan? advertisingTimeout,
IDiscoveryListener listener);
void StopDiscovery(string serviceId);
void RejectConnectionRequest(string requestingEndpointId);
void DisconnectFromEndpoint(string remoteEndpointId);
void StopAllConnections();
string GetAppBundleId();
string GetServiceId();
}
#endif
public interface IMessageListener
{
void OnMessageReceived(string remoteEndpointId, byte[] data,
bool isReliableMessage);
void OnRemoteEndpointDisconnected(string remoteEndpointId);
}
public interface IDiscoveryListener
{
void OnEndpointFound(EndpointDetails discoveredEndpoint);
void OnEndpointLost(string lostEndpointId);
}
}
\ No newline at end of file
fileFormatVersion: 2
guid: cb64b5b444dd34de5bd308c7eed6e509
labels:
- gvh
- gvh_version-0.11.01
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
// <copyright file="NearbyConnectionConfiguration.cs" company="Google Inc.">
// Copyright (C) 2014 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
namespace GooglePlayGames.BasicApi.Nearby
{
using System;
using GooglePlayGames.OurUtils;
public enum InitializationStatus
{
Success,
VersionUpdateRequired,
InternalError
}
public struct NearbyConnectionConfiguration
{
public const int MaxUnreliableMessagePayloadLength = 1168;
public const int MaxReliableMessagePayloadLength = 4096;
private readonly Action<InitializationStatus> mInitializationCallback;
private readonly long mLocalClientId;
public NearbyConnectionConfiguration(Action<InitializationStatus> callback,
long localClientId)
{
this.mInitializationCallback = Misc.CheckNotNull(callback);
this.mLocalClientId = localClientId;
}
public long LocalClientId
{
get { return mLocalClientId; }
}
public Action<InitializationStatus> InitializationCallback
{
get { return mInitializationCallback; }
}
}
}
\ No newline at end of file
fileFormatVersion: 2
guid: 968ac90e4a9094a4a92df9da1ee1f884
labels:
- gvh
- gvh_version-0.11.01
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
// <copyright file="Player.cs" company="Google Inc.">
// Copyright (C) 2014 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
#if UNITY_ANDROID
namespace GooglePlayGames.BasicApi
{
/// <summary>
/// Represents a player. A player is different from a participant! The participant is
/// an entity that takes part in a particular match; a Player is a real-world person
/// (tied to a Games account). The player exists across matches, the Participant
/// only exists in the context of a particular match.
/// </summary>
public class Player : PlayGamesUserProfile
{
internal Player(string displayName, string playerId, string avatarUrl)
: base(displayName, playerId, avatarUrl)
{
}
}
}
#endif
fileFormatVersion: 2
guid: a6dfb529ed3bfc58ea80e1e100af33fd
labels:
- gvh
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
// <copyright file="Player.cs" company="Google Inc.">
// Copyright (C) 2014 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
#if UNITY_ANDROID
namespace GooglePlayGames.BasicApi
{
/// <summary>
/// Represents a player, a real-world person (tied to a Games account).
/// </summary>
public class PlayerProfile : PlayGamesUserProfile
{
internal PlayerProfile(string displayName, string playerId, string avatarUrl, bool isFriend) : base(displayName,
playerId, avatarUrl, isFriend)
{
}
}
}
#endif
fileFormatVersion: 2
guid: 12cfec295ecf76a6fb0d0d48f59d374c
labels:
- gvh
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
// <copyright file="PlayerStats.cs" company="Google Inc.">
// Copyright (C) 2015 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
#if UNITY_ANDROID
namespace GooglePlayGames.BasicApi
{
using System;
/// <summary>
/// Player stats. See https://developers.google.com/games/services/android/stats
/// </summary>
public class PlayerStats
{
private static float UNSET_VALUE = -1.0f;
public PlayerStats(
int numberOfPurchases,
float avgSessionLength,
int daysSinceLastPlayed,
int numberOfSessions,
float sessPercentile,
float spendPercentile,
float spendProbability,
float churnProbability,
float highSpenderProbability,
float totalSpendNext28Days)
{
mValid = true;
mNumberOfPurchases = numberOfPurchases;
mAvgSessionLength = avgSessionLength;
mDaysSinceLastPlayed = daysSinceLastPlayed;
mNumberOfSessions = numberOfSessions;
mSessPercentile = sessPercentile;
mSpendPercentile = spendPercentile;
mSpendProbability = spendProbability;
mChurnProbability = churnProbability;
mHighSpenderProbability = highSpenderProbability;
mTotalSpendNext28Days = totalSpendNext28Days;
}
public PlayerStats()
{
mValid = false;
}
private bool mValid;
private int mNumberOfPurchases;
private float mAvgSessionLength;
private int mDaysSinceLastPlayed;
private int mNumberOfSessions;
private float mSessPercentile;
private float mSpendPercentile;
private float mSpendProbability;
private float mChurnProbability;
private float mHighSpenderProbability;
private float mTotalSpendNext28Days;
/// <summary>
/// If this PlayerStats object is valid (i.e. successfully retrieved from games services).
/// </summary>
/// <remarks>
/// Note that a PlayerStats with all stats unset may still be valid.
/// </remarks>
public bool Valid
{
get { return mValid; }
}
/// <summary>
/// The number of in-app purchases.
/// </summary>
public int NumberOfPurchases
{
get { return mNumberOfPurchases; }
}
/// <summary>
/// The length of the avg session in minutes.
/// </summary>
public float AvgSessionLength
{
get { return mAvgSessionLength; }
}
/// <summary>
/// The days since last played.
/// </summary>
public int DaysSinceLastPlayed
{
get { return mDaysSinceLastPlayed; }
}
/// <summary>
/// The number of sessions based on sign-ins.
/// </summary>
public int NumberOfSessions
{
get { return mNumberOfSessions; }
}
/// <summary>
/// The approximation of sessions percentile for the player.
/// </summary>
/// <remarks>
/// This value is given as a decimal value between 0 and 1 (inclusive).
/// It indicates how many sessions the current player has
/// played in comparison to the rest of this game's player base.
/// Higher numbers indicate that this player has played more sessions.
/// A return value less than zero indicates this value is not available.
/// </remarks>
public float SessPercentile
{
get { return mSessPercentile; }
}
/// <summary>
/// The approximate spend percentile of the player.
/// </summary>
/// <remarks>
/// This value is given as a decimal value between 0 and 1 (inclusive).
/// It indicates how much the current player has spent in
/// comparison to the rest of this game's player base. Higher
/// numbers indicate that this player has spent more.
/// A return value less than zero indicates this value is not available.
/// </remarks>
public float SpendPercentile
{
get { return mSpendPercentile; }
}
/// <summary>
/// The approximate probability of the player choosing to spend in this game.
/// </summary>
/// <remarks>
/// This value is given as a decimal value between 0 and 1 (inclusive).
/// Higher values indicate that a player is more likely to spend.
/// A return value less than zero indicates this value is not available.
/// </remarks>
public float SpendProbability
{
get { return mSpendProbability; }
}
/// <summary>
/// The approximate probability of the player not returning to play the game.
/// </summary>
/// <remarks>
/// Higher values indicate that a player is less likely to return.
/// A return value less than zero indicates this value is not available.
/// </remarks>
public float ChurnProbability
{
get { return mChurnProbability; }
}
/// <summary>
/// The high spender probability of this player.
/// </summary>
public float HighSpenderProbability
{
get { return mHighSpenderProbability; }
}
/// <summary>
/// The predicted total spend of this player over the next 28 days.
/// </summary>
public float TotalSpendNext28Days
{
get { return mTotalSpendNext28Days; }
}
/// <summary>
/// Determines whether this instance has NumberOfPurchases.
/// </summary>
/// <returns><c>true</c> if this instance has NumberOfPurchases; otherwise, <c>false</c>.</returns>
public bool HasNumberOfPurchases()
{
return NumberOfPurchases != (int) UNSET_VALUE;
}
/// <summary>
/// Determines whether this instance has AvgSessionLength.
/// </summary>
/// <returns><c>true</c> if this instance has AvgSessionLength; otherwise, <c>false</c>.</returns>
public bool HasAvgSessionLength()
{
return AvgSessionLength != UNSET_VALUE;
}
/// <summary>
/// Determines whether this instance has DaysSinceLastPlayed.
/// </summary>
/// <returns><c>true</c> if this instance has DaysSinceLastPlayed; otherwise, <c>false</c>.</returns>
public bool HasDaysSinceLastPlayed()
{
return DaysSinceLastPlayed != (int) UNSET_VALUE;
}
/// <summary>
/// Determines whether this instance has NumberOfSessions.
/// </summary>
/// <returns><c>true</c> if this instance has NumberOfSessions; otherwise, <c>false</c>.</returns>
public bool HasNumberOfSessions()
{
return NumberOfSessions != (int) UNSET_VALUE;
}
/// <summary>
/// Determines whether this instance has SessPercentile.
/// </summary>
/// <returns><c>true</c> if this instance has SessPercentile; otherwise, <c>false</c>.</returns>
public bool HasSessPercentile()
{
return SessPercentile != UNSET_VALUE;
}
/// <summary>
/// Determines whether this instance has SpendPercentile.
/// </summary>
/// <returns><c>true</c> if this instance has SpendPercentile; otherwise, <c>false</c>.</returns>
public bool HasSpendPercentile()
{
return SpendPercentile != UNSET_VALUE;
}
/// <summary>
/// Determines whether this instance has ChurnProbability.
/// </summary>
/// <returns><c>true</c> if this instance has ChurnProbability; otherwise, <c>false</c>.</returns>
public bool HasChurnProbability()
{
return ChurnProbability != UNSET_VALUE;
}
/// <summary>
/// Determines whether this instance has HighSpenderProbability.
/// </summary>
/// <returns><c>true</c> if this instance has HighSpenderProbability; otherwise, <c>false</c>.</returns>
public bool HasHighSpenderProbability()
{
return HighSpenderProbability != UNSET_VALUE;
}
/// <summary>
/// Determines whether this instance has TotalSpendNext28Days.
/// </summary>
/// <returns><c>true</c> if this instance has TotalSpendNext28Days; otherwise, <c>false</c>.</returns>
public bool HasTotalSpendNext28Days()
{
return TotalSpendNext28Days != UNSET_VALUE;
}
}
}
#endif
\ No newline at end of file
fileFormatVersion: 2
guid: 0cf73f44d6d524deab1717d6e71e2c6d
labels:
- gvh
- gvh_version-0.11.01
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 1bc47bd5631b849f88f2785c2d44019b
folderAsset: yes
timeCreated: 1435699548
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:
// <copyright file="ISavedGameClient.cs" company="Google Inc.">
// Copyright (C) 2014 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
namespace GooglePlayGames.BasicApi.SavedGame
{
using System;
using System.Collections.Generic;
/// <summary>
/// An enum for the different strategies that can be used to resolve saved game conflicts (i.e.
/// conflicts produced by two or more separate writes to the same saved game at once).
/// </summary>
public enum ConflictResolutionStrategy
{
/// <summary>
/// Choose which saved game should be used on the basis of which one has the longest recorded
/// play time. In other words, in the case of a conflicting write, the saved game with the
/// longest play time will be considered cannonical. If play time has not been provided by the
/// developer, or in the case of two saved games with equal play times,
/// <see cref="UseOriginal"/> will be used instead.
/// </summary>
UseLongestPlaytime,
/// <summary>
/// Choose the version of the saved game that existed before any conflicting write occurred.
/// Consider the following case:
/// - An initial version of a save game ("X") is written from a device ("Dev_A")
/// - The save game X is downloaded by another device ("Dev_B").
/// - Dev_A writes a new version of the save game to the cloud ("Y")
/// - Dev_B does not see the new save game Y, and attempts to write a new save game ("Z").
/// - Since Dev_B is performing a write using out of date information, a conflict is generated.
///
/// In this situation, we can resolve the conflict by declaring either keeping Y as the
/// canonical version of the saved game (i.e. choose "original" aka <see cref="UseOriginal"/>),
/// or by overwriting it with conflicting value, Z (i.e. choose "unmerged" aka
/// <see cref="UseUnmerged"/>).
/// </summary>
///
UseOriginal,
/// <summary>
/// See the documentation for <see cref="UseOriginal"/>
/// </summary>
UseUnmerged,
/// <summary>
/// Manual resolution, no automatic resolution is attempted.
/// </summary>
UseManual,
/// <summary>
/// The use last known good snapshot to resolve conflicts automatically.
/// </summary>
UseLastKnownGood,
/// <summary>
/// The use most recently saved snapshot to resolve conflicts automatically.
/// </summary>
UseMostRecentlySaved
}
public enum SavedGameRequestStatus
{
Success = 1,
/// <summary>
/// The request failed due to a timeout.
/// </summary>
///
TimeoutError = -1,
/// <summary>
/// An unexpected internal error. Check the log for error messages.
/// </summary>
///
InternalError = -2,
/// <summary>
/// A error related to authentication. This is probably due to the user being signed out
/// before the request could be issued.
/// </summary>
///
AuthenticationError = -3,
/// <summary>
/// The request failed because it was given bad input (e.g. a filename with 200 characters).
/// </summary>
///
BadInputError = -4
}
public enum SelectUIStatus
{
/// <summary>
/// The user selected a saved game.
/// </summary>
SavedGameSelected = 1,
/// <summary>
/// The user closed the UI without selecting a saved game.
/// </summary>
///
UserClosedUI = 2,
/// <summary>
/// An unexpected internal error. Check the log for error messages.
/// </summary>
///
InternalError = -1,
/// <summary>
/// There was a timeout while displaying the UI.
/// </summary>
///
TimeoutError = -2,
/// <summary>
/// A error related to authentication. This is probably due to the user being signed out
/// before the request could be issued.
/// </summary>
///
AuthenticationError = -3,
/// <summary>
/// The request failed because it was given bad input (e.g. a filename with 200 characters).
/// </summary>
///
BadInputError = -4,
UiBusy = -5
}
///
/// <summary>
/// A delegate that is invoked when we encounter a conflict during execution of
/// <see cref="ISavedGameClient.OpenWithAutomaticConflictResolution"/>. The caller must resolve the
/// conflict using the passed <see cref="IConflictResolver"/>. All passed metadata is open.
/// If <see cref="ISavedGameClient.OpenWithAutomaticConflictResolution"/> was invoked with
/// <c>prefetchDataOnConflict</c> set to <c>true</c>, the <paramref name="originalData"/> and
/// <paramref name="unmergedData"/> will be equal to the binary data of the "original" and
/// "unmerged" saved game respectively (and null otherwise). Since conflict files may be generated
/// by other clients, it is possible that neither of the passed saved games were originally written
/// by the current device. Consequently, any conflict resolution strategy should not rely on local
/// data that is not part of the binary data of the passed saved games - this data will not be
/// present if conflict resolution occurs on a different device. In addition, since a given saved
/// game may have multiple conflicts, this callback must be designed to handle multiple invocations.
/// </summary>
public delegate void ConflictCallback(IConflictResolver resolver, ISavedGameMetadata original,
byte[] originalData, ISavedGameMetadata unmerged, byte[] unmergedData);
/// <summary>
/// The main entry point for interacting with saved games. Saved games are persisted in the cloud
/// along with several game-specific properties (<see cref="ISavedGameMetadata"/> for more
/// information). There are several core concepts involved with saved games:
///
/// <para><strong>Filenames</strong> - act as unique identifiers for saved games. Two devices
/// performing a read or write using the same filename will end up reading or modifying the same
/// file (i.e. filenames are not device specific).
/// </para>
///
/// <para><strong>Saved Game Metadata</strong> are represented by <see cref="ISavedGameMetadata"/>.
/// The instances allow access to metadata properties about the underlying saved game (e.g.
/// description). In addition, metadata functions as a handle that are required to read and
/// manipulate saved game contents. Lastly, metadata may be "Open". Open metadata instances are
/// required to manipulate the underlying binary data of the saved game. See method comments to
/// determine whether a specific method requires or returns an open saved game.
/// </para>
///
/// <para><strong>Conflicts</strong> occur when multiple devices attempt to write to the same file
/// at the same time. The saved game system guarantees that no conflicting writes will be lost or
/// silently overwritten. Instead, they must be handled the next time the file with a conflict is
/// Opened. Conflicts can be handled automatically (
/// <see cref="OpenWithAutomaticConflictResolution"/>) or can be manuallyhandled by the developer
/// (<see cref="OpenWithManualConflictResolution"/>). See the Open methods for more discussion.
/// </para>
///
/// <para>Saved games will generally be used in the following workflow:</para>
/// <list type="number">
/// <item><description>Determine which saved game to use (either using a hardcoded filename or
/// ShowSelectSavedGameUI)</description></item>
/// <item><description>Open the file using OpenWithManualConflictResolution or
/// OpenWithAutomaticConflictResolution</description></item>
/// <item><description>Read the binary data of the saved game using ReadBinaryData handle it
/// as appropriate for your game.</description></item>
/// <item><description>When you have updates, persist them in the cloud using CommitUpdate. Note
/// that writing to the cloud is relatively expensive, and shouldn't be done frequently.
/// </description></item>
/// </list>
///
/// <para>See online <a href="https://developers.google.com/games/services/common/concepts/savedgames">
/// documentation for Saved Games</a> for more information.</para>
/// </summary>
public interface ISavedGameClient
{
/// <summary>
/// Opens the file with the indicated name and data source. If the file has an outstanding
/// conflict, it will be resolved using the specified conflict resolution strategy. The
/// metadata returned by this method will be "Open" - it can be used as a parameter for
/// <see cref="CommitUpdate"/> and <see cref="ResolveConflictByChoosingMetadata"/>.
/// </summary>
/// <param name="filename">The name of the file to open. Filenames must consist of
/// only non-URL reserved characters (i.e. a-z, A-Z, 0-9, or the symbols "-", ".", "_", or "~")
/// be between 1 and 100 characters in length (inclusive).</param>
/// <param name="source">The data source to use. <see cref="DataSource"/> for a description
/// of the available options here.</param>
/// <param name="resolutionStrategy">The conflict resolution that should be used if any
/// conflicts are encountered while opening the file.
/// <see cref="ConflictResolutionStrategy"/> for a description of these strategies.</param>
/// <param name="callback">The callback that is invoked when this operation finishes. The
/// returned metadata will only be non-null if the open succeeded. This callback will always
/// execute on the game thread and the returned metadata (if any) will be "Open".</param>
void OpenWithAutomaticConflictResolution(string filename, DataSource source,
ConflictResolutionStrategy resolutionStrategy,
Action<SavedGameRequestStatus, ISavedGameMetadata> callback);
/// <summary>
/// Opens the file with the indicated name and data source. If there is a conflict that
/// requires resolution, it will be resolved manually using the passed conflict callback. Once
/// all pending conflicts are resolved, the completed callback will be invoked with the
/// retrieved data. In the event of an error, the completed callback will be invoked with the
/// corresponding error status. All callbacks will be executed on the game thread.
/// </summary>
/// <param name="filename">The name of the file to open. Filenames must consist of
/// only non-URL reserved characters (i.e. a-z, A-Z, 0-9, or the symbols "-", ".", "_", or "~")
/// be between 1 and 100 characters in length (inclusive).</param>
/// <param name="source">The data source to use. <see cref="DataSource"/> for a description
/// of the available options here.</param>
/// <param name="prefetchDataOnConflict">If set to <c>true</c>, the data for the two
/// conflicting files will be automatically retrieved and passed as parameters in
/// <paramref name="conflictCallback"/>. If set to <c>false</c>, <c>null</c> binary data
/// will be passed into <paramref name="conflictCallback"/> and the caller will have to fetch
/// it themselves.</param>
/// <param name="conflictCallback">The callback that will be invoked if one or more conflict is
/// encountered while executing this method. Note that more than one conflict may be present
/// and that this callback might be executed more than once to resolve multiple conflicts.
/// This callback is always executed on the game thread.</param>
/// <param name="completedCallback">The callback that is invoked when this operation finishes.
/// The returned metadata will only be non-null if the open succeeded. If an error is
/// encountered during conflict resolution, that error will be reflected here. This callback
/// will always execute on the game thread and the returned metadata (if any) will be "Open".
/// </param>
void OpenWithManualConflictResolution(string filename, DataSource source,
bool prefetchDataOnConflict, ConflictCallback conflictCallback,
Action<SavedGameRequestStatus, ISavedGameMetadata> completedCallback);
/// <summary>
/// Reads the binary data of the passed saved game. The passed metadata must be opened (i.e.
/// <see cref="ISavedGameMetadata.IsOpen"/> returns true). The callback will always be executed
/// on the game thread.
/// </summary>
/// <param name="metadata">The metadata for the saved game whose binary data we want to read.
/// This metadata must be open. If it is not open, the method will immediately fail with status
/// <see cref="SelectUIStatus.BadInputError"/>.
/// </param>
/// <param name="completedCallback">The callback that is invoked when the read finishes. If the
/// read completed without error, the passed status will be <see cref="SavedGameRequestStatus.Success"/> and the passed
/// bytes will correspond to the binary data for the file. In the case of
/// </param>
void ReadBinaryData(ISavedGameMetadata metadata,
Action<SavedGameRequestStatus, byte[]> completedCallback);
/// <summary>
/// Shows the select saved game UI with the indicated configuration. If the user selects a
/// saved game in that UI, it will be returned in the passed callback. This metadata will be
/// unopened and must be passed to either <see cref="OpenWithManualConflictResolution"/> or
/// <see cref="OpenWithAutomaticConflictResolution"/> in order to retrieve the binary data.
/// The callback will always be executed on the game thread.
/// </summary>
/// <param name="uiTitle">The user-visible title of the displayed selection UI.</param>
/// <param name="maxDisplayedSavedGames">The maximum number of saved games the UI may display.
/// This value must be greater than 0.</param>
/// <param name="showCreateSaveUI">If set to <c>true</c>, show UI that will allow the user to
/// create a new saved game.</param>
/// <param name="showDeleteSaveUI">If set to <c>true</c> show UI that will allow the user to
/// delete a saved game.</param>
/// <param name="callback">The callback that is invoked when an error occurs or if the user
/// finishes interacting with the UI. If the user selected a saved game, this will be passed
/// into the callback along with the <see cref="SelectUIStatus.SavedGameSelected"/> status. This saved game
/// will not be Open, and must be opened before it can be written to or its binary data can be
/// read. If the user backs out of the UI without selecting a saved game, this callback will
/// receive <see cref="UserClosedUI"/> and a null saved game. This callback will always execute
/// on the game thread.</param>
void ShowSelectSavedGameUI(string uiTitle, uint maxDisplayedSavedGames, bool showCreateSaveUI,
bool showDeleteSaveUI, Action<SelectUIStatus, ISavedGameMetadata> callback);
/// <summary>
/// Durably commits an update to the passed saved game. When this method returns successfully,
/// the data is durably persisted to disk and will eventually be uploaded to the cloud (in
/// practice, this will happen very quickly unless the device does not have a network
/// connection). If an update to the saved game has occurred after the metadata was retrieved
/// from the cloud, this update will produce a conflict (this commonly occurs if two different
/// devices are writing to the cloud at the same time). All conflicts must be handled the next
/// time this saved game is opened. See <see cref="OpenWithManualConflictResolution"/> and
/// <see cref="OpenWithAutomaticConflictResolution"/> for more information.
/// </summary>
/// <param name="metadata">The metadata for the saved game to update. This metadata must be
/// Open (i.e. <see cref="ISavedGameMetadata.IsOpen"/> returns true)."/> If it is not open, the
/// method will immediately fail with status <see cref="SelectUIStatus.BadInputError"/></param>
/// <param name="updateForMetadata">All updates that should be applied to the saved game
/// metadata.</param>
/// <param name="updatedBinaryData">The new binary content of the saved game</param>
/// <param name="callback">The callback that is invoked when this operation finishes.
/// The returned metadata will only be non-null if the commit succeeded. If an error is
/// encountered during conflict resolution, that error will be reflected here. This callback
/// will always execute on the game thread and the returned metadata (if any) will NOT be
/// "Open" (i.e. commiting an update closes the metadata).</param>
void CommitUpdate(ISavedGameMetadata metadata, SavedGameMetadataUpdate updateForMetadata,
byte[] updatedBinaryData, Action<SavedGameRequestStatus, ISavedGameMetadata> callback);
/// <summary>
/// Returns the metadata for all known saved games for this game. All returned saved games are
/// not open, and must be opened before they can be used for writes or binary data reads. The
/// callback will always occur on the game thread.
/// </summary>
/// <param name="source">The data source to use. <see cref="DataSource"/> for a description
/// of the available options here.</param>
/// <param name="callback">The callback that is invoked when this operation finishes.
/// The returned metadata will only be non-empty if the commit succeeded. If an error is
/// encountered during the fetch, that error will be reflected here. This callback
/// will always execute on the game thread and the returned metadata (if any) will NOT be
/// "Open".</param>
void FetchAllSavedGames(DataSource source,
Action<SavedGameRequestStatus, List<ISavedGameMetadata>> callback);
/// <summary>
/// Delete the specified snapshot.
/// This will delete the data of the snapshot locally and on the server.
/// </summary>
/// <param name="metadata">the saved game metadata identifying the data to
/// delete.</param>
void Delete(ISavedGameMetadata metadata);
}
/// <summary>
/// An interface that allows developers to resolve metadata conflicts that may be encountered while
/// opening saved games.
/// </summary>
public interface IConflictResolver
{
/// <summary>
/// Resolves the conflict by choosing the passed metadata to be canonical. The passed metadata
/// must be one of the two instances passed as parameters into <see cref="ConflictCallback"/> -
/// this instance will be kept as the cannonical value in the cloud.
/// </summary>
/// <param name="chosenMetadata">The chosen metadata. This metadata must be open. If it is not
/// open, the invokation of <see cref="NativeSavedGameClient.OpenWithManualConflictResolution"/> that produced this
/// ConflictResolver will immediately fail with <see cref="SelectUIStatus.BadInputError"/>.</param>
void ChooseMetadata(ISavedGameMetadata chosenMetadata);
/// <summary>
/// Resolves the conflict and updates the data.
/// </summary>
/// <param name="chosenMetadata">Metadata for the chosen version. This is either the
/// original or unmerged metadata provided when the callback is invoked.</param>
/// <param name="metadataUpdate">Metadata update, same as when committing changes.</param>
/// <param name="updatedData">Updated data to use when resolving the conflict.</param>
void ResolveConflict(ISavedGameMetadata chosenMetadata, SavedGameMetadataUpdate metadataUpdate,
byte[] updatedData);
}
}
\ No newline at end of file
fileFormatVersion: 2
guid: 5d4ff89980bdd4c9780aa3ceee54a51b
labels:
- gvh
- gvh_version-0.11.01
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
// <copyright file="ISavedGameMetadata.cs" company="Google Inc.">
// Copyright (C) 2014 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
namespace GooglePlayGames.BasicApi.SavedGame
{
using System;
/// <summary>
/// Interface representing the metadata for a saved game. These instances are also used as handles
/// for reading and writing the content of the underlying file.
/// </summary>
public interface ISavedGameMetadata
{
/// <summary>
/// Returns true if this metadata can be used for operations related to raw file data (i.e.
/// the binary data contained in the underlying file). Metadata returned by Open operations
/// will be "Open". After an update to the file is committed or the metadata is used to resolve
/// a conflict, the corresponding Metadata is closed, and IsOpen will return false.
///
/// </summary>
/// <value><c>true</c> if this instance is open; otherwise, <c>false</c>.</value>
bool IsOpen { get; }
/// <summary>
/// Returns the filename for this saved game. A saved game filename will only consist of
/// non-URL reserved characters (i.e. a-z, A-Z, 0-9, or the symbols "-", ".", "_", or "~")
/// and will between 1 and 100 characters in length (inclusive).
/// </summary>
/// <value>The filename.</value>
string Filename { get; }
/// <summary>
/// Returns a human-readable description of what the saved game contains. This may be null.
/// </summary>
/// <value>The description.</value>
string Description { get; }
/// <summary>
/// A URL corresponding to the PNG-encoded image corresponding to this saved game. null if
/// the saved game does not have a cover image.
/// </summary>
/// <value>The cover image URL.</value>
string CoverImageURL { get; }
/// <summary>
/// Returns the total time played by the player for this saved game. This value is
/// developer-specified and may be tracked in any way that is appropriate to the game. Note
/// that this value is specific to this specific saved game (unless the developer intentionally
/// sets the same value on all saved games). If the value was not set, this will be equal to
/// <code>TimeSpan.FromMilliseconds(0)</code>
/// </summary>
/// <value>The total time played.</value>
TimeSpan TotalTimePlayed { get; }
/// <summary>
/// A timestamp corresponding to the last modification to the underlying saved game. If the
/// saved game is newly created, this value will correspond to the time the first Open
/// occurred. Otherwise, this corresponds to time the last successful write occurred (either by
/// CommitUpdate or Resolve methods).
/// </summary>
/// <value>The last modified timestamp.</value>
DateTime LastModifiedTimestamp { get; }
}
}
\ No newline at end of file
fileFormatVersion: 2
guid: a94650f478358403ea166d374b2a950c
labels:
- gvh
- gvh_version-0.11.01
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
// <copyright file="SavedGameMetadataUpdate.cs" company="Google Inc.">
// Copyright (C) 2014 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
namespace GooglePlayGames.BasicApi.SavedGame
{
using System;
using GooglePlayGames.OurUtils;
/// <summary>
/// A struct representing the mutation of saved game metadata. Fields can either have a new value
/// or be untouched (in which case the corresponding field in the saved game metadata will be
/// untouched). Instances must be built using <see cref="SavedGameMetadataUpdate.Builder"/>
/// and once created, these instances are immutable and threadsafe.
/// </summary>
public struct SavedGameMetadataUpdate
{
private readonly bool mDescriptionUpdated;
private readonly string mNewDescription;
private readonly bool mCoverImageUpdated;
private readonly byte[] mNewPngCoverImage;
private readonly TimeSpan? mNewPlayedTime;
private SavedGameMetadataUpdate(Builder builder)
{
mDescriptionUpdated = builder.mDescriptionUpdated;
mNewDescription = builder.mNewDescription;
mCoverImageUpdated = builder.mCoverImageUpdated;
mNewPngCoverImage = builder.mNewPngCoverImage;
mNewPlayedTime = builder.mNewPlayedTime;
}
public bool IsDescriptionUpdated
{
get { return mDescriptionUpdated; }
}
public string UpdatedDescription
{
get { return mNewDescription; }
}
public bool IsCoverImageUpdated
{
get { return mCoverImageUpdated; }
}
public byte[] UpdatedPngCoverImage
{
get { return mNewPngCoverImage; }
}
public bool IsPlayedTimeUpdated
{
get { return mNewPlayedTime.HasValue; }
}
public TimeSpan? UpdatedPlayedTime
{
get { return mNewPlayedTime; }
}
public struct Builder
{
internal bool mDescriptionUpdated;
internal string mNewDescription;
internal bool mCoverImageUpdated;
internal byte[] mNewPngCoverImage;
internal TimeSpan? mNewPlayedTime;
public Builder WithUpdatedDescription(string description)
{
mNewDescription = Misc.CheckNotNull(description);
mDescriptionUpdated = true;
return this;
}
public Builder WithUpdatedPngCoverImage(byte[] newPngCoverImage)
{
mCoverImageUpdated = true;
mNewPngCoverImage = newPngCoverImage;
return this;
}
public Builder WithUpdatedPlayedTime(TimeSpan newPlayedTime)
{
if (newPlayedTime.TotalMilliseconds > ulong.MaxValue)
{
throw new InvalidOperationException("Timespans longer than ulong.MaxValue " +
"milliseconds are not allowed");
}
mNewPlayedTime = newPlayedTime;
return this;
}
public SavedGameMetadataUpdate Build()
{
return new SavedGameMetadataUpdate(this);
}
}
}
}
\ No newline at end of file
fileFormatVersion: 2
guid: 602d9e1c90f0144e79536115f3614478
labels:
- gvh
- gvh_version-0.11.01
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
// <copyright file="ScorePageToken.cs" company="Google Inc.">
// Copyright (C) 2015 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
#if UNITY_ANDROID
namespace GooglePlayGames.BasicApi
{
public enum ScorePageDirection
{
Forward = 1,
Backward = 2,
}
/// <summary>
/// Score page token. This holds the internal token used
/// to page through the score pages. The id, collection, and
/// timespan are added as a convience, and not actually part of the
/// page token returned from the SDK.
/// </summary>
public class ScorePageToken
{
private string mId;
private object mInternalObject;
private LeaderboardCollection mCollection;
private LeaderboardTimeSpan mTimespan;
private ScorePageDirection mDirection;
internal ScorePageToken(object internalObject, string id,
LeaderboardCollection collection, LeaderboardTimeSpan timespan,
ScorePageDirection direction)
{
mInternalObject = internalObject;
mId = id;
mCollection = collection;
mTimespan = timespan;
mDirection = direction;
}
public LeaderboardCollection Collection
{
get { return mCollection; }
}
public LeaderboardTimeSpan TimeSpan
{
get { return mTimespan; }
}
public ScorePageDirection Direction
{
get { return mDirection; }
}
public string LeaderboardId
{
get { return mId; }
}
internal object InternalObject
{
get { return mInternalObject; }
}
}
}
#endif
\ No newline at end of file
fileFormatVersion: 2
guid: 3eade9d49f3e341ddb2ba8209e7ddf42
labels:
- gvh
- gvh_version-0.11.01
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
namespace GooglePlayGames.BasicApi
{
public enum SignInInteractivity
{
/// <summary>no UIs will be shown (if UIs are needed, it will fail rather than show them).</summary>
NoPrompt,
/// <summary>
/// This may show UIs, consent dialogs, etc.
/// At the end of the process, callback will be invoked to notify of the result.
/// Once the callback returns true, the user is considered to be authenticated.
/// </summary>
CanPromptAlways,
/// <summary>When this is selected, PlayGamesPlatform.Authenticate does the followings in order:
/// 1. Attempt to silent sign in.
/// 2. If silent sign in fails, check if user has previously declined to sign in and don’t prompt interactive
/// sign in if they have.
/// 3. Check the internet connection and fail with NO_INTERNET_CONNECTION if there is no internet connection.
/// 4. Prompt interactive sign in.
/// 5. If the interactive sign in is not successful (user declines or cancels), then
/// remember this for step 2 the next time the user opens the game and don’t ask for sign-in.
/// </summary>
CanPromptOnce
}
}
fileFormatVersion: 2
guid: f5c7733064f2b09dc8df0009b3bbb1d6
labels:
- gvh
- gvh_version-0.11.01
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
namespace GooglePlayGames.BasicApi
{
public enum SignInStatus
{
/// <summary>The operation was successful.</summary>
Success,
/// <summary>An internal error occurred.</summary>
InternalError,
/// <summary>The sign in was canceled.</summary>
Canceled,
}
}
fileFormatVersion: 2
guid: 0992bc2597d741e59dc3f8c963a3ca25
labels:
- gvh
- gvh_version-0.11.01
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
// <copyright file="GameInfo.cs" company="Google Inc.">
// Copyright (C) 2015 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
#if UNITY_ANDROID
namespace GooglePlayGames {
///
/// This file is automatically generated DO NOT EDIT!
///
/// These are the constants defined in the Play Games Console for Game Services
/// Resources.
///
/// <summary>
/// File containing information about the game. This is automatically updated by running the
/// platform-appropriate setup commands in the Unity editor (which does a simple search / replace
/// on the IDs in the form "__ID__"). We can check whether any particular field has been updated
/// by checking whether it still retains its initial value - we prevent the constants from being
/// replaced in the aforementioned search/replace by stripping off the leading and trailing "__".
/// </summary>
public static class GameInfo {
private const string UnescapedApplicationId = "APP_ID";
private const string UnescapedIosClientId = "IOS_CLIENTID";
private const string UnescapedWebClientId = "WEB_CLIENTID";
private const string UnescapedNearbyServiceId = "NEARBY_SERVICE_ID";
public const string ApplicationId = ""; // Filled in automatically
public const string IosClientId = "__IOS_CLIENTID__"; // Filled in automatically
public const string WebClientId = ""; // Filled in automatically
public const string NearbyConnectionServiceId = "";
public static bool ApplicationIdInitialized() {
return !string.IsNullOrEmpty(ApplicationId) && !ApplicationId.Equals(ToEscapedToken(UnescapedApplicationId));
}
public static bool IosClientIdInitialized() {
return !string.IsNullOrEmpty(IosClientId) && !IosClientId.Equals(ToEscapedToken(UnescapedIosClientId));
}
public static bool WebClientIdInitialized() {
return !string.IsNullOrEmpty(WebClientId) && !WebClientId.Equals(ToEscapedToken(UnescapedWebClientId));
}
public static bool NearbyConnectionsInitialized() {
return !string.IsNullOrEmpty(NearbyConnectionServiceId) &&
!NearbyConnectionServiceId.Equals(ToEscapedToken(UnescapedNearbyServiceId));
}
/// <summary>
/// Returns an escaped token (i.e. one flanked with "__") for the passed token
/// </summary>
/// <returns>The escaped token.</returns>
/// <param name="token">The Token</param>
private static string ToEscapedToken(string token) {
return string.Format("__{0}__", token);
}
}
}
#endif
fileFormatVersion: 2
guid: a722d413080904cc1bd07f4db21e1af1
labels:
- gvh
- gvh_version-0.11.01
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: ef66268ee929544fb82bbef6ac13bafe
folderAsset: yes
DefaultImporter:
userData:
// <copyright file="PlayGamesAchievement.cs" company="Google Inc.">
// Copyright (C) 2014 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
#if UNITY_ANDROID
namespace GooglePlayGames
{
using System;
using GooglePlayGames.BasicApi;
using UnityEngine;
#if UNITY_2017_1_OR_NEWER
using UnityEngine.Networking;
#endif
using UnityEngine.SocialPlatforms;
internal delegate void ReportProgress(string id, double progress, Action<bool> callback);
/// <summary>
/// Represents a Google Play Games achievement. It can be used to report an achievement
/// to the API, offering identical functionality as <see cref="PlayGamesPlatform.ReportProgress" />.
/// </summary>
internal class PlayGamesAchievement : IAchievement, IAchievementDescription
{
private readonly ReportProgress mProgressCallback;
private string mId = string.Empty;
private bool mIsIncremental = false;
private int mCurrentSteps = 0;
private int mTotalSteps = 0;
private double mPercentComplete = 0.0;
private bool mCompleted = false;
private bool mHidden = false;
private DateTime mLastModifiedTime = new DateTime(1970, 1, 1, 0, 0, 0, 0);
private string mTitle = string.Empty;
private string mRevealedImageUrl = string.Empty;
private string mUnlockedImageUrl = string.Empty;
#if UNITY_2017_1_OR_NEWER
private UnityWebRequest mImageFetcher = null;
#else
private WWW mImageFetcher = null;
#endif
private Texture2D mImage = null;
private string mDescription = string.Empty;
private ulong mPoints = 0;
internal PlayGamesAchievement()
: this(PlayGamesPlatform.Instance.ReportProgress)
{
}
internal PlayGamesAchievement(ReportProgress progressCallback)
{
mProgressCallback = progressCallback;
}
internal PlayGamesAchievement(Achievement ach) : this()
{
this.mId = ach.Id;
this.mIsIncremental = ach.IsIncremental;
this.mCurrentSteps = ach.CurrentSteps;
this.mTotalSteps = ach.TotalSteps;
if (ach.IsIncremental)
{
if (ach.TotalSteps > 0)
{
this.mPercentComplete =
((double) ach.CurrentSteps / (double) ach.TotalSteps) * 100.0;
}
else
{
this.mPercentComplete = 0.0;
}
}
else
{
this.mPercentComplete = ach.IsUnlocked ? 100.0 : 0.0;
}
this.mCompleted = ach.IsUnlocked;
this.mHidden = !ach.IsRevealed;
this.mLastModifiedTime = ach.LastModifiedTime;
this.mTitle = ach.Name;
this.mDescription = ach.Description;
this.mPoints = ach.Points;
this.mRevealedImageUrl = ach.RevealedImageUrl;
this.mUnlockedImageUrl = ach.UnlockedImageUrl;
}
/// <summary>
/// Reveals, unlocks or increment achievement.
/// </summary>
/// <remarks>
/// Call after setting <see cref="id" />, <see cref="completed" />,
/// as well as <see cref="currentSteps" /> and <see cref="totalSteps" />
/// for incremental achievements. Equivalent to calling
/// <see cref="PlayGamesPlatform.ReportProgress" />.
/// </remarks>
public void ReportProgress(Action<bool> callback)
{
mProgressCallback.Invoke(mId, mPercentComplete, callback);
}
/// <summary>
/// Loads the local user's image from the url. Loading urls
/// is asynchronous so the return from this call is fast,
/// the image is returned once it is loaded. null is returned
/// up to that point.
/// </summary>
private Texture2D LoadImage()
{
if (hidden)
{
// return null, we dont have images for hidden achievements.
return null;
}
string url = completed ? mUnlockedImageUrl : mRevealedImageUrl;
// the url can be null if the image is not configured.
if (!string.IsNullOrEmpty(url))
{
if (mImageFetcher == null || mImageFetcher.url != url)
{
#if UNITY_2017_1_OR_NEWER
mImageFetcher = UnityWebRequestTexture.GetTexture(url);
#else
mImageFetcher = new WWW(url);
#endif
mImage = null;
}
// if we have the texture, just return, this avoids excessive
// memory usage calling www.texture repeatedly.
if (mImage != null)
{
return mImage;
}
if (mImageFetcher.isDone)
{
#if UNITY_2017_1_OR_NEWER
mImage = DownloadHandlerTexture.GetContent(mImageFetcher);
#else
mImage = mImageFetcher.texture;
#endif
return mImage;
}
}
// if there is no url, always return null.
return null;
}
/// <summary>
/// Gets or sets the id of this achievement.
/// </summary>
/// <returns>
/// The identifier.
/// </returns>
public string id
{
get { return mId; }
set { mId = value; }
}
/// <summary>
/// Gets a value indicating whether this achievement is incremental.
/// </summary>
/// <remarks>
/// This value is only set by PlayGamesPlatform.LoadAchievements
/// </remarks>
/// <returns><c>true</c> if incremental; otherwise, <c>false</c>.</returns>
public bool isIncremental
{
get { return mIsIncremental; }
}
/// <summary>
/// Gets the current steps completed of this achievement.
/// </summary>
/// <remarks>
/// Undefined for standard (i.e. non-incremental) achievements.
/// This value is only set by PlayGamesPlatform.LoadAchievements, changing the
/// percentComplete will not affect this.
/// </remarks>
/// <returns>The current steps.</returns>
public int currentSteps
{
get { return mCurrentSteps; }
}
/// <summary>
/// Gets the total steps of this achievement.
/// </summary>
/// <remarks>
/// Undefined for standard (i.e. non-incremental) achievements.
/// This value is only set by PlayGamesPlatform.LoadAchievements, changing the
/// percentComplete will not affect this.
/// </remarks>
/// <returns>The total steps.</returns>
public int totalSteps
{
get { return mTotalSteps; }
}
/// <summary>
/// Gets or sets the percent completed.
/// </summary>
/// <returns>
/// The percent completed.
/// </returns>
public double percentCompleted
{
get { return mPercentComplete; }
set { mPercentComplete = value; }
}
/// <summary>
/// Gets a value indicating whether this achievement is completed.
/// </summary>
/// <remarks>
/// This value is only set by PlayGamesPlatform.LoadAchievements, changing the
/// percentComplete will not affect this.
/// </remarks>
/// <returns><c>true</c> if completed; otherwise, <c>false</c>.</returns>
public bool completed
{
get { return this.mCompleted; }
}
/// <summary>
/// Gets a value indicating whether this achievement is hidden.
/// </summary>
/// <value><c>true</c> if hidden; otherwise, <c>false</c>.</value>
public bool hidden
{
get { return this.mHidden; }
}
public DateTime lastReportedDate
{
get { return mLastModifiedTime; }
}
public String title
{
get { return mTitle; }
}
public Texture2D image
{
get { return LoadImage(); }
}
public string achievedDescription
{
get { return mDescription; }
}
public string unachievedDescription
{
get { return mDescription; }
}
public int points
{
get { return (int) mPoints; }
}
}
}
#endif
\ No newline at end of file
fileFormatVersion: 2
guid: e5354c32a5dc64372ba5102f7f787adf
labels:
- gvh
- gvh_version-0.11.01
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
// <copyright file="PlayGamesLeaderboard.cs" company="Google Inc.">
// Copyright (C) 2015 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
#if UNITY_ANDROID
namespace GooglePlayGames
{
using System.Collections.Generic;
using GooglePlayGames.BasicApi;
using UnityEngine;
using UnityEngine.SocialPlatforms;
public class PlayGamesLeaderboard : ILeaderboard
{
private string mId;
private UserScope mUserScope;
private Range mRange;
private TimeScope mTimeScope;
private string[] mFilteredUserIds;
private bool mLoading;
private IScore mLocalUserScore;
private uint mMaxRange;
private List<PlayGamesScore> mScoreList = new List<PlayGamesScore>();
private string mTitle;
public PlayGamesLeaderboard(string id)
{
mId = id;
}
#region ILeaderboard implementation
public void SetUserFilter(string[] userIDs)
{
mFilteredUserIds = userIDs;
}
public void LoadScores(System.Action<bool> callback)
{
PlayGamesPlatform.Instance.LoadScores(this, callback);
}
public bool loading
{
get { return mLoading; }
internal set { mLoading = value; }
}
public string id
{
get { return mId; }
set { mId = value; }
}
public UserScope userScope
{
get { return mUserScope; }
set { mUserScope = value; }
}
public Range range
{
get { return mRange; }
set { mRange = value; }
}
public TimeScope timeScope
{
get { return mTimeScope; }
set { mTimeScope = value; }
}
public IScore localUserScore
{
get { return mLocalUserScore; }
}
public uint maxRange
{
get { return mMaxRange; }
}
public IScore[] scores
{
get
{
PlayGamesScore[] arr = new PlayGamesScore[mScoreList.Count];
mScoreList.CopyTo(arr);
return arr;
}
}
public string title
{
get { return mTitle; }
}
#endregion
internal bool SetFromData(LeaderboardScoreData data)
{
if (data.Valid)
{
OurUtils.Logger.d("Setting leaderboard from: " + data);
SetMaxRange(data.ApproximateCount);
SetTitle(data.Title);
SetLocalUserScore((PlayGamesScore) data.PlayerScore);
foreach (IScore score in data.Scores)
{
AddScore((PlayGamesScore) score);
}
mLoading = data.Scores.Length == 0 || HasAllScores();
}
return data.Valid;
}
internal void SetMaxRange(ulong val)
{
mMaxRange = (uint) val;
}
internal void SetTitle(string value)
{
mTitle = value;
}
internal void SetLocalUserScore(PlayGamesScore score)
{
mLocalUserScore = score;
}
internal int AddScore(PlayGamesScore score)
{
if (mFilteredUserIds == null || mFilteredUserIds.Length == 0)
{
mScoreList.Add(score);
}
else
{
foreach (string fid in mFilteredUserIds)
{
if (fid.Equals(score.userID))
{
mScoreList.Add(score);
break;
}
}
}
return mScoreList.Count;
}
public int ScoreCount
{
get { return mScoreList.Count; }
}
internal bool HasAllScores()
{
return mScoreList.Count >= mRange.count || mScoreList.Count >= maxRange;
}
}
}
#endif
fileFormatVersion: 2
guid: a027e4767bd0f41509b9ef6bd2f6080e
labels:
- gvh
- gvh_version-0.11.01
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
// <copyright file="PlayGamesLocalUser.cs" company="Google Inc.">
// Copyright (C) 2014 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
#if UNITY_ANDROID
namespace GooglePlayGames
{
using System;
using GooglePlayGames.BasicApi;
using UnityEngine.SocialPlatforms;
/// <summary>
/// Represents the Google Play Games local user.
/// </summary>
public class PlayGamesLocalUser : PlayGamesUserProfile, ILocalUser
{
internal PlayGamesPlatform mPlatform;
private PlayerStats mStats;
internal PlayGamesLocalUser(PlayGamesPlatform plaf)
: base("localUser", string.Empty, string.Empty)
{
mPlatform = plaf;
mStats = null;
}
/// <summary>
/// Authenticates the local user. Equivalent to calling
/// <see cref="PlayGamesPlatform.Authenticate" />.
/// </summary>
public void Authenticate(Action<bool> callback)
{
mPlatform.Authenticate(status => callback(status == SignInStatus.Success));
}
/// <summary>
/// Authenticates the local user. Equivalent to calling
/// <see cref="PlayGamesPlatform.Authenticate" />.
/// </summary>
public void Authenticate(Action<bool, string> callback)
{
mPlatform.Authenticate(status => callback(status == SignInStatus.Success, status.ToString()));
}
/// <summary>
/// Loads all friends of the authenticated user.
/// </summary>
public void LoadFriends(Action<bool> callback)
{
mPlatform.LoadFriends(this, callback);
}
/// <summary>
/// Synchronous version of friends, returns null until loaded.
/// </summary>
public IUserProfile[] friends
{
get { return mPlatform.GetFriends(); }
}
/// <summary>
/// Returns whether or not the local user is authenticated to Google Play Games.
/// </summary>
/// <returns>
/// <c>true</c> if authenticated; otherwise, <c>false</c>.
/// </returns>
public bool authenticated
{
get { return mPlatform.IsAuthenticated(); }
}
/// <summary>
/// Not implemented. As safety placeholder, returns true.
/// </summary>
public bool underage
{
get { return true; }
}
/// <summary>
/// Gets the display name of the user.
/// </summary>
/// <returns>
/// The display name of the user.
/// </returns>
public new string userName
{
get
{
string retval = string.Empty;
if (authenticated)
{
retval = mPlatform.GetUserDisplayName();
if (!base.userName.Equals(retval))
{
ResetIdentity(retval, mPlatform.GetUserId(), mPlatform.GetUserImageUrl());
}
}
return retval;
}
}
/// <summary>
/// Gets the user's Google id.
/// </summary>
/// <remarks> This id is persistent and uniquely identifies the user
/// across all games that use Google Play Game Services. It is
/// the preferred method of uniquely identifying a player instead
/// of email address.
/// </remarks>
/// <returns>
/// The user's Google id.
/// </returns>
public new string id
{
get
{
string retval = string.Empty;
if (authenticated)
{
retval = mPlatform.GetUserId();
if (!base.id.Equals(retval))
{
ResetIdentity(mPlatform.GetUserDisplayName(), retval, mPlatform.GetUserImageUrl());
}
}
return retval;
}
}
/// <summary>
/// Returns true (since this is the local user).
/// </summary>
public new bool isFriend
{
get { return true; }
}
/// <summary>
/// Gets the local user's state. This is always <c>UserState.Online</c> for
/// the local user.
/// </summary>
public new UserState state
{
get { return UserState.Online; }
}
public new string AvatarURL
{
get
{
string retval = string.Empty;
if (authenticated)
{
retval = mPlatform.GetUserImageUrl();
if (!base.id.Equals(retval))
{
ResetIdentity(mPlatform.GetUserDisplayName(),
mPlatform.GetUserId(), retval);
}
}
return retval;
}
}
/// <summary>
/// Gets the player's stats.
/// </summary>
/// <param name="callback">Callback when they are available.</param>
public void GetStats(Action<CommonStatusCodes, PlayerStats> callback)
{
if (mStats == null || !mStats.Valid)
{
mPlatform.GetPlayerStats((rc, stats) =>
{
mStats = stats;
callback(rc, stats);
});
}
else
{
// 0 = success
callback(CommonStatusCodes.Success, mStats);
}
}
}
}
#endif
fileFormatVersion: 2
guid: 3b5f03fe051cb4a41a3b5489bd63c24c
labels:
- gvh
- gvh_version-0.11.01
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
// <copyright file="PlayGamesPlatform.cs" company="Google Inc.">
// Copyright (C) 2014 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
#if UNITY_ANDROID
namespace GooglePlayGames
{
using System;
using System.Collections.Generic;
using GooglePlayGames.BasicApi;
using GooglePlayGames.BasicApi.Events;
using GooglePlayGames.BasicApi.Nearby;
using GooglePlayGames.BasicApi.SavedGame;
using GooglePlayGames.OurUtils;
using UnityEngine;
using UnityEngine.SocialPlatforms;
/// <summary>
/// Provides access to the Google Play Games platform. This is an implementation of
/// UnityEngine.SocialPlatforms.ISocialPlatform. Activate this platform by calling
/// the <see cref="Activate" /> method, then authenticate by calling
/// the <see cref="Authenticate" /> method. After authentication
/// completes, you may call the other methods of this class. This is not a complete
/// implementation of the ISocialPlatform interface. Methods lacking an implementation
/// or whose behavior is at variance with the standard are noted as such.
/// </summary>
public class PlayGamesPlatform : ISocialPlatform
{
/// <summary>Singleton instance</summary>
private static volatile PlayGamesPlatform sInstance = null;
/// <summary>status of nearby connection initialization.</summary>
private static volatile bool sNearbyInitializePending;
/// <summary>Reference to the nearby client.</summary>
/// <remarks>This is static since it can be used without using play game services.</remarks>
private static volatile INearbyConnectionClient sNearbyConnectionClient;
/// <summary>The local user.</summary>
private PlayGamesLocalUser mLocalUser = null;
/// <summary>Reference to the platform specific implementation.</summary>
private IPlayGamesClient mClient = null;
/// <summary>the default leaderboard we show on ShowLeaderboardUI</summary>
private string mDefaultLbUi = null;
/// <summary>the mapping table from alias to leaderboard/achievement id.</summary>
private Dictionary<string, string> mIdMap = new Dictionary<string, string>();
/// <summary>
/// Initializes a new instance of the <see cref="GooglePlayGames.PlayGamesPlatform"/> class.
/// </summary>
/// <param name="client">Implementation client to use for this instance.</param>
internal PlayGamesPlatform(IPlayGamesClient client)
{
this.mClient = Misc.CheckNotNull(client);
this.mLocalUser = new PlayGamesLocalUser(this);
}
/// <summary>
/// Initializes a new instance of the <see cref="GooglePlayGames.PlayGamesPlatform"/> class.
/// </summary>
private PlayGamesPlatform()
{
GooglePlayGames.OurUtils.Logger.d("Creating new PlayGamesPlatform");
this.mLocalUser = new PlayGamesLocalUser(this);
}
/// <summary>
/// Gets or sets a value indicating whether debug logs are enabled. This property
/// may be set before calling <see cref="Activate" /> method.
/// </summary>
/// <returns>
/// <c>true</c> if debug log enabled; otherwise, <c>false</c>.
/// </returns>
public static bool DebugLogEnabled
{
get { return GooglePlayGames.OurUtils.Logger.DebugLogEnabled; }
set { GooglePlayGames.OurUtils.Logger.DebugLogEnabled = value; }
}
/// <summary>
/// Gets the singleton instance of the Play Games platform.
/// </summary>
/// <returns>
/// The instance.
/// </returns>
public static PlayGamesPlatform Instance
{
get
{
if (sInstance == null)
{
OurUtils.Logger.d("Initializing the PlayGamesPlatform instance.");
sInstance =
new PlayGamesPlatform(PlayGamesClientFactory.GetPlatformPlayGamesClient());
}
return sInstance;
}
}
/// <summary>
/// Gets the nearby connection client. NOTE: Can be null until the nearby client
/// is initialized. Call InitializeNearby to use callback to be notified when initialization
/// is complete.
/// </summary>
/// <value>The nearby.</value>
public static INearbyConnectionClient Nearby
{
get
{
if (sNearbyConnectionClient == null && !sNearbyInitializePending)
{
sNearbyInitializePending = true;
InitializeNearby(null);
}
return sNearbyConnectionClient;
}
}
/// <summary>Gets the saved game client object.</summary>
/// <value>The saved game client.</value>
public ISavedGameClient SavedGame
{
get { return mClient.GetSavedGameClient(); }
}
/// <summary>Gets the events client object.</summary>
/// <value>The events client.</value>
public IEventsClient Events
{
get { return mClient.GetEventsClient(); }
}
/// <summary>
/// Gets the local user.
/// </summary>
/// <returns>
/// The local user.
/// </returns>
public ILocalUser localUser
{
get { return mLocalUser; }
}
/// <summary>
/// Initializes the nearby connection platform.
/// </summary>
/// <remarks>This call initializes the nearby connection platform. This
/// is independent of the Play Game Services initialization. Multiple
/// calls to this method are ignored.
/// </remarks>
/// <param name="callback">Callback invoked when complete.</param>
public static void InitializeNearby(Action<INearbyConnectionClient> callback)
{
OurUtils.Logger.d("Calling InitializeNearby!");
if (sNearbyConnectionClient == null)
{
#if UNITY_ANDROID && !UNITY_EDITOR
NearbyConnectionClientFactory.Create(client => {
OurUtils.Logger.d("Nearby Client Created!!");
sNearbyConnectionClient = client;
if (callback != null) {
callback.Invoke(client);
}
else {
OurUtils.Logger.d("Initialize Nearby callback is null");
}
});
#else
sNearbyConnectionClient = new DummyNearbyConnectionClient();
if (callback != null)
{
callback.Invoke(sNearbyConnectionClient);
}
#endif
}
else if (callback != null)
{
OurUtils.Logger.d("Nearby Already initialized: calling callback directly");
callback.Invoke(sNearbyConnectionClient);
}
else
{
OurUtils.Logger.d("Nearby Already initialized");
}
}
/// <summary>
/// Activates the Play Games platform as the implementation of Social.Active.
/// After calling this method, you can call methods on Social.Active. For
/// example, <c>Social.Active.Authenticate()</c>.
/// </summary>
/// <returns>The singleton <see cref="PlayGamesPlatform" /> instance.</returns>
public static PlayGamesPlatform Activate()
{
GooglePlayGames.OurUtils.Logger.d("Activating PlayGamesPlatform.");
Social.Active = PlayGamesPlatform.Instance;
GooglePlayGames.OurUtils.Logger.d(
"PlayGamesPlatform activated: " + Social.Active);
return PlayGamesPlatform.Instance;
}
/// <summary>
/// Specifies that the ID <c>fromId</c> should be implicitly replaced by <c>toId</c>
/// on any calls that take a leaderboard or achievement ID.
/// </summary>
/// <remarks> After a mapping is
/// registered, you can use <c>fromId</c> instead of <c>toId</c> when making a call.
/// For example, the following two snippets are equivalent:
/// <code>
/// ReportProgress("Cfiwjew894_AQ", 100.0, callback);
/// </code>
/// ...is equivalent to:
/// <code>
/// AddIdMapping("super-combo", "Cfiwjew894_AQ");
/// ReportProgress("super-combo", 100.0, callback);
/// </code>
/// </remarks>
/// <param name='fromId'>
/// The identifier to map.
/// </param>
/// <param name='toId'>
/// The identifier that <c>fromId</c> will be mapped to.
/// </param>
public void AddIdMapping(string fromId, string toId)
{
mIdMap[fromId] = toId;
}
/// <summary>
/// Returns the result of the automatic sign-in attempt. Play Games SDK automatically
/// prompts users to sign in when the game is started. This API is useful for understanding
/// if your game has access to Play Games Services and should be used when your game is
/// started in order to conditionally enable or disable your Play Games Services
/// integration.
/// </summary>
/// <param name="callback">The callback to call when authentication finishes.</param>
public void Authenticate(Action<SignInStatus> callback)
{
mClient.Authenticate(callback);
}
/// <summary>
/// Provided for compatibility with ISocialPlatform.
/// </summary>
/// <seealso cref="Authenticate(Action&lt;bool&gt;,bool)"/>
/// <param name="unused">Unused parameter for this implementation.</param>
/// <param name="callback">Callback invoked when complete.</param>
public void Authenticate(ILocalUser unused, Action<bool> callback)
{
Authenticate(status => callback(status == SignInStatus.Success));
}
/// <summary>
/// Provided for compatibility with ISocialPlatform.
/// </summary>
/// <seealso cref="Authenticate(Action&lt;bool&gt;,bool)"/>
/// <param name="unused">Unused parameter for this implementation.</param>
/// <param name="callback">Callback invoked when complete.</param>
public void Authenticate(ILocalUser unused, Action<bool, string> callback)
{
Authenticate(status => callback(status == SignInStatus.Success, status.ToString()));
}
/// <summary>
/// Manually requests that your game performs sign in with Play Games Services.
/// </summary>
/// <remarks>
/// Note that a sign-in attempt will be made automatically when your game's application
/// started. For this reason most games will not need to manually request to perform sign-in
/// unless the automatic sign-in attempt failed and your game requires access to Play Games
/// Services.
/// </remarks>
/// <param name="callback"></param>
public void ManuallyAuthenticate(Action<SignInStatus> callback) {
mClient.ManuallyAuthenticate(callback);
}
/// <summary>
/// Determines whether the user is authenticated.
/// </summary>
/// <returns>
/// <c>true</c> if the user is authenticated; otherwise, <c>false</c>.
/// </returns>
public bool IsAuthenticated()
{
return mClient != null && mClient.IsAuthenticated();
}
/// <summary>
/// Requests server-side access to Player Games Services for the currently signed in player.
/// </summary>
/// When requested an authorization code is returned that can be used by your game-server to
/// exchange for an access token and conditionally a refresh token (when {@code
/// forceRefreshToken} is true). The access token may then be used by your game-server to
/// access the Play Games Services web APIs. This is commonly used to complete a sign-in flow
/// by verifying the Play Games Services player id.
///
/// <p>If {@code forceRefreshToken} is true, when exchanging the authorization code a refresh
/// token will be returned in addition to the access token. The refresh token allows the
/// game-server to request additional access tokens, allowing your game-server to continue
/// accesses Play Games Services while the user is not actively playing your app. <remarks>
///
/// </remarks>
/// <param name="forceRefreshToken">If {@code true} when the returned authorization code is
/// exchanged a refresh token will be included in addition to an access token.</param> <param
/// name="callback"></param>
public void RequestServerSideAccess(bool forceRefreshToken, Action<string> callback)
{
Misc.CheckNotNull(callback);
if (!IsAuthenticated())
{
OurUtils.Logger.e("RequestServerSideAccess() can only be called after authentication.");
InvokeCallbackOnGameThread(callback, null);
return;
}
mClient.RequestServerSideAccess(forceRefreshToken, callback);
}
/// <summary>
/// Loads the users.
/// </summary>
/// <param name="userIds">User identifiers.</param>
/// <param name="callback">Callback invoked when complete.</param>
public void LoadUsers(string[] userIds, Action<IUserProfile[]> callback)
{
if (!IsAuthenticated())
{
GooglePlayGames.OurUtils.Logger.e(
"GetUserId() can only be called after authentication.");
callback(new IUserProfile[0]);
return;
}
mClient.LoadUsers(userIds, callback);
}
/// <summary>
/// Returns the user's Google ID.
/// </summary>
/// <returns>
/// The user's Google ID. No guarantees are made as to the meaning or format of
/// this identifier except that it is unique to the user who is signed in.
/// </returns>
public string GetUserId()
{
if (!IsAuthenticated())
{
GooglePlayGames.OurUtils.Logger.e(
"GetUserId() can only be called after authentication.");
return "0";
}
return mClient.GetUserId();
}
/// <summary>
/// Gets the player stats.
/// </summary>
/// <param name="callback">Callback invoked when completed.</param>
public void GetPlayerStats(Action<CommonStatusCodes, PlayerStats> callback)
{
if (mClient != null && mClient.IsAuthenticated())
{
mClient.GetPlayerStats(callback);
}
else
{
GooglePlayGames.OurUtils.Logger.e(
"GetPlayerStats can only be called after authentication.");
callback(CommonStatusCodes.SignInRequired, new PlayerStats());
}
}
/// <summary>
/// Returns the user's display name.
/// </summary>
/// <returns>
/// The user display name (e.g. "Bruno Oliveira")
/// </returns>
public string GetUserDisplayName()
{
if (!IsAuthenticated())
{
GooglePlayGames.OurUtils.Logger.e(
"GetUserDisplayName can only be called after authentication.");
return string.Empty;
}
return mClient.GetUserDisplayName();
}
/// <summary>
/// Returns the user's avatar URL if they have one.
/// </summary>
/// <returns>
/// The URL, or <code>null</code> if the user is not authenticated or does not have
/// an avatar.
/// </returns>
public string GetUserImageUrl()
{
if (!IsAuthenticated())
{
GooglePlayGames.OurUtils.Logger.e(
"GetUserImageUrl can only be called after authentication.");
return null;
}
return mClient.GetUserImageUrl();
}
/// <summary>
/// Reports the progress of an achievement (reveal, unlock or increment). This method attempts
/// to implement the expected behavior of ISocialPlatform.ReportProgress as closely as possible,
/// as described below. Although this method works with incremental achievements for compatibility
/// purposes, calling this method for incremental achievements is not recommended,
/// since the Play Games API exposes incremental achievements in a very different way
/// than the interface presented by ISocialPlatform.ReportProgress. The implementation of this
/// method for incremental achievements attempts to produce the correct result, but may be
/// imprecise. If possible, call <see cref="IncrementAchievement" /> instead.
/// </summary>
/// <param name='achievementID'>
/// The ID of the achievement to unlock, reveal or increment. This can be a raw Google Play
/// Games achievement ID (alphanumeric string), or an alias that was previously configured
/// by a call to <see cref="AddIdMapping" />.
/// </param>
/// <param name='progress'>
/// Progress of the achievement. If the achievement is standard (not incremental), then
/// a progress of 0.0 will reveal the achievement and 100.0 will unlock it. Behavior of other
/// values is undefined. If the achievement is incremental, then this value is interpreted
/// as the total percentage of the achievement's progress that the player should have
/// as a result of this call (regardless of the progress they had before). So if the
/// player's previous progress was 30% and this call specifies 50.0, the new progress will
/// be 50% (not 80%).
/// </param>
/// <param name='callback'>
/// Callback that will be called to report the result of the operation: <c>true</c> on
/// success, <c>false</c> otherwise.
/// </param>
public void ReportProgress(string achievementID, double progress, Action<bool> callback)
{
callback = ToOnGameThread(callback);
if (!IsAuthenticated())
{
GooglePlayGames.OurUtils.Logger.e(
"ReportProgress can only be called after authentication.");
callback.Invoke(false);
return;
}
// map ID, if it's in the dictionary
GooglePlayGames.OurUtils.Logger.d("ReportProgress, " + achievementID + ", " + progress);
achievementID = MapId(achievementID);
// if progress is 0.0, we just want to reveal it
if (progress < 0.000001)
{
GooglePlayGames.OurUtils.Logger.d(
"Progress 0.00 interpreted as request to reveal.");
mClient.RevealAchievement(achievementID, callback);
return;
}
mClient.LoadAchievements(ach =>
{
for (int i = 0; i < ach.Length; i++)
{
if (ach[i].Id == achievementID)
{
if (ach[i].IsIncremental)
{
GooglePlayGames.OurUtils.Logger.d("Progress " + progress +
" interpreted as incremental target (approximate).");
if (progress >= 0.0 && progress <= 1.0)
{
// in a previous version, incremental progress was reported by using the range [0-1]
GooglePlayGames.OurUtils.Logger.w(
"Progress " + progress +
" is less than or equal to 1. You might be trying to use values in the range of [0,1], while values are expected to be within the range [0,100]. If you are using the latter, you can safely ignore this message.");
}
mClient.SetStepsAtLeast(achievementID, progressToSteps(progress, ach[i].TotalSteps), callback);
}
else
{
if (progress >= 100)
{
// unlock it!
GooglePlayGames.OurUtils.Logger.d("Progress " + progress + " interpreted as UNLOCK.");
mClient.UnlockAchievement(achievementID, callback);
}
else
{
// not enough to unlock
GooglePlayGames.OurUtils.Logger.d(
"Progress " + progress + " not enough to unlock non-incremental achievement.");
callback.Invoke(false);
}
}
return;
}
}
// Achievement not found
GooglePlayGames.OurUtils.Logger.e("Unable to locate achievement " + achievementID);
callback.Invoke(false);
});
}
internal static int progressToSteps(double progress, int totalSteps) {
return (progress >= 100.0) ? totalSteps : (int) (progress * totalSteps / 100.0);
}
/// <summary>
/// Reveals the achievement with the passed identifier. This is a Play Games extension of the ISocialPlatform API.
/// </summary>
/// <remarks>If the operation succeeds, the callback
/// will be invoked on the game thread with <code>true</code>. If the operation fails, the
/// callback will be invoked with <code>false</code>. This operation will immediately fail if
/// the user is not authenticated (i.e. the callback will immediately be invoked with
/// <code>false</code>). If the achievement is already in a revealed state, this call will
/// succeed immediately.
/// </remarks>
/// <param name='achievementID'>
/// The ID of the achievement to increment. This can be a raw Google Play
/// Games achievement ID (alphanumeric string), or an alias that was previously configured
/// by a call to <see cref="AddIdMapping" />.
/// </param>
/// <param name='callback'>
/// The callback to call to report the success or failure of the operation. The callback
/// will be called with <c>true</c> to indicate success or <c>false</c> for failure.
/// </param>
public void RevealAchievement(string achievementID, Action<bool> callback = null)
{
if (!IsAuthenticated())
{
GooglePlayGames.OurUtils.Logger.e(
"RevealAchievement can only be called after authentication.");
if (callback != null)
{
callback.Invoke(false);
}
return;
}
// map ID, if it's in the dictionary
GooglePlayGames.OurUtils.Logger.d(
"RevealAchievement: " + achievementID);
achievementID = MapId(achievementID);
mClient.RevealAchievement(achievementID, callback);
}
/// <summary>
/// Unlocks the achievement with the passed identifier. This is a Play Games extension of the ISocialPlatform API.
/// </summary>
/// <remarks>If the operation succeeds, the callback
/// will be invoked on the game thread with <code>true</code>. If the operation fails, the
/// callback will be invoked with <code>false</code>. This operation will immediately fail if
/// the user is not authenticated (i.e. the callback will immediately be invoked with
/// <code>false</code>). If the achievement is already unlocked, this call will
/// succeed immediately.
/// </remarks>
/// <param name='achievementID'>
/// The ID of the achievement to increment. This can be a raw Google Play
/// Games achievement ID (alphanumeric string), or an alias that was previously configured
/// by a call to <see cref="AddIdMapping" />.
/// </param>
/// <param name='callback'>
/// The callback to call to report the success or failure of the operation. The callback
/// will be called with <c>true</c> to indicate success or <c>false</c> for failure.
/// </param>
public void UnlockAchievement(string achievementID, Action<bool> callback = null)
{
if (!IsAuthenticated())
{
GooglePlayGames.OurUtils.Logger.e(
"UnlockAchievement can only be called after authentication.");
if (callback != null)
{
callback.Invoke(false);
}
return;
}
// map ID, if it's in the dictionary
GooglePlayGames.OurUtils.Logger.d(
"UnlockAchievement: " + achievementID);
achievementID = MapId(achievementID);
mClient.UnlockAchievement(achievementID, callback);
}
/// <summary>
/// Increments an achievement. This is a Play Games extension of the ISocialPlatform API.
/// </summary>
/// <param name='achievementID'>
/// The ID of the achievement to increment. This can be a raw Google Play
/// Games achievement ID (alphanumeric string), or an alias that was previously configured
/// by a call to <see cref="AddIdMapping" />.
/// </param>
/// <param name='steps'>
/// The number of steps to increment the achievement by.
/// </param>
/// <param name='callback'>
/// The callback to call to report the success or failure of the operation. The callback
/// will be called with <c>true</c> to indicate success or <c>false</c> for failure.
/// </param>
public void IncrementAchievement(string achievementID, int steps, Action<bool> callback)
{
if (!IsAuthenticated())
{
GooglePlayGames.OurUtils.Logger.e(
"IncrementAchievement can only be called after authentication.");
if (callback != null)
{
callback.Invoke(false);
}
return;
}
// map ID, if it's in the dictionary
GooglePlayGames.OurUtils.Logger.d(
"IncrementAchievement: " + achievementID + ", steps " + steps);
achievementID = MapId(achievementID);
mClient.IncrementAchievement(achievementID, steps, callback);
}
/// <summary>
/// Set an achievement to have at least the given number of steps completed.
/// Calling this method while the achievement already has more steps than
/// the provided value is a no-op. Once the achievement reaches the
/// maximum number of steps, the achievement is automatically unlocked,
/// and any further mutation operations are ignored.
/// </summary>
/// <param name='achievementID'>
/// The ID of the achievement to increment. This can be a raw Google Play
/// Games achievement ID (alphanumeric string), or an alias that was previously configured
/// by a call to <see cref="AddIdMapping" />.
/// </param>
/// <param name='steps'>
/// The number of steps to increment the achievement by.
/// </param>
/// <param name='callback'>
/// The callback to call to report the success or failure of the operation. The callback
/// will be called with <c>true</c> to indicate success or <c>false</c> for failure.
/// </param>
public void SetStepsAtLeast(string achievementID, int steps, Action<bool> callback)
{
if (!IsAuthenticated())
{
GooglePlayGames.OurUtils.Logger.e(
"SetStepsAtLeast can only be called after authentication.");
if (callback != null)
{
callback.Invoke(false);
}
return;
}
// map ID, if it's in the dictionary
GooglePlayGames.OurUtils.Logger.d(
"SetStepsAtLeast: " + achievementID + ", steps " + steps);
achievementID = MapId(achievementID);
mClient.SetStepsAtLeast(achievementID, steps, callback);
}
/// <summary>
/// Loads the Achievement descriptions.
/// </summary>
/// <param name="callback">The callback to receive the descriptions</param>
public void LoadAchievementDescriptions(Action<IAchievementDescription[]> callback)
{
if (!IsAuthenticated())
{
GooglePlayGames.OurUtils.Logger.e(
"LoadAchievementDescriptions can only be called after authentication.");
if (callback != null)
{
callback.Invoke(null);
}
return;
}
mClient.LoadAchievements(ach =>
{
IAchievementDescription[] data = new IAchievementDescription[ach.Length];
for (int i = 0; i < data.Length; i++)
{
data[i] = new PlayGamesAchievement(ach[i]);
}
callback.Invoke(data);
});
}
/// <summary>
/// Loads the achievement state for the current user.
/// </summary>
/// <param name="callback">The callback to receive the achievements</param>
public void LoadAchievements(Action<IAchievement[]> callback)
{
if (!IsAuthenticated())
{
GooglePlayGames.OurUtils.Logger.e("LoadAchievements can only be called after authentication.");
callback.Invoke(null);
return;
}
mClient.LoadAchievements(ach =>
{
IAchievement[] data = new IAchievement[ach.Length];
for (int i = 0; i < data.Length; i++)
{
data[i] = new PlayGamesAchievement(ach[i]);
}
callback.Invoke(data);
});
}
/// <summary>
/// Creates an achievement object which may be subsequently used to report an
/// achievement.
/// </summary>
/// <returns>
/// The achievement object.
/// </returns>
public IAchievement CreateAchievement()
{
return new PlayGamesAchievement();
}
/// <summary>
/// Reports a score to a leaderboard.
/// </summary>
/// <param name='score'>
/// The score to report.
/// </param>
/// <param name='board'>
/// The ID of the leaderboard on which the score is to be posted. This may be a raw
/// Google Play Games leaderboard ID or an alias configured through a call to
/// <see cref="AddIdMapping" />.
/// </param>
/// <param name='callback'>
/// The callback to call to report the success or failure of the operation. The callback
/// will be called with <c>true</c> to indicate success or <c>false</c> for failure.
/// </param>
public void ReportScore(long score, string board, Action<bool> callback)
{
if (!IsAuthenticated())
{
GooglePlayGames.OurUtils.Logger.e("ReportScore can only be called after authentication.");
if (callback != null)
{
callback.Invoke(false);
}
return;
}
GooglePlayGames.OurUtils.Logger.d("ReportScore: score=" + score + ", board=" + board);
string leaderboardId = MapId(board);
mClient.SubmitScore(leaderboardId, score, callback);
}
/// <summary>
/// Submits the score for the currently signed-in player
/// to the leaderboard associated with a specific id
/// and metadata (such as something the player did to earn the score).
/// </summary>
/// <param name="score">Score to report.</param>
/// <param name="board">leaderboard id.</param>
/// <param name="metadata">metadata about the score.</param>
/// <param name="callback">Callback invoked upon completion.</param>
public void ReportScore(long score, string board, string metadata, Action<bool> callback)
{
if (!IsAuthenticated())
{
GooglePlayGames.OurUtils.Logger.e("ReportScore can only be called after authentication.");
if (callback != null)
{
callback.Invoke(false);
}
return;
}
GooglePlayGames.OurUtils.Logger.d("ReportScore: score=" + score +
", board=" + board +
" metadata=" + metadata);
string leaderboardId = MapId(board);
mClient.SubmitScore(leaderboardId, score, metadata, callback);
}
/// <summary>
/// Loads the scores relative the player.
/// </summary>
/// <remarks>This returns the 25
/// (which is the max results returned by the SDK per call) scores
/// that are around the player's score on the Public, all time leaderboard.
/// Use the overloaded methods which are specific to GPGS to modify these
/// parameters.
/// </remarks>
/// <param name="leaderboardId">Leaderboard Id</param>
/// <param name="callback">Callback to invoke when completed.</param>
public void LoadScores(string leaderboardId, Action<IScore[]> callback)
{
LoadScores(
leaderboardId,
LeaderboardStart.PlayerCentered,
mClient.LeaderboardMaxResults(),
LeaderboardCollection.Public,
LeaderboardTimeSpan.AllTime,
(scoreData) => callback(scoreData.Scores));
}
/// <summary>
/// Loads the scores using the provided parameters. This call may fail when trying to load friends with
/// ResponseCode.ResolutionRequired if the user has not share the friends list with the game. In this case, use
/// AskForLoadFriendsResolution to request access.
/// </summary>
/// <param name="leaderboardId">Leaderboard identifier.</param>
/// <param name="start">Start either top scores, or player centered.</param>
/// <param name="rowCount">Row count. the number of rows to return.</param>
/// <param name="collection">Collection. social or public</param>
/// <param name="timeSpan">Time span. daily, weekly, all-time</param>
/// <param name="callback">Callback to invoke when completed.</param>
public void LoadScores(
string leaderboardId,
LeaderboardStart start,
int rowCount,
LeaderboardCollection collection,
LeaderboardTimeSpan timeSpan,
Action<LeaderboardScoreData> callback)
{
if (!IsAuthenticated())
{
GooglePlayGames.OurUtils.Logger.e("LoadScores can only be called after authentication.");
callback(new LeaderboardScoreData(
leaderboardId,
ResponseStatus.NotAuthorized));
return;
}
mClient.LoadScores(
leaderboardId,
start,
rowCount,
collection,
timeSpan,
callback);
}
/// <summary>
/// Loads more scores. This call may fail when trying to load friends with
/// ResponseCode.ResolutionRequired if the user has not share the friends list with the game. In this case, use
/// AskForLoadFriendsResolution to request access.
/// </summary>
/// <remarks>This is used to load the next "page" of scores. </remarks>
/// <param name="token">Token used to recording the loading.</param>
/// <param name="rowCount">Row count.</param>
/// <param name="callback">Callback invoked when complete.</param>
public void LoadMoreScores(
ScorePageToken token,
int rowCount,
Action<LeaderboardScoreData> callback)
{
if (!IsAuthenticated())
{
GooglePlayGames.OurUtils.Logger.e("LoadMoreScores can only be called after authentication.");
callback(
new LeaderboardScoreData(
token.LeaderboardId,
ResponseStatus.NotAuthorized));
return;
}
mClient.LoadMoreScores(token, rowCount, callback);
}
/// <summary>
/// Returns a leaderboard object that can be configured to
/// load scores.
/// </summary>
/// <returns>The leaderboard object.</returns>
public ILeaderboard CreateLeaderboard()
{
return new PlayGamesLeaderboard(mDefaultLbUi);
}
/// <summary>
/// Shows the standard Google Play Games achievements user interface,
/// which allows the player to browse their achievements.
/// </summary>
public void ShowAchievementsUI()
{
ShowAchievementsUI(null);
}
/// <summary>
/// Shows the standard Google Play Games achievements user interface,
/// which allows the player to browse their achievements.
/// </summary>
/// <param name="callback">If non-null, the callback is invoked when
/// the achievement UI is dismissed</param>
public void ShowAchievementsUI(Action<UIStatus> callback)
{
if (!IsAuthenticated())
{
GooglePlayGames.OurUtils.Logger.e("ShowAchievementsUI can only be called after authentication.");
return;
}
GooglePlayGames.OurUtils.Logger.d("ShowAchievementsUI callback is " + callback);
mClient.ShowAchievementsUI(callback);
}
/// <summary>
/// Shows the standard Google Play Games leaderboards user interface,
/// which allows the player to browse their leaderboards. If you have
/// configured a specific leaderboard as the default through a call to
/// <see cref="SetDefaultLeaderboardForUI" />, the UI will show that
/// specific leaderboard only. Otherwise, a list of all the leaderboards
/// will be shown.
/// </summary>
public void ShowLeaderboardUI()
{
GooglePlayGames.OurUtils.Logger.d("ShowLeaderboardUI with default ID");
ShowLeaderboardUI(MapId(mDefaultLbUi), null);
}
/// <summary>
/// Shows the standard Google Play Games leaderboard UI for the given
/// leaderboard.
/// </summary>
/// <param name='leaderboardId'>
/// The ID of the leaderboard to display. This may be a raw
/// Google Play Games leaderboard ID or an alias configured through a call to
/// <see cref="AddIdMapping" />.
/// </param>
public void ShowLeaderboardUI(string leaderboardId)
{
if (leaderboardId != null)
{
leaderboardId = MapId(leaderboardId);
}
ShowLeaderboardUI(leaderboardId, LeaderboardTimeSpan.AllTime, null);
}
/// <summary>
/// Shows the leaderboard UI and calls the specified callback upon
/// completion.
/// </summary>
/// <param name="leaderboardId">leaderboard ID, can be null meaning all leaderboards.</param>
/// <param name="callback">Callback to call. If null, nothing is called.</param>
public void ShowLeaderboardUI(string leaderboardId, Action<UIStatus> callback)
{
ShowLeaderboardUI(leaderboardId, LeaderboardTimeSpan.AllTime, callback);
}
/// <summary>
/// Shows the leaderboard UI and calls the specified callback upon
/// completion.
/// </summary>
/// <param name="leaderboardId">leaderboard ID, can be null meaning all leaderboards.</param>
/// <param name="span">Timespan to display scores in the leaderboard.</param>
/// <param name="callback">Callback to call. If null, nothing is called.</param>
public void ShowLeaderboardUI(
string leaderboardId,
LeaderboardTimeSpan span,
Action<UIStatus> callback)
{
if (!IsAuthenticated())
{
GooglePlayGames.OurUtils.Logger.e("ShowLeaderboardUI can only be called after authentication.");
if (callback != null)
{
callback(UIStatus.NotAuthorized);
}
return;
}
GooglePlayGames.OurUtils.Logger.d("ShowLeaderboardUI, lbId=" +
leaderboardId + " callback is " + callback);
mClient.ShowLeaderboardUI(leaderboardId, span, callback);
}
/// <summary>
/// Sets the default leaderboard for the leaderboard UI. After calling this
/// method, a call to <see cref="ShowLeaderboardUI" /> will show only the specified
/// leaderboard instead of showing the list of all leaderboards.
/// </summary>
/// <param name='lbid'>
/// The ID of the leaderboard to display on the default UI. This may be a raw
/// Google Play Games leaderboard ID or an alias configured through a call to
/// <see cref="AddIdMapping" />.
/// </param>
public void SetDefaultLeaderboardForUI(string lbid)
{
GooglePlayGames.OurUtils.Logger.d("SetDefaultLeaderboardForUI: " + lbid);
if (lbid != null)
{
lbid = MapId(lbid);
}
mDefaultLbUi = lbid;
}
/// <summary>
/// Loads the friends that also play this game. See loadConnectedPlayers.
/// </summary>
/// <remarks>This is a callback variant of LoadFriends. When completed,
/// the friends list set in the user object, so they can accessed via the
/// friends property as needed.
/// </remarks>
/// <param name="user">The current local user</param>
/// <param name="callback">Callback invoked when complete.</param>
public void LoadFriends(ILocalUser user, Action<bool> callback)
{
if (!IsAuthenticated())
{
GooglePlayGames.OurUtils.Logger.e(
"LoadScores can only be called after authentication.");
if (callback != null)
{
callback(false);
}
return;
}
mClient.LoadFriends(callback);
}
/// <summary>
/// Loads the leaderboard based on the constraints in the leaderboard
/// object.
/// </summary>
/// <param name="board">The leaderboard object. This is created by
/// calling CreateLeaderboard(), and then initialized appropriately.</param>
/// <param name="callback">Callback invoked when complete.</param>
public void LoadScores(ILeaderboard board, Action<bool> callback)
{
if (!IsAuthenticated())
{
GooglePlayGames.OurUtils.Logger.e("LoadScores can only be called after authentication.");
if (callback != null)
{
callback(false);
}
return;
}
LeaderboardTimeSpan timeSpan;
switch (board.timeScope)
{
case TimeScope.AllTime:
timeSpan = LeaderboardTimeSpan.AllTime;
break;
case TimeScope.Week:
timeSpan = LeaderboardTimeSpan.Weekly;
break;
case TimeScope.Today:
timeSpan = LeaderboardTimeSpan.Daily;
break;
default:
timeSpan = LeaderboardTimeSpan.AllTime;
break;
}
((PlayGamesLeaderboard) board).loading = true;
GooglePlayGames.OurUtils.Logger.d("LoadScores, board=" + board +
" callback is " + callback);
mClient.LoadScores(
board.id,
LeaderboardStart.PlayerCentered,
board.range.count > 0 ? board.range.count : mClient.LeaderboardMaxResults(),
board.userScope == UserScope.FriendsOnly ? LeaderboardCollection.Social : LeaderboardCollection.Public,
timeSpan,
(scoreData) => HandleLoadingScores(
(PlayGamesLeaderboard) board, scoreData, callback));
}
/// <summary>
/// Check if the leaderboard is currently loading.
/// </summary>
/// <returns><c>true</c>, if loading was gotten, <c>false</c> otherwise.</returns>
/// <param name="board">The leaderboard to check for loading in progress</param>
public bool GetLoading(ILeaderboard board)
{
return board != null && board.loading;
}
/// <summary>
/// Shows the Player Profile UI for the given user identifier.
/// </summary>
/// <param name="userId">User Identifier.</param>
/// <param name="otherPlayerInGameName">
/// The game's own display name of the player referred to by userId.
/// </param>
/// <param name="currentPlayerInGameName">
/// The game's own display name of the current player.
/// </param>
/// <param name="callback">Callback invoked upon completion.</param>
public void ShowCompareProfileWithAlternativeNameHintsUI(string userId,
string otherPlayerInGameName,
string currentPlayerInGameName,
Action<UIStatus> callback)
{
if (!IsAuthenticated())
{
GooglePlayGames.OurUtils.Logger.e(
"ShowCompareProfileWithAlternativeNameHintsUI can only be called after authentication.");
InvokeCallbackOnGameThread(callback, UIStatus.NotAuthorized);
return;
}
GooglePlayGames.OurUtils.Logger.d(
"ShowCompareProfileWithAlternativeNameHintsUI, userId=" + userId + " callback is " +
callback);
mClient.ShowCompareProfileWithAlternativeNameHintsUI(userId, otherPlayerInGameName,
currentPlayerInGameName, callback);
}
/// <summary>
/// Returns if the user has allowed permission for the game to access the friends list.
/// </summary>
/// <param name="forceReload">If true, this call will clear any locally cached data and
/// attempt to fetch the latest data from the server. Normally, this should be set to {@code
/// false} to gain advantages of data caching.</param>
/// <param name="callback">Callback invoked upon completion.</param>
public void GetFriendsListVisibility(bool forceReload,
Action<FriendsListVisibilityStatus> callback)
{
if (!IsAuthenticated())
{
GooglePlayGames.OurUtils.Logger.e(
"GetFriendsListVisibility can only be called after authentication.");
InvokeCallbackOnGameThread(callback, FriendsListVisibilityStatus.NotAuthorized);
return;
}
GooglePlayGames.OurUtils.Logger.d("GetFriendsListVisibility, callback is " + callback);
mClient.GetFriendsListVisibility(forceReload, callback);
}
/// <summary>
/// Shows the appropriate platform-specific friends sharing UI.
/// <param name="callback">The callback to invoke when complete. If null,
/// no callback is called. </param>
/// </summary>
public void AskForLoadFriendsResolution(Action<UIStatus> callback)
{
if (!IsAuthenticated())
{
GooglePlayGames.OurUtils.Logger.e(
"AskForLoadFriendsResolution can only be called after authentication.");
InvokeCallbackOnGameThread(callback, UIStatus.NotAuthorized);
return;
}
GooglePlayGames.OurUtils.Logger.d("AskForLoadFriendsResolution callback is " + callback);
mClient.AskForLoadFriendsResolution(callback);
}
/// <summary>
/// Gets status of the last call to load friends.
/// </summary>
public LoadFriendsStatus GetLastLoadFriendsStatus()
{
if (!IsAuthenticated())
{
GooglePlayGames.OurUtils.Logger.e(
"GetLastLoadFriendsStatus can only be called after authentication.");
return LoadFriendsStatus.NotAuthorized;
}
return mClient.GetLastLoadFriendsStatus();
}
/// <summary>
/// Loads the first page of the user's friends
/// </summary>
/// <param name="pageSize">
/// The number of entries to request for this initial page. Note that if cached
/// data already exists, the returned buffer may contain more than this size, but it is
/// guaranteed to contain at least this many if the collection contains enough records.
/// </param>
/// <param name="forceReload">
/// If true, this call will clear any locally cached data and attempt to
/// fetch the latest data from the server. This would commonly be used for something like a
/// user-initiated refresh. Normally, this should be set to {@code false} to gain advantages
/// of data caching.</param> <param name="callback">Callback invoked upon
/// completion.</param>
public void LoadFriends(int pageSize, bool forceReload,
Action<LoadFriendsStatus> callback)
{
if (!IsAuthenticated())
{
GooglePlayGames.OurUtils.Logger.e(
"LoadFriends can only be called after authentication.");
InvokeCallbackOnGameThread(callback, LoadFriendsStatus.NotAuthorized);
return;
}
mClient.LoadFriends(pageSize, forceReload, callback);
}
/// <summary>
/// Loads the friends list page
/// </summary>
/// <param name="pageSize">
/// The number of entries to request for this initial page. Note that if cached
/// data already exists, the returned buffer may contain more than this size, but it is
/// guaranteed to contain at least this many if the collection contains enough records.
/// </param>
/// <param name="callback"></param>
public void LoadMoreFriends(int pageSize, Action<LoadFriendsStatus> callback)
{
if (!IsAuthenticated())
{
GooglePlayGames.OurUtils.Logger.e(
"LoadMoreFriends can only be called after authentication.");
InvokeCallbackOnGameThread(callback, LoadFriendsStatus.NotAuthorized);
return;
}
mClient.LoadMoreFriends(pageSize, callback);
}
/// <summary>
/// Handles the processing of scores during loading.
/// </summary>
/// <param name="board">leaderboard being loaded</param>
/// <param name="scoreData">Score data.</param>
/// <param name="callback">Callback invoked when complete.</param>
internal void HandleLoadingScores(
PlayGamesLeaderboard board,
LeaderboardScoreData scoreData,
Action<bool> callback)
{
bool ok = board.SetFromData(scoreData);
if (ok && !board.HasAllScores() && scoreData.NextPageToken != null)
{
int rowCount = board.range.count - board.ScoreCount;
// need to load more scores
mClient.LoadMoreScores(
scoreData.NextPageToken,
rowCount,
(nextScoreData) =>
HandleLoadingScores(board, nextScoreData, callback));
}
else
{
callback(ok);
}
}
/// <summary>
/// Internal implmentation of getFriends.Gets the friends.
/// </summary>
/// <returns>The friends.</returns>
internal IUserProfile[] GetFriends()
{
if (!IsAuthenticated())
{
GooglePlayGames.OurUtils.Logger.d("Cannot get friends when not authenticated!");
return new IUserProfile[0];
}
return mClient.GetFriends();
}
/// <summary>
/// Maps the alias to the identifier.
/// </summary>
/// <remarks>This maps an aliased ID to the actual id. The intent of
/// this method is to allow easy to read constants to be used instead of
/// the generated ids.
/// </remarks>
/// <returns>The identifier, or null if not found.</returns>
/// <param name="id">Alias to map</param>
private string MapId(string id)
{
if (id == null)
{
return null;
}
if (mIdMap.ContainsKey(id))
{
string result = mIdMap[id];
GooglePlayGames.OurUtils.Logger.d("Mapping alias " + id + " to ID " + result);
return result;
}
return id;
}
private static void InvokeCallbackOnGameThread<T>(Action<T> callback, T data)
{
if (callback == null)
{
return;
}
PlayGamesHelperObject.RunOnGameThread(() => { callback(data); });
}
private static Action<T> ToOnGameThread<T>(Action<T> toConvert)
{
if (toConvert == null)
{
return delegate { };
}
return (val) => PlayGamesHelperObject.RunOnGameThread(() => toConvert(val));
}
}
}
#endif
fileFormatVersion: 2
guid: c1de7754a6e7f4fb08b76780a184b3ca
labels:
- gvh
- gvh_version-0.11.01
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
// <copyright file="PlayGamesScore.cs" company="Google Inc.">
// Copyright (C) 2014 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
#if UNITY_ANDROID
namespace GooglePlayGames
{
using System;
using UnityEngine.SocialPlatforms;
/// <summary>
/// Represents a Google Play Games score that can be sent to a leaderboard.
/// </summary>
public class PlayGamesScore : IScore
{
private string mLbId = null;
private long mValue = 0;
private ulong mRank = 0;
private string mPlayerId = string.Empty;
private string mMetadata = string.Empty;
private DateTime mDate = new DateTime(1970, 1, 1, 0, 0, 0);
internal PlayGamesScore(DateTime date, string leaderboardId,
ulong rank, string playerId, ulong value, string metadata)
{
this.mDate = date;
mLbId = leaderboardID;
this.mRank = rank;
this.mPlayerId = playerId;
this.mValue = (long) value;
this.mMetadata = metadata;
}
/// <summary>
/// Reports the score. Equivalent to <see cref="PlayGamesPlatform.ReportScore" />.
/// </summary>
public void ReportScore(Action<bool> callback)
{
PlayGamesPlatform.Instance.ReportScore(mValue, mLbId, mMetadata, callback);
}
/// <summary>
/// Gets or sets the leaderboard id.
/// </summary>
/// <returns>
/// The leaderboard id.
/// </returns>
public string leaderboardID
{
get { return mLbId; }
set { mLbId = value; }
}
/// <summary>
/// Gets or sets the score value.
/// </summary>
/// <returns>
/// The value.
/// </returns>
public long value
{
get { return mValue; }
set { mValue = value; }
}
/// <summary>
/// Not implemented. Returns Jan 01, 1970, 00:00:00
/// </summary>
public DateTime date
{
get { return mDate; }
}
/// <summary>
/// Not implemented. Returns the value converted to a string, unformatted.
/// </summary>
public string formattedValue
{
get { return mValue.ToString(); }
}
/// <summary>
/// Not implemented. Returns the empty string.
/// </summary>
public string userID
{
get { return mPlayerId; }
}
/// <summary>
/// Not implemented. Returns 1.
/// </summary>
public int rank
{
get { return (int) mRank; }
}
/// <summary>
/// Gets the metaData (scoreTag).
/// </summary>
/// <returns>
/// The metaData.
/// </returns>
public string metaData
{
get { return mMetadata; }
}
}
}
#endif
\ No newline at end of file
fileFormatVersion: 2
guid: 2a6e2425305ab455a91061b1eb955b38
labels:
- gvh
- gvh_version-0.11.01
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
// <copyright file="PlayGamesUserProfile.cs" company="Google Inc.">
// Copyright (C) 2014 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
#if UNITY_ANDROID
namespace GooglePlayGames
{
using System;
using System.Collections;
using GooglePlayGames.OurUtils;
using UnityEngine;
#if UNITY_2017_2_OR_NEWER
using UnityEngine.Networking;
#endif
using UnityEngine.SocialPlatforms;
/// <summary>
/// Represents a Google Play Games user profile. In the current implementation,
/// this is only used as a base class of <see cref="PlayGamesLocalUser" />
/// and should not be used directly.
/// </summary>
public class PlayGamesUserProfile : IUserProfile
{
private string mDisplayName;
private string mPlayerId;
private string mAvatarUrl;
private bool mIsFriend;
private volatile bool mImageLoading = false;
private Texture2D mImage;
internal PlayGamesUserProfile(string displayName, string playerId,
string avatarUrl)
{
mDisplayName = displayName;
mPlayerId = playerId;
setAvatarUrl(avatarUrl);
mImageLoading = false;
mIsFriend = false;
}
internal PlayGamesUserProfile(string displayName, string playerId, string avatarUrl,
bool isFriend)
{
mDisplayName = displayName;
mPlayerId = playerId;
mAvatarUrl = avatarUrl;
mImageLoading = false;
mIsFriend = isFriend;
}
protected void ResetIdentity(string displayName, string playerId,
string avatarUrl)
{
mDisplayName = displayName;
mPlayerId = playerId;
mIsFriend = false;
if (mAvatarUrl != avatarUrl)
{
mImage = null;
setAvatarUrl(avatarUrl);
}
mImageLoading = false;
}
#region IUserProfile implementation
public string userName
{
get { return mDisplayName; }
}
public string id
{
get { return mPlayerId; }
}
public string gameId
{
get { return mPlayerId; }
}
public bool isFriend
{
get { return mIsFriend; }
}
public UserState state
{
get { return UserState.Online; }
}
public Texture2D image
{
get
{
if (!mImageLoading && mImage == null && !string.IsNullOrEmpty(AvatarURL))
{
OurUtils.Logger.d("Starting to load image: " + AvatarURL);
mImageLoading = true;
PlayGamesHelperObject.RunCoroutine(LoadImage());
}
return mImage;
}
}
#endregion
public string AvatarURL
{
get { return mAvatarUrl; }
}
/// <summary>
/// Loads the local user's image from the url. Loading urls
/// is asynchronous so the return from this call is fast,
/// the image is returned once it is loaded. null is returned
/// up to that point.
/// </summary>
internal IEnumerator LoadImage()
{
// the url can be null if the user does not have an
// avatar configured.
if (!string.IsNullOrEmpty(AvatarURL))
{
#if UNITY_2017_2_OR_NEWER
UnityWebRequest www = UnityWebRequestTexture.GetTexture(AvatarURL);
www.SendWebRequest();
#else
WWW www = new WWW(AvatarURL);
#endif
while (!www.isDone)
{
yield return null;
}
if (www.error == null)
{
#if UNITY_2017_2_OR_NEWER
this.mImage = DownloadHandlerTexture.GetContent(www);
#else
this.mImage = www.texture;
#endif
}
else
{
mImage = Texture2D.blackTexture;
OurUtils.Logger.e("Error downloading image: " + www.error);
}
mImageLoading = false;
}
else
{
OurUtils.Logger.e("No URL found.");
mImage = Texture2D.blackTexture;
mImageLoading = false;
}
}
public override bool Equals(object obj)
{
if (obj == null)
{
return false;
}
if (ReferenceEquals(this, obj))
{
return true;
}
PlayGamesUserProfile other = obj as PlayGamesUserProfile;
if (other == null)
{
return false;
}
return StringComparer.Ordinal.Equals(mPlayerId, other.mPlayerId);
}
public override int GetHashCode()
{
return typeof(PlayGamesUserProfile).GetHashCode() ^ mPlayerId.GetHashCode();
}
public override string ToString()
{
return string.Format("[Player: '{0}' (id {1})]", mDisplayName, mPlayerId);
}
private void setAvatarUrl(string avatarUrl)
{
mAvatarUrl = avatarUrl;
if (!avatarUrl.StartsWith("https") && avatarUrl.StartsWith("http"))
{
mAvatarUrl = avatarUrl.Insert(4, "s");
}
}
}
}
#endif
fileFormatVersion: 2
guid: ab1b90315f37e498a849765260dd436c
labels:
- gvh
- gvh_version-0.11.01
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: dc34e4ac2f7e6420da72898e7b511098
folderAsset: yes
DefaultImporter:
userData:
// <copyright file="Logger.cs" company="Google Inc.">
// Copyright (C) 2014 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
namespace GooglePlayGames.OurUtils
{
using System;
using UnityEngine;
public class Logger
{
private static bool debugLogEnabled = false;
public static bool DebugLogEnabled
{
get { return debugLogEnabled; }
set { debugLogEnabled = value; }
}
private static bool warningLogEnabled = true;
public static bool WarningLogEnabled
{
get { return warningLogEnabled; }
set { warningLogEnabled = value; }
}
public static void d(string msg)
{
if (debugLogEnabled)
{
PlayGamesHelperObject.RunOnGameThread(() =>
Debug.Log(ToLogMessage(string.Empty, "DEBUG", msg)));
}
}
public static void w(string msg)
{
if (warningLogEnabled)
{
PlayGamesHelperObject.RunOnGameThread(() =>
Debug.LogWarning(ToLogMessage("!!!", "WARNING", msg)));
}
}
public static void e(string msg)
{
if (warningLogEnabled)
{
PlayGamesHelperObject.RunOnGameThread(() =>
Debug.LogWarning(ToLogMessage("***", "ERROR", msg)));
}
}
public static string describe(byte[] b)
{
return b == null ? "(null)" : "byte[" + b.Length + "]";
}
private static string ToLogMessage(string prefix, string logType, string msg)
{
string timeString = null;
try
{
timeString = DateTime.Now.ToString("MM/dd/yy H:mm:ss zzz");
}
catch (Exception)
{
PlayGamesHelperObject.RunOnGameThread(() =>
Debug.LogWarning("*** [Play Games Plugin " + PluginVersion.VersionString + "] ERROR: Failed to format DateTime.Now"));
timeString = string.Empty;
}
return string.Format("{0} [Play Games Plugin " + PluginVersion.VersionString+ "] {1} {2}: {3}",
prefix, timeString, logType, msg);
}
}
}
fileFormatVersion: 2
guid: cde7cfd197b4a47edac2efe305e22e78
labels:
- gvh
- gvh_version-0.11.01
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
// <copyright file="Misc.cs" company="Google Inc.">
// Copyright (C) 2014 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
namespace GooglePlayGames.OurUtils
{
using System;
public static class Misc
{
public static bool BuffersAreIdentical(byte[] a, byte[] b)
{
if (a == b)
{
// not only identical but the very same!
return true;
}
if (a == null || b == null)
{
// one of them is null, the other one isn't
return false;
}
if (a.Length != b.Length)
{
return false;
}
for (int i = 0; i < a.Length; i++)
{
if (a[i] != b[i])
{
return false;
}
}
return true;
}
public static byte[] GetSubsetBytes(byte[] array, int offset, int length)
{
if (array == null)
{
throw new ArgumentNullException("array");
}
if (offset < 0 || offset >= array.Length)
{
throw new ArgumentOutOfRangeException("offset");
}
if (length < 0 || (array.Length - offset) < length)
{
throw new ArgumentOutOfRangeException("length");
}
if (offset == 0 && length == array.Length)
{
return array;
}
byte[] piece = new byte[length];
Array.Copy(array, offset, piece, 0, length);
return piece;
}
public static T CheckNotNull<T>(T value)
{
if (value == null)
{
throw new ArgumentNullException();
}
return value;
}
public static T CheckNotNull<T>(T value, string paramName)
{
if (value == null)
{
throw new ArgumentNullException(paramName);
}
return value;
}
}
}
\ No newline at end of file
fileFormatVersion: 2
guid: ee52269f55933442fa5ea52e688ebec2
labels:
- gvh
- gvh_version-0.11.01
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
#if UNITY_ANDROID
namespace GooglePlayGames.OurUtils
{
using BasicApi.Nearby;
using System;
using UnityEngine;
public class NearbyHelperObject : MonoBehaviour
{
// our (singleton) instance
private static NearbyHelperObject instance = null;
// timers to keep track of discovery and advertising
private static double mAdvertisingRemaining = 0;
private static double mDiscoveryRemaining = 0;
// nearby client to stop discovery and to stop advertising
private static INearbyConnectionClient mClient = null;
public static void CreateObject(INearbyConnectionClient client)
{
if (instance != null)
{
return;
}
mClient = client;
if (Application.isPlaying)
{
// add an invisible game object to the scene
GameObject obj = new GameObject("PlayGames_NearbyHelper");
DontDestroyOnLoad(obj);
instance = obj.AddComponent<NearbyHelperObject>();
}
else
{
instance = new NearbyHelperObject();
}
}
private static double ToSeconds(TimeSpan? span)
{
if (!span.HasValue)
{
return 0;
}
if (span.Value.TotalSeconds < 0)
{
return 0;
}
return span.Value.TotalSeconds;
}
public static void StartAdvertisingTimer(TimeSpan? span)
{
mAdvertisingRemaining = ToSeconds(span);
}
public static void StartDiscoveryTimer(TimeSpan? span)
{
mDiscoveryRemaining = ToSeconds(span);
}
public void Awake()
{
DontDestroyOnLoad(gameObject);
}
public void OnDisable()
{
if (instance == this)
{
instance = null;
}
}
public void Update()
{
// check if currently advertising
if (mAdvertisingRemaining > 0)
{
mAdvertisingRemaining -= Time.deltaTime;
if (mAdvertisingRemaining < 0)
{
mClient.StopAdvertising();
}
}
// check if currently discovering
if (mDiscoveryRemaining > 0)
{
mDiscoveryRemaining -= Time.deltaTime;
if (mDiscoveryRemaining < 0)
{
mClient.StopDiscovery(mClient.GetServiceId());
}
}
}
}
}
#endif
\ No newline at end of file
fileFormatVersion: 2
guid: b66cca4a5a1f4a5092a280c452185308
labels:
- gvh
- gvh_version-0.11.01
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
// <copyright file="PlayGamesHelperObject.cs" company="Google Inc.">
// Copyright (C) 2014 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
#if UNITY_ANDROID
namespace GooglePlayGames.OurUtils
{
using UnityEngine;
using System;
public static class PlatformUtils
{
/// <summary>
/// Check if the Google Play Games platform is supported at runtime.
/// </summary>
/// <value>If the platform is supported.</value>
public static bool Supported
{
get
{
#if UNITY_EDITOR
return false;
#else
var up = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
var ca = up.GetStatic<AndroidJavaObject>("currentActivity");
var packageManager = ca.Call<AndroidJavaObject>("getPackageManager");
AndroidJavaObject launchIntent = null;
//if the app is installed, no errors. Else, doesn't get past next line
try
{
launchIntent =
packageManager.Call<AndroidJavaObject>("getLaunchIntentForPackage", "com.google.android.play.games");
}
catch (Exception)
{
return false;
}
return launchIntent != null;
#endif
}
}
}
}
#endif //UNITY_ANDROID
\ No newline at end of file
fileFormatVersion: 2
guid: 053811e778f3d4e3e98065f5db5bd005
labels:
- gvh
- gvh_version-0.11.01
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
// <copyright file="PlayGamesHelperObject.cs" company="Google Inc.">
// Copyright (C) 2014 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
namespace GooglePlayGames.OurUtils
{
using System;
using System.Collections;
using UnityEngine;
using System.Collections.Generic;
public class PlayGamesHelperObject : MonoBehaviour
{
// our (singleton) instance
private static PlayGamesHelperObject instance = null;
// are we a dummy instance (used in the editor?)
private static bool sIsDummy = false;
// queue of actions to run on the game thread
private static List<System.Action> sQueue = new List<Action>();
// member variable used to copy actions from the sQueue and
// execute them on the game thread. It is a member variable
// to help minimize memory allocations.
List<System.Action> localQueue = new List<System.Action>();
// flag that alerts us that we should check the queue
// (we do this just so we don't have to lock() the queue every
// frame to check if it's empty or not).
private volatile static bool sQueueEmpty = true;
// callback for application pause and focus events
private static List<Action<bool>> sPauseCallbackList =
new List<Action<bool>>();
private static List<Action<bool>> sFocusCallbackList =
new List<Action<bool>>();
// Call this once from the game thread
public static void CreateObject()
{
if (instance != null)
{
return;
}
if (Application.isPlaying)
{
// add an invisible game object to the scene
GameObject obj = new GameObject("PlayGames_QueueRunner");
DontDestroyOnLoad(obj);
instance = obj.AddComponent<PlayGamesHelperObject>();
}
else
{
instance = new PlayGamesHelperObject();
sIsDummy = true;
}
}
public void Awake()
{
DontDestroyOnLoad(gameObject);
}
public void OnDisable()
{
if (instance == this)
{
instance = null;
}
}
public static void RunCoroutine(IEnumerator action)
{
if (instance != null)
{
RunOnGameThread(() => instance.StartCoroutine(action));
}
}
public static void RunOnGameThread(System.Action action)
{
if (action == null)
{
throw new ArgumentNullException("action");
}
if (sIsDummy)
{
return;
}
lock (sQueue)
{
sQueue.Add(action);
sQueueEmpty = false;
}
}
public void Update()
{
if (sIsDummy || sQueueEmpty)
{
return;
}
// first copy the shared queue into a local queue
localQueue.Clear();
lock (sQueue)
{
// transfer the whole queue to our local queue
localQueue.AddRange(sQueue);
sQueue.Clear();
sQueueEmpty = true;
}
// execute queued actions (from local queue)
// use a loop to avoid extra memory allocations using the
// forEach
for (int i = 0; i < localQueue.Count; i++)
{
localQueue[i].Invoke();
}
}
public void OnApplicationFocus(bool focused)
{
foreach (Action<bool> cb in sFocusCallbackList)
{
try
{
cb(focused);
}
catch (Exception e)
{
Logger.e("Exception in OnApplicationFocus:" +
e.Message + "\n" + e.StackTrace);
}
}
}
public void OnApplicationPause(bool paused)
{
foreach (Action<bool> cb in sPauseCallbackList)
{
try
{
cb(paused);
}
catch (Exception e)
{
Logger.e("Exception in OnApplicationPause:" +
e.Message + "\n" + e.StackTrace);
}
}
}
/// <summary>
/// Adds a callback that is called when the Unity method OnApplicationFocus
/// is called.
/// </summary>
/// <see cref="OnApplicationFocus"/>
/// <param name="callback">Callback.</param>
public static void AddFocusCallback(Action<bool> callback)
{
if (!sFocusCallbackList.Contains(callback))
{
sFocusCallbackList.Add(callback);
}
}
/// <summary>
/// Removes the callback from the list to call when handling OnApplicationFocus
/// is called.
/// </summary>
/// <returns><c>true</c>, if focus callback was removed, <c>false</c> otherwise.</returns>
/// <param name="callback">Callback.</param>
public static bool RemoveFocusCallback(Action<bool> callback)
{
return sFocusCallbackList.Remove(callback);
}
/// <summary>
/// Adds a callback that is called when the Unity method OnApplicationPause
/// is called.
/// </summary>
/// <see cref="OnApplicationPause"/>
/// <param name="callback">Callback.</param>
public static void AddPauseCallback(Action<bool> callback)
{
if (!sPauseCallbackList.Contains(callback))
{
sPauseCallbackList.Add(callback);
}
}
/// <summary>
/// Removes the callback from the list to call when handling OnApplicationPause
/// is called.
/// </summary>
/// <returns><c>true</c>, if focus callback was removed, <c>false</c> otherwise.</returns>
/// <param name="callback">Callback.</param>
public static bool RemovePauseCallback(Action<bool> callback)
{
return sPauseCallbackList.Remove(callback);
}
}
}
\ No newline at end of file
fileFormatVersion: 2
guid: 7dd6f93ee6cb54945aea72a87542f720
labels:
- gvh
- gvh_version-0.11.01
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 58fac82a81a11415b99606841f6040a6
folderAsset: yes
DefaultImporter:
userData:
fileFormatVersion: 2
guid: 5c9032ae026414e1bbe872da53708edd
folderAsset: yes
timeCreated: 1441206393
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:
// <copyright file="NativeClient.cs" company="Google Inc.">
// Copyright (C) 2014 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
#if UNITY_ANDROID
#pragma warning disable 0642 // Possible mistaken empty statement
namespace GooglePlayGames.Android
{
using GooglePlayGames.BasicApi;
using GooglePlayGames.BasicApi.Events;
using GooglePlayGames.BasicApi.SavedGame;
using GooglePlayGames.OurUtils;
using System;
using UnityEngine;
using UnityEngine.SocialPlatforms;
public class AndroidClient : IPlayGamesClient
{
private enum AuthState
{
Unauthenticated,
Authenticated
}
private readonly object GameServicesLock = new object();
private readonly object AuthStateLock = new object();
private readonly static String PlayGamesSdkClassName =
"com.google.android.gms.games.PlayGamesSdk";
private volatile ISavedGameClient mSavedGameClient;
private volatile IEventsClient mEventsClient;
private volatile Player mUser = null;
private volatile AuthState mAuthState = AuthState.Unauthenticated;
private IUserProfile[] mFriends = new IUserProfile[0];
private LoadFriendsStatus mLastLoadFriendsStatus = LoadFriendsStatus.Unknown;
AndroidJavaClass mGamesClass = new AndroidJavaClass("com.google.android.gms.games.PlayGames");
private static string TasksClassName = "com.google.android.gms.tasks.Tasks";
private AndroidJavaObject mFriendsResolutionException = null;
private readonly int mLeaderboardMaxResults = 25; // can be from 1 to 25
private readonly int mFriendsMaxResults = 200; // the maximum load friends page size
internal AndroidClient()
{
PlayGamesHelperObject.CreateObject();
InitializeSdk();
}
private static void InitializeSdk() {
using (var playGamesSdkClass = new AndroidJavaClass(PlayGamesSdkClassName)) {
playGamesSdkClass.CallStatic("initialize", AndroidHelperFragment.GetActivity());
}
}
public void Authenticate(Action<SignInStatus> callback)
{
Authenticate( /* isAutoSignIn= */ true, callback);
}
public void ManuallyAuthenticate(Action<SignInStatus> callback)
{
Authenticate( /* isAutoSignIn= */ false, callback);
}
private void Authenticate(bool isAutoSignIn, Action<SignInStatus> callback)
{
callback = AsOnGameThreadCallback(callback);
lock (AuthStateLock)
{
// If the user is already authenticated, just fire the callback, we don't need
// any additional work.
if (mAuthState == AuthState.Authenticated)
{
OurUtils.Logger.d("Already authenticated.");
InvokeCallbackOnGameThread(callback, SignInStatus.Success);
return;
}
}
string methodName = isAutoSignIn ? "isAuthenticated" : "signIn";
OurUtils.Logger.d("Starting Auth using the method " + methodName);
using (var client = getGamesSignInClient())
using (
var task = client.Call<AndroidJavaObject>(methodName))
{
AndroidTaskUtils.AddOnSuccessListener<AndroidJavaObject>(task, authenticationResult =>
{
bool isAuthenticated = authenticationResult.Call<bool>("isAuthenticated");
SignInOnResult(isAuthenticated, callback);
});
AndroidTaskUtils.AddOnFailureListener(task, exception =>
{
OurUtils.Logger.e("Authentication failed - " + exception.Call<string>("toString"));
callback(SignInStatus.InternalError);
});
}
}
private void SignInOnResult(bool isAuthenticated, Action<SignInStatus> callback)
{
if (isAuthenticated)
{
using (var signInTasks = new AndroidJavaObject("java.util.ArrayList"))
{
AndroidJavaObject taskGetPlayer =
getPlayersClient().Call<AndroidJavaObject>("getCurrentPlayer");
signInTasks.Call<bool>("add", taskGetPlayer);
using (var tasks = new AndroidJavaClass(TasksClassName))
using (var allTask = tasks.CallStatic<AndroidJavaObject>("whenAll", signInTasks))
{
AndroidTaskUtils.AddOnCompleteListener<AndroidJavaObject>(
allTask,
completeTask =>
{
if (completeTask.Call<bool>("isSuccessful"))
{
using (var resultObject = taskGetPlayer.Call<AndroidJavaObject>("getResult"))
{
mUser = AndroidJavaConverter.ToPlayer(resultObject);
}
lock (GameServicesLock)
{
mSavedGameClient = new AndroidSavedGameClient(this);
mEventsClient = new AndroidEventsClient();
}
mAuthState = AuthState.Authenticated;
InvokeCallbackOnGameThread(callback, SignInStatus.Success);
OurUtils.Logger.d("Authentication succeeded");
LoadAchievements(ignore => { });
}
else
{
if (completeTask.Call<bool>("isCanceled"))
{
InvokeCallbackOnGameThread(callback, SignInStatus.Canceled);
return;
}
using (var exception = completeTask.Call<AndroidJavaObject>("getException"))
{
OurUtils.Logger.e(
"Authentication failed - " + exception.Call<string>("toString"));
InvokeCallbackOnGameThread(callback, SignInStatus.InternalError);
}
}
}
);
}
}
}
else
{
lock (AuthStateLock)
{
OurUtils.Logger.e("Returning an error code.");
InvokeCallbackOnGameThread(callback, SignInStatus.Canceled);
}
}
}
public void RequestServerSideAccess(bool forceRefreshToken, Action<string> callback)
{
callback = AsOnGameThreadCallback(callback);
if (!GameInfo.WebClientIdInitialized())
{
throw new InvalidOperationException("Requesting server side access requires web " +
"client id to be configured.");
}
using (var client = getGamesSignInClient())
using (var task = client.Call<AndroidJavaObject>("requestServerSideAccess",
GameInfo.WebClientId, forceRefreshToken))
{
AndroidTaskUtils.AddOnSuccessListener<string>(
task,
authCode => callback(authCode)
);
AndroidTaskUtils.AddOnFailureListener(task, exception =>
{
OurUtils.Logger.e("Requesting server side access task failed - " +
exception.Call<string>("toString"));
callback(null);
});
}
}
private static Action<T> AsOnGameThreadCallback<T>(Action<T> callback)
{
if (callback == null)
{
return delegate { };
}
return result => InvokeCallbackOnGameThread(callback, result);
}
private static void InvokeCallbackOnGameThread(Action callback)
{
if (callback == null)
{
return;
}
PlayGamesHelperObject.RunOnGameThread(() => { callback(); });
}
private static void InvokeCallbackOnGameThread<T>(Action<T> callback, T data)
{
if (callback == null)
{
return;
}
PlayGamesHelperObject.RunOnGameThread(() => { callback(data); });
}
private static Action<T1, T2> AsOnGameThreadCallback<T1, T2>(
Action<T1, T2> toInvokeOnGameThread)
{
return (result1, result2) =>
{
if (toInvokeOnGameThread == null)
{
return;
}
PlayGamesHelperObject.RunOnGameThread(() => toInvokeOnGameThread(result1, result2));
};
}
private static void InvokeCallbackOnGameThread<T1, T2>(Action<T1, T2> callback, T1 t1, T2 t2)
{
if (callback == null)
{
return;
}
PlayGamesHelperObject.RunOnGameThread(() => { callback(t1, t2); });
}
public bool IsAuthenticated()
{
lock (AuthStateLock)
{
return mAuthState == AuthState.Authenticated;
}
}
public void LoadFriends(Action<bool> callback)
{
LoadAllFriends(mFriendsMaxResults, /* forceReload= */ false, /* loadMore= */ false, callback);
}
private void LoadAllFriends(int pageSize, bool forceReload, bool loadMore,
Action<bool> callback)
{
LoadFriendsPaginated(pageSize, loadMore, forceReload, result =>
{
mLastLoadFriendsStatus = result;
switch (result)
{
case LoadFriendsStatus.Completed:
InvokeCallbackOnGameThread(callback, true);
break;
case LoadFriendsStatus.LoadMore:
// There are more friends to load.
LoadAllFriends(pageSize, /* forceReload= */ false, /* loadMore= */ true, callback);
break;
case LoadFriendsStatus.ResolutionRequired:
case LoadFriendsStatus.InternalError:
case LoadFriendsStatus.NotAuthorized:
InvokeCallbackOnGameThread(callback, false);
break;
default:
GooglePlayGames.OurUtils.Logger.d("There was an error when loading friends." + result);
InvokeCallbackOnGameThread(callback, false);
break;
}
});
}
public void LoadFriends(int pageSize, bool forceReload,
Action<LoadFriendsStatus> callback)
{
LoadFriendsPaginated(pageSize, /* isLoadMore= */ false, /* forceReload= */ forceReload,
callback);
}
public void LoadMoreFriends(int pageSize, Action<LoadFriendsStatus> callback)
{
LoadFriendsPaginated(pageSize, /* isLoadMore= */ true, /* forceReload= */ false,
callback);
}
private void LoadFriendsPaginated(int pageSize, bool isLoadMore, bool forceReload,
Action<LoadFriendsStatus> callback)
{
mFriendsResolutionException = null;
using (var playersClient = getPlayersClient())
using (var task = isLoadMore
? playersClient.Call<AndroidJavaObject>("loadMoreFriends", pageSize)
: playersClient.Call<AndroidJavaObject>("loadFriends", pageSize,
forceReload))
{
AndroidTaskUtils.AddOnSuccessListener<AndroidJavaObject>(
task, annotatedData =>
{
using (var playersBuffer = annotatedData.Call<AndroidJavaObject>("get"))
{
AndroidJavaObject metadata = playersBuffer.Call<AndroidJavaObject>("getMetadata");
var areMoreFriendsToLoad = metadata != null &&
metadata.Call<AndroidJavaObject>("getString",
"next_page_token") != null;
mFriends = AndroidJavaConverter.playersBufferToArray(playersBuffer);
mLastLoadFriendsStatus = areMoreFriendsToLoad
? LoadFriendsStatus.LoadMore
: LoadFriendsStatus.Completed;
InvokeCallbackOnGameThread(callback, mLastLoadFriendsStatus);
}
});
AndroidTaskUtils.AddOnFailureListener(task, exception =>
{
AndroidHelperFragment.IsResolutionRequired(exception, resolutionRequired =>
{
if (resolutionRequired)
{
mFriendsResolutionException =
exception.Call<AndroidJavaObject>("getResolution");
mLastLoadFriendsStatus = LoadFriendsStatus.ResolutionRequired;
mFriends = new IUserProfile[0];
InvokeCallbackOnGameThread(callback, LoadFriendsStatus.ResolutionRequired);
}
else
{
mFriendsResolutionException = null;
if (IsApiException(exception))
{
var statusCode = exception.Call<int>("getStatusCode");
if (statusCode == /* GamesClientStatusCodes.NETWORK_ERROR_NO_DATA */ 26504)
{
mLastLoadFriendsStatus = LoadFriendsStatus.NetworkError;
InvokeCallbackOnGameThread(callback, LoadFriendsStatus.NetworkError);
return;
}
}
mLastLoadFriendsStatus = LoadFriendsStatus.InternalError;
OurUtils.Logger.e("LoadFriends failed: " +
exception.Call<string>("toString"));
InvokeCallbackOnGameThread(callback, LoadFriendsStatus.InternalError);
}
});
return;
});
}
}
private static bool IsApiException(AndroidJavaObject exception) {
var exceptionClassName = exception.Call<AndroidJavaObject>("getClass")
.Call<String>("getName");
return exceptionClassName == "com.google.android.gms.common.api.ApiException";
}
public LoadFriendsStatus GetLastLoadFriendsStatus()
{
return mLastLoadFriendsStatus;
}
public void AskForLoadFriendsResolution(Action<UIStatus> callback)
{
if (mFriendsResolutionException == null)
{
GooglePlayGames.OurUtils.Logger.d("The developer asked for access to the friends " +
"list but there is no intent to trigger the UI. This may be because the user " +
"has granted access already or the game has not called loadFriends() before.");
using (var playersClient = getPlayersClient())
using (
var task = playersClient.Call<AndroidJavaObject>("loadFriends", /* pageSize= */ 1,
/* forceReload= */ false))
{
AndroidTaskUtils.AddOnSuccessListener<AndroidJavaObject>(
task, annotatedData => { InvokeCallbackOnGameThread(callback, UIStatus.Valid); });
AndroidTaskUtils.AddOnFailureListener(task, exception =>
{
AndroidHelperFragment.IsResolutionRequired(exception, resolutionRequired =>
{
if (resolutionRequired)
{
mFriendsResolutionException =
exception.Call<AndroidJavaObject>("getResolution");
AndroidHelperFragment.AskForLoadFriendsResolution(
mFriendsResolutionException, AsOnGameThreadCallback(callback));
return;
}
if (IsApiException(exception))
{
var statusCode = exception.Call<int>("getStatusCode");
if (statusCode ==
/* GamesClientStatusCodes.NETWORK_ERROR_NO_DATA */ 26504)
{
InvokeCallbackOnGameThread(callback, UIStatus.NetworkError);
return;
}
}
OurUtils.Logger.e("LoadFriends failed: " +
exception.Call<string>("toString"));
InvokeCallbackOnGameThread(callback, UIStatus.InternalError);
});
});
}
}
else
{
AndroidHelperFragment.AskForLoadFriendsResolution(mFriendsResolutionException,
AsOnGameThreadCallback(callback));
}
}
public void ShowCompareProfileWithAlternativeNameHintsUI(string playerId,
string otherPlayerInGameName,
string currentPlayerInGameName,
Action<UIStatus> callback)
{
AndroidHelperFragment.ShowCompareProfileWithAlternativeNameHintsUI(
playerId, otherPlayerInGameName, currentPlayerInGameName,
AsOnGameThreadCallback(callback));
}
public void GetFriendsListVisibility(bool forceReload,
Action<FriendsListVisibilityStatus> callback)
{
using (var playersClient = getPlayersClient())
using (
var task = playersClient.Call<AndroidJavaObject>("getCurrentPlayer", forceReload))
{
AndroidTaskUtils.AddOnSuccessListener<AndroidJavaObject>(task, annotatedData =>
{
AndroidJavaObject currentPlayerInfo =
annotatedData.Call<AndroidJavaObject>("get").Call<AndroidJavaObject>(
"getCurrentPlayerInfo");
int playerListVisibility =
currentPlayerInfo.Call<int>("getFriendsListVisibilityStatus");
InvokeCallbackOnGameThread(callback,
AndroidJavaConverter.ToFriendsListVisibilityStatus(playerListVisibility));
});
AndroidTaskUtils.AddOnFailureListener(task, exception =>
{
InvokeCallbackOnGameThread(callback, FriendsListVisibilityStatus.NetworkError);
return;
});
}
}
public IUserProfile[] GetFriends()
{
return mFriends;
}
public string GetUserId()
{
if (mUser == null)
{
return null;
}
return mUser.id;
}
public string GetUserDisplayName()
{
if (mUser == null)
{
return null;
}
return mUser.userName;
}
public string GetUserImageUrl()
{
if (mUser == null)
{
return null;
}
return mUser.AvatarURL;
}
public void GetPlayerStats(Action<CommonStatusCodes, PlayerStats> callback)
{
using (var playerStatsClient = getPlayerStatsClient())
using (var task = playerStatsClient.Call<AndroidJavaObject>("loadPlayerStats", /* forceReload= */ false))
{
AndroidTaskUtils.AddOnSuccessListener<AndroidJavaObject>(
task,
annotatedData =>
{
using (var playerStatsJava = annotatedData.Call<AndroidJavaObject>("get"))
{
int numberOfPurchases = playerStatsJava.Call<int>("getNumberOfPurchases");
float avgSessionLength = playerStatsJava.Call<float>("getAverageSessionLength");
int daysSinceLastPlayed = playerStatsJava.Call<int>("getDaysSinceLastPlayed");
int numberOfSessions = playerStatsJava.Call<int>("getNumberOfSessions");
float sessionPercentile = playerStatsJava.Call<float>("getSessionPercentile");
float spendPercentile = playerStatsJava.Call<float>("getSpendPercentile");
float spendProbability = playerStatsJava.Call<float>("getSpendProbability");
float churnProbability = playerStatsJava.Call<float>("getChurnProbability");
float highSpenderProbability = playerStatsJava.Call<float>("getHighSpenderProbability");
float totalSpendNext28Days = playerStatsJava.Call<float>("getTotalSpendNext28Days");
PlayerStats result = new PlayerStats(
numberOfPurchases,
avgSessionLength,
daysSinceLastPlayed,
numberOfSessions,
sessionPercentile,
spendPercentile,
spendProbability,
churnProbability,
highSpenderProbability,
totalSpendNext28Days);
InvokeCallbackOnGameThread(callback, CommonStatusCodes.Success, result);
}
});
AndroidTaskUtils.AddOnFailureListener(task, exception =>
{
OurUtils.Logger.e("GetPlayerStats failed: " + exception.Call<string>("toString"));
var statusCode = IsAuthenticated()
? CommonStatusCodes.InternalError
: CommonStatusCodes.SignInRequired;
InvokeCallbackOnGameThread(callback, statusCode, new PlayerStats());
});
}
}
public void LoadUsers(string[] userIds, Action<IUserProfile[]> callback)
{
if (!IsAuthenticated())
{
InvokeCallbackOnGameThread(callback, new IUserProfile[0]);
return;
}
using (var playersClient = getPlayersClient())
{
object countLock = new object();
int count = userIds.Length;
int resultCount = 0;
IUserProfile[] users = new IUserProfile[count];
for (int i = 0; i < count; ++i)
{
using (var task = playersClient.Call<AndroidJavaObject>("loadPlayer", userIds[i]))
{
AndroidTaskUtils.AddOnSuccessListener<AndroidJavaObject>(
task,
annotatedData =>
{
using (var player = annotatedData.Call<AndroidJavaObject>("get"))
{
string playerId = player.Call<string>("getPlayerId");
for (int j = 0; j < count; ++j)
{
if (playerId == userIds[j])
{
users[j] = AndroidJavaConverter.ToPlayer(player);
break;
}
}
lock (countLock)
{
++resultCount;
if (resultCount == count)
{
InvokeCallbackOnGameThread(callback, users);
}
}
}
});
AndroidTaskUtils.AddOnFailureListener(task, exception =>
{
OurUtils.Logger.e("LoadUsers failed for index " + i +
" with: " + exception.Call<string>("toString"));
lock (countLock)
{
++resultCount;
if (resultCount == count)
{
InvokeCallbackOnGameThread(callback, users);
}
}
});
}
}
}
}
public void LoadAchievements(Action<Achievement[]> callback)
{
using (var achievementsClient = getAchievementsClient())
using (var task = achievementsClient.Call<AndroidJavaObject>("load", /* forceReload= */ false))
{
AndroidTaskUtils.AddOnSuccessListener<AndroidJavaObject>(
task,
annotatedData =>
{
using (var achievementBuffer = annotatedData.Call<AndroidJavaObject>("get"))
{
int count = achievementBuffer.Call<int>("getCount");
Achievement[] result = new Achievement[count];
for (int i = 0; i < count; ++i)
{
Achievement achievement = new Achievement();
using (var javaAchievement = achievementBuffer.Call<AndroidJavaObject>("get", i))
{
achievement.Id = javaAchievement.Call<string>("getAchievementId");
achievement.Description = javaAchievement.Call<string>("getDescription");
achievement.Name = javaAchievement.Call<string>("getName");
achievement.Points = javaAchievement.Call<ulong>("getXpValue");
long timestamp = javaAchievement.Call<long>("getLastUpdatedTimestamp");
achievement.LastModifiedTime = AndroidJavaConverter.ToDateTime(timestamp);
achievement.RevealedImageUrl = javaAchievement.Call<string>("getRevealedImageUrl");
achievement.UnlockedImageUrl = javaAchievement.Call<string>("getUnlockedImageUrl");
achievement.IsIncremental =
javaAchievement.Call<int>("getType") == 1 /* TYPE_INCREMENTAL */;
if (achievement.IsIncremental)
{
achievement.CurrentSteps = javaAchievement.Call<int>("getCurrentSteps");
achievement.TotalSteps = javaAchievement.Call<int>("getTotalSteps");
}
int state = javaAchievement.Call<int>("getState");
achievement.IsUnlocked = state == 0 /* STATE_UNLOCKED */;
achievement.IsRevealed = state == 1 /* STATE_REVEALED */;
}
result[i] = achievement;
}
achievementBuffer.Call("release");
InvokeCallbackOnGameThread(callback, result);
}
});
AndroidTaskUtils.AddOnFailureListener(task, exception =>
{
OurUtils.Logger.e("LoadAchievements failed: " + exception.Call<string>("toString"));
InvokeCallbackOnGameThread(callback, new Achievement[0]);
});
}
}
public void UnlockAchievement(string achId, Action<bool> callback)
{
if (!IsAuthenticated())
{
InvokeCallbackOnGameThread(callback, false);
return;
}
using (var achievementsClient = getAchievementsClient())
{
achievementsClient.Call("unlock", achId);
InvokeCallbackOnGameThread(callback, true);
}
}
public void RevealAchievement(string achId, Action<bool> callback)
{
if (!IsAuthenticated())
{
InvokeCallbackOnGameThread(callback, false);
return;
}
using (var achievementsClient = getAchievementsClient())
{
achievementsClient.Call("reveal", achId);
InvokeCallbackOnGameThread(callback, true);
}
}
public void IncrementAchievement(string achId, int steps, Action<bool> callback)
{
if (!IsAuthenticated())
{
InvokeCallbackOnGameThread(callback, false);
return;
}
using (var achievementsClient = getAchievementsClient())
{
achievementsClient.Call("increment", achId, steps);
InvokeCallbackOnGameThread(callback, true);
}
}
public void SetStepsAtLeast(string achId, int steps, Action<bool> callback)
{
if (!IsAuthenticated())
{
InvokeCallbackOnGameThread(callback, false);
return;
}
using (var achievementsClient = getAchievementsClient())
{
achievementsClient.Call("setSteps", achId, steps);
InvokeCallbackOnGameThread(callback, true);
}
}
public void ShowAchievementsUI(Action<UIStatus> callback)
{
if (!IsAuthenticated())
{
InvokeCallbackOnGameThread(callback, UIStatus.NotAuthorized);
return;
}
AndroidHelperFragment.ShowAchievementsUI(AsOnGameThreadCallback(callback));
}
public int LeaderboardMaxResults()
{
return mLeaderboardMaxResults;
}
public void ShowLeaderboardUI(string leaderboardId, LeaderboardTimeSpan span, Action<UIStatus> callback)
{
if (!IsAuthenticated())
{
InvokeCallbackOnGameThread(callback, UIStatus.NotAuthorized);
return;
}
if (leaderboardId == null)
{
AndroidHelperFragment.ShowAllLeaderboardsUI(AsOnGameThreadCallback(callback));
}
else
{
AndroidHelperFragment.ShowLeaderboardUI(leaderboardId, span,
AsOnGameThreadCallback(callback));
}
}
public void LoadScores(string leaderboardId, LeaderboardStart start,
int rowCount, LeaderboardCollection collection,
LeaderboardTimeSpan timeSpan,
Action<LeaderboardScoreData> callback)
{
using (var client = getLeaderboardsClient())
{
string loadScoresMethod =
start == LeaderboardStart.TopScores ? "loadTopScores" : "loadPlayerCenteredScores";
using (var task = client.Call<AndroidJavaObject>(
loadScoresMethod,
leaderboardId,
AndroidJavaConverter.ToLeaderboardVariantTimeSpan(timeSpan),
AndroidJavaConverter.ToLeaderboardVariantCollection(collection),
rowCount))
{
AndroidTaskUtils.AddOnSuccessListener<AndroidJavaObject>(
task,
annotatedData =>
{
using (var leaderboardScores = annotatedData.Call<AndroidJavaObject>("get"))
{
InvokeCallbackOnGameThread(callback, CreateLeaderboardScoreData(
leaderboardId,
collection,
timeSpan,
annotatedData.Call<bool>("isStale")
? ResponseStatus.SuccessWithStale
: ResponseStatus.Success,
leaderboardScores));
leaderboardScores.Call("release");
}
});
AndroidTaskUtils.AddOnFailureListener(task, exception =>
{
AndroidHelperFragment.IsResolutionRequired(
exception, resolutionRequired =>
{
if (resolutionRequired)
{
mFriendsResolutionException = exception.Call<AndroidJavaObject>(
"getResolution");
InvokeCallbackOnGameThread(
callback, new LeaderboardScoreData(leaderboardId,
ResponseStatus.ResolutionRequired));
}
else
{
mFriendsResolutionException = null;
}
});
OurUtils.Logger.e("LoadScores failed: " + exception.Call<string>("toString"));
InvokeCallbackOnGameThread(
callback, new LeaderboardScoreData(leaderboardId,
ResponseStatus.InternalError));
});
}
}
}
public void LoadMoreScores(ScorePageToken token, int rowCount,
Action<LeaderboardScoreData> callback)
{
using (var client = getLeaderboardsClient())
using (var task = client.Call<AndroidJavaObject>("loadMoreScores",
token.InternalObject, rowCount, AndroidJavaConverter.ToPageDirection(token.Direction)))
{
AndroidTaskUtils.AddOnSuccessListener<AndroidJavaObject>(
task,
annotatedData =>
{
using (var leaderboardScores = annotatedData.Call<AndroidJavaObject>("get"))
{
InvokeCallbackOnGameThread(callback, CreateLeaderboardScoreData(
token.LeaderboardId,
token.Collection,
token.TimeSpan,
annotatedData.Call<bool>("isStale")
? ResponseStatus.SuccessWithStale
: ResponseStatus.Success,
leaderboardScores));
leaderboardScores.Call("release");
}
});
AndroidTaskUtils.AddOnFailureListener(task, exception =>
{
AndroidHelperFragment.IsResolutionRequired(exception, resolutionRequired =>
{
if (resolutionRequired)
{
mFriendsResolutionException =
exception.Call<AndroidJavaObject>("getResolution");
InvokeCallbackOnGameThread(
callback, new LeaderboardScoreData(token.LeaderboardId,
ResponseStatus.ResolutionRequired));
}
else
{
mFriendsResolutionException = null;
}
});
OurUtils.Logger.e("LoadMoreScores failed: " + exception.Call<string>("toString"));
InvokeCallbackOnGameThread(
callback, new LeaderboardScoreData(token.LeaderboardId,
ResponseStatus.InternalError));
});
}
}
private LeaderboardScoreData CreateLeaderboardScoreData(
string leaderboardId,
LeaderboardCollection collection,
LeaderboardTimeSpan timespan,
ResponseStatus status,
AndroidJavaObject leaderboardScoresJava)
{
LeaderboardScoreData leaderboardScoreData = new LeaderboardScoreData(leaderboardId, status);
var scoresBuffer = leaderboardScoresJava.Call<AndroidJavaObject>("getScores");
int count = scoresBuffer.Call<int>("getCount");
for (int i = 0; i < count; ++i)
{
using (var leaderboardScore = scoresBuffer.Call<AndroidJavaObject>("get", i))
{
long timestamp = leaderboardScore.Call<long>("getTimestampMillis");
System.DateTime date = AndroidJavaConverter.ToDateTime(timestamp);
ulong rank = (ulong) leaderboardScore.Call<long>("getRank");
string scoreHolderId = "";
using (var scoreHolder = leaderboardScore.Call<AndroidJavaObject>("getScoreHolder"))
{
scoreHolderId = scoreHolder.Call<string>("getPlayerId");
}
ulong score = (ulong) leaderboardScore.Call<long>("getRawScore");
string metadata = leaderboardScore.Call<string>("getScoreTag");
leaderboardScoreData.AddScore(new PlayGamesScore(date, leaderboardId,
rank, scoreHolderId, score, metadata));
}
}
leaderboardScoreData.NextPageToken = new ScorePageToken(scoresBuffer, leaderboardId, collection,
timespan, ScorePageDirection.Forward);
leaderboardScoreData.PrevPageToken = new ScorePageToken(scoresBuffer, leaderboardId, collection,
timespan, ScorePageDirection.Backward);
using (var leaderboard = leaderboardScoresJava.Call<AndroidJavaObject>("getLeaderboard"))
using (var variants = leaderboard.Call<AndroidJavaObject>("getVariants"))
using (var variant = variants.Call<AndroidJavaObject>("get", 0))
{
leaderboardScoreData.Title = leaderboard.Call<string>("getDisplayName");
if (variant.Call<bool>("hasPlayerInfo"))
{
System.DateTime date = AndroidJavaConverter.ToDateTime(0);
ulong rank = (ulong) variant.Call<long>("getPlayerRank");
ulong score = (ulong) variant.Call<long>("getRawPlayerScore");
string metadata = variant.Call<string>("getPlayerScoreTag");
leaderboardScoreData.PlayerScore = new PlayGamesScore(date, leaderboardId,
rank, mUser.id, score, metadata);
}
leaderboardScoreData.ApproximateCount = (ulong) variant.Call<long>("getNumScores");
}
return leaderboardScoreData;
}
public void SubmitScore(string leaderboardId, long score, Action<bool> callback)
{
if (!IsAuthenticated())
{
InvokeCallbackOnGameThread(callback, false);
}
using (var client = getLeaderboardsClient())
{
client.Call("submitScore", leaderboardId, score);
InvokeCallbackOnGameThread(callback, true);
}
}
public void SubmitScore(string leaderboardId, long score, string metadata,
Action<bool> callback)
{
if (!IsAuthenticated())
{
InvokeCallbackOnGameThread(callback, false);
}
using (var client = getLeaderboardsClient())
{
client.Call("submitScore", leaderboardId, score, metadata);
InvokeCallbackOnGameThread(callback, true);
}
}
public ISavedGameClient GetSavedGameClient()
{
lock (GameServicesLock)
{
return mSavedGameClient;
}
}
public IEventsClient GetEventsClient()
{
lock (GameServicesLock)
{
return mEventsClient;
}
}
private AndroidJavaObject getAchievementsClient()
{
return mGamesClass.CallStatic<AndroidJavaObject>("getAchievementsClient",
AndroidHelperFragment.GetActivity());
}
private AndroidJavaObject getPlayersClient()
{
return mGamesClass.CallStatic<AndroidJavaObject>("getPlayersClient", AndroidHelperFragment.GetActivity());
}
private AndroidJavaObject getLeaderboardsClient()
{
return mGamesClass.CallStatic<AndroidJavaObject>("getLeaderboardsClient",
AndroidHelperFragment.GetActivity());
}
private AndroidJavaObject getPlayerStatsClient()
{
return mGamesClass.CallStatic<AndroidJavaObject>("getPlayerStatsClient",
AndroidHelperFragment.GetActivity());
}
private AndroidJavaObject getGamesSignInClient()
{
return mGamesClass.CallStatic<AndroidJavaObject>("getGamesSignInClient",
AndroidHelperFragment.GetActivity());
}
}
}
#endif
fileFormatVersion: 2
guid: 32e99ad5da22248a28a9ca51282b121f
labels:
- gvh
- gvh_version-0.11.01
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
#if UNITY_ANDROID
namespace GooglePlayGames.Android
{
using System;
using System.Collections.Generic;
using GooglePlayGames.BasicApi;
using GooglePlayGames.BasicApi.Events;
using GooglePlayGames.OurUtils;
using UnityEngine;
internal class AndroidEventsClient : IEventsClient
{
private volatile AndroidJavaObject mEventsClient;
public AndroidEventsClient()
{
using (var gamesClass = new AndroidJavaClass("com.google.android.gms.games.PlayGames"))
{
mEventsClient = gamesClass.CallStatic<AndroidJavaObject>("getEventsClient",
AndroidHelperFragment.GetActivity());
}
}
public void FetchAllEvents(DataSource source, Action<ResponseStatus, List<IEvent>> callback)
{
callback = ToOnGameThread(callback);
using (var task =
mEventsClient.Call<AndroidJavaObject>("load", source == DataSource.ReadNetworkOnly ? true : false))
{
AndroidTaskUtils.AddOnSuccessListener<AndroidJavaObject>(
task,
annotatedData =>
{
using (var buffer = annotatedData.Call<AndroidJavaObject>("get"))
{
int count = buffer.Call<int>("getCount");
List<IEvent> result = new List<IEvent>();
for (int i = 0; i < count; ++i)
{
using (var eventJava = buffer.Call<AndroidJavaObject>("get", i))
{
result.Add(CreateEvent(eventJava));
}
}
buffer.Call("release");
callback.Invoke(
annotatedData.Call<bool>("isStale")
? ResponseStatus.SuccessWithStale
: ResponseStatus.Success,
result
);
}
});
AndroidTaskUtils.AddOnFailureListener(
task,
exception =>
{
Debug.Log("FetchAllEvents failed");
callback.Invoke(ResponseStatus.InternalError, null);
});
}
}
public void FetchEvent(DataSource source, string eventId, Action<ResponseStatus, IEvent> callback)
{
callback = ToOnGameThread(callback);
string[] ids = new string[1];
ids[0] = eventId;
using (var task = mEventsClient.Call<AndroidJavaObject>("loadByIds",
source == DataSource.ReadNetworkOnly ? true : false, ids))
{
AndroidTaskUtils.AddOnSuccessListener<AndroidJavaObject>(
task,
annotatedData =>
{
using (var buffer = annotatedData.Call<AndroidJavaObject>("get"))
{
int count = buffer.Call<int>("getCount");
if (count > 0)
{
using (var eventJava = buffer.Call<AndroidJavaObject>("get", 0))
{
callback.Invoke(
annotatedData.Call<bool>("isStale")
? ResponseStatus.SuccessWithStale
: ResponseStatus.Success,
CreateEvent(eventJava)
);
}
}
else
{
callback.Invoke(
annotatedData.Call<bool>("isStale")
? ResponseStatus.SuccessWithStale
: ResponseStatus.Success,
null
);
}
buffer.Call("release");
}
});
AndroidTaskUtils.AddOnFailureListener(
task,
exception =>
{
Debug.Log("FetchEvent failed");
callback.Invoke(ResponseStatus.InternalError, null);
});
}
}
public void IncrementEvent(string eventId, uint stepsToIncrement)
{
mEventsClient.Call("increment", eventId, (int) stepsToIncrement);
}
private static Action<T1, T2> ToOnGameThread<T1, T2>(Action<T1, T2> toConvert)
{
return (val1, val2) => PlayGamesHelperObject.RunOnGameThread(() => toConvert(val1, val2));
}
private static BasicApi.Events.Event CreateEvent(AndroidJavaObject eventJava)
{
string id = eventJava.Call<string>("getEventId");
string name = eventJava.Call<string>("getName");
string description = eventJava.Call<string>("getDescription");
string imageUrl = eventJava.Call<string>("getIconImageUrl");
ulong currentCount = (ulong) eventJava.Call<long>("getValue");
EventVisibility visibility = eventJava.Call<bool>("isVisible")
? EventVisibility.Revealed
: EventVisibility.Hidden;
return new BasicApi.Events.Event(id, name, description, imageUrl, currentCount, visibility);
}
}
}
#endif
fileFormatVersion: 2
guid: 311e1761661a341bebebd422a144b5e8
labels:
- gvh
- gvh_version-0.11.01
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
// <copyright file="AndroidTokenClient.cs" company="Google Inc.">
// Copyright (C) 2015 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
#if UNITY_ANDROID
namespace GooglePlayGames.Android
{
using GooglePlayGames.BasicApi;
using GooglePlayGames.BasicApi.SavedGame;
using OurUtils;
using UnityEngine;
using System;
using System.Collections.Generic;
internal class AndroidHelperFragment
{
private const string HelperFragmentClass = "com.google.games.bridge.HelperFragment";
public static AndroidJavaObject GetActivity()
{
using (var jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
{
return jc.GetStatic<AndroidJavaObject>("currentActivity");
}
}
public static AndroidJavaObject GetDefaultPopupView()
{
using (var helperFragment = new AndroidJavaClass(HelperFragmentClass))
using (var activity = AndroidHelperFragment.GetActivity())
{
return helperFragment.CallStatic<AndroidJavaObject>("getDecorView", activity);
}
}
public static void ShowAchievementsUI(Action<UIStatus> cb)
{
using (var helperFragment = new AndroidJavaClass(HelperFragmentClass))
using (var task =
helperFragment.CallStatic<AndroidJavaObject>("showAchievementUi", AndroidHelperFragment.GetActivity()))
{
AndroidTaskUtils.AddOnSuccessListener<int>(
task,
uiCode =>
{
OurUtils.Logger.d("ShowAchievementsUI result " + uiCode);
cb.Invoke((UIStatus) uiCode);
});
AndroidTaskUtils.AddOnFailureListener(
task,
exception =>
{
OurUtils.Logger.e("ShowAchievementsUI failed with exception");
cb.Invoke(UIStatus.InternalError);
});
}
}
public static void ShowCaptureOverlayUI()
{
using (var helperFragment = new AndroidJavaClass(HelperFragmentClass))
{
helperFragment.CallStatic("showCaptureOverlayUi", AndroidHelperFragment.GetActivity());
}
}
public static void ShowAllLeaderboardsUI(Action<UIStatus> cb)
{
using (var helperFragment = new AndroidJavaClass(HelperFragmentClass))
using (var task =
helperFragment.CallStatic<AndroidJavaObject>("showAllLeaderboardsUi",
AndroidHelperFragment.GetActivity()))
{
AndroidTaskUtils.AddOnSuccessListener<int>(
task,
uiCode =>
{
OurUtils.Logger.d("ShowAllLeaderboardsUI result " + uiCode);
cb.Invoke((UIStatus) uiCode);
});
AndroidTaskUtils.AddOnFailureListener(
task,
exception =>
{
OurUtils.Logger.e("ShowAllLeaderboardsUI failed with exception");
cb.Invoke(UIStatus.InternalError);
});
}
}
public static void ShowLeaderboardUI(string leaderboardId, LeaderboardTimeSpan timeSpan, Action<UIStatus> cb)
{
using (var helperFragment = new AndroidJavaClass(HelperFragmentClass))
using (var task = helperFragment.CallStatic<AndroidJavaObject>("showLeaderboardUi",
AndroidHelperFragment.GetActivity(), leaderboardId,
AndroidJavaConverter.ToLeaderboardVariantTimeSpan(timeSpan)))
{
AndroidTaskUtils.AddOnSuccessListener<int>(
task,
uiCode =>
{
OurUtils.Logger.d("ShowLeaderboardUI result " + uiCode);
cb.Invoke((UIStatus) uiCode);
});
AndroidTaskUtils.AddOnFailureListener(
task,
exception =>
{
OurUtils.Logger.e("ShowLeaderboardUI failed with exception");
cb.Invoke(UIStatus.InternalError);
});
}
}
public static void ShowCompareProfileWithAlternativeNameHintsUI(
string playerId, string otherPlayerInGameName, string currentPlayerInGameName,
Action<UIStatus> cb)
{
using (var helperFragment = new AndroidJavaClass(HelperFragmentClass))
using (
var task = helperFragment.CallStatic<AndroidJavaObject>(
"showCompareProfileWithAlternativeNameHintsUI",
AndroidHelperFragment.GetActivity(), playerId, otherPlayerInGameName,
currentPlayerInGameName))
{
AndroidTaskUtils.AddOnSuccessListener<int>(task, uiCode =>
{
OurUtils.Logger.d("ShowCompareProfileWithAlternativeNameHintsUI result " + uiCode);
cb.Invoke((UIStatus) uiCode);
});
AndroidTaskUtils.AddOnFailureListener(task, exception =>
{
OurUtils.Logger.e("ShowCompareProfileWithAlternativeNameHintsUI failed with exception");
cb.Invoke(UIStatus.InternalError);
});
}
}
public static void IsResolutionRequired(
AndroidJavaObject friendsSharingConsentException, Action<bool> cb)
{
using (var helperFragment = new AndroidJavaClass(HelperFragmentClass))
{
var isResolutionRequired = helperFragment.CallStatic<bool>(
"isResolutionRequired", friendsSharingConsentException);
cb.Invoke(isResolutionRequired);
}
}
public static void AskForLoadFriendsResolution(
AndroidJavaObject friendsSharingConsentException, Action<UIStatus> cb)
{
using (var helperFragment = new AndroidJavaClass(HelperFragmentClass))
using (
var task = helperFragment.CallStatic<AndroidJavaObject>(
"askForLoadFriendsResolution", AndroidHelperFragment.GetActivity(),
friendsSharingConsentException))
{
AndroidTaskUtils.AddOnSuccessListener<int>(task, uiCode =>
{
OurUtils.Logger.d("AskForLoadFriendsResolution result " + uiCode);
cb.Invoke((UIStatus) uiCode);
});
AndroidTaskUtils.AddOnFailureListener(task, exception =>
{
OurUtils.Logger.e("AskForLoadFriendsResolution failed with exception");
cb.Invoke(UIStatus.InternalError);
});
}
}
public static void ShowSelectSnapshotUI(bool showCreateSaveUI, bool showDeleteSaveUI,
int maxDisplayedSavedGames, string uiTitle, Action<SelectUIStatus, ISavedGameMetadata> cb)
{
using (var helperFragment = new AndroidJavaClass(HelperFragmentClass))
using (var task = helperFragment.CallStatic<AndroidJavaObject>("showSelectSnapshotUi",
AndroidHelperFragment.GetActivity(), uiTitle, showCreateSaveUI, showDeleteSaveUI,
maxDisplayedSavedGames))
{
AndroidTaskUtils.AddOnSuccessListener<AndroidJavaObject>(
task,
result =>
{
SelectUIStatus status = (SelectUIStatus) result.Get<int>("status");
OurUtils.Logger.d("ShowSelectSnapshotUI result " + status);
AndroidJavaObject javaMetadata = result.Get<AndroidJavaObject>("metadata");
AndroidSnapshotMetadata metadata =
javaMetadata == null
? null
: new AndroidSnapshotMetadata(javaMetadata, /* contents= */null);
cb.Invoke(status, metadata);
});
AndroidTaskUtils.AddOnFailureListener(
task,
exception =>
{
OurUtils.Logger.e("ShowSelectSnapshotUI failed with exception");
cb.Invoke(SelectUIStatus.InternalError, null);
});
}
}
}
}
#endif
fileFormatVersion: 2
guid: 6eb353a6ffa554bacb374cfaf0cc45e7
labels:
- gvh
- gvh_version-0.11.01
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
// <copyright file="AndroidTokenClient.cs" company="Google Inc.">
// Copyright (C) 2015 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
#if UNITY_ANDROID
namespace GooglePlayGames.Android
{
using GooglePlayGames.BasicApi;
using GooglePlayGames.BasicApi.SavedGame;
using OurUtils;
using UnityEngine;
using UnityEngine.SocialPlatforms;
using System;
using System.Collections.Generic;
internal class AndroidJavaConverter
{
internal static System.DateTime ToDateTime(long milliseconds)
{
System.DateTime result = new System.DateTime(1970, 1, 1, 0, 0, 0, 0);
return result.AddMilliseconds(milliseconds);
}
// Convert to LeaderboardVariant.java#TimeSpan
internal static int ToLeaderboardVariantTimeSpan(LeaderboardTimeSpan span)
{
switch (span)
{
case LeaderboardTimeSpan.Daily:
return 0 /* TIME_SPAN_DAILY */;
case LeaderboardTimeSpan.Weekly:
return 1 /* TIME_SPAN_WEEKLY */;
case LeaderboardTimeSpan.AllTime:
default:
return 2 /* TIME_SPAN_ALL_TIME */;
}
}
// Convert to LeaderboardVariant.java#Collection
internal static int ToLeaderboardVariantCollection(LeaderboardCollection collection)
{
switch (collection)
{
case LeaderboardCollection.Social:
return 3 /* COLLECTION_FRIENDS */;
case LeaderboardCollection.Public:
default:
return 0 /* COLLECTION_PUBLIC */;
}
}
// Convert to PageDirection.java#Direction
internal static int ToPageDirection(ScorePageDirection direction)
{
switch (direction)
{
case ScorePageDirection.Forward:
return 0 /* NEXT */;
case ScorePageDirection.Backward:
return 1 /* PREV */;
default:
return -1 /* NONE */;
}
}
internal static Player ToPlayer(AndroidJavaObject player)
{
if (player == null)
{
return null;
}
string displayName = player.Call<String>("getDisplayName");
string playerId = player.Call<String>("getPlayerId");
string avatarUrl = player.Call<String>("getIconImageUrl");
return new Player(displayName, playerId, avatarUrl);
}
internal static PlayerProfile ToPlayerProfile(AndroidJavaObject player) {
if (player == null) {
return null;
}
string displayName = player.Call<String>("getDisplayName");
string playerId = player.Call<String>("getPlayerId");
string avatarUrl = player.Call<String>("getIconImageUrl");
bool isFriend =
player.Call<AndroidJavaObject>("getRelationshipInfo").Call<int>("getFriendStatus") ==
4 /* PlayerFriendStatus.Friend*/;
return new PlayerProfile(displayName, playerId, avatarUrl, isFriend);
}
internal static List<string> ToStringList(AndroidJavaObject stringList)
{
if (stringList == null)
{
return new List<string>();
}
int size = stringList.Call<int>("size");
List<string> converted = new List<string>(size);
for (int i = 0; i < size; i++)
{
converted.Add(stringList.Call<string>("get", i));
}
return converted;
}
// from C#: List<string> to Java: ArrayList<String>
internal static AndroidJavaObject ToJavaStringList(List<string> list)
{
AndroidJavaObject converted = new AndroidJavaObject("java.util.ArrayList");
for (int i = 0; i < list.Count; i++)
{
converted.Call<bool>("add", list[i]);
}
return converted;
}
internal static FriendsListVisibilityStatus ToFriendsListVisibilityStatus(int playerListVisibility) {
switch (playerListVisibility)
{
case /* FriendsListVisibilityStatus.UNKNOWN */ 0:
return FriendsListVisibilityStatus.Unknown;
case /* FriendsListVisibilityStatus.VISIBLE */ 1:
return FriendsListVisibilityStatus.Visible;
case /* FriendsListVisibilityStatus.REQUEST_REQUIRED */ 2:
return FriendsListVisibilityStatus.ResolutionRequired;
case /* FriendsListVisibilityStatus.FEATURE_UNAVAILABLE */ 3:
return FriendsListVisibilityStatus.Unavailable;
default:
return FriendsListVisibilityStatus.Unknown;
}
}
internal static IUserProfile[] playersBufferToArray(AndroidJavaObject playersBuffer) {
int count = playersBuffer.Call<int>("getCount");
IUserProfile[] users = new IUserProfile[count];
for (int i = 0; i < count; ++i) {
using (var player = playersBuffer.Call<AndroidJavaObject>("get", i)) {
users[i] = AndroidJavaConverter.ToPlayerProfile(player);
}
}
playersBuffer.Call("release");
return users;
}
}
}
#endif
fileFormatVersion: 2
guid: d498c17d61b504b4f984a99b4542d02f
labels:
- gvh
- gvh_version-0.11.01
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
#if UNITY_ANDROID
#pragma warning disable 0642 // Possible mistaken empty statement
namespace GooglePlayGames.Android
{
using System;
using System.Collections.Generic;
using GooglePlayGames.BasicApi;
using GooglePlayGames.BasicApi.Nearby;
using GooglePlayGames.OurUtils;
using UnityEngine;
public class AndroidNearbyConnectionClient : INearbyConnectionClient
{
private volatile AndroidJavaObject mClient;
private readonly static long NearbyClientId = 0L;
private readonly static int ApplicationInfoFlags = 0x00000080;
private readonly static string ServiceId = ReadServiceId();
protected IMessageListener mAdvertisingMessageListener;
public AndroidNearbyConnectionClient()
{
PlayGamesHelperObject.CreateObject();
NearbyHelperObject.CreateObject(this);
using (var nearbyClass = new AndroidJavaClass("com.google.android.gms.nearby.Nearby"))
{
mClient = nearbyClass.CallStatic<AndroidJavaObject>("getConnectionsClient",
AndroidHelperFragment.GetActivity());
}
}
public int MaxUnreliableMessagePayloadLength()
{
return NearbyConnectionConfiguration.MaxUnreliableMessagePayloadLength;
}
public int MaxReliableMessagePayloadLength()
{
return NearbyConnectionConfiguration.MaxReliableMessagePayloadLength;
}
public void SendReliable(List<string> recipientEndpointIds, byte[] payload)
{
InternalSend(recipientEndpointIds, payload);
}
public void SendUnreliable(List<string> recipientEndpointIds, byte[] payload)
{
InternalSend(recipientEndpointIds, payload);
}
private void InternalSend(List<string> recipientEndpointIds, byte[] payload)
{
Misc.CheckNotNull(recipientEndpointIds);
Misc.CheckNotNull(payload);
using (var payloadClass = new AndroidJavaClass("com.google.android.gms.nearby.connection.Payload"))
using (var payloadObject = payloadClass.CallStatic<AndroidJavaObject>("fromBytes", payload))
using (var task = mClient.Call<AndroidJavaObject>("sendPayload",
AndroidJavaConverter.ToJavaStringList(recipientEndpointIds),
payloadObject))
;
}
public void StartAdvertising(string name, List<string> appIdentifiers,
TimeSpan? advertisingDuration, Action<AdvertisingResult> resultCallback,
Action<ConnectionRequest> connectionRequestCallback)
{
Misc.CheckNotNull(resultCallback, "resultCallback");
Misc.CheckNotNull(connectionRequestCallback, "connectionRequestCallback");
if (advertisingDuration.HasValue && advertisingDuration.Value.Ticks < 0)
{
throw new InvalidOperationException("advertisingDuration must be positive");
}
connectionRequestCallback = ToOnGameThread(connectionRequestCallback);
resultCallback = ToOnGameThread(resultCallback);
AdvertisingConnectionLifecycleCallbackProxy callbackProxy =
new AdvertisingConnectionLifecycleCallbackProxy(resultCallback, connectionRequestCallback, this);
using (var connectionLifecycleCallback =
new AndroidJavaObject("com.google.games.bridge.ConnectionLifecycleCallbackProxy", callbackProxy))
using (var advertisingOptions = CreateAdvertisingOptions())
using (var task = mClient.Call<AndroidJavaObject>("startAdvertising", name, GetServiceId(),
connectionLifecycleCallback, advertisingOptions))
{
AndroidTaskUtils.AddOnSuccessListener<AndroidJavaObject>(
task,
v => NearbyHelperObject.StartAdvertisingTimer(advertisingDuration)
);
}
}
private AndroidJavaObject CreateAdvertisingOptions()
{
using (var strategy = new AndroidJavaClass("com.google.android.gms.nearby.connection.Strategy")
.GetStatic<AndroidJavaObject>("P2P_CLUSTER"))
using (var builder =
new AndroidJavaObject("com.google.android.gms.nearby.connection.AdvertisingOptions$Builder"))
using (builder.Call<AndroidJavaObject>("setStrategy", strategy))
{
return builder.Call<AndroidJavaObject>("build");
}
}
private class AdvertisingConnectionLifecycleCallbackProxy : AndroidJavaProxy
{
private Action<AdvertisingResult> mResultCallback;
private Action<ConnectionRequest> mConnectionRequestCallback;
private AndroidNearbyConnectionClient mClient;
private string mLocalEndpointName;
public AdvertisingConnectionLifecycleCallbackProxy(Action<AdvertisingResult> resultCallback,
Action<ConnectionRequest> connectionRequestCallback, AndroidNearbyConnectionClient client) : base(
"com/google/games/bridge/ConnectionLifecycleCallbackProxy$Callback")
{
mResultCallback = resultCallback;
mConnectionRequestCallback = connectionRequestCallback;
mClient = client;
}
public void onConnectionInitiated(string endpointId, AndroidJavaObject connectionInfo)
{
mLocalEndpointName = connectionInfo.Call<string>("getEndpointName");
mConnectionRequestCallback(new ConnectionRequest(endpointId, mLocalEndpointName, mClient.GetServiceId(),
new byte[0]));
}
public void onConnectionResult(string endpointId, AndroidJavaObject connectionResolution)
{
int statusCode;
using (var status = connectionResolution.Call<AndroidJavaObject>("getStatus"))
{
statusCode = status.Call<int>("getStatusCode");
}
if (statusCode == 0) // STATUS_OK
{
mResultCallback(new AdvertisingResult(ResponseStatus.Success, mLocalEndpointName));
return;
}
if (statusCode == 8001) // STATUS_ALREADY_ADVERTISING
{
mResultCallback(new AdvertisingResult(ResponseStatus.NotAuthorized, mLocalEndpointName));
return;
}
mResultCallback(new AdvertisingResult(ResponseStatus.InternalError, mLocalEndpointName));
}
public void onDisconnected(string endpointId)
{
if (mClient.mAdvertisingMessageListener != null)
{
mClient.mAdvertisingMessageListener.OnRemoteEndpointDisconnected(endpointId);
}
}
}
public void StopAdvertising()
{
mClient.Call("stopAdvertising");
mAdvertisingMessageListener = null;
}
public void SendConnectionRequest(string name, string remoteEndpointId, byte[] payload,
Action<ConnectionResponse> responseCallback, IMessageListener listener)
{
Misc.CheckNotNull(listener, "listener");
var listenerOnGameThread = new OnGameThreadMessageListener(listener);
DiscoveringConnectionLifecycleCallback cb =
new DiscoveringConnectionLifecycleCallback(responseCallback, listenerOnGameThread, mClient);
using (var connectionLifecycleCallback =
new AndroidJavaObject("com.google.games.bridge.ConnectionLifecycleCallbackProxy", cb))
using (mClient.Call<AndroidJavaObject>("requestConnection", name, remoteEndpointId,
connectionLifecycleCallback))
;
}
public void AcceptConnectionRequest(string remoteEndpointId, byte[] payload, IMessageListener listener)
{
Misc.CheckNotNull(listener, "listener");
mAdvertisingMessageListener = new OnGameThreadMessageListener(listener);
using (var payloadCallback = new AndroidJavaObject("com.google.games.bridge.PayloadCallbackProxy",
new PayloadCallback(listener)))
using (mClient.Call<AndroidJavaObject>("acceptConnection", remoteEndpointId, payloadCallback))
;
}
private class PayloadCallback : AndroidJavaProxy
{
private IMessageListener mListener;
public PayloadCallback(IMessageListener listener) : base(
"com/google/games/bridge/PayloadCallbackProxy$Callback")
{
mListener = listener;
}
public void onPayloadReceived(String endpointId, AndroidJavaObject payload)
{
if (payload.Call<int>("getType") != 1) // 1 for BYTES
{
return;
}
mListener.OnMessageReceived(endpointId, payload.Call<byte[]>("asBytes"), /* isReliableMessage */ true);
}
}
public void StartDiscovery(string serviceId, TimeSpan? advertisingDuration,
IDiscoveryListener listener)
{
Misc.CheckNotNull(serviceId, "serviceId");
Misc.CheckNotNull(listener, "listener");
var listenerOnGameThread = new OnGameThreadDiscoveryListener(listener);
if (advertisingDuration.HasValue && advertisingDuration.Value.Ticks < 0)
{
throw new InvalidOperationException("advertisingDuration must be positive");
}
using (var endpointDiscoveryCallback = new AndroidJavaObject(
"com.google.games.bridge.EndpointDiscoveryCallbackProxy",
new EndpointDiscoveryCallback(listenerOnGameThread)))
using (var discoveryOptions = CreateDiscoveryOptions())
using (var task = mClient.Call<AndroidJavaObject>("startDiscovery", serviceId, endpointDiscoveryCallback,
discoveryOptions))
{
AndroidTaskUtils.AddOnSuccessListener<AndroidJavaObject>(
task,
v => NearbyHelperObject.StartDiscoveryTimer(advertisingDuration)
);
}
}
private class DiscoveringConnectionLifecycleCallback : AndroidJavaProxy
{
private Action<ConnectionResponse> mResponseCallback;
private IMessageListener mListener;
private AndroidJavaObject mClient;
public DiscoveringConnectionLifecycleCallback(Action<ConnectionResponse> responseCallback,
IMessageListener listener, AndroidJavaObject client) : base(
"com/google/games/bridge/ConnectionLifecycleCallbackProxy$Callback")
{
mResponseCallback = responseCallback;
mListener = listener;
mClient = client;
}
public void onConnectionInitiated(string endpointId, AndroidJavaObject connectionInfo)
{
using (var payloadCallback = new AndroidJavaObject("com.google.games.bridge.PayloadCallbackProxy",
new PayloadCallback(mListener)))
using (mClient.Call<AndroidJavaObject>("acceptConnection", endpointId, payloadCallback))
;
}
public void onConnectionResult(string endpointId, AndroidJavaObject connectionResolution)
{
int statusCode;
using (var status = connectionResolution.Call<AndroidJavaObject>("getStatus"))
{
statusCode = status.Call<int>("getStatusCode");
}
if (statusCode == 0) // STATUS_OK
{
mResponseCallback(ConnectionResponse.Accepted(NearbyClientId, endpointId, new byte[0]));
return;
}
if (statusCode == 8002) // STATUS_ALREADY_DISCOVERING
{
mResponseCallback(ConnectionResponse.AlreadyConnected(NearbyClientId, endpointId));
return;
}
mResponseCallback(ConnectionResponse.Rejected(NearbyClientId, endpointId));
}
public void onDisconnected(string endpointId)
{
mListener.OnRemoteEndpointDisconnected(endpointId);
}
}
private AndroidJavaObject CreateDiscoveryOptions()
{
using (var strategy =
new AndroidJavaClass("com.google.android.gms.nearby.connection.Strategy").GetStatic<AndroidJavaObject>(
"P2P_CLUSTER"))
using (var builder =
new AndroidJavaObject("com.google.android.gms.nearby.connection.DiscoveryOptions$Builder"))
using (builder.Call<AndroidJavaObject>("setStrategy", strategy))
{
return builder.Call<AndroidJavaObject>("build");
}
}
private class EndpointDiscoveryCallback : AndroidJavaProxy
{
private IDiscoveryListener mListener;
public EndpointDiscoveryCallback(IDiscoveryListener listener) : base(
"com/google/games/bridge/EndpointDiscoveryCallbackProxy$Callback")
{
mListener = listener;
}
public void onEndpointFound(string endpointId, AndroidJavaObject endpointInfo)
{
mListener.OnEndpointFound(CreateEndPointDetails(endpointId, endpointInfo));
}
public void onEndpointLost(string endpointId)
{
mListener.OnEndpointLost(endpointId);
}
private EndpointDetails CreateEndPointDetails(string endpointId, AndroidJavaObject endpointInfo)
{
return new EndpointDetails(
endpointId,
endpointInfo.Call<string>("getEndpointName"),
endpointInfo.Call<string>("getServiceId")
);
}
}
private class OnGameThreadMessageListener : IMessageListener
{
private readonly IMessageListener mListener;
public OnGameThreadMessageListener(IMessageListener listener)
{
mListener = Misc.CheckNotNull(listener);
}
public void OnMessageReceived(string remoteEndpointId, byte[] data,
bool isReliableMessage)
{
PlayGamesHelperObject.RunOnGameThread(() => mListener.OnMessageReceived(
remoteEndpointId, data, isReliableMessage));
}
public void OnRemoteEndpointDisconnected(string remoteEndpointId)
{
PlayGamesHelperObject.RunOnGameThread(
() => mListener.OnRemoteEndpointDisconnected(remoteEndpointId));
}
}
private class OnGameThreadDiscoveryListener : IDiscoveryListener
{
private readonly IDiscoveryListener mListener;
public OnGameThreadDiscoveryListener(IDiscoveryListener listener)
{
mListener = listener;
}
public void OnEndpointFound(EndpointDetails discoveredEndpoint)
{
PlayGamesHelperObject.RunOnGameThread(() => mListener.OnEndpointFound(discoveredEndpoint));
}
public void OnEndpointLost(string lostEndpointId)
{
PlayGamesHelperObject.RunOnGameThread(() => mListener.OnEndpointLost(lostEndpointId));
}
}
public void StopDiscovery(string serviceId)
{
mClient.Call("stopDiscovery");
}
public void RejectConnectionRequest(string requestingEndpointId)
{
Misc.CheckNotNull(requestingEndpointId, "requestingEndpointId");
using (var task = mClient.Call<AndroidJavaObject>("rejectConnection", requestingEndpointId)) ;
}
public void DisconnectFromEndpoint(string remoteEndpointId)
{
mClient.Call("disconnectFromEndpoint", remoteEndpointId);
}
public void StopAllConnections()
{
mClient.Call("stopAllEndpoints");
mAdvertisingMessageListener = null;
}
public string GetAppBundleId()
{
using (var activity = AndroidHelperFragment.GetActivity())
{
return activity.Call<string>("getPackageName");
}
}
public string GetServiceId()
{
return ServiceId;
}
private static string ReadServiceId()
{
using (var activity = AndroidHelperFragment.GetActivity())
{
string packageName = activity.Call<string>("getPackageName");
using (var pm = activity.Call<AndroidJavaObject>("getPackageManager"))
using (var appInfo =
pm.Call<AndroidJavaObject>("getApplicationInfo", packageName, ApplicationInfoFlags))
using (var bundle = appInfo.Get<AndroidJavaObject>("metaData"))
{
string sysId = bundle.Call<string>("getString",
"com.google.android.gms.nearby.connection.SERVICE_ID");
OurUtils.Logger.d("SystemId from Manifest: " + sysId);
return sysId;
}
}
}
private static Action<T> ToOnGameThread<T>(Action<T> toConvert)
{
return (val) => PlayGamesHelperObject.RunOnGameThread(() => toConvert(val));
}
private static Action<T1, T2> ToOnGameThread<T1, T2>(Action<T1, T2> toConvert)
{
return (val1, val2) => PlayGamesHelperObject.RunOnGameThread(() => toConvert(val1, val2));
}
}
}
#endif
fileFormatVersion: 2
guid: d69ac0a61e8943ff82b14f7469f0fe97
labels:
- gvh
- gvh_version-0.11.01
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
#if UNITY_ANDROID
#pragma warning disable 0642 // Possible mistaken empty statement
namespace GooglePlayGames.Android
{
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using GooglePlayGames.BasicApi;
using GooglePlayGames.BasicApi.SavedGame;
using GooglePlayGames.OurUtils;
using UnityEngine;
internal class AndroidSavedGameClient : ISavedGameClient
{
// Regex for a valid filename. Valid file names are between 1 and 100 characters (inclusive)
// and only include URL-safe characters: a-z, A-Z, 0-9, or the symbols "-", ".", "_", or "~".
// This regex is guarded by \A and \Z which guarantee that the entire string matches this
// regex. If these were omitted, then illegal strings containing legal subsequences would be
// allowed (since the regex would match those subsequences).
private static readonly Regex ValidFilenameRegex = new Regex(@"\A[a-zA-Z0-9-._~]{1,100}\Z");
private volatile AndroidJavaObject mSnapshotsClient;
private volatile AndroidClient mAndroidClient;
public AndroidSavedGameClient(AndroidClient androidClient)
{
mAndroidClient = androidClient;
using (var gamesClass = new AndroidJavaClass("com.google.android.gms.games.PlayGames"))
{
mSnapshotsClient = gamesClass.CallStatic<AndroidJavaObject>("getSnapshotsClient",
AndroidHelperFragment.GetActivity());
}
}
public void OpenWithAutomaticConflictResolution(string filename, DataSource source,
ConflictResolutionStrategy resolutionStrategy,
Action<SavedGameRequestStatus, ISavedGameMetadata> completedCallback)
{
Misc.CheckNotNull(filename);
Misc.CheckNotNull(completedCallback);
bool prefetchDataOnConflict = false;
ConflictCallback conflictCallback = null;
completedCallback = ToOnGameThread(completedCallback);
if (conflictCallback == null)
{
conflictCallback = (resolver, original, originalData, unmerged, unmergedData) =>
{
switch (resolutionStrategy)
{
case ConflictResolutionStrategy.UseOriginal:
resolver.ChooseMetadata(original);
return;
case ConflictResolutionStrategy.UseUnmerged:
resolver.ChooseMetadata(unmerged);
return;
case ConflictResolutionStrategy.UseLongestPlaytime:
if (original.TotalTimePlayed >= unmerged.TotalTimePlayed)
{
resolver.ChooseMetadata(original);
}
else
{
resolver.ChooseMetadata(unmerged);
}
return;
default:
OurUtils.Logger.e("Unhandled strategy " + resolutionStrategy);
completedCallback(SavedGameRequestStatus.InternalError, null);
return;
}
};
}
conflictCallback = ToOnGameThread(conflictCallback);
if (!IsValidFilename(filename))
{
OurUtils.Logger.e("Received invalid filename: " + filename);
completedCallback(SavedGameRequestStatus.BadInputError, null);
return;
}
InternalOpen(filename, source, resolutionStrategy, prefetchDataOnConflict, conflictCallback,
completedCallback);
}
public void OpenWithManualConflictResolution(string filename, DataSource source, bool prefetchDataOnConflict,
ConflictCallback conflictCallback, Action<SavedGameRequestStatus, ISavedGameMetadata> completedCallback)
{
Misc.CheckNotNull(filename);
Misc.CheckNotNull(conflictCallback);
Misc.CheckNotNull(completedCallback);
conflictCallback = ToOnGameThread(conflictCallback);
completedCallback = ToOnGameThread(completedCallback);
if (!IsValidFilename(filename))
{
OurUtils.Logger.e("Received invalid filename: " + filename);
completedCallback(SavedGameRequestStatus.BadInputError, null);
return;
}
InternalOpen(filename, source, ConflictResolutionStrategy.UseManual, prefetchDataOnConflict,
conflictCallback, completedCallback);
}
private void InternalOpen(string filename, DataSource source, ConflictResolutionStrategy resolutionStrategy,
bool prefetchDataOnConflict, ConflictCallback conflictCallback,
Action<SavedGameRequestStatus, ISavedGameMetadata> completedCallback)
{
int conflictPolicy; // SnapshotsClient.java#RetentionPolicy
switch (resolutionStrategy)
{
case ConflictResolutionStrategy.UseLastKnownGood:
conflictPolicy = 2 /* RESOLUTION_POLICY_LAST_KNOWN_GOOD */;
break;
case ConflictResolutionStrategy.UseMostRecentlySaved:
conflictPolicy = 3 /* RESOLUTION_POLICY_MOST_RECENTLY_MODIFIED */;
break;
case ConflictResolutionStrategy.UseLongestPlaytime:
conflictPolicy = 1 /* RESOLUTION_POLICY_LONGEST_PLAYTIME*/;
break;
case ConflictResolutionStrategy.UseManual:
conflictPolicy = -1 /* RESOLUTION_POLICY_MANUAL */;
break;
default:
conflictPolicy = 3 /* RESOLUTION_POLICY_MOST_RECENTLY_MODIFIED */;
break;
}
using (var task =
mSnapshotsClient.Call<AndroidJavaObject>("open", filename, /* createIfNotFound= */ true,
conflictPolicy))
{
AndroidTaskUtils.AddOnSuccessListener<AndroidJavaObject>(
task,
dataOrConflict =>
{
if (dataOrConflict.Call<bool>("isConflict"))
{
var conflict = dataOrConflict.Call<AndroidJavaObject>("getConflict");
AndroidSnapshotMetadata original =
new AndroidSnapshotMetadata(conflict.Call<AndroidJavaObject>("getSnapshot"));
AndroidSnapshotMetadata unmerged =
new AndroidSnapshotMetadata(
conflict.Call<AndroidJavaObject>("getConflictingSnapshot"));
// Instantiate the conflict resolver. Note that the retry callback closes over
// all the parameters we need to retry the open attempt. Once the conflict is
// resolved by invoking the appropriate resolution method on
// AndroidConflictResolver, the resolver will invoke this callback, which will
// result in this method being re-executed. This recursion will continue until
// all conflicts are resolved or an error occurs.
AndroidConflictResolver resolver = new AndroidConflictResolver(
this,
mSnapshotsClient,
conflict,
original,
unmerged,
completedCallback,
() => InternalOpen(filename, source, resolutionStrategy,
prefetchDataOnConflict,
conflictCallback, completedCallback));
var originalBytes = original.JavaContents.Call<byte[]>("readFully");
var unmergedBytes = unmerged.JavaContents.Call<byte[]>("readFully");
conflictCallback(resolver, original, originalBytes, unmerged, unmergedBytes);
}
else
{
using (var snapshot = dataOrConflict.Call<AndroidJavaObject>("getData"))
{
AndroidJavaObject metadata = snapshot.Call<AndroidJavaObject>("freeze");
completedCallback(SavedGameRequestStatus.Success,
new AndroidSnapshotMetadata(metadata));
}
}
});
AndroidTaskUtils.AddOnFailureListener(
task,
exception => {
OurUtils.Logger.d("InternalOpen has failed: " + exception.Call<string>("toString"));
var status = mAndroidClient.IsAuthenticated() ?
SavedGameRequestStatus.InternalError :
SavedGameRequestStatus.AuthenticationError;
completedCallback(status, null);
}
);
}
}
public void ReadBinaryData(ISavedGameMetadata metadata,
Action<SavedGameRequestStatus, byte[]> completedCallback)
{
Misc.CheckNotNull(metadata);
Misc.CheckNotNull(completedCallback);
completedCallback = ToOnGameThread(completedCallback);
AndroidSnapshotMetadata convertedMetadata = metadata as AndroidSnapshotMetadata;
if (convertedMetadata == null)
{
OurUtils.Logger.e("Encountered metadata that was not generated by this ISavedGameClient");
completedCallback(SavedGameRequestStatus.BadInputError, null);
return;
}
if (!convertedMetadata.IsOpen)
{
OurUtils.Logger.e("This method requires an open ISavedGameMetadata.");
completedCallback(SavedGameRequestStatus.BadInputError, null);
return;
}
byte[] data = convertedMetadata.JavaContents.Call<byte[]>("readFully");
if (data == null)
{
completedCallback(SavedGameRequestStatus.BadInputError, null);
}
else
{
completedCallback(SavedGameRequestStatus.Success, data);
}
}
public void ShowSelectSavedGameUI(string uiTitle, uint maxDisplayedSavedGames, bool showCreateSaveUI,
bool showDeleteSaveUI, Action<SelectUIStatus, ISavedGameMetadata> callback)
{
Misc.CheckNotNull(uiTitle);
Misc.CheckNotNull(callback);
callback = ToOnGameThread(callback);
if (!(maxDisplayedSavedGames > 0))
{
OurUtils.Logger.e("maxDisplayedSavedGames must be greater than 0");
callback(SelectUIStatus.BadInputError, null);
return;
}
AndroidHelperFragment.ShowSelectSnapshotUI(
showCreateSaveUI, showDeleteSaveUI, (int) maxDisplayedSavedGames, uiTitle, callback);
}
public void CommitUpdate(ISavedGameMetadata metadata, SavedGameMetadataUpdate updateForMetadata,
byte[] updatedBinaryData, Action<SavedGameRequestStatus, ISavedGameMetadata> callback)
{
Misc.CheckNotNull(metadata);
Misc.CheckNotNull(updatedBinaryData);
Misc.CheckNotNull(callback);
callback = ToOnGameThread(callback);
AndroidSnapshotMetadata convertedMetadata = metadata as AndroidSnapshotMetadata;
if (convertedMetadata == null)
{
OurUtils.Logger.e("Encountered metadata that was not generated by this ISavedGameClient");
callback(SavedGameRequestStatus.BadInputError, null);
return;
}
if (!convertedMetadata.IsOpen)
{
OurUtils.Logger.e("This method requires an open ISavedGameMetadata.");
callback(SavedGameRequestStatus.BadInputError, null);
return;
}
if (!convertedMetadata.JavaContents.Call<bool>("writeBytes", updatedBinaryData))
{
OurUtils.Logger.e("This method requires an open ISavedGameMetadata.");
callback(SavedGameRequestStatus.BadInputError, null);
}
using (var convertedMetadataChange = AsMetadataChange(updateForMetadata))
using (var task = mSnapshotsClient.Call<AndroidJavaObject>("commitAndClose", convertedMetadata.JavaSnapshot,
convertedMetadataChange))
{
AndroidTaskUtils.AddOnSuccessListener<AndroidJavaObject>(
task,
/* disposeResult= */ false,
snapshotMetadata =>
{
OurUtils.Logger.d("commitAndClose.succeed");
callback(SavedGameRequestStatus.Success,
new AndroidSnapshotMetadata(snapshotMetadata, /* contents= */null));
});
AndroidTaskUtils.AddOnFailureListener(
task,
exception =>
{
OurUtils.Logger.e("commitAndClose.failed: " + exception.Call<string>("toString"));
var status = mAndroidClient.IsAuthenticated() ?
SavedGameRequestStatus.InternalError :
SavedGameRequestStatus.AuthenticationError;
callback(status, null);
});
}
}
public void FetchAllSavedGames(DataSource source,
Action<SavedGameRequestStatus, List<ISavedGameMetadata>> callback)
{
Misc.CheckNotNull(callback);
callback = ToOnGameThread(callback);
using (var task =
mSnapshotsClient.Call<AndroidJavaObject>("load", /* forecReload= */
source == DataSource.ReadNetworkOnly))
{
AndroidTaskUtils.AddOnSuccessListener<AndroidJavaObject>(
task,
annotatedData =>
{
using (var buffer = annotatedData.Call<AndroidJavaObject>("get"))
{
int count = buffer.Call<int>("getCount");
List<ISavedGameMetadata> result = new List<ISavedGameMetadata>();
for (int i = 0; i < count; ++i)
{
using (var metadata = buffer.Call<AndroidJavaObject>("get", i))
{
result.Add(new AndroidSnapshotMetadata(
metadata.Call<AndroidJavaObject>("freeze"), /* contents= */null));
}
}
buffer.Call("release");
callback(SavedGameRequestStatus.Success, result);
}
});
AndroidTaskUtils.AddOnFailureListener(
task,
exception => {
OurUtils.Logger.d("FetchAllSavedGames failed: " + exception.Call<string>("toString"));
var status = mAndroidClient.IsAuthenticated() ?
SavedGameRequestStatus.InternalError :
SavedGameRequestStatus.AuthenticationError;
callback(status, new List<ISavedGameMetadata>());
}
);
}
}
public void Delete(ISavedGameMetadata metadata)
{
AndroidSnapshotMetadata androidMetadata = metadata as AndroidSnapshotMetadata;
Misc.CheckNotNull(androidMetadata);
using (mSnapshotsClient.Call<AndroidJavaObject>("delete", androidMetadata.JavaMetadata)) ;
}
private ConflictCallback ToOnGameThread(ConflictCallback conflictCallback)
{
return (resolver, original, originalData, unmerged, unmergedData) =>
{
OurUtils.Logger.d("Invoking conflict callback");
PlayGamesHelperObject.RunOnGameThread(() =>
conflictCallback(resolver, original, originalData, unmerged, unmergedData));
};
}
/// <summary>
/// A helper class that encapsulates the state around resolving a file conflict. It holds all
/// the state that is necessary to invoke <see cref="SnapshotManager.Resolve"/> as well as a
/// callback that will re-attempt to open the file after the resolution concludes.
/// </summary>
private class AndroidConflictResolver : IConflictResolver
{
private readonly AndroidJavaObject mSnapshotsClient;
private readonly AndroidJavaObject mConflict;
private readonly AndroidSnapshotMetadata mOriginal;
private readonly AndroidSnapshotMetadata mUnmerged;
private readonly Action<SavedGameRequestStatus, ISavedGameMetadata> mCompleteCallback;
private readonly Action mRetryFileOpen;
private readonly AndroidSavedGameClient mAndroidSavedGameClient;
internal AndroidConflictResolver(AndroidSavedGameClient androidSavedGameClient, AndroidJavaObject snapshotClient, AndroidJavaObject conflict,
AndroidSnapshotMetadata original, AndroidSnapshotMetadata unmerged,
Action<SavedGameRequestStatus, ISavedGameMetadata> completeCallback, Action retryOpen)
{
this.mAndroidSavedGameClient = androidSavedGameClient;
this.mSnapshotsClient = Misc.CheckNotNull(snapshotClient);
this.mConflict = Misc.CheckNotNull(conflict);
this.mOriginal = Misc.CheckNotNull(original);
this.mUnmerged = Misc.CheckNotNull(unmerged);
this.mCompleteCallback = Misc.CheckNotNull(completeCallback);
this.mRetryFileOpen = Misc.CheckNotNull(retryOpen);
}
public void ResolveConflict(ISavedGameMetadata chosenMetadata, SavedGameMetadataUpdate metadataUpdate,
byte[] updatedData)
{
AndroidSnapshotMetadata convertedMetadata = chosenMetadata as AndroidSnapshotMetadata;
if (convertedMetadata != mOriginal && convertedMetadata != mUnmerged)
{
OurUtils.Logger.e("Caller attempted to choose a version of the metadata that was not part " +
"of the conflict");
mCompleteCallback(SavedGameRequestStatus.BadInputError, null);
return;
}
using (var contentUpdate = mConflict.Call<AndroidJavaObject>("getResolutionSnapshotContents"))
{
if (!contentUpdate.Call<bool>("writeBytes", updatedData))
{
OurUtils.Logger.e("Can't update snapshot contents during conflict resolution.");
mCompleteCallback(SavedGameRequestStatus.BadInputError, null);
}
using (var convertedMetadataChange = AsMetadataChange(metadataUpdate))
using (var task = mSnapshotsClient.Call<AndroidJavaObject>(
"resolveConflict",
mConflict.Call<string>("getConflictId"),
convertedMetadata.JavaMetadata.Call<string>("getSnapshotId"),
convertedMetadataChange,
contentUpdate))
{
AndroidTaskUtils.AddOnSuccessListener<AndroidJavaObject>(
task,
dataOrConflict => mRetryFileOpen());
AndroidTaskUtils.AddOnFailureListener(
task,
exception => {
OurUtils.Logger.d("ResolveConflict failed: " + exception.Call<string>("toString"));
var status = mAndroidSavedGameClient.mAndroidClient.IsAuthenticated() ?
SavedGameRequestStatus.InternalError :
SavedGameRequestStatus.AuthenticationError;
mCompleteCallback(status, null);
}
);
}
}
}
public void ChooseMetadata(ISavedGameMetadata chosenMetadata)
{
AndroidSnapshotMetadata convertedMetadata = chosenMetadata as AndroidSnapshotMetadata;
if (convertedMetadata != mOriginal && convertedMetadata != mUnmerged)
{
OurUtils.Logger.e("Caller attempted to choose a version of the metadata that was not part " +
"of the conflict");
mCompleteCallback(SavedGameRequestStatus.BadInputError, null);
return;
}
using (var task = mSnapshotsClient.Call<AndroidJavaObject>(
"resolveConflict", mConflict.Call<string>("getConflictId"), convertedMetadata.JavaSnapshot))
{
AndroidTaskUtils.AddOnSuccessListener<AndroidJavaObject>(
task,
dataOrConflict => mRetryFileOpen());
AndroidTaskUtils.AddOnFailureListener(
task,
exception => {
OurUtils.Logger.d("ChooseMetadata failed: " + exception.Call<string>("toString"));
var status = mAndroidSavedGameClient.mAndroidClient.IsAuthenticated() ?
SavedGameRequestStatus.InternalError :
SavedGameRequestStatus.AuthenticationError;
mCompleteCallback(status, null);
}
);
}
}
}
internal static bool IsValidFilename(string filename)
{
if (filename == null)
{
return false;
}
return ValidFilenameRegex.IsMatch(filename);
}
private static AndroidJavaObject AsMetadataChange(SavedGameMetadataUpdate update)
{
using (var builder =
new AndroidJavaObject("com.google.android.gms.games.snapshot.SnapshotMetadataChange$Builder"))
{
if (update.IsCoverImageUpdated)
{
using (var bitmapFactory = new AndroidJavaClass("android.graphics.BitmapFactory"))
using (var bitmap = bitmapFactory.CallStatic<AndroidJavaObject>(
"decodeByteArray", update.UpdatedPngCoverImage, /* offset= */0,
update.UpdatedPngCoverImage.Length))
using (builder.Call<AndroidJavaObject>("setCoverImage", bitmap))
;
}
if (update.IsDescriptionUpdated)
{
using (builder.Call<AndroidJavaObject>("setDescription", update.UpdatedDescription)) ;
}
if (update.IsPlayedTimeUpdated)
{
using (builder.Call<AndroidJavaObject>("setPlayedTimeMillis",
Convert.ToInt64(update.UpdatedPlayedTime.Value.TotalMilliseconds))) ;
}
return builder.Call<AndroidJavaObject>("build");
}
}
private static Action<T1, T2> ToOnGameThread<T1, T2>(Action<T1, T2> toConvert)
{
return (val1, val2) => PlayGamesHelperObject.RunOnGameThread(() => toConvert(val1, val2));
}
}
}
#endif
fileFormatVersion: 2
guid: a52ca79a06d83464e89d0d052c9af7d9
labels:
- gvh
- gvh_version-0.11.01
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
#if UNITY_ANDROID
namespace GooglePlayGames.Android
{
using System;
using System.Collections.Generic;
using GooglePlayGames.BasicApi;
using GooglePlayGames.BasicApi.SavedGame;
using UnityEngine;
internal class AndroidSnapshotMetadata : ISavedGameMetadata
{
private AndroidJavaObject mJavaSnapshot;
private AndroidJavaObject mJavaMetadata;
private AndroidJavaObject mJavaContents;
public AndroidSnapshotMetadata(AndroidJavaObject javaSnapshot)
{
mJavaSnapshot = javaSnapshot;
mJavaMetadata = javaSnapshot.Call<AndroidJavaObject>("getMetadata");
mJavaContents = javaSnapshot.Call<AndroidJavaObject>("getSnapshotContents");
}
public AndroidSnapshotMetadata(AndroidJavaObject javaMetadata, AndroidJavaObject javaContents)
{
mJavaSnapshot = null;
mJavaMetadata = javaMetadata;
mJavaContents = javaContents;
}
public AndroidJavaObject JavaSnapshot
{
get { return mJavaSnapshot; }
}
public AndroidJavaObject JavaMetadata
{
get { return mJavaMetadata; }
}
public AndroidJavaObject JavaContents
{
get { return mJavaContents; }
}
public bool IsOpen
{
get
{
if (mJavaContents == null)
{
return false;
}
return !mJavaContents.Call<bool>("isClosed");
}
}
public string Filename
{
get { return mJavaMetadata.Call<string>("getUniqueName"); }
}
public string Description
{
get { return mJavaMetadata.Call<string>("getDescription"); }
}
public string CoverImageURL
{
get { return mJavaMetadata.Call<string>("getCoverImageUrl"); }
}
public TimeSpan TotalTimePlayed
{
get { return TimeSpan.FromMilliseconds(mJavaMetadata.Call<long>("getPlayedTime")); }
}
public DateTime LastModifiedTimestamp
{
get
{
long timestamp = mJavaMetadata.Call<long>("getLastModifiedTimestamp");
System.DateTime lastModifiedTime = AndroidJavaConverter.ToDateTime(timestamp);
return lastModifiedTime;
}
}
}
}
#endif
fileFormatVersion: 2
guid: 330ac7fa11d9a4bc099f0db5a3c26ad7
labels:
- gvh
- gvh_version-0.11.01
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
#if UNITY_ANDROID
#pragma warning disable 0642 // Possible mistaken empty statement
namespace GooglePlayGames.Android
{
using UnityEngine;
using System;
class AndroidTaskUtils
{
private AndroidTaskUtils()
{
}
public static void AddOnSuccessListener<T>(AndroidJavaObject task, Action<T> callback)
{
using (task.Call<AndroidJavaObject>("addOnSuccessListener",
new TaskOnSuccessProxy<T>(callback, /* disposeResult= */ true))) ;
}
public static void AddOnSuccessListener<T>(AndroidJavaObject task, bool disposeResult, Action<T> callback)
{
using (task.Call<AndroidJavaObject>("addOnSuccessListener",
new TaskOnSuccessProxy<T>(callback, disposeResult))) ;
}
public static void AddOnFailureListener(AndroidJavaObject task, Action<AndroidJavaObject> callback)
{
using (task.Call<AndroidJavaObject>("addOnFailureListener", new TaskOnFailedProxy(callback))) ;
}
public static void AddOnCompleteListener<T>(AndroidJavaObject task, Action<T> callback)
{
using (task.Call<AndroidJavaObject>("addOnCompleteListener", new TaskOnCompleteProxy<T>(callback))) ;
}
private class TaskOnCompleteProxy<T> : AndroidJavaProxy
{
private Action<T> mCallback;
public TaskOnCompleteProxy(Action<T> callback)
: base("com/google/android/gms/tasks/OnCompleteListener")
{
mCallback = callback;
}
public void onComplete(T result)
{
if (result is IDisposable)
{
using ((IDisposable) result)
{
mCallback(result);
}
}
else
{
mCallback(result);
}
}
}
private class TaskOnSuccessProxy<T> : AndroidJavaProxy
{
private Action<T> mCallback;
private bool mDisposeResult;
public TaskOnSuccessProxy(Action<T> callback, bool disposeResult)
: base("com/google/android/gms/tasks/OnSuccessListener")
{
mCallback = callback;
mDisposeResult = disposeResult;
}
public void onSuccess(T result)
{
if (result is IDisposable && mDisposeResult)
{
using ((IDisposable) result)
{
mCallback(result);
}
}
else
{
mCallback(result);
}
}
}
private class TaskOnFailedProxy : AndroidJavaProxy
{
private Action<AndroidJavaObject> mCallback;
public TaskOnFailedProxy(Action<AndroidJavaObject> callback)
: base("com/google/android/gms/tasks/OnFailureListener")
{
mCallback = callback;
}
public void onFailure(AndroidJavaObject exception)
{
using (exception)
{
mCallback(exception);
}
}
}
}
}
#endif
fileFormatVersion: 2
guid: 5d045a29538404b2da664bb55de949de
labels:
- gvh
- gvh_version-0.11.01
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
// <copyright file="NearbyConnectionClientFactory.cs" company="Google Inc.">
// Copyright (C) 2014 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
// Android only feature
#if (UNITY_ANDROID)
namespace GooglePlayGames
{
using UnityEngine;
using System;
using GooglePlayGames.OurUtils;
using GooglePlayGames.BasicApi.Nearby;
public static class NearbyConnectionClientFactory
{
public static void Create(Action<INearbyConnectionClient> callback)
{
if (Application.isEditor)
{
GooglePlayGames.OurUtils.Logger.d("Creating INearbyConnection in editor, using DummyClient.");
callback.Invoke(new GooglePlayGames.BasicApi.Nearby.DummyNearbyConnectionClient());
}
callback.Invoke(new GooglePlayGames.Android.AndroidNearbyConnectionClient());
}
}
}
#endif //UNITY_ANDROID
\ No newline at end of file
fileFormatVersion: 2
guid: ff1201bd0205943ba9c881e50e38156b
labels:
- gvh
- gvh_version-0.11.01
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
// <copyright file="PlayGamesClientFactory.cs" company="Google Inc.">
// Copyright (C) 2014 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
#if UNITY_ANDROID
namespace GooglePlayGames
{
using UnityEngine;
using GooglePlayGames.BasicApi;
using GooglePlayGames.OurUtils;
internal class PlayGamesClientFactory
{
internal static IPlayGamesClient GetPlatformPlayGamesClient()
{
if (Application.isEditor)
{
GooglePlayGames.OurUtils.Logger.d("Creating IPlayGamesClient in editor, using DummyClient.");
return new GooglePlayGames.BasicApi.DummyClient();
}
#if UNITY_ANDROID
GooglePlayGames.OurUtils.Logger.d("Creating Android IPlayGamesClient Client");
return new GooglePlayGames.Android.AndroidClient();
#else
GooglePlayGames.OurUtils.Logger.d("Cannot create IPlayGamesClient for unknown platform, returning DummyClient");
return new GooglePlayGames.BasicApi.DummyClient();
#endif
}
}
}
#endif
fileFormatVersion: 2
guid: 435fc2d0dc0ba475e9c8b0796303d6dd
labels:
- gvh
- gvh_version-0.11.01
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
// <copyright file="PluginVersion.cs" company="Google Inc.">
// Copyright (C) 2014 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
namespace GooglePlayGames
{
public class PluginVersion
{
// Current Version.
public const int VersionInt = 0x01101;
public const string VersionString = "0.11.01";
public const string VersionKey = "01101" ;
}
}
fileFormatVersion: 2
guid: 4539142948daf4a26bf9cd6870ffa0b2
labels:
- gvh
- gvh_version-0.11.01
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
{
"name": "com.google.play.games",
"displayName": "Google Play Games",
"description": "The Google Play Games plugin for Unity allows you to access the Google Play Games API through Unity's social interface.",
"version": "0.11.01",
"unity": "2018.4",
"author": {
"name": "Google LLC"
},
"dependencies": {}
}
fileFormatVersion: 2
guid: 51dd7d46faed94b31a71d5f4cec6ce14
labels:
- gvh
- gvh_version-0.11.01
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 44f4150f398dc4f22b230f8c74866383
folderAsset: yes
timeCreated: 1504033921
licenseType: Pro
PluginImporter:
serializedVersion: 2
iconMap: {}
executionOrder: {}
isPreloaded: 0
isOverridable: 0
platformData:
data:
first:
'': Any
second:
enabled: 0
settings:
Exclude Android: 0
Exclude Editor: 0
Exclude Linux: 0
Exclude Linux64: 0
Exclude LinuxUniversal: 0
Exclude OSXIntel: 0
Exclude OSXIntel64: 0
Exclude OSXUniversal: 0
Exclude WebGL: 0
Exclude Win: 0
Exclude Win64: 0
Exclude iOS: 0
data:
first:
'': Editor
second:
enabled: 0
settings:
CPU: AnyCPU
OS: AnyOS
data:
first:
Android: Android
second:
enabled: 1
settings:
CPU: ARMv7
data:
first:
Any:
second:
enabled: 1
settings: {}
data:
first:
Editor: Editor
second:
enabled: 1
settings:
DefaultValueInitialized: true
data:
first:
Facebook: Win
second:
enabled: 0
settings:
CPU: AnyCPU
data:
first:
Facebook: Win64
second:
enabled: 0
settings:
CPU: AnyCPU
data:
first:
Standalone: Linux
second:
enabled: 1
settings:
CPU: x86
data:
first:
Standalone: Linux64
second:
enabled: 1
settings:
CPU: x86_64
data:
first:
Standalone: LinuxUniversal
second:
enabled: 1
settings: {}
data:
first:
Standalone: OSXIntel
second:
enabled: 1
settings:
CPU: AnyCPU
data:
first:
Standalone: OSXIntel64
second:
enabled: 1
settings:
CPU: AnyCPU
data:
first:
Standalone: OSXUniversal
second:
enabled: 1
settings: {}
data:
first:
Standalone: Win
second:
enabled: 1
settings:
CPU: AnyCPU
data:
first:
Standalone: Win64
second:
enabled: 1
settings:
CPU: AnyCPU
data:
first:
WebGL: WebGL
second:
enabled: 1
settings: {}
data:
first:
iPhone: iOS
second:
enabled: 1
settings:
CompileFlags:
FrameworkDependencies:
userData:
assetBundleName:
assetBundleVariant:
<?xml version="1.0" encoding="utf-8"?>
<!-- This file was automatically generated by the Google Play Games plugin for Unity
Do not edit. -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.google.example.games.mainlibproj"
android:versionCode="1"
android:versionName="1.0" >
<application>
<!-- The space in these forces it to be interpreted as a string vs. int -->
<meta-data android:name="com.google.android.gms.games.APP_ID"
android:value="\u003" />
<!-- Keep track of which plugin is being used -->
<meta-data android:name="com.google.android.gms.games.unityVersion"
android:value="\u0030.11.01" />
<activity android:name="com.google.games.bridge.NativeBridgeActivity"
android:theme="@android:style/Theme.Translucent.NoTitleBar.Fullscreen" />
</application>
</manifest>
fileFormatVersion: 2
guid: 61ba7accaf3fd35448ce9a56377da37a
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 6156f0fc2bafa4f0c86d61673c0068d0
labels:
- gvh
- gvh_version-0.11.01
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
<package>com.facebook.android:facebook-gamingservices:[16.0,17)</package> <package>com.facebook.android:facebook-gamingservices:[16.0,17)</package>
<package>com.facebook.android:facebook-login:[16.0,17)</package> <package>com.facebook.android:facebook-login:[16.0,17)</package>
<package>com.facebook.android:facebook-share:[16.0,17)</package> <package>com.facebook.android:facebook-share:[16.0,17)</package>
<package>com.google.games:gpgs-plugin-support:0.11.01</package>
<package>com.parse.bolts:bolts-android:1.4.0</package> <package>com.parse.bolts:bolts-android:1.4.0</package>
</packages> </packages>
<files> <files>
......
lastUpgrade=01101
proj.pluginVersion=0.11.01
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<projectSettings> <projectSettings>
<projectSetting name="com.google.external-dependency-managerAnalyticsCookie" value="78875aebed1641719f6d2a42ac3b5780" /> <projectSetting name="com.google.external-dependency-managerAnalyticsCookie" value="78875aebed1641719f6d2a42ac3b5780" />
<projectSetting name="com.google.external-dependency-managerAnalyticsEnabled" value="True" /> <projectSetting name="com.google.external-dependency-managerAnalyticsEnabled" value="True" />
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment