diff --git a/.gitignore b/.gitignore index 863c5d0..c906b51 100644 --- a/.gitignore +++ b/.gitignore @@ -38,6 +38,7 @@ proguard/ captures/ # IntelliJ +/.idea/ *.iml .idea/workspace.xml .idea/tasks.xml diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml deleted file mode 100644 index f9bd542..0000000 --- a/.idea/codeStyles/Project.xml +++ /dev/null @@ -1,128 +0,0 @@ - - - - - - - - - - -
- - - - xmlns:android - - ^$ - - - -
-
- - - - xmlns:.* - - ^$ - - - BY_NAME - -
-
- - - - .*:id - - http://schemas.android.com/apk/res/android - - - -
-
- - - - .*:name - - http://schemas.android.com/apk/res/android - - - -
-
- - - - name - - ^$ - - - -
-
- - - - style - - ^$ - - - -
-
- - - - .* - - ^$ - - - BY_NAME - -
-
- - - - .* - - http://schemas.android.com/apk/res/android - - - ANDROID_ATTRIBUTE_ORDER - -
-
- - - - .* - - .* - - - BY_NAME - -
-
-
-
- - -
-
\ No newline at end of file diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml deleted file mode 100644 index 79ee123..0000000 --- a/.idea/codeStyles/codeStyleConfig.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/compiler.xml b/.idea/compiler.xml index fb7f4a8..b589d56 100644 --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -1,6 +1,6 @@ - + \ No newline at end of file diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml deleted file mode 100644 index e34606c..0000000 --- a/.idea/jarRepositories.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index c124186..0000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/README.md b/README.md index 28ae086..326ec98 100644 --- a/README.md +++ b/README.md @@ -1,52 +1,34 @@ -# Google Play Games Services Plugin for Godot -Google Play Games Services [Android plugin](https://docs.godotengine.org/en/stable/tutorials/platform/android/android_plugin.html#android-plugin) for Godot 3.2.3 and newer Godot 3.x versions. +# Google Play Games Services Plugin for Godot 4.2.x +This is an Android Play Games Services plugin for Godot Game Engine 4.2.x. [![Android](https://img.shields.io/badge/Platform-Android-brightgreen.svg)](https://developer.android.com) -[![Godot](https://img.shields.io/badge/Godot%20Engine-3.2.3-blue.svg)](https://github.com/godotengine/godot/) -[![PGS](https://img.shields.io/badge/Play%20Games%20Services-22.0.1-green.svg)](https://developers.google.com/games/services/android/quickstart) +[![Godot](https://img.shields.io/badge/Godot%20Engine-3.5.2-blue.svg)](https://github.com/godotengine/godot/) +[![PGS](https://img.shields.io/badge/Play%20Games%20Services-20.0.1-green.svg)](https://developers.google.com/games/services/android/quickstart) [![MIT license](https://img.shields.io/badge/License-MIT-yellowgreen.svg)](https://lbesson.mit-license.org/) -### Supported features: -- [Sign-in / Sign out](#sign-in--sign-out) -- [Achievements](#achievements) -- [Leaderboards](#leaderboards) -- [Events](#events) -- [Player Stats](#player-stats) -- [Player Info](#player-info) -- [Saved Games](#saved-games) - -*If you want to use the old plugin version (older than 3.2.2) visit [Old README file](https://github.com/cgisca/PGSGP/blob/master/README_OLD.md).* - ---- - -## About - -**This is a fork of the [PGSGP](https://github.com/cgisca/PGSGP) repo originally by [cgisca](https://github.com/cgisca), which I forked for my own use at [Gameka](https://github.com/Gameka-games).** Commits from forks of this repo, or the orignal repo and other forks are pulled into this repo as I continue to use this plugin. - -### Contributors - -[cgisca](https://github.com/cgisca) (original author) and other contributors in no particular order: -- [Ozzadar](https://github.com/oneseedfruit/PGSGP/commits?author=Ozzadar) ([pulled from](https://github.com/mauville-technologies/PGSGP/commits?author=Ozzadar)) -- [DeleteSystem32](https://github.com/DeleteSystem32) ([pull request](https://github.com/cgisca/PGSGP/pull/60) | [commit](https://github.com/oneseedfruit/PGSGP/commit/acce3a2078e6839c3f59b71027b7480693b4d809) ) -- [Hamdiovish](https://github.com/Hamdiovish) ([pull request](https://github.com/cgisca/PGSGP/pull/48) | [commit](https://github.com/oneseedfruit/PGSGP/commit/bdf7ddd46d34e9c89981e5f88d1f330435eb3b45)) -- [spietika](https://github.com/oneseedfruit/PGSGP/commits?author=spietika) -- [dala00](https://github.com/oneseedfruit/PGSGP/commits?author=dala00) -- [RandomShaper](https://github.com/oneseedfruit/PGSGP/commits?author=RandomShaper) -- [anisc](https://github.com/oneseedfruit/PGSGP/commits?author=anisc) +If you want to use the old plugin version visit [Old README file](https://github.com/cgisca/PGSGP/blob/master/README_OLD.md). ---- +### Supported features: +- Sign-in/Sign out +- Achievements +- Leaderboards +- Events +- Player Stats +- Player Info +- Saved Games ## Getting started Before using this plugin please follow instructions on [Setting Up Google Play Games Services](https://developers.google.com/games/services/console/enabling) official guide. - ---- - -## Set up -- Download `GodotPlayGamesServices.release.aar` and `GodotPlayGamesServices.gdap` from [releases](https://github.com/cgisca/PGSGP/releases) page. -- Move the plugin configuration file (`GodotPlayGamesServices.gdap`) and the binary (`GodotPlayGamesServices.release.aar`) downloaded from the previous step to the Godot project's res://android/plugins directory. -- Enable plugin by accessing `Project` -> `Export`, Plugins section. Follow the [image](https://docs.godotengine.org/en/stable/_images/android_export_preset_plugins_section.png). +### Set up +- Download `GPGSS.zip` from [releases](https://github.com/finepointcgi/PGSGP/releases) page. +- Unzip the file into the `res://addons/` folder +- Go out to Project -> Project Settings + ![image](https://github.com/finepointcgi/PGSGP/assets/12012300/bff52c33-033e-4e0f-a5b4-1c8e2a1452e9) +- Enable the plugin +- Go out to Project -> Export and enable Gradle Build +- Go to Project -> Install Android Build Template to install the android build template. - Go to res://android/build directory. Add below lines to `AndroidManifest.xml`: ```xml ``` + +- Also add in a file called integers.xml in that same directory and add the following: +```xml + + + 12451000 + +``` + - In the same res://android/build directory,(if it is not already created) create `res` -> `values` -> `Strings.xml`. Add below lines to `Strings.xml`: ```xml @@ -66,9 +57,34 @@ Replace ADD_YOUR_APP_ID with the app id that was generated after following instr Check demo project. In order demo project to work, replace ADD_YOUR_APP_ID with your own app id, and in Main.gd add your ids for achievements and leaderboards. ---- +### Generate plugin .aar file + +If there is no release for your Godot version, you need to generate new plugin .aar file. +Follow these instruction: [ official documentation](https://docs.godotengine.org/en/stable/tutorials/plugins/android/android_plugin.html "documentation"). + +In short follow these steps: + +1. Download [ AAR library for Android plugins](https://godotengine.org/download/windows "Godot download"). + +2. Copy .aar file to `godot-lib.release/*` and rename it to `godot-lib.4.2.1.stable.template_release.aar` + +3. Compile the project: + + Open command window and *cd* into *PGSGP* direcory and run command below + + * Windows: + + gradlew.bat assembleRelease + + * Linux: + + ./gradlew assembleRelease + +4. Copy the newly created .aar file to your plugin directory: + +*app/build/outputs/aar/GodotPlayGamesServices.release.aar* to *[your godot project]/android/plugins/* -## How to use +### How to use First step is plugin initialization ```gdscript var play_games_services @@ -102,16 +118,12 @@ if Engine.has_singleton("GodotPlayGamesServices"): play_games_services.connect("_on_achievement_incrementing_failed", self, "_on_achievement_incrementing_failed") # achievement: String play_games_services.connect("_on_achievement_info_loaded", self, "_on_achievement_info_loaded") # achievements_json : String play_games_services.connect("_on_achievement_info_load_failed", self, "_on_achievement_info_load_failed") - play_games_services.connect("_on_achievement_info_load_failed", self, "_on_achievement_info_load_failed") - play_games_services.connect("_on_achievement_info_load_failed", self, "_on_achievement_info_load_failed") - play_games_services.connect("_on_leaderboard_score_retrieved", self, "_on_leaderboard_score_retrieved") # playerstats: String (JSON) - play_games_services.connect("_on_leaderboard_score_retrieve_failed", self, "_on_leaderboard_score_retrieve_failed") play_games_services.connect("_on_leaderboard_score_submitted", self, "_on_leaderboard_score_submitted") # leaderboard_id: String play_games_services.connect("_on_leaderboard_score_submitting_failed", self, "_on_leaderboard_score_submitting_failed") # leaderboard_id: String play_games_services.connect("_on_game_saved_success", self, "_on_game_saved_success") # no params - play_games_services.connect("_on_game_saved_fail", self, "_on_game_saved_fail") # no params + play_games_services.connect("_on_game_saved_fail", self, "_on_game_saved_fail") # data: String play_games_services.connect("_on_game_load_success", self, "_on_game_load_success") # data: String - play_games_services.connect("_on_game_load_fail", self, "_on_game_load_fail") # no params + play_games_services.connect("_on_game_load_fail", self, "_on_game_load_fail") # data: String play_games_services.connect("_on_create_new_snapshot", self, "_on_create_new_snapshot") # name: String play_games_services.connect("_on_player_info_loaded", self, "_on_player_info_loaded") # json_response: String play_games_services.connect("_on_player_info_loading_failed", self, "_on_player_info_loading_failed") @@ -120,18 +132,14 @@ if Engine.has_singleton("GodotPlayGamesServices"): ``` After what plugin was initialized you can use supported features ---- - -## Check Google services availability on device +#### Check Google services availability on device ```gdscript var is_gpgs_available: bool = play_game_services.isGooglePlayServicesAvailable() ``` ---- - -## Sign-in / Sign out -### Sign-in +#### Sign-in / Sign out +##### Sign-in ```gdscript play_games_services.signIn() @@ -145,14 +153,13 @@ func _on_sign_in_success(userProfile_json: String) -> void: userProfile["displayName"] # The user's display name userProfile["email"] # The user's email userProfile["token"] # User token for backend use - userProfile["authCode"] # ServerAuthCode one-time token to enable server-side access (like Firebase Auth) userProfile["id"] # The user's id func _on_sign_in_failed(error_code: int) -> void: pass ``` -### Sign out +##### Sign out ```gdscript play_games_services.signOut() @@ -163,15 +170,12 @@ func _on_sign_out_success(): func _on_sign_out_failed(): pass ``` -### Check if signed in +##### Check if signed in ```gdscript var is_signed_in: bool = play_games_services.isSignedIn() ``` - ---- - -## Achievements -### Unlock Achievement +#### Achievements +##### Unlock Achievement ```gdscript play_games_services.unlockAchievement("ACHIEVEMENT_ID") @@ -182,7 +186,7 @@ func _on_achievement_unlocked(achievement: String): func _on_achievement_unlocking_failed(achievement: String): pass ``` -### Increment Achievement +##### Increment Achievement ```gdscript var step = 1 play_games_services.incrementAchievement("ACHIEVEMENT_ID", step) @@ -194,7 +198,7 @@ func _on_achievement_incremented(achievement: String): func _on_achievement_incrementing_failed(achievement: String): pass ``` -### Set Achievement Steps +##### Set Achievement Steps ```gdscript var steps = 3 play_games_services.setAchievementSteps("ACHIEVEMENT_ID", steps) @@ -206,7 +210,7 @@ func _on_achievement_steps_set(achievement: String): func _on_achievement_steps_setting_failed(achievement: String): pass ``` -### Reveal Achievement +##### Reveal Achievement ```gdscript play_games_services.revealAchievement("ACHIEVEMENT_ID") @@ -217,11 +221,11 @@ func _on_achievement_revealed(achievement: String): func _on_achievement_revealing_failed(achievement: String): pass ``` -### Show Achievements List +##### Show Achievements List ```gdscript play_games_services.showAchievements() ``` -### Load Achievement info +##### Load Achievement info ```gdscript play_games_services.loadAchievementInfo(false) # forceReload @@ -247,11 +251,8 @@ func _on_achievement_info_loaded(achievements_json: String): a["current_steps"] # Users current progress a["total_steps"] # Total steps to unlock achievement ``` - ---- - -## Leaderboards -### Submit leaderboard score +#### Leaderboards +##### Submit leaderboard score ```gdscript var score = 1234 play_games_services.submitLeaderBoardScore("LEADERBOARD_ID", score) @@ -262,9 +263,8 @@ func _on_leaderboard_score_submitted(leaderboard_id: String): func _on_leaderboard_score_submitting_failed(leaderboard_id: String): pass - ``` -### Show leaderboard +##### Show leaderboard ```gdscript play_games_services.showLeaderBoard("LEADERBOARD_ID") @@ -272,27 +272,8 @@ play_games_services.showLeaderBoard("LEADERBOARD_ID") play_games_services.showAllLeaderBoards() ``` -### Get player high score and rank -```gdscript -# Span can be: TIME_SPAN_DAILY, TIME_SPAN_WEEKLY, or TIME_SPAN_ALL_TIME -# LeaderboardCollection can be: COLLECTION_PUBLIC or COLLECTION_FRIENDS -play_games_services.retrieveLeaderboardScore("LEADERBOARD_ID", "ALL_TIME", "ALL") - -func _on_leaderboard_score_retrieved(leaderboardId : String, playerScore : String): - var score_dictionary: Dictionary = parse_json(playerScore) - # Using below keys you can retrieve data about a player’s in-game activity - score_dictionary["score"] # Player high score - score_dictionary["rank"] # Player rank - pass - -func _on_leaderboard_score_retrieve_failed(leaderboardId : String): - pass -``` - ---- - -## Events -### Submit event +#### Events +##### Submit event ```gdscript var increment_by := 2 play_games_services.submitEvent("EVENT_ID", increment_by) @@ -304,7 +285,7 @@ func _on_event_submitted(event_id: String): func _on_event_submitted_failed(event_id: String): pass ``` -### Load events +##### Load events ```gdscript # Load all events play_games_services.loadEvents() @@ -333,10 +314,7 @@ func _on_events_loading_failed(): pass ``` - ---- - -## Player Stats +#### Player Stats ```gdscript var force_refresh := true # If true, this call will clear any locally cached data and attempt to fetch the latest data from the server. play_games_services.loadPlayerStats(force_refresh) @@ -355,10 +333,7 @@ func _on_player_stats_loaded(stats): func _on_player_stats_loading_failed(): pass ``` - ---- - -## Player Info +#### Player Info ```gdscript play_games_services.loadPlayerInfo() @@ -393,11 +368,8 @@ func _on_player_info_loaded(info): func _on_player_info_loading_failed(): pass ``` - ---- - -## Saved Games -### Save game snapshot +#### Saved Games +##### Save game snapshot ```gdscript var data_to_save: Dictionary = { "name": "John", @@ -414,7 +386,7 @@ func _on_game_saved_success(): func _on_game_saved_fail(): pass ``` -### Load game snapshot +##### Load game snapshot ```gdscript play_games_services.loadSnapshot("SNAPSHOT_NAME") @@ -429,7 +401,7 @@ func _on_game_load_success(data): func _on_game_load_fail(): pass ``` -### Show saved snapshots screen +##### Show saved snapshots screen ```gdscript var allow_add_button := true var allow_delete_button := true @@ -449,9 +421,6 @@ func _on_create_new_snapshot(name): play_games_services.save_snapshot(name, to_json(game_data_to_save), "DESCRIPTION") ``` - ---- - ## Troubleshooting Check `adb logcat` for debuging. To filter only Godot messages use next command: diff --git a/app/build.gradle b/app/build.gradle index e54396f..b2230f4 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -2,43 +2,54 @@ apply plugin: 'com.android.library' apply plugin: 'kotlin-android' android { - compileSdkVersion 32 - buildToolsVersion "30.0.3" - + compileSdk 34 + namespace 'io.cgisca.godot.gpgs' + def libName = project.property("library_name") defaultConfig { - minSdkVersion 21 - targetSdkVersion 32 - versionCode 1 - versionName "1.0" - } + targetSdk 34 + buildConfigField "String", "LIBRARY_NAME", "\"$libName\"" + } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } - - def libName = project.property("library_name") - - defaultConfig{ - buildConfigField "String", "LIBRARY_NAME", "\"$libName\"" + compileOptions { + sourceCompatibility JavaVersion.VERSION_17 + targetCompatibility JavaVersion.VERSION_17 + } + kotlinOptions { + jvmTarget = "17" + } + defaultConfig { + minSdkVersion 24 + versionCode 1 + versionName "1.0" } + libraryVariants.all { variant -> variant.outputs.all { output -> output.outputFileName = "$libName.${variant.name}.aar" } } + + buildFeatures { + viewBinding true + buildConfig true + } + buildToolsVersion '34.0.0' } dependencies { - compileOnly fileTree(dir:"libs", include:["godot-lib.aar"]) implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" - implementation 'com.google.android.gms:play-services-games:22.0.1' - implementation 'com.google.android.gms:play-services-auth:20.1.0' - implementation 'com.google.code.gson:gson:2.9.0' + implementation 'com.google.android.gms:play-services-games:23.2.0' + implementation 'com.google.android.gms:play-services-auth:21.2.0' + implementation 'com.google.android.gms:play-services-location:21.3.0' + implementation 'com.google.code.gson:gson:2.10' + implementation("org.godotengine:godot:4.2.1.stable") testImplementation 'junit:junit:4.13.2' -} - +} \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index bc79312..33954d1 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -6,7 +6,7 @@ diff --git a/app/src/main/java/io/cgisca/godot/gpgs/PlayGameServicesGodot.kt b/app/src/main/java/io/cgisca/godot/gpgs/PlayGameServicesGodot.kt index 3d9807e..b812c88 100644 --- a/app/src/main/java/io/cgisca/godot/gpgs/PlayGameServicesGodot.kt +++ b/app/src/main/java/io/cgisca/godot/gpgs/PlayGameServicesGodot.kt @@ -2,6 +2,7 @@ package io.cgisca.godot.gpgs import android.app.Activity import android.content.Intent +import android.util.Log import com.google.android.gms.common.GoogleApiAvailability import com.google.android.gms.common.ConnectionResult import com.google.android.gms.auth.api.Auth @@ -28,9 +29,11 @@ import io.cgisca.godot.gpgs.signin.SignInListener import io.cgisca.godot.gpgs.signin.UserProfile import io.cgisca.godot.gpgs.stats.PlayerStatsController import io.cgisca.godot.gpgs.stats.PlayerStatsListener +import org.godotengine.godot.BuildConfig import org.godotengine.godot.Godot import org.godotengine.godot.plugin.GodotPlugin import org.godotengine.godot.plugin.SignalInfo +import org.godotengine.godot.plugin.UsedByGodot import java.math.BigInteger import java.util.Random @@ -66,9 +69,8 @@ class PlayGameServicesGodot(godot: Godot) : GodotPlugin(godot), AchievementsList SignalInfo("_on_achievement_steps_setting_failed", String::class.java) val SIGNAL_ACHIEVEMENT_INFO_LOAD = SignalInfo("_on_achievement_info_loaded", String::class.java) val SIGNAL_ACHIEVEMENT_INFO_LOAD_FAILED = SignalInfo("_on_achievement_info_load_failed", String::class.java) - val SIGNAL_LEADERBOARD_SCORE_RETRIEVED = SignalInfo("_on_leaderboard_score_retrieved", String::class.java, String::class.java) - val SIGNAL_LEADERBOARD_SCORE_RETRIEVED_FAILED = SignalInfo("_on_leaderboard_score_retrieve_failed", String::class.java) val SIGNAL_LEADERBOARD_SCORE_SUBMITTED = SignalInfo("_on_leaderboard_score_submitted", String::class.java) + val SIGNAL_CURRENT_PLAYER_LEADERBOARD_SCORE_LOADED = SignalInfo("_on_current_player_leaderboard_score_loaded", String::class.java) val SIGNAL_LEADERBOARD_SCORE_SUBMITTED_FAILED = SignalInfo("_on_leaderboard_score_submitting_failed", String::class.java) val SIGNAL_EVENT_SUBMITTED = SignalInfo("_on_event_submitted", String::class.java) @@ -79,18 +81,19 @@ class PlayGameServicesGodot(godot: Godot) : GodotPlugin(godot), AchievementsList val SIGNAL_PLAYER_STATS_LOADED = SignalInfo("_on_player_stats_loaded", String::class.java) val SIGNAL_PLAYER_STATS_LOADED_FAILED = SignalInfo("_on_player_stats_loading_failed") val SIGNAL_SAVED_GAME_SUCCESS = SignalInfo("_on_game_saved_success") - val SIGNAL_SAVED_GAME_FAILED = SignalInfo("_on_game_saved_fail") + val SIGNAL_SAVED_GAME_FAILED = SignalInfo("_on_game_saved_fail", String::class.java) val SIGNAL_SAVED_GAME_LOAD_SUCCESS = SignalInfo("_on_game_load_success", String::class.java) - val SIGNAL_SAVED_GAME_LOAD_FAIL = SignalInfo("_on_game_load_fail") + val SIGNAL_SAVED_GAME_LOAD_FAIL = SignalInfo("_on_game_load_fail", String::class.java) val SIGNAL_SAVED_GAME_CREATE_SNAPSHOT = SignalInfo("_on_create_new_snapshot", String::class.java) val SIGNAL_PLAYER_INFO_LOADED = SignalInfo("_on_player_info_loaded", String::class.java) val SIGNAL_PLAYER_INFO_LOADED_FAILED = SignalInfo("_on_player_info_loading_failed") } override fun getPluginName(): String { - return BuildConfig.LIBRARY_NAME + return "GodotPlayGamesServices" } + @Deprecated("Deprecated in Java") override fun getPluginMethods(): MutableList { return mutableListOf( "isGooglePlayServicesAvailable", @@ -105,7 +108,6 @@ class PlayGameServicesGodot(godot: Godot) : GodotPlugin(godot), AchievementsList "incrementAchievement", "setAchievementSteps", "loadAchievementInfo", - "retrieveLeaderboardScore", "showLeaderBoard", "showAllLeaderBoards", "submitLeaderBoardScore", @@ -136,10 +138,9 @@ class PlayGameServicesGodot(godot: Godot) : GodotPlugin(godot), AchievementsList SIGNAL_ACHIEVEMENT_STEPS_SET_FAILED, SIGNAL_ACHIEVEMENT_INFO_LOAD, SIGNAL_ACHIEVEMENT_INFO_LOAD_FAILED, - SIGNAL_LEADERBOARD_SCORE_RETRIEVED, - SIGNAL_LEADERBOARD_SCORE_RETRIEVED_FAILED, SIGNAL_LEADERBOARD_SCORE_SUBMITTED, SIGNAL_LEADERBOARD_SCORE_SUBMITTED_FAILED, + SIGNAL_CURRENT_PLAYER_LEADERBOARD_SCORE_LOADED, SIGNAL_EVENT_SUBMITTED, SIGNAL_EVENT_SUBMITTED_FAILED, SIGNAL_EVENTS_LOADED, @@ -158,40 +159,52 @@ class PlayGameServicesGodot(godot: Godot) : GodotPlugin(godot), AchievementsList } override fun onMainActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { - if (requestCode == SignInController.RC_SIGN_IN) { - if (data != null) { - val googleSignInResult = Auth.GoogleSignInApi.getSignInResultFromIntent(data) - signInController.onSignInActivityResult(googleSignInResult) - } - } else if (requestCode == SavedGamesController.RC_SAVED_GAMES) { - if (data != null) { - if (data.hasExtra(SnapshotsClient.EXTRA_SNAPSHOT_METADATA)) { - data.getParcelableExtra(SnapshotsClient.EXTRA_SNAPSHOT_METADATA)?.let { - savedGamesController.loadSnapshot(it.uniqueName) + if (::signInController.isInitialized) { + if (requestCode == SignInController.RC_SIGN_IN) { + if (data != null) { + val googleSignInResult = Auth.GoogleSignInApi.getSignInResultFromIntent(data) + signInController.onSignInActivityResult(googleSignInResult) + } else { + Log.e("PlayGameServicesGodot", "Intent data is null.") + } + } else if (requestCode == SavedGamesController.RC_SAVED_GAMES) { + if (data != null) { + if (data.hasExtra(SnapshotsClient.EXTRA_SNAPSHOT_METADATA)) { + data.getParcelableExtra(SnapshotsClient.EXTRA_SNAPSHOT_METADATA)?.let { + savedGamesController.loadSnapshot(it.uniqueName) + } + } else if (data.hasExtra(SnapshotsClient.EXTRA_SNAPSHOT_NEW)) { + val unique = BigInteger(281, Random()).toString(13) + savedGamesController.createNewSnapshot("$saveGameName$unique") } - } else if (data.hasExtra(SnapshotsClient.EXTRA_SNAPSHOT_NEW)) { - val unique = BigInteger(281, Random()).toString(13) - savedGamesController.createNewSnapshot("$saveGameName$unique") + } else { + Log.e("PlayGameServicesGodot", "Saved games intent data is null.") } } + } else { + Log.e("PlayGameServicesGodot", "signInController is not initialized.") } } - + @UsedByGodot fun isGooglePlayServicesAvailable(): Boolean { - val result: Int = GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(godot.activity as Activity) + val result: Int = GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(godot.getActivity() as Activity) return result == ConnectionResult.SUCCESS } + @UsedByGodot fun init(enablePopups: Boolean, requestEmail: Boolean, requestProfile: Boolean, requestToken: String) { initialize(false, enablePopups, "DefaultGame", requestEmail, requestProfile, requestToken) } + @UsedByGodot fun initWithSavedGames(enablePopups: Boolean, saveGameName: String, requestEmail: Boolean, requestProfile: Boolean, requestToken: String) { initialize(true, enablePopups, saveGameName, requestEmail, requestProfile, requestToken) } private fun initialize(enableSaveGamesFunctionality: Boolean, enablePopups: Boolean, saveGameName: String, requestEmail: Boolean, requestProfile: Boolean, requestToken: String) { + Log.i("godot","Initalizing PGSGP") + this.saveGameName = saveGameName val signInOptions = run { val signInOptionsBuilder = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN) @@ -199,7 +212,6 @@ class PlayGameServicesGodot(godot: Godot) : GodotPlugin(godot), AchievementsList signInOptionsBuilder.requestScopes(Scope(Scopes.DRIVE_APPFOLDER)) if (requestToken.isNotEmpty()) { signInOptionsBuilder.requestIdToken(requestToken) - signInOptionsBuilder.requestServerAuthCode(requestToken) } if (requestEmail) signInOptionsBuilder.requestEmail() @@ -209,147 +221,162 @@ class PlayGameServicesGodot(godot: Godot) : GodotPlugin(godot), AchievementsList signInOptionsBuilder.build() } - connectionController = ConnectionController(godot.activity as Activity, signInOptions) - signInController = SignInController(godot.activity as Activity, this, connectionController) - achievementsController = AchievementsController(godot.activity as Activity, this, connectionController) - leaderboardsController = LeaderboardsController(godot.activity as Activity, this, connectionController) - eventsController = EventsController(godot.activity as Activity, this, connectionController) - playerStatsController = PlayerStatsController(godot.activity as Activity, this, connectionController) - playerInfoController = PlayerInfoController(godot.activity as Activity, this, connectionController) - savedGamesController = SavedGamesController(godot.activity as Activity, this, connectionController) + connectionController = ConnectionController(godot.getActivity() as Activity, signInOptions) + signInController = SignInController(godot.getActivity() as Activity, this, connectionController) + achievementsController = AchievementsController(godot.getActivity() as Activity, this, connectionController) + leaderboardsController = LeaderboardsController(godot.getActivity() as Activity, this, connectionController) + eventsController = EventsController(godot.getActivity() as Activity, this, connectionController) + playerStatsController = PlayerStatsController(godot.getActivity() as Activity, this, connectionController) + playerInfoController = PlayerInfoController(godot.getActivity() as Activity, this, connectionController) + savedGamesController = SavedGamesController(godot.getActivity() as Activity, this, connectionController) - googleSignInClient = GoogleSignIn.getClient(godot.activity as Activity, signInOptions) + googleSignInClient = GoogleSignIn.getClient(godot.getActivity() as Activity, signInOptions) runOnUiThread { + Log.i("godot","enabling popups : " + enablePopups) + Log.i("godot", "created sigin in Controller" + signInController) + signInController.setShowPopups(enablePopups) } } + @UsedByGodot fun signIn() { + Log.i("godot","Attempting To Sign In") runOnUiThread { signInController.signIn(googleSignInClient) } } + @UsedByGodot fun signOut() { runOnUiThread { signInController.signOut(googleSignInClient) } } + @UsedByGodot fun isSignedIn(): Boolean { return signInController.isSignedIn() } + @UsedByGodot fun showAchievements() { runOnUiThread { achievementsController.showAchievements() } } + @UsedByGodot fun unlockAchievement(achievementName: String) { runOnUiThread { achievementsController.unlockAchievement(achievementName) } } + @UsedByGodot fun revealAchievement(achievementName: String) { runOnUiThread { achievementsController.revealAchievement(achievementName) } } + @UsedByGodot fun incrementAchievement(achievementName: String, step: Int) { runOnUiThread { achievementsController.incrementAchievement(achievementName, step) } } + @UsedByGodot fun setAchievementSteps(achievementName: String, steps: Int) { runOnUiThread { achievementsController.setAchievementSteps(achievementName, steps) } } + @UsedByGodot fun loadAchievementInfo(forceReload: Boolean) { runOnUiThread { achievementsController.loadAchievementInfo(forceReload) } } + @UsedByGodot fun showLeaderBoard(leaderBoardId: String) { runOnUiThread { leaderboardsController.showLeaderboard(leaderBoardId) } } + @UsedByGodot fun showAllLeaderBoards() { runOnUiThread { leaderboardsController.showAllLeaderboards() } } - fun retrieveLeaderboardScore(leaderBoardId: String, span: String, leaderboardCollection: String) { - runOnUiThread { - - leaderboardsController.retrieveLeaderboardScore(leaderBoardId, span, leaderboardCollection) - } - } - + @UsedByGodot fun submitLeaderBoardScore(leaderBoardId: String, score: Int) { runOnUiThread { leaderboardsController.submitScore(leaderBoardId, score) } } + @UsedByGodot fun submitEvent(eventId: String, incrementBy: Int) { runOnUiThread { eventsController.submitEvent(eventId, incrementBy) } } + @UsedByGodot fun loadEvents() { runOnUiThread { eventsController.loadEvents() } } + @UsedByGodot fun loadEventsById(ids: Array) { runOnUiThread { eventsController.loadEventById(ids) } } + @UsedByGodot fun loadPlayerStats(forceRefresh: Boolean) { runOnUiThread { playerStatsController.checkPlayerStats(forceRefresh) } } + @UsedByGodot fun showSavedGames(title: String, allowAdBtn: Boolean, allowDeleteBtn: Boolean, maxNumberOfSavedGamesToShow: Int) { runOnUiThread { savedGamesController.showSavedGamesUI(title, allowAdBtn, allowDeleteBtn, maxNumberOfSavedGamesToShow) } } + @UsedByGodot fun saveSnapshot(name: String, data: String, description: String) { runOnUiThread { savedGamesController.saveSnapshot(name, data, description) } } - + @UsedByGodot fun loadSnapshot(name: String) { runOnUiThread { savedGamesController.loadSnapshot(name) } } + @UsedByGodot fun loadPlayerInfo() { runOnUiThread { playerInfoController.fetchPlayerInfo() } } - override fun onAchievementUnlocked(achievementName: String) { emitSignal(SIGNAL_ACHIEVEMENT_UNLOCKED.name, achievementName) } @@ -411,11 +438,11 @@ class PlayGameServicesGodot(godot: Godot) : GodotPlugin(godot), AchievementsList } override fun onCurrentPlayerLeaderBoardScoreLoadingFailed(leaderboardId: String) { - emitSignal(SIGNAL_LEADERBOARD_SCORE_RETRIEVED_FAILED.name, leaderboardId) + emitSignal(SIGNAL_LEADERBOARD_SCORE_SUBMITTED_FAILED.name, leaderboardId) } override fun onCurrentPlayerLeaderBoardScoreLoaded(leaderboardId: String, scoreJson: String) { - emitSignal(SIGNAL_LEADERBOARD_SCORE_RETRIEVED.name, leaderboardId, scoreJson) + emitSignal(SIGNAL_CURRENT_PLAYER_LEADERBOARD_SCORE_LOADED.name, leaderboardId, scoreJson) } override fun onLeaderBoardScoreSubmitted(leaderboardId: String) { @@ -430,12 +457,12 @@ class PlayGameServicesGodot(godot: Godot) : GodotPlugin(godot), AchievementsList emitSignal(SIGNAL_SAVED_GAME_SUCCESS.name) } - override fun onSavedGameFailed() { - emitSignal(SIGNAL_SAVED_GAME_FAILED.name) + override fun onSavedGameFailed(saveError: String) { + emitSignal(SIGNAL_SAVED_GAME_FAILED.name, saveError) } - override fun onSavedGameLoadFailed() { - emitSignal(SIGNAL_SAVED_GAME_LOAD_FAIL.name) + override fun onSavedGameLoadFailed(loadError: String) { + emitSignal(SIGNAL_SAVED_GAME_LOAD_FAIL.name, loadError) } override fun onSavedGameLoadSuccess(data: String) { @@ -477,4 +504,4 @@ class PlayGameServicesGodot(godot: Godot) : GodotPlugin(godot), AchievementsList override fun onPlayerInfoLoadingFailed() { emitSignal(SIGNAL_PLAYER_INFO_LOADED_FAILED.name) } -} \ No newline at end of file +} diff --git a/app/src/main/java/io/cgisca/godot/gpgs/accountinfo/PlayerInfoController.kt b/app/src/main/java/io/cgisca/godot/gpgs/accountinfo/PlayerInfoController.kt index d666459..45798d8 100644 --- a/app/src/main/java/io/cgisca/godot/gpgs/accountinfo/PlayerInfoController.kt +++ b/app/src/main/java/io/cgisca/godot/gpgs/accountinfo/PlayerInfoController.kt @@ -45,7 +45,7 @@ class PlayerInfoController( val playerInfo = PlayerInfo( player.playerId, player.displayName, - player.name, + "TODO: get the name somehow", player.iconImageUrl, player.hiResImageUrl, player.title, diff --git a/app/src/main/java/io/cgisca/godot/gpgs/savedgames/SavedGamesController.kt b/app/src/main/java/io/cgisca/godot/gpgs/savedgames/SavedGamesController.kt index 592b4dc..48cfc37 100644 --- a/app/src/main/java/io/cgisca/godot/gpgs/savedgames/SavedGamesController.kt +++ b/app/src/main/java/io/cgisca/godot/gpgs/savedgames/SavedGamesController.kt @@ -47,9 +47,7 @@ class SavedGamesController( data: ByteArray?, desc: String ) { - if (data != null) { - snapshot.snapshotContents.writeBytes(data) - } + snapshot.snapshotContents.writeBytes(data!!) val metadataChange = SnapshotMetadataChange.Builder() .setDescription(desc) .build() @@ -61,11 +59,11 @@ class SavedGamesController( if (task.isSuccessful) { savedGamesListener.onSavedGameSuccess() } else { - savedGamesListener.onSavedGameFailed() + savedGamesListener.onSavedGameFailed("Failed to write Snapshot:") } } } else { - savedGamesListener.onSavedGameFailed() + savedGamesListener.onSavedGameFailed("No Connection to Googleplay") } } @@ -78,9 +76,10 @@ class SavedGamesController( if (connectionController.isConnected().first && googleSignInAccount != null) { val snapshotsClient = Games.getSnapshotsClient(activity, googleSignInAccount) val conflictResolutionPolicy = SnapshotsClient.RESOLUTION_POLICY_MOST_RECENTLY_MODIFIED - snapshotsClient.open(gameName, true, conflictResolutionPolicy) + val validGameName = gameName.replace("\\s.".toRegex(),"_") + snapshotsClient.open(validGameName, true, conflictResolutionPolicy) .addOnFailureListener { - savedGamesListener.onSavedGameFailed() + savedGamesListener.onSavedGameFailed("Failed to save Game: ${it.message}") } .continueWith>( Continuation, Pair> { task -> @@ -96,11 +95,11 @@ class SavedGamesController( val data = task.result!!.second writeSnapshot(snapshot, data, description) } else { - savedGamesListener.onSavedGameFailed() + savedGamesListener.onSavedGameFailed("Save Task not successful or task result is null") } } } else { - savedGamesListener.onSavedGameFailed() + savedGamesListener.onSavedGameFailed("No Connection to Google PLay") } } @@ -109,9 +108,10 @@ class SavedGamesController( if (connectionController.isConnected().first && googleSignInAccount != null) { val snapshotsClient = Games.getSnapshotsClient(activity, googleSignInAccount) val conflictResolutionPolicy = SnapshotsClient.RESOLUTION_POLICY_MOST_RECENTLY_MODIFIED - snapshotsClient.open(gameName, true, conflictResolutionPolicy) + val validGameName = gameName.replace("\\s.".toRegex(),"_") + snapshotsClient.open(validGameName, true, conflictResolutionPolicy) .addOnFailureListener { - savedGamesListener.onSavedGameLoadFailed() + savedGamesListener.onSavedGameLoadFailed("Failed to load Game: ${it.message}") } .continueWith(Continuation { task -> val snapshot = task.result @@ -132,11 +132,11 @@ class SavedGamesController( savedGamesListener.onSavedGameLoadSuccess(data) } } else { - savedGamesListener.onSavedGameLoadFailed() + savedGamesListener.onSavedGameLoadFailed("Load Task not Successful") } } } else { - savedGamesListener.onSavedGameLoadFailed() + savedGamesListener.onSavedGameLoadFailed("No Conection to GooglePlay") } } @@ -151,4 +151,4 @@ class SavedGamesController( private fun toStringData(bytes: ByteArray): String { return String(bytes) } -} \ No newline at end of file +} diff --git a/app/src/main/java/io/cgisca/godot/gpgs/savedgames/SavedGamesListener.kt b/app/src/main/java/io/cgisca/godot/gpgs/savedgames/SavedGamesListener.kt index 3d806fe..9f66c48 100644 --- a/app/src/main/java/io/cgisca/godot/gpgs/savedgames/SavedGamesListener.kt +++ b/app/src/main/java/io/cgisca/godot/gpgs/savedgames/SavedGamesListener.kt @@ -2,8 +2,8 @@ package io.cgisca.godot.gpgs.savedgames interface SavedGamesListener { fun onSavedGameSuccess() - fun onSavedGameFailed() - fun onSavedGameLoadFailed() + fun onSavedGameFailed(saveError: String) + fun onSavedGameLoadFailed(loadError: String) fun onSavedGameLoadSuccess(data: String) fun onSavedGameCreateSnapshot(currentSaveName: String) } \ No newline at end of file diff --git a/app/src/main/java/io/cgisca/godot/gpgs/signin/SignInController.kt b/app/src/main/java/io/cgisca/godot/gpgs/signin/SignInController.kt index cd472ff..99a99d1 100644 --- a/app/src/main/java/io/cgisca/godot/gpgs/signin/SignInController.kt +++ b/app/src/main/java/io/cgisca/godot/gpgs/signin/SignInController.kt @@ -26,6 +26,7 @@ class SignInController( } fun signIn(googleSignInClient: GoogleSignInClient) { + Log.i("godot","Attempting To Sign In") val userProfile = UserProfile(null, null, null, null, null) val connection: Pair = connectionController.isConnected() if (connection.first) { @@ -35,7 +36,9 @@ class SignInController( } else { Log.i("godot","Using new signin data") googleSignInClient - .silentSignIn() + .silentSignIn().addOnFailureListener{ exception -> + Log.e("SignInController", "Silent sign-in failed: ${exception.message}") + } .addOnCompleteListener(activity) { task -> if (task.isSuccessful) { val googleSignInAccount = task.result diff --git a/build.gradle b/build.gradle index c61dcf9..ab55734 100644 --- a/build.gradle +++ b/build.gradle @@ -1,15 +1,12 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { - ext { - agp_version = '7.1.2' - } - ext.kotlin_version = '1.6.10' + ext.kotlin_version = "1.8.0" repositories { google() - mavenCentral() + jcenter() } dependencies { - classpath "com.android.tools.build:gradle:$agp_version" + classpath 'com.android.tools.build:gradle:8.0.2' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" // NOTE: Do not place your application dependencies here; they belong @@ -20,10 +17,10 @@ buildscript { allprojects { repositories { google() - mavenCentral() + jcenter() } } task clean(type: Delete) { delete rootProject.buildDir -} +} \ No newline at end of file diff --git a/demo/Main.gd b/demo/Main.gd index 5f99c1f..9fc052d 100644 --- a/demo/Main.gd +++ b/demo/Main.gd @@ -1,11 +1,11 @@ extends Control #REPLACE BELOW IDS WITH YOUR OWN -const UNLOCK_ACHIEVEMENT = "CgkIqt-jg_MWEAIQAQ" -const REVEAL_ACHIEVEMENT = "CgkIqt-jg_MWEAIQAQ" -const INCREMENT_ACHIEVEMENT = "CgkIqt-jg_MWEAIQAQ" -const SET_ACHIEVEMENT_STEPS = "CgkIqt-jg_MWEAIQAQ" -const LEADERBOARD_ID = "CgkIqt-jg_MWEAIQAQ" +const UNLOCK_ACHIEVEMENT = "CgkIz_-Zz4gFEAIQAg" +const REVEAL_ACHIEVEMENT = "CgkIz_-Zz4gFEAIQAg" +const INCREMENT_ACHIEVEMENT = "CgkIz_-Zz4gFEAIQAw" +const SET_ACHIEVEMENT_STEPS = "CgkIz_-Zz4gFEAIQAw" +const LEADERBOARD_ID = "CgkIz_-Zz4gFEAIQBQ" var play_games_services @@ -14,27 +14,27 @@ func _ready(): if Engine.has_singleton("GodotPlayGamesServices"): play_games_services = Engine.get_singleton("GodotPlayGamesServices") - play_games_services.connect("_on_sign_in_success", self, "_on_sign_in_success") - play_games_services.connect("_on_sign_in_failed", self, "_on_sign_in_failed") - play_games_services.connect("_on_sign_out_success", self, "_on_sign_out_success") - play_games_services.connect("_on_sign_out_failed", self, "_on_sign_out_failed") - play_games_services.connect("_on_achievement_unlocked", self, "_on_achievement_unlocked") - play_games_services.connect("_on_achievement_unlocking_failed", self, "_on_achievement_unlocking_failed") - play_games_services.connect("_on_achievement_revealed", self, "_on_achievement_revealed") - play_games_services.connect("_on_achievement_revealing_failed", self, "_on_achievement_revealing_failed") - play_games_services.connect("_on_achievement_incremented", self, "_on_achievement_incremented") - play_games_services.connect("_on_achievement_incrementing_failed", self, "_on_achievement_incrementing_failed") - play_games_services.connect("_on_achievement_steps_set", self, "_on_achievement_steps_set") - play_games_services.connect("_on_achievement_steps_setting_failed", self, "_on_achievement_steps_setting_failed") - play_games_services.connect("_on_leaderboard_score_submitted", self, "_on_leaderboard_score_submitted") - play_games_services.connect("_on_leaderboard_score_submitting_failed", self, "_on_leaderboard_score_submitting_failed") - play_games_services.connect("_on_game_saved_success", self, "_on_game_saved_success") - play_games_services.connect("_on_game_saved_fail", self, "_on_game_saved_fail") - play_games_services.connect("_on_game_load_success", self, "_on_game_load_success") - play_games_services.connect("_on_game_load_fail", self, "_on_game_load_fail") - play_games_services.connect("_on_create_new_snapshot", self, "_on_create_new_snapshot") - play_games_services.connect("_on_player_info_loaded", self, "_on_player_info_loaded") - play_games_services.connect("_on_player_info_loading_failed", self, "_on_player_info_loading_failed") + play_games_services.connect("_on_sign_in_success", Callable(self, "_on_sign_in_success")) + play_games_services.connect("_on_sign_in_failed", Callable(self, "_on_sign_in_failed")) + play_games_services.connect("_on_sign_out_success", Callable(self, "_on_sign_out_success")) + play_games_services.connect("_on_sign_out_failed", Callable(self, "_on_sign_out_failed")) + play_games_services.connect("_on_achievement_unlocked", Callable(self, "_on_achievement_unlocked")) + play_games_services.connect("_on_achievement_unlocking_failed", Callable(self, "_on_achievement_unlocking_failed")) + play_games_services.connect("_on_achievement_revealed", Callable(self, "_on_achievement_revealed")) + play_games_services.connect("_on_achievement_revealing_failed", Callable(self, "_on_achievement_revealing_failed")) + play_games_services.connect("_on_achievement_incremented", Callable(self, "_on_achievement_incremented")) + play_games_services.connect("_on_achievement_incrementing_failed", Callable(self, "_on_achievement_incrementing_failed")) + play_games_services.connect("_on_achievement_steps_set", Callable(self, "_on_achievement_steps_set")) + play_games_services.connect("_on_achievement_steps_setting_failed", Callable(self, "_on_achievement_steps_setting_failed")) + play_games_services.connect("_on_leaderboard_score_submitted", Callable(self, "_on_leaderboard_score_submitted")) + play_games_services.connect("_on_leaderboard_score_submitting_failed", Callable(self, "_on_leaderboard_score_submitting_failed")) + play_games_services.connect("_on_game_saved_success", Callable(self, "_on_game_saved_success")) + play_games_services.connect("_on_game_saved_fail", Callable(self, "_on_game_saved_fail")) + play_games_services.connect("_on_game_load_success", Callable(self, "_on_game_load_success")) + play_games_services.connect("_on_game_load_fail", Callable(self, "_on_game_load_fail")) + play_games_services.connect("_on_create_new_snapshot", Callable(self, "_on_create_new_snapshot")) + play_games_services.connect("_on_player_info_loaded", Callable(self, "_on_player_info_loaded")) + play_games_services.connect("_on_player_info_loading_failed", Callable(self, "_on_player_info_loading_failed")) play_games_services.init(true,false,false,"") # play_games_services.init(true,true,false,"") # Use this init if you want to get email of the player @@ -114,7 +114,7 @@ func save_game() -> void: } if play_games_services: - play_games_services.saveSnapshot("SNAPSHOT_NAME", to_json(data_to_save), "DESCRIPTION") + play_games_services.saveSnapshot("SNAPSHOT_NAME", JSON.new().stringify(data_to_save), "DESCRIPTION") func show_saved_games() -> void: @@ -130,7 +130,9 @@ func load_player_info() -> void: # CALLBACKS # Sign-in / sign-out callbacks func _on_sign_in_success(userProfile_json: String) -> void: - var userProfile = parse_json(userProfile_json) + var test_json_conv = JSON.new() + test_json_conv.parse(userProfile_json) + var userProfile = test_json_conv.get_data() print("Sign in success ",userProfile) func _on_sign_in_failed(error_code: int) -> void: @@ -184,10 +186,14 @@ func _on_game_saved_fail(): print("Game saved fail") func _on_game_load_success(data): - var game_data: Dictionary = parse_json(data) + var test_json_conv = JSON.new() + test_json_conv.parse(data) + var game_data: Dictionary = test_json_conv.get_data() print(data) print("=====") - print(parse_json(data)) + var test_json_conv2 = JSON.new() + test_json_conv2.parse(data) + print(test_json_conv.get_data()) func _on_game_load_fail(): print("Game load fail") @@ -198,7 +204,9 @@ func _on_create_new_snapshot(name:String): # Player Info Callbacks func _on_player_info_loaded(player_info: String): - var player_info_dictionary: Dictionary = parse_json(player_info) + var test_json_conv = JSON.new() + test_json_conv.parse(player_info) + var player_info_dictionary: Dictionary = test_json_conv.get_data() print(player_info_dictionary) func _on_player_info_loading_failed(): diff --git a/demo/Main.tscn b/demo/Main.tscn index 8b7f8fa..2ed19a1 100644 --- a/demo/Main.tscn +++ b/demo/Main.tscn @@ -1,78 +1,63 @@ -[gd_scene load_steps=2 format=2] +[gd_scene load_steps=2 format=3 uid="uid://cknv4jbc2gnq3"] -[ext_resource path="res://Main.gd" type="Script" id=1] +[ext_resource type="Script" path="res://Main.gd" id="1"] [node name="Main" type="Control"] +layout_mode = 3 +anchors_preset = 15 anchor_right = 1.0 anchor_bottom = 1.0 -script = ExtResource( 1 ) -__meta__ = { -"_edit_use_anchors_": false -} +grow_horizontal = 2 +grow_vertical = 2 +script = ExtResource("1") [node name="VBoxContainer" type="VBoxContainer" parent="."] +custom_minimum_size = Vector2(300, 0) +layout_mode = 0 anchor_right = 1.0 anchor_bottom = 1.0 -rect_min_size = Vector2( 300, 0 ) -custom_constants/separation = 40 -__meta__ = { -"_edit_use_anchors_": false -} +theme_override_constants/separation = 40 [node name="SignInButton" type="Button" parent="VBoxContainer"] -margin_right = 600.0 -margin_bottom = 100.0 -rect_min_size = Vector2( 200, 100 ) +custom_minimum_size = Vector2(200, 100) +layout_mode = 2 text = "Sign In" [node name="SignOutButton" type="Button" parent="VBoxContainer"] -margin_top = 140.0 -margin_right = 600.0 -margin_bottom = 240.0 -rect_min_size = Vector2( 200, 100 ) +custom_minimum_size = Vector2(200, 100) +layout_mode = 2 text = "Sign Out" [node name="CheckIfSignedInButton" type="Button" parent="VBoxContainer"] -margin_top = 280.0 -margin_right = 600.0 -margin_bottom = 380.0 -rect_min_size = Vector2( 200, 100 ) +custom_minimum_size = Vector2(200, 100) +layout_mode = 2 text = "Check If Signed In" [node name="SaveGameButton" type="Button" parent="VBoxContainer"] -margin_top = 420.0 -margin_right = 600.0 -margin_bottom = 520.0 -rect_min_size = Vector2( 200, 100 ) +custom_minimum_size = Vector2(200, 100) +layout_mode = 2 text = "Save game" [node name="ShowSavedGamesButton" type="Button" parent="VBoxContainer"] -margin_top = 560.0 -margin_right = 600.0 -margin_bottom = 660.0 -rect_min_size = Vector2( 200, 100 ) +custom_minimum_size = Vector2(200, 100) +layout_mode = 2 text = "ShowSavedGames" [node name="Button" type="Button" parent="VBoxContainer"] -margin_top = 700.0 -margin_right = 600.0 -margin_bottom = 800.0 -rect_min_size = Vector2( 200, 100 ) +custom_minimum_size = Vector2(200, 100) +layout_mode = 2 text = "Load saved game" [node name="ShowLeaderBoardsButton" type="Button" parent="VBoxContainer"] -margin_top = 840.0 -margin_right = 600.0 -margin_bottom = 940.0 -rect_min_size = Vector2( 0, 100 ) +custom_minimum_size = Vector2(0, 100) +layout_mode = 2 text = "Show leaderboards" [node name="AchievementUnlockButton" type="Button" parent="VBoxContainer"] -margin_top = 980.0 -margin_right = 600.0 -margin_bottom = 1080.0 -rect_min_size = Vector2( 0, 100 ) +custom_minimum_size = Vector2(0, 100) +layout_mode = 2 text = "Unlock achievement" + [connection signal="pressed" from="VBoxContainer/SignInButton" to="." method="_on_SignInButton_pressed"] [connection signal="pressed" from="VBoxContainer/SignOutButton" to="." method="_on_SignOutButton_pressed"] [connection signal="pressed" from="VBoxContainer/CheckIfSignedInButton" to="." method="_on_CheckIfSignedInButton_pressed"] diff --git a/demo/addons/PGSGP/PGSGP.gd b/demo/addons/PGSGP/PGSGP.gd new file mode 100644 index 0000000..c8b0058 --- /dev/null +++ b/demo/addons/PGSGP/PGSGP.gd @@ -0,0 +1,44 @@ +@tool +extends EditorPlugin + +# A class member to hold the editor export plugin during its lifecycle. +var export_plugin : AndroidExportPlugin + +func _enter_tree(): + # Initialization of the plugin goes here. + export_plugin = AndroidExportPlugin.new() + add_export_plugin(export_plugin) + + +func _exit_tree(): + # Clean-up of the plugin goes here. + remove_export_plugin(export_plugin) + export_plugin = null + + +class AndroidExportPlugin extends EditorExportPlugin: + # Plugin's name. + var _plugin_name = "PGSGP" + + # Specifies which platform is supported by the plugin. + func _supports_platform(platform): + if platform is EditorExportPlatformAndroid: + return true + return false + + # Return the paths of the plugin's AAR binaries relative to the 'addons' directory. + func _get_android_libraries(platform, debug): + if debug: + return PackedStringArray(["PGSGP/GodotPlayGamesServices.release.aar"]) + else: + return PackedStringArray(["PGSGP/GodotPlayGamesServices.release.aar"]) + + func _get_android_dependencies(platform, debug): + # TODO: Add remote dependices here. + if debug: + return PackedStringArray(["com.google.android.gms:play-services-games:23.1.0","com.google.android.gms:play-services-auth:20.6.0", "com.google.code.gson:gson:2.8.6"]) + else: + return PackedStringArray(["com.google.android.gms:play-services-games:23.1.0","com.google.android.gms:play-services-auth:20.6.0", "com.google.code.gson:gson:2.8.6"]) + # Return the plugin's name. + func _get_name(): + return _plugin_name diff --git a/demo/addons/PGSGP/plugin.cfg b/demo/addons/PGSGP/plugin.cfg new file mode 100644 index 0000000..a1eb9e0 --- /dev/null +++ b/demo/addons/PGSGP/plugin.cfg @@ -0,0 +1,7 @@ +[plugin] + +name="PGSGP" +description="Google Play Game Services" +author="FinepointCGI" +version="1.1" +script="PGSGP.gd" diff --git a/demo/android/.build_version b/demo/android/.build_version index 5eebfbc..f98af0f 100644 --- a/demo/android/.build_version +++ b/demo/android/.build_version @@ -1 +1 @@ -3.2.3.stable +4.1.stable diff --git a/demo/android/plugins/GodotPlayGamesServices.gdap b/demo/android/plugins/GodotPlayGamesServices.gdap index 42dfe8e..c21f781 100644 --- a/demo/android/plugins/GodotPlayGamesServices.gdap +++ b/demo/android/plugins/GodotPlayGamesServices.gdap @@ -6,6 +6,6 @@ binary="GodotPlayGamesServices.release.aar" [dependencies] -remote=["com.google.android.gms:play-services-games:21.0.0", "com.google.android.gms:play-services-auth:19.0.0", "com.google.code.gson:gson:2.8.6"] +remote=["com.google.android.gms:play-services-games:23.1.0", "com.google.android.gms:play-services-auth:20.5.0", "com.google.android.gms:play-services-location:21.0.1", "com.google.code.gson:gson:2.8.9"] diff --git a/demo/android/plugins/GodotPlayGamesServices.release.aar b/demo/android/plugins/GodotPlayGamesServices.release.aar deleted file mode 100644 index 140cbb4..0000000 Binary files a/demo/android/plugins/GodotPlayGamesServices.release.aar and /dev/null differ diff --git a/demo/default_env.tres b/demo/default_env.tres index 20207a4..8f9ee1f 100644 --- a/demo/default_env.tres +++ b/demo/default_env.tres @@ -1,7 +1,7 @@ -[gd_resource type="Environment" load_steps=2 format=2] +[gd_resource type="Environment" load_steps=2 format=3 uid="uid://dckcado38gts2"] -[sub_resource type="ProceduralSky" id=1] +[sub_resource type="Sky" id="1"] [resource] background_mode = 2 -background_sky = SubResource( 1 ) +sky = SubResource("1") diff --git a/demo/export_presets.cfg b/demo/export_presets.cfg index 4000153..4a54bae 100644 --- a/demo/export_presets.cfg +++ b/demo/export_presets.cfg @@ -3,57 +3,57 @@ name="Android" platform="Android" runnable=true +dedicated_server=false custom_features="" export_filter="all_resources" include_filter="" exclude_filter="" export_path="" -patch_list=PoolStringArray( ) -script_export_mode=1 -script_encryption_key="" +encryption_include_filters="" +encryption_exclude_filters="" +encrypt_pck=false +encrypt_directory=false [preset.0.options] -graphics/32_bits_framebuffer=true -xr_features/xr_mode=0 -xr_features/degrees_of_freedom=0 -xr_features/hand_tracking=0 -xr_features/focus_awareness=false -one_click_deploy/clear_previous_install=false custom_template/debug="" custom_template/release="" -custom_template/use_custom_build=true +gradle_build/use_gradle_build=true +gradle_build/export_format=0 +gradle_build/min_sdk="" +gradle_build/target_sdk="" plugins/GodotPlayGamesServices=true -command_line/extra_args="" +architectures/armeabi-v7a=true +architectures/arm64-v8a=true +architectures/x86=false +architectures/x86_64=false version/code=1 version/name="1.0" package/unique_name="com.example.godot.gpgs" package/name="Godot" package/signed=true +package/app_category=2 +package/retain_data_on_uninstall=false +package/exclude_from_recents=false +launcher_icons/main_192x192="" +launcher_icons/adaptive_foreground_432x432="" +launcher_icons/adaptive_background_432x432="" +graphics/opengl_debug=false +xr_features/xr_mode=0 +xr_features/hand_tracking=0 +xr_features/hand_tracking_frequency=0 +xr_features/passthrough=0 screen/immersive_mode=true -screen/orientation=0 screen/support_small=true screen/support_normal=true screen/support_large=true screen/support_xlarge=true -screen/opengl_debug=false -launcher_icons/main_192x192="" -launcher_icons/adaptive_foreground_432x432="" -launcher_icons/adaptive_background_432x432="" -keystore/debug="" -keystore/debug_user="" -keystore/debug_password="" -keystore/release="" -keystore/release_user="" -keystore/release_password="" +user_data_backup/allow=false +command_line/extra_args="" apk_expansion/enable=false apk_expansion/SALT="" apk_expansion/public_key="" -architectures/armeabi-v7a=true -architectures/arm64-v8a=true -architectures/x86=false -architectures/x86_64=false -permissions/custom_permissions=PoolStringArray( ) +permissions/custom_permissions=PackedStringArray() permissions/access_checkin_properties=false permissions/access_coarse_location=false permissions/access_fine_location=false @@ -126,6 +126,7 @@ permissions/location_hardware=false permissions/manage_accounts=false permissions/manage_app_tokens=false permissions/manage_documents=false +permissions/manage_external_storage=false permissions/master_clear=false permissions/media_content_control=false permissions/modify_audio_settings=false diff --git a/demo/icon.png.import b/demo/icon.png.import index 96cbf46..de3d497 100644 --- a/demo/icon.png.import +++ b/demo/icon.png.import @@ -1,8 +1,9 @@ [remap] importer="texture" -type="StreamTexture" -path="res://.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex" +type="CompressedTexture2D" +uid="uid://bva2c38nyce62" +path="res://.godot/imported/icon.png-487276ed1e3a0c39cad0279d744ee560.ctex" metadata={ "vram_texture": false } @@ -10,25 +11,24 @@ metadata={ [deps] source_file="res://icon.png" -dest_files=[ "res://.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex" ] +dest_files=["res://.godot/imported/icon.png-487276ed1e3a0c39cad0279d744ee560.ctex"] [params] compress/mode=0 +compress/high_quality=false compress/lossy_quality=0.7 -compress/hdr_mode=0 -compress/bptc_ldr=0 +compress/hdr_compression=1 compress/normal_map=0 -flags/repeat=0 -flags/filter=true -flags/mipmaps=false -flags/anisotropic=false -flags/srgb=2 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" process/fix_alpha_border=true process/premult_alpha=false -process/HDR_as_SRGB=false -process/invert_color=false -stream=false -size_limit=0 -detect_3d=true -svg/scale=1.0 +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/demo/project.godot b/demo/project.godot index 3c2b95a..773697a 100644 --- a/demo/project.godot +++ b/demo/project.godot @@ -6,25 +6,26 @@ ; [section] ; section goes between [] ; param=value ; assign values to parameters -config_version=4 - -_global_script_classes=[ ] -_global_script_class_icons={ - -} +config_version=5 [application] config/name="Demo" run/main_scene="res://Main.tscn" +config/features=PackedStringArray("4.1") config/icon="res://icon.png" [display] -window/size/width=600 -window/size/height=1024 -window/handheld/orientation="portrait" +window/size/viewport_width=600 +window/size/viewport_height=1024 +window/handheld/orientation=1 + +[dotnet] + +project/assembly_name="Demo" [rendering] -environment/default_environment="res://default_env.tres" +textures/vram_compression/import_etc2_astc=true +environment/defaults/default_environment="res://default_env.tres" diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index fc7fc95..3e989a0 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Sat Mar 26 08:33:05 MYT 2022 +#Fri Jul 14 10:37:01 EDT 2023 distributionBase=GRADLE_USER_HOME -distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.1-bin.zip distributionPath=wrapper/dists -zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.2.1-bin.zip zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/settings.gradle b/settings.gradle index 9d495b3..ffc89a4 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1 +1 @@ -include ':app' \ No newline at end of file +include ':app', ':godot-lib.release'