{"id":14961566,"url":"https://github.com/cgisca/pgsgp","last_synced_at":"2025-06-22T18:08:53.721Z","repository":{"id":36486950,"uuid":"223044917","full_name":"cgisca/PGSGP","owner":"cgisca","description":"Play Games Services plugin for Godot Game Engine - Android","archived":false,"fork":false,"pushed_at":"2023-05-04T14:47:37.000Z","size":37746,"stargazers_count":223,"open_issues_count":27,"forks_count":59,"subscribers_count":12,"default_branch":"master","last_synced_at":"2025-06-22T18:08:47.131Z","etag":null,"topics":["achievements","game-services","godot","godot-engine","godot-gpgs","godot-module","godot-play-games-services","godot-plugin","godotengine","google-play-game-services","leaderboards","player-stats","saved-games"],"latest_commit_sha":null,"homepage":"","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cgisca.png","metadata":{"files":{"readme":"README.md","changelog":"Changelog.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-11-20T23:12:41.000Z","updated_at":"2025-04-30T20:58:08.000Z","dependencies_parsed_at":"2024-09-24T13:43:16.529Z","dependency_job_id":"a05dbd8f-e758-4d36-ba5e-ef3e8a3d69cf","html_url":"https://github.com/cgisca/PGSGP","commit_stats":{"total_commits":50,"total_committers":8,"mean_commits":6.25,"dds":0.52,"last_synced_commit":"7cc60029b4dba5780056ba4079d1ef9c246df575"},"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/cgisca/PGSGP","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cgisca%2FPGSGP","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cgisca%2FPGSGP/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cgisca%2FPGSGP/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cgisca%2FPGSGP/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cgisca","download_url":"https://codeload.github.com/cgisca/PGSGP/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cgisca%2FPGSGP/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":261338998,"owners_count":23143900,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["achievements","game-services","godot","godot-engine","godot-gpgs","godot-module","godot-play-games-services","godot-plugin","godotengine","google-play-game-services","leaderboards","player-stats","saved-games"],"created_at":"2024-09-24T13:25:42.814Z","updated_at":"2025-06-22T18:08:48.705Z","avatar_url":"https://github.com/cgisca.png","language":"Kotlin","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Google Play Games Services Plugin for Godot \nThis is an Android Play Games Services plugin for Godot Game Engine 3.2.2+. \n\n[![Android](https://img.shields.io/badge/Platform-Android-brightgreen.svg)](https://developer.android.com)\n[![Godot](https://img.shields.io/badge/Godot%20Engine-3.2.2-blue.svg)](https://github.com/godotengine/godot/)\n[![PGS](https://img.shields.io/badge/Play%20Games%20Services-20.0.1-green.svg)](https://developers.google.com/games/services/android/quickstart)\n[![MIT license](https://img.shields.io/badge/License-MIT-yellowgreen.svg)](https://lbesson.mit-license.org/)\n\n\nIf you want to use the old plugin version visit [Old README file](https://github.com/cgisca/PGSGP/blob/master/README_OLD.md).\n\n\n### Supported features:\n- Sign-in/Sign out\n- Achievements\n- Leaderboards\n- Events\n- Player Stats\n- Player Info\n- Saved Games\n\n## Getting started\nBefore using this plugin please follow instructions on [Setting Up Google Play Games Services](https://developers.google.com/games/services/console/enabling) official guide.\n### Set up\n- Download `GodotPlayGamesServices.release.aar` and `GodotPlayGamesServices.gdap` from [releases](https://github.com/cgisca/PGSGP/releases) page.\n- 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.\n- Enable plugin by accessing `Project` -\u003e `Export`, Plugins section. Follow the [image](https://docs.godotengine.org/en/stable/_images/android_export_preset_plugins_section.png).\n- Go to res://android/build directory. Add below lines to `AndroidManifest.xml`:\n```xml\t\n    \u003cmeta-data android:name=\"com.google.android.gms.games.APP_ID\"\n   \t    android:value=\"@string/app_id\" /\u003e\n   \n   \t\u003cmeta-data android:name=\"com.google.android.gms.version\"\n   \t   android:value=\"@integer/google_play_services_version\"/\u003e\n```\n- In the same res://android/build directory,(if it is not already created) create  `res` -\u003e `values` -\u003e `Strings.xml`. Add below lines to `Strings.xml`:\n```xml\n\u003c?xml version=\"1.0\" encoding=\"utf-8\"?\u003e\n\u003cresources\u003e\n    \t\u003cstring name=\"app_id\"\u003eADD_YOUR_APP_ID\u003c/string\u003e\n\u003c/resources\u003e\n```\nReplace ADD_YOUR_APP_ID with the app id that was generated after following instructions on [Setting Up Google Play Games Services](https://developers.google.com/games/services/console/enabling)\n\nCheck demo project. In order demo project to work, replace \u003cstring name=\"app_id\"\u003eADD_YOUR_APP_ID\u003c/string\u003e with your own app id, and in Main.gd add your ids for achievements and leaderboards.\n\n### Generate plugin .aar file\n\nIf there is no release for your Godot version, you need to generate new plugin .aar file.  \nFollow these instruction: [ official documentation](https://docs.godotengine.org/en/stable/tutorials/plugins/android/android_plugin.html \"documentation\").\n\nIn short follow these steps:\n\n1. Download [ AAR library for Android plugins](https://godotengine.org/download/windows \"Godot download\").\n\n2. Copy .aar file to *godot-lib.release/* and rename it to *godot-lib.release.aar*\n\n3. Compile the project:\n\n\tOpen command window and *cd* into *PGSGP* direcory and run command below\n\t\n\t* Windows:\n\t\n\t\tgradlew.bat assembleRelease\n\t\t\n\t* Linux:\n\t\n\t\t./gradlew assembleRelease\n\t\n4. Copy the newly created .aar file to your plugin directory:\n\n*app/build/outputs/aar/GodotPlayGamesServices.release.aar* to *[your godot project]/android/plugins/*\n\n### How to use\nFirst step is plugin initialization\n```gdscript\nvar play_games_services\n# Check if plugin was added to the project\nif Engine.has_singleton(\"GodotPlayGamesServices\"):\n  play_games_services = Engine.get_singleton(\"GodotPlayGamesServices\")\n\t\n  # Initialize plugin by calling init method and passing to it a boolean to enable/disable displaying game pop-ups\n  \n  var show_popups := true \n  play_games_services.init(show_popups)\n  # For enabling saved games functionality use below initialization instead\n  # play_games_services.initWithSavedGames(show_popups, \"SavedGamesName\")\n  \n  # Connect callbacks (Use only those that you need)\n  play_games_services.connect(\"_on_sign_in_success\", self, \"_on_sign_in_success\") # account_id: String\n  play_games_services.connect(\"_on_sign_in_failed\", self, \"_on_sign_in_failed\") # error_code: int\n  play_games_services.connect(\"_on_sign_out_success\", self, \"_on_sign_out_success\") # no params\n  play_games_services.connect(\"_on_sign_out_failed\", self, \"_on_sign_out_failed\") # no params\n  play_games_services.connect(\"_on_achievement_unlocked\", self, \"_on_achievement_unlocked\") # achievement: String\n  play_games_services.connect(\"_on_achievement_unlocking_failed\", self, \"_on_achievement_unlocking_failed\") # achievement: String\n  play_games_services.connect(\"_on_achievement_revealed\", self, \"_on_achievement_revealed\") # achievement: String\n  play_games_services.connect(\"_on_achievement_revealing_failed\", self, \"_on_achievement_revealing_failed\") # achievement: String\n  play_games_services.connect(\"_on_achievement_incremented\", self, \"_on_achievement_incremented\") # achievement: String\n  play_games_services.connect(\"_on_achievement_incrementing_failed\", self, \"_on_achievement_incrementing_failed\") # achievement: String\n  play_games_services.connect(\"_on_achievement_info_loaded\", self, \"_on_achievement_info_loaded\") # achievements_json : String\n  play_games_services.connect(\"_on_achievement_info_load_failed\", self, \"_on_achievement_info_load_failed\")\n  play_games_services.connect(\"_on_leaderboard_score_submitted\", self, \"_on_leaderboard_score_submitted\") # leaderboard_id: String\n  play_games_services.connect(\"_on_leaderboard_score_submitting_failed\", self, \"_on_leaderboard_score_submitting_failed\") # leaderboard_id: String\n  play_games_services.connect(\"_on_game_saved_success\", self, \"_on_game_saved_success\") # no params\n  play_games_services.connect(\"_on_game_saved_fail\", self, \"_on_game_saved_fail\") # no params\n  play_games_services.connect(\"_on_game_load_success\", self, \"_on_game_load_success\") # data: String\n  play_games_services.connect(\"_on_game_load_fail\", self, \"_on_game_load_fail\") # no params\n  play_games_services.connect(\"_on_create_new_snapshot\", self, \"_on_create_new_snapshot\") # name: String\n  play_games_services.connect(\"_on_player_info_loaded\", self, \"_on_player_info_loaded\")  # json_response: String\n  play_games_services.connect(\"_on_player_info_loading_failed\", self, \"_on_player_info_loading_failed\")\n  play_games_services.connect(\"_on_player_stats_loaded\", self, \"_on_player_stats_loaded\")  # json_response: String\n  play_games_services.connect(\"_on_player_stats_loading_failed\", self, \"_on_player_stats_loading_failed\")\n```\nAfter what plugin was initialized you can use supported features\n#### Sign-in / Sign out\n##### Sign-in\n\n```gdscript\nplay_games_services.signIn()\n\n# Callbacks:\nfunc _on_sign_in_success(account_id: String) -\u003e void:\n\tpass\n  \nfunc _on_sign_in_failed(error_code: int) -\u003e void:\n\tpass\n\n```\n##### Sign out\n```gdscript\nplay_games_services.signOut()\n\n# Callbacks:\nfunc _on_sign_out_success():\n\tpass\n  \nfunc _on_sign_out_failed():\n\tpass\n```\n##### Check if signed in\n```gdscript\nvar is_signed_in: bool = play_games_services.isSignedIn()\n```\n#### Achievements\n##### Unlock Achievement\n```gdscript\nplay_games_services.unlockAchievement(\"ACHIEVEMENT_ID\")\n\n# Callbacks:\nfunc _on_achievement_unlocked(achievement: String):\n\tpass\n\nfunc _on_achievement_unlocking_failed(achievement: String):\n\tpass\n```\n##### Increment Achievement\n```gdscript\nvar step = 1\nplay_games_services.incrementAchievement(\"ACHIEVEMENT_ID\", step)\n\n# Callbacks:\nfunc _on_achievement_incremented(achievement: String):\n\tpass\n\nfunc _on_achievement_incrementing_failed(achievement: String):\n\tpass\n```\n##### Set Achievement Steps\n```gdscript\nvar steps = 3\nplay_games_services.setAchievementSteps(\"ACHIEVEMENT_ID\", steps)\n\n# Callbacks:\nfunc _on_achievement_steps_set(achievement: String):\n\tpass\n\nfunc _on_achievement_steps_setting_failed(achievement: String):\n\tpass\n```\n##### Reveal Achievement\n```gdscript\nplay_games_services.revealAchievement(\"ACHIEVEMENT_ID\")\n\n# Callbacks:\nfunc _on_achievement_revealed(achievement: String):\n\tpass\n\nfunc _on_achievement_revealing_failed(achievement: String):\n\tpass\n```\n##### Show Achievements List\n```gdscript\nplay_games_services.showAchievements()\n```\n##### Load Achievement info\n```gdscript\nplay_games_services.loadAchievementInfo(false) # forceReload\n\n# Callbacks:\nfunc _on_achievement_info_load_failed(event_id: String):\n\tpass\n\nfunc _on_achievement_info_loaded(achievements_json: String):\n\tvar achievements = parse_json(achievements_json)\n\n\t# The returned JSON contains an array of achievement info items.\n\t# Use the following keys to access the fields\n\tfor a in achievements:\n\t\ta[\"id\"] # Achievement ID\n\t\ta[\"name\"]\n\t\ta[\"description\"]\n\t\ta[\"state\"] # unlocked=0, revealed=1, hidden=2 (for the current player)\n\t\ta[\"type\"] # standard=0, incremental=1\n\t\ta[\"xp\"] # Experience gain when unlocked\n\n\t\t# Steps only available for incremental achievements\n\t\tif a[\"type\"] == 1:\n\t\t\ta[\"current_steps\"] # Users current progress\n\t\t\ta[\"total_steps\"] # Total steps to unlock achievement\n```\n#### Leaderboards\n##### Submit leaderboard score\n```gdscript\nvar score = 1234\nplay_games_services.submitLeaderBoardScore(\"LEADERBOARD_ID\", score)\n\n# Callbacks:\nfunc _on_leaderboard_score_submitted(leaderboard_id: String):\n\tpass\n\nfunc _on_leaderboard_score_submitting_failed(leaderboard_id: String):\n\tpass\n```\n##### Show leaderboard\n```gdscript\nplay_games_services.showLeaderBoard(\"LEADERBOARD_ID\")\n\n\nplay_games_services.showAllLeaderBoards()\n```\n\n#### Events\n##### Submit event\n```gdscript\nvar increment_by := 2\nplay_games_services.submitEvent(\"EVENT_ID\", increment_by)\n\n# Callbacks:\nfunc _on_event_submitted(event_id: String):\n\tpass\n\t\nfunc _on_event_submitted_failed(event_id: String):\n\tpass\n```\n##### Load events\n```gdscript\n# Load all events\nplay_games_services.loadEvents()\n# Or load events by given ids\nplay_games_services.loadEventsById([\"EVENT_ID_1\", \"EVENT_ID_2\", ...])\n\n# Callbacks:\n# If there is at least one event, following callback will be triggered:\nfunc _on_events_loaded(events_array):\n\t# Parse received string json of events using parse_json\n\tvar available_events = parse_json(events_array)\n\t# Iterate through the events_list to retrieve data for specific events\n\tfor event in available_events:\n\t\tvar event_id = event[\"id\"] # you can get event id using 'id' key\n\t\tvar event_name = event[\"name\"] # you can get event name using 'name' key\n\t\tvar event_desc = event[\"description\"] # you can get event name using 'description' key \n\t\tvar event_img = event[\"imgUrl\"] # you can get event name using 'imgUrl' key\n\t\tvar event_value = event[\"value\"] # you can get event name using 'value' key  \n\t\n# Triggered if there are no events:\nfunc _on_events_empty():\n\tpass\n\n# Triggered if something went wrong:\nfunc _on_events_loading_failed():\n\tpass\n\n```\n#### Player Stats\n```gdscript\nvar force_refresh := true # If true, this call will clear any locally cached data and attempt to fetch the latest data from the server.\nplay_games_services.loadPlayerStats(force_refresh)\n\n# Callbacks:\t\nfunc _on_player_stats_loaded(stats):\n\tvar stats_dictionary: Dictionary = parse_json(stats)\n\t# Using below keys you can retrieve data about a player’s in-game activity\n\tstats_dictionary[\"avg_session_length\"] # Average session length\n\tstats_dictionary[\"days_last_played\"] # Days since last played\n\tstats_dictionary[\"purchases\"] # Number of purchases\n\tstats_dictionary[\"sessions\"] # Number of sessions\n\tstats_dictionary[\"session_percentile\"] # Session percentile\n\tstats_dictionary[\"spend_percentile\"] # Spend percentile\n\nfunc _on_player_stats_loading_failed():\n\tpass\n```\n#### Player Info\n```gdscript\nplay_games_services.loadPlayerInfo()\n\n# Callbacks:\t\nfunc _on_player_info_loaded(info):\n\tvar info_dictionary: Dictionary = parse_json(info)\n\t# Using below keys you can retrieve player’s info\n\tinfo_dictionary[\"display_name\"]\n\tinfo_dictionary[\"name\"]\n\tinfo_dictionary[\"title\"]\n\tinfo_dictionary[\"player_id\"]\n\tinfo_dictionary[\"hi_res_image_url\"]\n\tinfo_dictionary[\"icon_image_url\"]\n\tinfo_dictionary[\"banner_image_landscape_url\"] \n\tinfo_dictionary[\"banner_image_portrait_url\"]\n    # Also you can get level info for the player\n    var level_info_dictionary = info_dictionary[\"level_info\"]\n\tlevel_info_dictionary[\"current_xp_total\"]\n\tlevel_info_dictionary[\"last_level_up_timestamp\"]\n    \n    var current_level_dictionary = level_info_dictionary[\"current_level\"]\n    current_level_dictionary[\"level_number\"]\n    current_level_dictionary[\"max_xp\"]\n    current_level_dictionary[\"min_xp\"]\n\n    var next_level_dictionary = level_info_dictionary[\"next_level\"]\n    next_level_dictionary[\"level_number\"]\n    next_level_dictionary[\"max_xp\"]\n    next_level_dictionary[\"min_xp\"]\n    \n\nfunc _on_player_info_loading_failed():\n\tpass\n```\n#### Saved Games\n##### Save game snapshot\n```gdscript\nvar data_to_save: Dictionary = {\n\t\t\"name\": \"John\", \n\t\t\"age\": 22,\n\t\t\"height\": 1.82,\n\t\t\"is_gamer\": true\n\t}\nplay_games_services.saveSnapshot(\"SNAPSHOT_NAME\", to_json(data_to_save), \"DESCRIPTION\")\n\n# Callbacks:\nfunc _on_game_saved_success():\n\tpass\n\t\nfunc _on_game_saved_fail():\n\tpass\n```\n##### Load game snapshot\n```gdscript\nplay_games_services.loadSnapshot(\"SNAPSHOT_NAME\")\n\n# Callbacks:\nfunc _on_game_load_success(data):\n\tvar game_data: Dictionary = parse_json(data)\n\tvar name = game_data[\"name\"]\n\tvar age = game_data[\"age\"]\n\t#...\n\t\n\t\nfunc _on_game_load_fail():\n\tpass\n```\n##### Show saved snapshots screen\n```gdscript\nvar allow_add_button := true\nvar allow_delete_button := true\nvar max_saved_games_snapshots := 5\nvar saved_games_screen_title := \"TITLE\"\nplay_games_services.showSavedGames(saved_games_screen_title, allow_add_button, allow_delete_button, max_saved_games_snapshots)\n\n#Godot callback\t\n# If user clicked on add new snapshot button on the screen with all saved snapshots, below callback will be triggered:\nfunc _on_create_new_snapshot(name):\n\tvar game_data_to_save: Dictionary = {\n\t\t\"name\": \"John\", \n\t\t\"age\": 22,\n\t\t\"height\": 1.82,\n\t\t\"is_gamer\": true\n\t}\n\tplay_games_services.save_snapshot(name, to_json(game_data_to_save), \"DESCRIPTION\")\n\n```\n## Troubleshooting\nCheck `adb logcat` for debuging.\nTo filter only Godot messages use next command:\n`adb logcat -s godot`\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcgisca%2Fpgsgp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcgisca%2Fpgsgp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcgisca%2Fpgsgp/lists"}