├── gpgs
├── ext.manifest
├── ext.properties
├── manifests
│ └── android
│ │ ├── build.gradle
│ │ └── AndroidManifest.xml
├── src
│ ├── com_defold_gpgs_GpgsJNI.h
│ ├── private_gpgs_callback.h
│ ├── gpgs_extension.h
│ ├── gpgs_callback.cpp
│ └── java
│ │ └── com
│ │ └── defold
│ │ └── gpgs
│ │ └── GpgsJNI.java
└── api
│ └── gpgs.script_api
├── main
├── logo.atlas
├── images
│ └── logo.png
├── main.script
├── menu.collection
├── snapshot.collection
├── events.collection
├── achievements.collection
├── authentication.collection
├── leaderboards.collection
├── menu.gui_script
├── authentication.gui_script
├── events.gui_script
├── achievements.gui_script
├── leaderboards.gui_script
├── authentication.gui
├── menu.gui
├── snapshot.gui_script
├── main.collection
├── events.gui
├── achievements.gui
├── leaderboards.gui
└── snapshot.gui
├── input
└── game.input_binding
├── .github
├── FUNDING.yml
└── workflows
│ ├── bob.yml
│ └── trigger-site-rebuild.yml
├── .gitignore
├── README.md
├── LICENSE.md
├── game.project
├── generated.appmanifest
└── docs
└── index.md
/gpgs/ext.manifest:
--------------------------------------------------------------------------------
1 | name: GpgsExt
--------------------------------------------------------------------------------
/main/logo.atlas:
--------------------------------------------------------------------------------
1 | images {
2 | image: "/main/images/logo.png"
3 | }
4 |
--------------------------------------------------------------------------------
/main/images/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/defold/extension-gpgs/HEAD/main/images/logo.png
--------------------------------------------------------------------------------
/input/game.input_binding:
--------------------------------------------------------------------------------
1 | mouse_trigger {
2 | input: MOUSE_BUTTON_1
3 | action: "touch"
4 | }
5 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | github: defold
2 | patreon: Defold
3 | custom: ['https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=NBNBHTUW4GS4C']
4 |
--------------------------------------------------------------------------------
/.github/workflows/bob.yml:
--------------------------------------------------------------------------------
1 | name: Build with bob
2 |
3 | on: [push, pull_request]
4 |
5 | jobs:
6 | build:
7 | uses: defold/github-actions-common/.github/workflows/bob.yml@master
8 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /.internal
2 | /build
3 | .externalToolBuilders
4 | .DS_Store
5 | Thumbs.db
6 | .lock-wscript
7 | *.pyc
8 | .project
9 | .cproject
10 | builtins
11 | _site
12 | /.editor_settings
--------------------------------------------------------------------------------
/gpgs/ext.properties:
--------------------------------------------------------------------------------
1 | [gpgs]
2 | group = Runtime
3 | title = GPGS
4 | help = Settings for Google Play Game Services extension
5 |
6 | app_id.type = string
7 |
8 | client_id.type = string
9 |
10 | use_saved_games.type = bool
11 |
12 | request_server_auth_code.type = bool
13 |
--------------------------------------------------------------------------------
/main/main.script:
--------------------------------------------------------------------------------
1 | local monarch = require "monarch.monarch"
2 |
3 | function init(self)
4 | msg.post(".", "acquire_input_focus")
5 | if gpgs then
6 | for k,v in pairs(gpgs) do
7 | print("gpgs." .. tostring(k))
8 | end
9 | end
10 | timer.delay(0, false, function()
11 | monarch.show("menu")
12 | end)
13 | end
14 |
--------------------------------------------------------------------------------
/gpgs/manifests/android/build.gradle:
--------------------------------------------------------------------------------
1 | repositories {
2 | mavenCentral()
3 | }
4 |
5 | dependencies {
6 | // https://developers.google.com/android/guides/setup#split
7 | implementation 'com.google.android.gms:play-services-base:18.5.0'
8 | implementation 'com.google.android.gms:play-services-auth:21.3.0'
9 | implementation 'com.google.android.gms:play-services-games-v2:21.0.0'
10 | }
11 |
--------------------------------------------------------------------------------
/gpgs/manifests/android/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://github.com/defold/extension-gpgs/actions)
2 |
3 | # Google Play Game Services for Defold
4 |
5 | Defold [native extension](https://www.defold.com/manuals/extensions/) which provides access to Google Play Game Services functionality on Android devices.
6 |
7 | [Manual, API and setup instructions](https://www.defold.com/extension-gpgs/) is available on the official Defold site.
8 |
--------------------------------------------------------------------------------
/gpgs/src/com_defold_gpgs_GpgsJNI.h:
--------------------------------------------------------------------------------
1 | #include
2 | /* Header for class com_defold_gpgs_GpgsJNI */
3 |
4 | #ifndef COM_DEFOLD_GPGS_GPGSJNI_H
5 | #define COM_DEFOLD_GPGS_GPGSJNI_H
6 | #ifdef __cplusplus
7 | extern "C" {
8 | #endif
9 | /*
10 | * Class: com_defold_gpgs_GpgsJNI
11 | * Method: gpgsAddToQueue_first_arg
12 | * Signature: (ILjava/lang/String;I)V
13 | */
14 | JNIEXPORT void JNICALL Java_com_defold_gpgs_GpgsJNI_gpgsAddToQueue
15 | (JNIEnv *, jclass, jint, jstring);
16 |
17 | #ifdef __cplusplus
18 | }
19 | #endif
20 | #endif
21 |
--------------------------------------------------------------------------------
/.github/workflows/trigger-site-rebuild.yml:
--------------------------------------------------------------------------------
1 | name: Trigger site rebuild
2 |
3 | on: [push]
4 |
5 | jobs:
6 | site-rebuild:
7 | runs-on: ubuntu-latest
8 |
9 | steps: [
10 | {
11 | name: 'Repository dispatch',
12 | uses: defold/repository-dispatch@1.2.1,
13 | with: {
14 | repo: 'defold/defold.github.io',
15 | token: '${{ secrets.SERVICES_GITHUB_TOKEN }}',
16 | user: 'services@defold.se',
17 | action: 'extension-gpgs'
18 | }
19 | }]
20 |
--------------------------------------------------------------------------------
/gpgs/src/private_gpgs_callback.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include "gpgs_extension.h"
5 |
6 | struct GPGS_callback
7 | {
8 | GPGS_callback() : m_L(0), m_Callback(LUA_NOREF), m_Self(LUA_NOREF) {}
9 | lua_State* m_L;
10 | int m_Callback;
11 | int m_Self;
12 | };
13 |
14 | struct CallbackData
15 | {
16 | MESSAGE_ID msg;
17 | char* json;
18 | };
19 |
20 | void gpgs_set_callback(lua_State* L, int pos);
21 | void gpgs_callback_initialize();
22 | void gpgs_callback_finalize();
23 | void gpgs_callback_update();
24 | void gpgs_add_to_queue(MESSAGE_ID msg, const char*json);
25 |
--------------------------------------------------------------------------------
/main/menu.collection:
--------------------------------------------------------------------------------
1 | name: "menu"
2 | scale_along_z: 0
3 | embedded_instances {
4 | id: "go"
5 | data: "components {\n"
6 | " id: \"gui\"\n"
7 | " component: \"/main/menu.gui\"\n"
8 | " position {\n"
9 | " x: 0.0\n"
10 | " y: 0.0\n"
11 | " z: 0.0\n"
12 | " }\n"
13 | " rotation {\n"
14 | " x: 0.0\n"
15 | " y: 0.0\n"
16 | " z: 0.0\n"
17 | " w: 1.0\n"
18 | " }\n"
19 | "}\n"
20 | ""
21 | position {
22 | x: 0.0
23 | y: 0.0
24 | z: 0.0
25 | }
26 | rotation {
27 | x: 0.0
28 | y: 0.0
29 | z: 0.0
30 | w: 1.0
31 | }
32 | scale3 {
33 | x: 1.0
34 | y: 1.0
35 | z: 1.0
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/main/snapshot.collection:
--------------------------------------------------------------------------------
1 | name: "snapshot"
2 | scale_along_z: 0
3 | embedded_instances {
4 | id: "go"
5 | data: "components {\n"
6 | " id: \"snapshot\"\n"
7 | " component: \"/main/snapshot.gui\"\n"
8 | " position {\n"
9 | " x: 0.0\n"
10 | " y: 0.0\n"
11 | " z: 0.0\n"
12 | " }\n"
13 | " rotation {\n"
14 | " x: 0.0\n"
15 | " y: 0.0\n"
16 | " z: 0.0\n"
17 | " w: 1.0\n"
18 | " }\n"
19 | "}\n"
20 | ""
21 | position {
22 | x: 0.0
23 | y: 0.0
24 | z: 0.0
25 | }
26 | rotation {
27 | x: 0.0
28 | y: 0.0
29 | z: 0.0
30 | w: 1.0
31 | }
32 | scale3 {
33 | x: 1.0
34 | y: 1.0
35 | z: 1.0
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/main/events.collection:
--------------------------------------------------------------------------------
1 | name: "events"
2 | scale_along_z: 0
3 | embedded_instances {
4 | id: "go"
5 | data: "components {\n"
6 | " id: \"monarch\"\n"
7 | " component: \"/main/events.gui\"\n"
8 | " position {\n"
9 | " x: 0.0\n"
10 | " y: 0.0\n"
11 | " z: 0.0\n"
12 | " }\n"
13 | " rotation {\n"
14 | " x: 0.0\n"
15 | " y: 0.0\n"
16 | " z: 0.0\n"
17 | " w: 1.0\n"
18 | " }\n"
19 | "}\n"
20 | ""
21 | position {
22 | x: 0.0
23 | y: 0.0
24 | z: 0.0
25 | }
26 | rotation {
27 | x: 0.0
28 | y: 0.0
29 | z: 0.0
30 | w: 1.0
31 | }
32 | scale3 {
33 | x: 1.0
34 | y: 1.0
35 | z: 1.0
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/main/achievements.collection:
--------------------------------------------------------------------------------
1 | name: "achievements"
2 | scale_along_z: 0
3 | embedded_instances {
4 | id: "go"
5 | data: "components {\n"
6 | " id: \"achievements\"\n"
7 | " component: \"/main/achievements.gui\"\n"
8 | " position {\n"
9 | " x: 0.0\n"
10 | " y: 0.0\n"
11 | " z: 0.0\n"
12 | " }\n"
13 | " rotation {\n"
14 | " x: 0.0\n"
15 | " y: 0.0\n"
16 | " z: 0.0\n"
17 | " w: 1.0\n"
18 | " }\n"
19 | "}\n"
20 | ""
21 | position {
22 | x: 0.0
23 | y: 0.0
24 | z: 0.0
25 | }
26 | rotation {
27 | x: 0.0
28 | y: 0.0
29 | z: 0.0
30 | w: 1.0
31 | }
32 | scale3 {
33 | x: 1.0
34 | y: 1.0
35 | z: 1.0
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/main/authentication.collection:
--------------------------------------------------------------------------------
1 | name: "authentication"
2 | scale_along_z: 0
3 | embedded_instances {
4 | id: "go"
5 | data: "components {\n"
6 | " id: \"authentication\"\n"
7 | " component: \"/main/authentication.gui\"\n"
8 | " position {\n"
9 | " x: 0.0\n"
10 | " y: 0.0\n"
11 | " z: 0.0\n"
12 | " }\n"
13 | " rotation {\n"
14 | " x: 0.0\n"
15 | " y: 0.0\n"
16 | " z: 0.0\n"
17 | " w: 1.0\n"
18 | " }\n"
19 | "}\n"
20 | ""
21 | position {
22 | x: 0.0
23 | y: 0.0
24 | z: 0.0
25 | }
26 | rotation {
27 | x: 0.0
28 | y: 0.0
29 | z: 0.0
30 | w: 1.0
31 | }
32 | scale3 {
33 | x: 1.0
34 | y: 1.0
35 | z: 1.0
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/main/leaderboards.collection:
--------------------------------------------------------------------------------
1 | name: "leaderboards"
2 | scale_along_z: 0
3 | embedded_instances {
4 | id: "go"
5 | data: "components {\n"
6 | " id: \"monarch\"\n"
7 | " component: \"/main/leaderboards.gui\"\n"
8 | " position {\n"
9 | " x: 0.0\n"
10 | " y: 0.0\n"
11 | " z: 0.0\n"
12 | " }\n"
13 | " rotation {\n"
14 | " x: 0.0\n"
15 | " y: 0.0\n"
16 | " z: 0.0\n"
17 | " w: 1.0\n"
18 | " }\n"
19 | "}\n"
20 | ""
21 | position {
22 | x: 0.0
23 | y: 0.0
24 | z: 0.0
25 | }
26 | rotation {
27 | x: 0.0
28 | y: 0.0
29 | z: 0.0
30 | w: 1.0
31 | }
32 | scale3 {
33 | x: 1.0
34 | y: 1.0
35 | z: 1.0
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 Defold
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/main/menu.gui_script:
--------------------------------------------------------------------------------
1 | local dirtylarry = require "dirtylarry.dirtylarry"
2 | local monarch = require "monarch.monarch"
3 |
4 | function init(self)
5 | msg.post(".", "acquire_input_focus")
6 | self.popup_pos = 3
7 |
8 | if gpgs and gpgs.is_supported() then
9 | gui.set_text(gui.get_node("support_status"), "Is Supported")
10 | else
11 | gui.set_text(gui.get_node("support_status"), "Not Supported")
12 | end
13 | end
14 |
15 |
16 | function on_input(self, action_id, action)
17 | dirtylarry:button("authentication", action_id, action, function ()
18 | monarch.show("authentication")
19 | end)
20 |
21 | dirtylarry:button("snapshot", action_id, action, function ()
22 | monarch.show("snapshot")
23 | end)
24 |
25 | dirtylarry:button("achievements", action_id, action, function ()
26 | monarch.show("achievements")
27 | end)
28 |
29 | dirtylarry:button("leaderboards", action_id, action, function ()
30 | monarch.show("leaderboards")
31 | end)
32 |
33 | dirtylarry:button("events", action_id, action, function ()
34 | monarch.show("events")
35 | end)
36 | end
--------------------------------------------------------------------------------
/game.project:
--------------------------------------------------------------------------------
1 | [project]
2 | title = extension-gpgs
3 | version = 0.2
4 | dependencies#0 = https://github.com/andsve/dirtylarry/archive/master.zip
5 | dependencies#1 = https://github.com/britzl/defold-screenshot/archive/master.zip
6 | dependencies#2 = https://github.com/britzl/monarch/archive/3.1.0.zip
7 |
8 | [bootstrap]
9 | main_collection = /main/main.collectionc
10 |
11 | [input]
12 | game_binding = /input/game.input_bindingc
13 |
14 | [display]
15 | width = 1280
16 | height = 720
17 |
18 | [physics]
19 | scale = 0.02
20 |
21 | [script]
22 | shared_state = 1
23 |
24 | [android]
25 | package = com.defold.extension.gpgs
26 | minimum_sdk_version = 21
27 | target_sdk_version = 34
28 |
29 | [ios]
30 | bundle_identifier = com.defold.extension.gpgs
31 | infoplist = /builtins/manifests/ios/Info.plist
32 |
33 | [gpgs]
34 | app_id = 741832396715
35 | client_id = 741832396715-sl2dn4pjiqop78t1pgflb6ob4aqsvom5.apps.googleusercontent.com
36 | use_saved_games = 1
37 | request_server_auth_code = 0
38 |
39 | [library]
40 | include_dirs = gpgs
41 |
42 | [osx]
43 | bundle_identifier = com.defold.extension.gpgs
44 |
45 | [native_extension]
46 | app_manifest = /generated.appmanifest
47 |
48 |
--------------------------------------------------------------------------------
/main/authentication.gui_script:
--------------------------------------------------------------------------------
1 | local dirtylarry = require "dirtylarry.dirtylarry"
2 | local monarch = require "monarch.monarch"
3 |
4 |
5 | local function gpgs_callback(self, message_id, message)
6 | if message_id == gpgs.MSG_SIGN_IN or message_id == gpgs.MSG_SILENT_SIGN_IN then
7 | if message.status == gpgs.STATUS_SUCCESS then
8 | gui.set_text(gui.get_node("id"), gpgs.get_id())
9 | gui.set_text(gui.get_node("name"), gpgs.get_display_name())
10 |
11 | if sys.get_config_int("gpgs.request_server_auth_code") == 1 then
12 | print("auth_code: ", gpgs.get_server_auth_code())
13 | end
14 | end
15 | end
16 | gui.set_text(gui.get_node("authorized"), "is_logged_in: " .. tostring(gpgs.is_logged_in()))
17 | end
18 |
19 | function init(self)
20 | msg.post(".", "acquire_input_focus")
21 | if gpgs then
22 | gpgs.set_callback(gpgs_callback)
23 | gpgs.silent_login()
24 | end
25 | end
26 |
27 | function on_input(self, action_id, action)
28 | dirtylarry:button("login", action_id, action, function ()
29 | print("LOGIN was pressed")
30 | if gpgs then
31 | gpgs.login()
32 | end
33 | end)
34 |
35 | dirtylarry:button("back", action_id, action, function ()
36 | monarch.back()
37 | end)
38 | end
39 |
40 | function on_reload(self)
41 | -- Add input-handling code here
42 | -- Remove this function if not needed
43 | end
44 |
--------------------------------------------------------------------------------
/main/events.gui_script:
--------------------------------------------------------------------------------
1 | local dirtylarry = require "dirtylarry.dirtylarry"
2 | local monarch = require "monarch.monarch"
3 |
4 |
5 | local function gpgs_callback(self, message_id, message)
6 | print(message_id)
7 | pprint(message)
8 | if message_id == gpgs.MSG_GET_EVENTS then
9 | local s = ""
10 | for _,event in ipairs(message) do
11 | event = json.decode(event)
12 | s = s .. ("%s (%s) = %s\n"):format(event.name, event.id, event.value)
13 | end
14 | gui.set_text(gui.get_node("events"), s)
15 | end
16 | end
17 |
18 | function init(self)
19 | msg.post(".", "acquire_input_focus")
20 | if gpgs then
21 | gpgs.set_callback(gpgs_callback)
22 | end
23 | end
24 |
25 | function on_input(self, action_id, action)
26 | dirtylarry:button("kill_zombie", action_id, action, function ()
27 | gpgs.event_increment("CgkIq5-gxcsVEAIQAw", 1)
28 | end)
29 |
30 | dirtylarry:button("earn_gold", action_id, action, function ()
31 | gpgs.event_increment("CgkIq5-gxcsVEAIQBA", 1)
32 | end)
33 |
34 | dirtylarry:button("spend_gold", action_id, action, function ()
35 | gpgs.event_increment("CgkIq5-gxcsVEAIQBQ", 1)
36 | end)
37 |
38 | dirtylarry:button("get", action_id, action, function ()
39 | gpgs.event_get()
40 | end)
41 |
42 | dirtylarry:button("back", action_id, action, function ()
43 | monarch.back()
44 | end)
45 | end
46 |
47 | function on_reload(self)
48 | -- Add input-handling code here
49 | -- Remove this function if not needed
50 | end
51 |
--------------------------------------------------------------------------------
/main/achievements.gui_script:
--------------------------------------------------------------------------------
1 | local dirtylarry = require "dirtylarry.dirtylarry"
2 | local monarch = require "monarch.monarch"
3 |
4 |
5 | local function gpgs_callback(self, message_id, message)
6 | print(message_id)
7 | pprint(message)
8 | end
9 |
10 | function init(self)
11 | msg.post(".", "acquire_input_focus")
12 | if gpgs then
13 | gpgs.set_callback(gpgs_callback)
14 | end
15 | end
16 |
17 | function on_input(self, action_id, action)
18 | dirtylarry:button("reveal", action_id, action, function ()
19 | if gpgs then
20 | gpgs.achievement_reveal("CgkIq5-gxcsVEAIQAQ")
21 | end
22 | end)
23 |
24 | dirtylarry:button("unlock", action_id, action, function ()
25 | if gpgs then
26 | gpgs.achievement_unlock("CgkIq5-gxcsVEAIQAQ")
27 | end
28 | end)
29 |
30 | dirtylarry:button("increment", action_id, action, function ()
31 | if gpgs then
32 | gpgs.achievement_increment("CgkIq5-gxcsVEAIQAQ", 1)
33 | end
34 | end)
35 |
36 | dirtylarry:button("set", action_id, action, function ()
37 | if gpgs then
38 | gpgs.achievement_set("CgkIq5-gxcsVEAIQAQ", 10)
39 | end
40 | end)
41 |
42 | dirtylarry:button("show", action_id, action, function ()
43 | if gpgs then
44 | gpgs.achievement_show()
45 | end
46 | end)
47 |
48 | dirtylarry:button("get", action_id, action, function ()
49 | if gpgs then
50 | gpgs.achievement_get()
51 | end
52 | end)
53 |
54 | dirtylarry:button("back", action_id, action, function ()
55 | monarch.back()
56 | end)
57 | end
58 |
59 | function on_reload(self)
60 | -- Add input-handling code here
61 | -- Remove this function if not needed
62 | end
63 |
--------------------------------------------------------------------------------
/main/leaderboards.gui_script:
--------------------------------------------------------------------------------
1 | local dirtylarry = require "dirtylarry.dirtylarry"
2 | local monarch = require "monarch.monarch"
3 |
4 | local function gpgs_callback(self, message_id, message)
5 | print(message_id)
6 | pprint(message)
7 | if message_id == gpgs.MSG_GET_PLAYER_SCORE then
8 | local text = ("%s (%s)"):format(message.display_score, message.display_rank)
9 | gui.set_text(gui.get_node("score"), text)
10 | elseif message_id == gpgs.MSG_GET_PLAYER_CENTERED_SCORES
11 | or message_id == gpgs.MSG_GET_TOP_SCORES then
12 | local s = ""
13 | for _,score in ipairs(message) do
14 | score = json.decode(score)
15 | s = s .. ("%s - %s (%s)\n"):format(score.score_holder_name, score.display_score, score.display_rank)
16 | end
17 | gui.set_text(gui.get_node("scores"), s)
18 | end
19 | end
20 |
21 | function init(self)
22 | msg.post(".", "acquire_input_focus")
23 | if gpgs then
24 | gpgs.set_callback(gpgs_callback)
25 | end
26 | self.clicks = 0
27 | end
28 |
29 | function on_input(self, action_id, action)
30 | if action_id == hash("touch") and action.released then
31 | self.clicks = self.clicks + 1
32 | print(self.clicks)
33 | gui.set_text(gui.get_node("clicks"), tostring(self.clicks))
34 | end
35 |
36 | dirtylarry:button("submit_score", action_id, action, function ()
37 | gpgs.leaderboard_submit_score("CgkIq5-gxcsVEAIQAg", self.clicks)
38 | end)
39 |
40 | dirtylarry:button("top_scores", action_id, action, function ()
41 | gpgs.leaderboard_get_top_scores("CgkIq5-gxcsVEAIQAg", gpgs.TIME_SPAN_ALL_TIME, gpgs.COLLECTION_PUBLIC, 10)
42 | end)
43 |
44 | dirtylarry:button("player_centered_scores", action_id, action, function ()
45 | gpgs.leaderboard_get_player_centered_scores("CgkIq5-gxcsVEAIQAg", gpgs.TIME_SPAN_ALL_TIME, gpgs.COLLECTION_PUBLIC, 10)
46 | end)
47 |
48 | dirtylarry:button("player_score", action_id, action, function ()
49 | gpgs.leaderboard_get_player_score("CgkIq5-gxcsVEAIQAg", gpgs.TIME_SPAN_ALL_TIME, gpgs.COLLECTION_PUBLIC)
50 | end)
51 |
52 | dirtylarry:button("show_leaderboard", action_id, action, function ()
53 | gpgs.leaderboard_show("CgkIq5-gxcsVEAIQAg", gpgs.TIME_SPAN_ALL_TIME, gpgs.COLLECTION_PUBLIC)
54 | end)
55 |
56 | dirtylarry:button("back", action_id, action, function ()
57 | monarch.back()
58 | end)
59 | end
60 |
61 | function on_reload(self)
62 | end
63 |
--------------------------------------------------------------------------------
/gpgs/src/gpgs_extension.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | // https://developers.google.com/android/reference/com/google/android/gms/games/SnapshotsClient#RESOLUTION_POLICY_HIGHEST_PROGRESS
4 | enum ResolutionPolicy
5 | {
6 | RESOLUTION_POLICY_MANUAL = -1,
7 | RESOLUTION_POLICY_LONGEST_PLAYTIME = 1,
8 | RESOLUTION_POLICY_LAST_KNOWN_GOOD = 2,
9 | RESOLUTION_POLICY_MOST_RECENTLY_MODIFIED = 3,
10 | RESOLUTION_POLICY_HIGHEST_PROGRESS = 4
11 | };
12 |
13 | // https://developers.google.com/android/reference/com/google/android/gms/games/GamesClientStatusCodes.html
14 | enum ERROR
15 | {
16 | ERROR_STATUS_SNAPSHOT_NOT_FOUND = 26570,
17 | ERROR_STATUS_SNAPSHOT_CREATION_FAILED = 26571,
18 | ERROR_STATUS_SNAPSHOT_CONTENTS_UNAVAILABLE = 26572,
19 | ERROR_STATUS_SNAPSHOT_COMMIT_FAILED = 26573,
20 | ERROR_STATUS_SNAPSHOT_FOLDER_UNAVAILABLE = 26575,
21 | ERROR_STATUS_SNAPSHOT_CONFLICT_MISSING = 26576,
22 | };
23 |
24 | // https://developers.google.com/android/reference/com/google/android/gms/games/leaderboard/LeaderboardVariant#TIME_SPAN_DAILY
25 | enum LeaderboardTimeSpan
26 | {
27 | TIME_SPAN_DAILY = 0,
28 | TIME_SPAN_WEEKLY = 1,
29 | TIME_SPAN_ALL_TIME = 2
30 | };
31 |
32 | // https://developers.google.com/android/reference/com/google/android/gms/games/leaderboard/LeaderboardVariant#public-static-final-int-collection_public
33 | enum LeaderboardCollection {
34 | COLLECTION_PUBLIC = 0,
35 | COLLECTION_SOCIAL = 1
36 | };
37 |
38 |
39 | // Internal to the extension
40 | enum SNAPSHOT_TYPE
41 | {
42 | SNAPSHOT_CURRENT = 1,
43 | SNAPSHOT_CONFLICTING = 2
44 | };
45 |
46 | // Internal to the extension
47 | enum MESSAGE_ID
48 | {
49 | MSG_SIGN_IN = 1,
50 | MSG_SILENT_SIGN_IN = 2,
51 | MSG_SHOW_SNAPSHOTS = 4,
52 | MSG_LOAD_SNAPSHOT = 5,
53 | MSG_SAVE_SNAPSHOT = 6,
54 | MSG_GET_ACHIEVEMENTS = 7,
55 | MSG_GET_TOP_SCORES = 8,
56 | MSG_GET_PLAYER_CENTERED_SCORES = 9,
57 | MSG_GET_PLAYER_SCORE = 10,
58 | MSG_GET_EVENTS = 11,
59 | MSG_GET_SERVER_TOKEN = 12
60 | };
61 |
62 | // Internal to the extension
63 | enum STATUS
64 | {
65 | STATUS_SUCCESS = 1,
66 | STATUS_FAILED = 2,
67 | STATUS_CREATE_NEW_SAVE = 3,
68 | STATUS_CONFLICT = 4,
69 | };
70 |
--------------------------------------------------------------------------------
/main/authentication.gui:
--------------------------------------------------------------------------------
1 | script: "/main/authentication.gui_script"
2 | fonts {
3 | name: "larryfont"
4 | font: "/dirtylarry/larryfont.font"
5 | }
6 | textures {
7 | name: "dirtylarry"
8 | texture: "/dirtylarry/dirtylarry.atlas"
9 | }
10 | nodes {
11 | position {
12 | x: 170.0
13 | y: 650.0
14 | }
15 | type: TYPE_TEMPLATE
16 | id: "login"
17 | inherit_alpha: true
18 | template: "/dirtylarry/button.gui"
19 | }
20 | nodes {
21 | type: TYPE_BOX
22 | id: "login/larrybutton"
23 | parent: "login"
24 | template_node_child: true
25 | }
26 | nodes {
27 | type: TYPE_TEXT
28 | text: "Login"
29 | id: "login/larrylabel"
30 | parent: "login/larrybutton"
31 | overridden_fields: 8
32 | template_node_child: true
33 | }
34 | nodes {
35 | position {
36 | x: 829.0
37 | y: 679.168
38 | }
39 | size {
40 | x: 440.0
41 | y: 40.0
42 | }
43 | type: TYPE_TEXT
44 | font: "larryfont"
45 | id: "authorized"
46 | pivot: PIVOT_W
47 | outline {
48 | x: 1.0
49 | y: 1.0
50 | z: 1.0
51 | }
52 | shadow {
53 | x: 1.0
54 | y: 1.0
55 | z: 1.0
56 | }
57 | line_break: true
58 | inherit_alpha: true
59 | }
60 | nodes {
61 | position {
62 | x: 170.0
63 | y: 74.0
64 | }
65 | type: TYPE_TEMPLATE
66 | id: "back"
67 | inherit_alpha: true
68 | template: "/dirtylarry/button.gui"
69 | }
70 | nodes {
71 | type: TYPE_BOX
72 | id: "back/larrybutton"
73 | parent: "back"
74 | template_node_child: true
75 | }
76 | nodes {
77 | type: TYPE_TEXT
78 | text: "BACK"
79 | id: "back/larrylabel"
80 | parent: "back/larrybutton"
81 | overridden_fields: 8
82 | template_node_child: true
83 | }
84 | nodes {
85 | position {
86 | x: 829.0
87 | y: 629.0
88 | }
89 | size {
90 | x: 440.0
91 | y: 40.0
92 | }
93 | type: TYPE_TEXT
94 | font: "larryfont"
95 | id: "id"
96 | pivot: PIVOT_W
97 | outline {
98 | x: 1.0
99 | y: 1.0
100 | z: 1.0
101 | }
102 | shadow {
103 | x: 1.0
104 | y: 1.0
105 | z: 1.0
106 | }
107 | inherit_alpha: true
108 | }
109 | nodes {
110 | position {
111 | x: 829.0
112 | y: 577.0
113 | }
114 | size {
115 | x: 440.0
116 | y: 40.0
117 | }
118 | type: TYPE_TEXT
119 | font: "larryfont"
120 | id: "name"
121 | pivot: PIVOT_W
122 | outline {
123 | x: 1.0
124 | y: 1.0
125 | z: 1.0
126 | }
127 | shadow {
128 | x: 1.0
129 | y: 1.0
130 | z: 1.0
131 | }
132 | inherit_alpha: true
133 | }
134 | material: "/builtins/materials/gui.material"
135 | adjust_reference: ADJUST_REFERENCE_PARENT
136 |
--------------------------------------------------------------------------------
/generated.appmanifest:
--------------------------------------------------------------------------------
1 | # App manifest generated Fri Nov 20 2020 09:28:33 GMT+0100 (Central European Standard Time)
2 | # Settings: OpenGL
3 | platforms:
4 | x86_64-osx:
5 | context:
6 | excludeLibs: []
7 | excludeSymbols: []
8 | symbols: []
9 | libs: []
10 | frameworks: []
11 | linkFlags: []
12 |
13 | x86_64-linux:
14 | context:
15 | excludeLibs: []
16 | excludeSymbols: []
17 | symbols: []
18 | libs: []
19 | linkFlags: []
20 |
21 | js-web:
22 | context:
23 | excludeLibs: []
24 | excludeJsLibs: []
25 | excludeSymbols: []
26 | symbols: []
27 | libs: []
28 | linkFlags: []
29 |
30 | wasm-web:
31 | context:
32 | excludeLibs: []
33 | excludeJsLibs: []
34 | excludeSymbols: []
35 | symbols: []
36 | libs: []
37 | linkFlags: []
38 |
39 | x86-win32:
40 | context:
41 | excludeLibs: []
42 | excludeSymbols: []
43 | symbols: []
44 | libs: []
45 | linkFlags: []
46 |
47 | x86_64-win32:
48 | context:
49 | excludeLibs: []
50 | excludeSymbols: []
51 | symbols: []
52 | libs: []
53 | linkFlags: []
54 |
55 | armv7-android:
56 | context:
57 | excludeLibs: []
58 | excludeJars: []
59 | excludeSymbols: []
60 | symbols: []
61 | libs: []
62 | linkFlags: []
63 | jetifier: true
64 |
65 | arm64-android:
66 | context:
67 | excludeLibs: []
68 | excludeJars: []
69 | excludeSymbols: []
70 | symbols: []
71 | libs: []
72 | linkFlags: []
73 | jetifier: true
74 |
75 | armv7-ios:
76 | context:
77 | excludeLibs: []
78 | excludeSymbols: []
79 | symbols: []
80 | libs: []
81 | frameworks: []
82 | linkFlags: []
83 |
84 | arm64-ios:
85 | context:
86 | excludeLibs: []
87 | excludeSymbols: []
88 | symbols: []
89 | libs: []
90 | frameworks: []
91 | linkFlags: []
92 |
93 | x86_64-ios:
94 | context:
95 | excludeLibs: []
96 | excludeSymbols: []
97 | symbols: []
98 | libs: []
99 | frameworks: []
100 | linkFlags: []
101 |
--------------------------------------------------------------------------------
/gpgs/src/gpgs_callback.cpp:
--------------------------------------------------------------------------------
1 | #if defined(DM_PLATFORM_IOS) || defined(DM_PLATFORM_ANDROID)
2 | #include "private_gpgs_callback.h"
3 | #include
4 |
5 | static GPGS_callback m_callback;
6 | static dmArray m_callbacksQueue;
7 | static dmMutex::HMutex m_mutex;
8 |
9 | static void RegisterCallback(lua_State* L, int index)
10 | {
11 | GPGS_callback *cbk = &m_callback;
12 | if(cbk->m_Callback != LUA_NOREF)
13 | {
14 | dmScript::Unref(cbk->m_L, LUA_REGISTRYINDEX, cbk->m_Callback);
15 | dmScript::Unref(cbk->m_L, LUA_REGISTRYINDEX, cbk->m_Self);
16 | }
17 |
18 | cbk->m_L = dmScript::GetMainThread(L);
19 |
20 | luaL_checktype(L, index, LUA_TFUNCTION);
21 | lua_pushvalue(L, index);
22 | cbk->m_Callback = dmScript::Ref(L, LUA_REGISTRYINDEX);
23 |
24 | dmScript::GetInstance(L);
25 | cbk->m_Self = dmScript::Ref(L, LUA_REGISTRYINDEX);
26 | }
27 |
28 | static void UnregisterCallback()
29 | {
30 | GPGS_callback *cbk = &m_callback;
31 | if(cbk->m_Callback != LUA_NOREF)
32 | {
33 | dmScript::Unref(cbk->m_L, LUA_REGISTRYINDEX, cbk->m_Callback);
34 | dmScript::Unref(cbk->m_L, LUA_REGISTRYINDEX, cbk->m_Self);
35 | cbk->m_Callback = LUA_NOREF;
36 | }
37 | }
38 |
39 | static void gpgs_invoke_callback(MESSAGE_ID type, const char* json)
40 | {
41 | GPGS_callback *cbk = &m_callback;
42 | if(cbk->m_Callback == LUA_NOREF)
43 | {
44 | dmLogInfo("GPGS callback do not exist.");
45 | return;
46 | }
47 |
48 | lua_State* L = cbk->m_L;
49 | int top = lua_gettop(L);
50 | lua_rawgeti(L, LUA_REGISTRYINDEX, cbk->m_Callback);
51 | lua_rawgeti(L, LUA_REGISTRYINDEX, cbk->m_Self);
52 | lua_pushvalue(L, -1);
53 | dmScript::SetInstance(L);
54 |
55 | if (!dmScript::IsInstanceValid(L))
56 | {
57 | UnregisterCallback();
58 | dmLogError("Could not run GPGS callback because the instance has been deleted.");
59 | lua_pop(L, 2);
60 | }
61 | else {
62 | lua_pushnumber(L, type);
63 | dmScript::JsonToLua(L, json, strlen(json)); // throws lua error if it fails
64 |
65 | int number_of_arguments = 3;
66 | int ret = lua_pcall(L, number_of_arguments, 0, 0);
67 | if(ret != 0)
68 | {
69 | dmLogError("Error running callback: %s", lua_tostring(L, -1));
70 | lua_pop(L, 1);
71 | }
72 | }
73 | assert(top == lua_gettop(L));
74 | }
75 |
76 | void gpgs_callback_initialize()
77 | {
78 | m_mutex = dmMutex::New();
79 | }
80 |
81 | void gpgs_callback_finalize()
82 | {
83 | dmMutex::Delete(m_mutex);
84 | UnregisterCallback();
85 | }
86 |
87 | void gpgs_set_callback(lua_State* L, int pos)
88 | {
89 | int type = lua_type(L, pos);
90 | if (type == LUA_TNONE || type == LUA_TNIL)
91 | {
92 | UnregisterCallback();
93 | }
94 | else
95 | {
96 | RegisterCallback(L, pos);
97 | }
98 | }
99 |
100 | void gpgs_add_to_queue(MESSAGE_ID msg, const char*json)
101 | {
102 | CallbackData data;
103 | data.msg = msg;
104 | data.json = json ? strdup(json) : NULL;
105 |
106 | DM_MUTEX_SCOPED_LOCK(m_mutex);
107 | if(m_callbacksQueue.Full())
108 | {
109 | m_callbacksQueue.OffsetCapacity(1);
110 | }
111 | m_callbacksQueue.Push(data);
112 | }
113 |
114 | void gpgs_callback_update()
115 | {
116 | if (m_callbacksQueue.Empty())
117 | {
118 | return;
119 | }
120 |
121 | dmArray tmp;
122 | {
123 | DM_MUTEX_SCOPED_LOCK(m_mutex);
124 | tmp.Swap(m_callbacksQueue);
125 | }
126 |
127 | for(uint32_t i = 0; i != tmp.Size(); ++i)
128 | {
129 | CallbackData* data = &tmp[i];
130 | gpgs_invoke_callback(data->msg, data->json);
131 | if(data->json)
132 | {
133 | free(data->json);
134 | data->json = 0;
135 | }
136 | }
137 | }
138 | #endif
139 |
--------------------------------------------------------------------------------
/main/menu.gui:
--------------------------------------------------------------------------------
1 | script: "/main/menu.gui_script"
2 | fonts {
3 | name: "larryfont"
4 | font: "/dirtylarry/larryfont.font"
5 | }
6 | textures {
7 | name: "logo"
8 | texture: "/main/logo.atlas"
9 | }
10 | nodes {
11 | position {
12 | x: 977.0
13 | y: 646.094
14 | }
15 | size {
16 | x: 300.0
17 | y: 100.0
18 | }
19 | type: TYPE_TEXT
20 | text: "Google Play Games Services"
21 | font: "larryfont"
22 | id: "title"
23 | outline {
24 | x: 1.0
25 | y: 1.0
26 | z: 1.0
27 | }
28 | shadow {
29 | x: 1.0
30 | y: 1.0
31 | z: 1.0
32 | }
33 | line_break: true
34 | inherit_alpha: true
35 | }
36 | nodes {
37 | position {
38 | x: 1206.857
39 | y: 645.837
40 | }
41 | type: TYPE_BOX
42 | texture: "logo/logo"
43 | id: "logo"
44 | inherit_alpha: true
45 | size_mode: SIZE_MODE_AUTO
46 | }
47 | nodes {
48 | position {
49 | x: 170.0
50 | y: 650.0
51 | }
52 | type: TYPE_TEMPLATE
53 | id: "authentication"
54 | inherit_alpha: true
55 | template: "/dirtylarry/button.gui"
56 | }
57 | nodes {
58 | type: TYPE_BOX
59 | id: "authentication/larrybutton"
60 | parent: "authentication"
61 | template_node_child: true
62 | }
63 | nodes {
64 | type: TYPE_TEXT
65 | text: "Authentication"
66 | id: "authentication/larrylabel"
67 | parent: "authentication/larrybutton"
68 | overridden_fields: 8
69 | template_node_child: true
70 | }
71 | nodes {
72 | position {
73 | x: 170.0
74 | y: 530.0
75 | }
76 | type: TYPE_TEMPLATE
77 | id: "snapshot"
78 | inherit_alpha: true
79 | template: "/dirtylarry/button.gui"
80 | }
81 | nodes {
82 | type: TYPE_BOX
83 | id: "snapshot/larrybutton"
84 | parent: "snapshot"
85 | template_node_child: true
86 | }
87 | nodes {
88 | type: TYPE_TEXT
89 | text: "Snapshot"
90 | id: "snapshot/larrylabel"
91 | parent: "snapshot/larrybutton"
92 | overridden_fields: 8
93 | template_node_child: true
94 | }
95 | nodes {
96 | position {
97 | x: 170.0
98 | y: 408.0
99 | }
100 | type: TYPE_TEMPLATE
101 | id: "achievements"
102 | inherit_alpha: true
103 | template: "/dirtylarry/button.gui"
104 | }
105 | nodes {
106 | type: TYPE_BOX
107 | id: "achievements/larrybutton"
108 | parent: "achievements"
109 | template_node_child: true
110 | }
111 | nodes {
112 | type: TYPE_TEXT
113 | text: "Achievements"
114 | id: "achievements/larrylabel"
115 | parent: "achievements/larrybutton"
116 | overridden_fields: 8
117 | template_node_child: true
118 | }
119 | nodes {
120 | position {
121 | x: 170.0
122 | y: 289.0
123 | }
124 | type: TYPE_TEMPLATE
125 | id: "leaderboards"
126 | inherit_alpha: true
127 | template: "/dirtylarry/button.gui"
128 | }
129 | nodes {
130 | type: TYPE_BOX
131 | id: "leaderboards/larrybutton"
132 | parent: "leaderboards"
133 | template_node_child: true
134 | }
135 | nodes {
136 | type: TYPE_TEXT
137 | text: "Leaderboards\t"
138 | id: "leaderboards/larrylabel"
139 | parent: "leaderboards/larrybutton"
140 | overridden_fields: 8
141 | template_node_child: true
142 | }
143 | nodes {
144 | position {
145 | x: 170.0
146 | y: 169.0
147 | }
148 | type: TYPE_TEMPLATE
149 | id: "events"
150 | inherit_alpha: true
151 | template: "/dirtylarry/button.gui"
152 | }
153 | nodes {
154 | type: TYPE_BOX
155 | id: "events/larrybutton"
156 | parent: "events"
157 | template_node_child: true
158 | }
159 | nodes {
160 | type: TYPE_TEXT
161 | text: "Events\t"
162 | id: "events/larrylabel"
163 | parent: "events/larrybutton"
164 | overridden_fields: 8
165 | template_node_child: true
166 | }
167 | nodes {
168 | position {
169 | x: 977.0
170 | y: 543.094
171 | }
172 | size {
173 | x: 300.0
174 | y: 100.0
175 | }
176 | type: TYPE_TEXT
177 | text: "Support Status"
178 | font: "larryfont"
179 | id: "support_status"
180 | outline {
181 | x: 1.0
182 | y: 1.0
183 | z: 1.0
184 | }
185 | shadow {
186 | x: 1.0
187 | y: 1.0
188 | z: 1.0
189 | }
190 | line_break: true
191 | inherit_alpha: true
192 | }
193 | material: "/builtins/materials/gui.material"
194 | adjust_reference: ADJUST_REFERENCE_PARENT
195 |
--------------------------------------------------------------------------------
/main/snapshot.gui_script:
--------------------------------------------------------------------------------
1 | local dirtylarry = require "dirtylarry.dirtylarry"
2 | local monarch = require "monarch.monarch"
3 |
4 |
5 | local use_saved_games = sys.get_config_int("gpgs.use_saved_games") == 1
6 |
7 | local function gpgs_callback(self, message_id, message)
8 | if message_id == gpgs.MSG_LOAD_SNAPSHOT then
9 | if message.status == gpgs.STATUS_CONFLICT then
10 | self.conflictId = message.conflictId
11 | end
12 | end
13 | end
14 |
15 | function init(self)
16 | msg.post(".", "acquire_input_focus")
17 | if gpgs then
18 | gpgs.set_callback(gpgs_callback)
19 | end
20 | end
21 |
22 | function update(self, dt)
23 | if gpgs and use_saved_games then
24 | if self.snapshot_is_opened ~= gpgs.snapshot_is_opened() then
25 | self.snapshot_is_opened = gpgs.snapshot_is_opened()
26 | gui.set_text(gui.get_node("snapshotOpened"), "snapshot_is_opened: "..tostring(gpgs.snapshot_is_opened()))
27 | end
28 | if self.conflictId then
29 | gui.set_text(gui.get_node("snapshotConflict"), "conflict: "..tostring(self.conflictId))
30 | else
31 | gui.set_text(gui.get_node("snapshotConflict"), "no conflict")
32 | end
33 | end
34 | end
35 |
36 | function on_input(self, action_id, action)
37 | dirtylarry:button("show_snapshots", action_id, action, function ()
38 | if gpgs then
39 | gpgs.snapshot_display_saves("My cool saves", true, true, 3)
40 | end
41 | end)
42 |
43 | dirtylarry:button("snapshot_open", action_id, action, function ()
44 | if gpgs then
45 | gpgs.snapshot_open("my_save", true, gpgs.RESOLUTION_POLICY_MANUAL)
46 | end
47 | end)
48 |
49 | dirtylarry:button("snapshot_get_data", action_id, action, function ()
50 | if gpgs then
51 | local bytes, error_message = gpgs.snapshot_get_data()
52 | if not bytes then
53 | print("snapshot_get_data ERROR:", error_message)
54 | else
55 | print("snapshot_get_data",bytes)
56 | end
57 | end
58 | end)
59 |
60 | dirtylarry:button("save_snapshot", action_id, action, function ()
61 | if gpgs then
62 | local png, w, h = screenshot.png()
63 | gpgs.snapshot_commit_and_close({
64 | coverImage = png,
65 | description = "LEVEL 31, CAVE",
66 | playedTime = math.random(1000, 2000),
67 | progressValue = math.random(1000, 2000)
68 | })
69 | end
70 | end)
71 |
72 | dirtylarry:button("snapshot_get_conflicting_data", action_id, action, function ()
73 | if gpgs then
74 | local bytes, error_message = gpgs.snapshot_get_conflicting_data()
75 | if not bytes then
76 | print("snapshot_get_conflicting_data ERROR: ", error_message)
77 | else
78 | print("snapshot_get_conflicting_data: ",bytes)
79 | end
80 | end
81 | end)
82 |
83 | dirtylarry:button("snapshot_set_data", action_id, action, function ()
84 | if gpgs then
85 | local success, error_message = gpgs.snapshot_set_data("MyCustomBytesForSnapshot")
86 | if not success then
87 | print("snapshot_set_data ERROR:", error_message)
88 | end
89 | end
90 | end)
91 |
92 | dirtylarry:button("snapshot_resolve_conflict", action_id, action, function ()
93 | if gpgs then
94 | local success, error_message = gpgs.snapshot_resolve_conflict(self.conflictId, gpgs.SNAPSHOT_CURRENT)
95 | if not success then
96 | print("snapshot_resolve_conflict ERROR:", error_message)
97 | end
98 | end
99 | end)
100 |
101 | dirtylarry:button("snapshot_resolve_conflict_conflicting", action_id, action, function ()
102 | if gpgs then
103 | gpgs.snapshot_resolve_conflict(self.conflictId, gpgs.SNAPSHOT_CONFLICTING)
104 | end
105 | end)
106 |
107 | dirtylarry:button("back", action_id, action, function ()
108 | monarch.back()
109 | end)
110 |
111 | end
--------------------------------------------------------------------------------
/docs/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Defold Google Play Game Services documentation
3 | brief: This manual covers how to setup and use Google Play Game Services in Defold.
4 | ---
5 |
6 | # Defold Google Play Game Services documentation
7 |
8 | This extension provides functions for interacting with Google Play Game Services. Supported on Android. The extension supports the following services:
9 |
10 | * Achievements
11 | * Authentication
12 | * Cloud save
13 | * Events
14 | * Leaderboards
15 |
16 |
17 | ## Installation
18 | To use this library in your Defold project, add the following URL to your `game.project` dependencies:
19 |
20 | https://github.com/defold/extension-gpgs/archive/master.zip
21 |
22 | We recommend using a link to a zip file of a [specific release](https://github.com/defold/extension-gpgs/releases).
23 |
24 |
25 | ## Google App Setup
26 | In order to use Google Play Game Services your application needs to be added to the Google Play store. It doesn't have to be published but it must be registered. Read more about how to sign up for and use the Google Play store in [the official documentation](https://support.google.com/googleplay/android-developer/answer/6112435).
27 |
28 | Once the application is registered you also need to enable Google Play Game Services for the application. Follow the official documentation to [enable Google Play Game Services](https://developers.google.com/games/services/console/enabling).
29 |
30 |
31 | ## Defold Setup
32 |
33 | Add the following section into your `game.project` file (open and edit as a text file):
34 |
35 | ```
36 | [gpgs]
37 | app_id = 1234567890
38 | use_saved_games = 1
39 | request_server_auth_code = 0
40 | ```
41 |
42 | Where `app_id` is the 12 or 13 digit Project ID from the Google Play Console. The Project ID can be found under "Grow users" > "Play Games Services" > "Setup and management" > "Configuration".
43 |
44 | Where `use_saved_games` indicates if the [Game Saves service](https://developers.google.com/games/services/common/concepts/savedgames) should be used (0 is disabled, 1 is enabled).
45 |
46 | If you want to retrieve server auth code set `gpgs.request_server_auth_code` to 1 and provide `gpgs.client_token`. Client token should be configured to Web application.
47 |
48 | ## Usage
49 |
50 | The API uses a callback based system where events and data coming from Google Play Game Services are passed to the game client through a callback function. The kind of event coming from Google Play Game Services is identified by a pre-defined event id. Example:
51 |
52 | ```Lua
53 | local function gpgs_callback(self, message_id, message)
54 | if message_id == gpgs.MSG_SIGN_IN then
55 | print("Signed in")
56 | end
57 | end
58 |
59 | gpgs.set_callback(gpgs_callback)
60 | ```
61 |
62 | ### Authentication:
63 |
64 | ```Lua
65 |
66 | local function gpgs_callback(self, message_id, message)
67 | if message_id == gpgs.MSG_SIGN_IN or message_id == gpgs.MSG_SILENT_SIGN_IN then
68 | if message.status == gpgs.STATUS_SUCCESS then
69 | print("Signed in")
70 | print(gpgs.get_id())
71 | print(gpgs.get_display_name())
72 | else
73 | print("Sign in error!")
74 | end
75 | end
76 | end
77 |
78 | gpgs.set_callback(gpgs_callback)
79 | gpgs.silent_login()
80 |
81 | ```
82 |
83 |
84 | ### Achievements
85 |
86 | ```Lua
87 | gpgs.achievement_reveal("CgkIq5-gxcsVEAIQAQ")
88 | gpgs.achievement_unlock("CgkIq5-gxcsVEAIQAQ")
89 | gpgs.achievement_increment("CgkIq5-gxcsVEAIQAQ", 1)
90 | gpgs.achievement_set("CgkIq5-gxcsVEAIQAQ", 10)
91 | gpgs.achievement_show()
92 | gpgs.achievement_get()
93 | ```
94 |
95 |
96 | ### Cloud save
97 |
98 | ```Lua
99 | local function gpgs_callback(self, message_id, message)
100 | if message_id == gpgs.MSG_LOAD_SNAPSHOT then
101 | if message.status == gpgs.STATUS_CONFLICT then
102 | print(message.conflictId)
103 | end
104 | end
105 | end
106 |
107 |
108 | gpgs.set_callback(gpgs_callback)
109 |
110 | gpgs.snapshot_display_saves("My saves", true, true, 3)
111 | gpgs.snapshot_open("my_save", true, gpgs.RESOLUTION_POLICY_MANUAL)
112 |
113 | local success, error_message = gpgs.snapshot_set_data("MyCustomBytesForSnapshot")
114 |
115 | local bytes, error_message = gpgs.snapshot_get_data()
116 | local bytes, error_message = gpgs.snapshot_get_conflicting_data()
117 |
118 | gpgs.snapshot_resolve_conflict(self.conflictId, gpgs.SNAPSHOT_CURRENT)
119 | gpgs.snapshot_resolve_conflict(self.conflictId, gpgs.SNAPSHOT_CONFLICTING)
120 |
121 | gpgs.snapshot_commit_and_close({
122 | coverImage = screenshot.png(),
123 | description = "LEVEL 31, CAVE",
124 | playedTime = 1000,
125 | progressValue = 1234
126 | })
127 |
128 | gpgs.snapshot_is_opened()
129 |
130 | ```
131 |
132 |
133 | ### Events
134 |
135 | ```lua
136 | local function gpgs_callback(self, message_id, message)
137 | if message_id == gpgs.MSG_GET_EVENTS then
138 | for _,event in ipairs(message) do
139 | event = json.decode(event)
140 | print(event.name, event.id, event.value)
141 | end
142 | end
143 | end
144 |
145 | gpgs.set_callback(gpgs_callback)
146 | gpgs.event_increment("CgkIq5-gxcsVEAIQAw", 1)
147 | gpgs.event_get()
148 | ```
149 |
150 |
151 | ### Leaderboards
152 |
153 | ```Lua
154 |
155 | local function gpgs_callback(self, message_id, message)
156 | if message_id == gpgs.MSG_GET_PLAYER_SCORE then
157 | print(message.display_score, message.display_rank)
158 | elseif message_id == gpgs.MSG_GET_PLAYER_CENTERED_SCORES or message_id == gpgs.MSG_GET_TOP_SCORES then
159 | for _,score in ipairs(message) do
160 | score = json.decode(score)
161 | print(score.score_holder_name, score.display_score, score.display_rank)
162 | end
163 | end
164 | end
165 |
166 | gpgs.set_callback(gpgs_callback)
167 |
168 | gpgs.leaderboard_submit_score("CgkIq5-gxcsVEAIQAg", 1337)
169 | gpgs.leaderboard_get_top_scores("CgkIq5-gxcsVEAIQAg", gpgs.TIME_SPAN_ALL_TIME, gpgs.COLLECTION_PUBLIC, 10)
170 | gpgs.leaderboard_get_player_centered_scores("CgkIq5-gxcsVEAIQAg", gpgs.TIME_SPAN_ALL_TIME, gpgs.COLLECTION_PUBLIC, 10)
171 | gpgs.leaderboard_get_player_score("CgkIq5-gxcsVEAIQAg", gpgs.TIME_SPAN_ALL_TIME, gpgs.COLLECTION_PUBLIC)
172 | gpgs.leaderboard_show("CgkIq5-gxcsVEAIQAg", gpgs.TIME_SPAN_ALL_TIME, gpgs.COLLECTION_PUBLIC)
173 | ```
174 |
175 |
176 |
177 | ## Source code
178 |
179 | The source code is available on [GitHub](https://github.com/defold/extension-gpgs)
180 |
--------------------------------------------------------------------------------
/main/main.collection:
--------------------------------------------------------------------------------
1 | name: "main"
2 | scale_along_z: 0
3 | embedded_instances {
4 | id: "main"
5 | data: "components {\n"
6 | " id: \"main\"\n"
7 | " component: \"/main/main.script\"\n"
8 | " position {\n"
9 | " x: 0.0\n"
10 | " y: 0.0\n"
11 | " z: 0.0\n"
12 | " }\n"
13 | " rotation {\n"
14 | " x: 0.0\n"
15 | " y: 0.0\n"
16 | " z: 0.0\n"
17 | " w: 1.0\n"
18 | " }\n"
19 | "}\n"
20 | ""
21 | position {
22 | x: 0.0
23 | y: 0.0
24 | z: 0.0
25 | }
26 | rotation {
27 | x: 0.0
28 | y: 0.0
29 | z: 0.0
30 | w: 1.0
31 | }
32 | scale3 {
33 | x: 1.0
34 | y: 1.0
35 | z: 1.0
36 | }
37 | }
38 | embedded_instances {
39 | id: "authentication"
40 | data: "components {\n"
41 | " id: \"screen_proxy\"\n"
42 | " component: \"/monarch/screen_proxy.script\"\n"
43 | " position {\n"
44 | " x: 0.0\n"
45 | " y: 0.0\n"
46 | " z: 0.0\n"
47 | " }\n"
48 | " rotation {\n"
49 | " x: 0.0\n"
50 | " y: 0.0\n"
51 | " z: 0.0\n"
52 | " w: 1.0\n"
53 | " }\n"
54 | " properties {\n"
55 | " id: \"screen_id\"\n"
56 | " value: \"authentication\"\n"
57 | " type: PROPERTY_TYPE_HASH\n"
58 | " }\n"
59 | "}\n"
60 | "embedded_components {\n"
61 | " id: \"collectionproxy\"\n"
62 | " type: \"collectionproxy\"\n"
63 | " data: \"collection: \\\"/main/authentication.collection\\\"\\n"
64 | "exclude: false\\n"
65 | "\"\n"
66 | " position {\n"
67 | " x: 0.0\n"
68 | " y: 0.0\n"
69 | " z: 0.0\n"
70 | " }\n"
71 | " rotation {\n"
72 | " x: 0.0\n"
73 | " y: 0.0\n"
74 | " z: 0.0\n"
75 | " w: 1.0\n"
76 | " }\n"
77 | "}\n"
78 | ""
79 | position {
80 | x: 0.0
81 | y: 0.0
82 | z: 0.0
83 | }
84 | rotation {
85 | x: 0.0
86 | y: 0.0
87 | z: 0.0
88 | w: 1.0
89 | }
90 | scale3 {
91 | x: 1.0
92 | y: 1.0
93 | z: 1.0
94 | }
95 | }
96 | embedded_instances {
97 | id: "menu"
98 | data: "components {\n"
99 | " id: \"screen_proxy\"\n"
100 | " component: \"/monarch/screen_proxy.script\"\n"
101 | " position {\n"
102 | " x: 0.0\n"
103 | " y: 0.0\n"
104 | " z: 0.0\n"
105 | " }\n"
106 | " rotation {\n"
107 | " x: 0.0\n"
108 | " y: 0.0\n"
109 | " z: 0.0\n"
110 | " w: 1.0\n"
111 | " }\n"
112 | " properties {\n"
113 | " id: \"screen_id\"\n"
114 | " value: \"menu\"\n"
115 | " type: PROPERTY_TYPE_HASH\n"
116 | " }\n"
117 | "}\n"
118 | "embedded_components {\n"
119 | " id: \"collectionproxy\"\n"
120 | " type: \"collectionproxy\"\n"
121 | " data: \"collection: \\\"/main/menu.collection\\\"\\n"
122 | "exclude: false\\n"
123 | "\"\n"
124 | " position {\n"
125 | " x: 0.0\n"
126 | " y: 0.0\n"
127 | " z: 0.0\n"
128 | " }\n"
129 | " rotation {\n"
130 | " x: 0.0\n"
131 | " y: 0.0\n"
132 | " z: 0.0\n"
133 | " w: 1.0\n"
134 | " }\n"
135 | "}\n"
136 | ""
137 | position {
138 | x: 0.0
139 | y: 0.0
140 | z: 0.0
141 | }
142 | rotation {
143 | x: 0.0
144 | y: 0.0
145 | z: 0.0
146 | w: 1.0
147 | }
148 | scale3 {
149 | x: 1.0
150 | y: 1.0
151 | z: 1.0
152 | }
153 | }
154 | embedded_instances {
155 | id: "snapshot"
156 | data: "components {\n"
157 | " id: \"screen_proxy\"\n"
158 | " component: \"/monarch/screen_proxy.script\"\n"
159 | " position {\n"
160 | " x: 0.0\n"
161 | " y: 0.0\n"
162 | " z: 0.0\n"
163 | " }\n"
164 | " rotation {\n"
165 | " x: 0.0\n"
166 | " y: 0.0\n"
167 | " z: 0.0\n"
168 | " w: 1.0\n"
169 | " }\n"
170 | " properties {\n"
171 | " id: \"screen_id\"\n"
172 | " value: \"snapshot\"\n"
173 | " type: PROPERTY_TYPE_HASH\n"
174 | " }\n"
175 | "}\n"
176 | "embedded_components {\n"
177 | " id: \"collectionproxy\"\n"
178 | " type: \"collectionproxy\"\n"
179 | " data: \"collection: \\\"/main/snapshot.collection\\\"\\n"
180 | "exclude: false\\n"
181 | "\"\n"
182 | " position {\n"
183 | " x: 0.0\n"
184 | " y: 0.0\n"
185 | " z: 0.0\n"
186 | " }\n"
187 | " rotation {\n"
188 | " x: 0.0\n"
189 | " y: 0.0\n"
190 | " z: 0.0\n"
191 | " w: 1.0\n"
192 | " }\n"
193 | "}\n"
194 | ""
195 | position {
196 | x: 0.0
197 | y: 0.0
198 | z: 0.0
199 | }
200 | rotation {
201 | x: 0.0
202 | y: 0.0
203 | z: 0.0
204 | w: 1.0
205 | }
206 | scale3 {
207 | x: 1.0
208 | y: 1.0
209 | z: 1.0
210 | }
211 | }
212 | embedded_instances {
213 | id: "achievements"
214 | data: "components {\n"
215 | " id: \"screen_proxy\"\n"
216 | " component: \"/monarch/screen_proxy.script\"\n"
217 | " position {\n"
218 | " x: 0.0\n"
219 | " y: 0.0\n"
220 | " z: 0.0\n"
221 | " }\n"
222 | " rotation {\n"
223 | " x: 0.0\n"
224 | " y: 0.0\n"
225 | " z: 0.0\n"
226 | " w: 1.0\n"
227 | " }\n"
228 | " properties {\n"
229 | " id: \"screen_id\"\n"
230 | " value: \"achievements\"\n"
231 | " type: PROPERTY_TYPE_HASH\n"
232 | " }\n"
233 | "}\n"
234 | "embedded_components {\n"
235 | " id: \"collectionproxy\"\n"
236 | " type: \"collectionproxy\"\n"
237 | " data: \"collection: \\\"/main/achievements.collection\\\"\\n"
238 | "exclude: false\\n"
239 | "\"\n"
240 | " position {\n"
241 | " x: 0.0\n"
242 | " y: 0.0\n"
243 | " z: 0.0\n"
244 | " }\n"
245 | " rotation {\n"
246 | " x: 0.0\n"
247 | " y: 0.0\n"
248 | " z: 0.0\n"
249 | " w: 1.0\n"
250 | " }\n"
251 | "}\n"
252 | ""
253 | position {
254 | x: 0.0
255 | y: 0.0
256 | z: 0.0
257 | }
258 | rotation {
259 | x: 0.0
260 | y: 0.0
261 | z: 0.0
262 | w: 1.0
263 | }
264 | scale3 {
265 | x: 1.0
266 | y: 1.0
267 | z: 1.0
268 | }
269 | }
270 | embedded_instances {
271 | id: "leaderboards"
272 | data: "components {\n"
273 | " id: \"screen_proxy\"\n"
274 | " component: \"/monarch/screen_proxy.script\"\n"
275 | " position {\n"
276 | " x: 0.0\n"
277 | " y: 0.0\n"
278 | " z: 0.0\n"
279 | " }\n"
280 | " rotation {\n"
281 | " x: 0.0\n"
282 | " y: 0.0\n"
283 | " z: 0.0\n"
284 | " w: 1.0\n"
285 | " }\n"
286 | " properties {\n"
287 | " id: \"screen_id\"\n"
288 | " value: \"leaderboards\"\n"
289 | " type: PROPERTY_TYPE_HASH\n"
290 | " }\n"
291 | "}\n"
292 | "embedded_components {\n"
293 | " id: \"collectionproxy\"\n"
294 | " type: \"collectionproxy\"\n"
295 | " data: \"collection: \\\"/main/leaderboards.collection\\\"\\n"
296 | "exclude: false\\n"
297 | "\"\n"
298 | " position {\n"
299 | " x: 0.0\n"
300 | " y: 0.0\n"
301 | " z: 0.0\n"
302 | " }\n"
303 | " rotation {\n"
304 | " x: 0.0\n"
305 | " y: 0.0\n"
306 | " z: 0.0\n"
307 | " w: 1.0\n"
308 | " }\n"
309 | "}\n"
310 | ""
311 | position {
312 | x: 0.0
313 | y: 0.0
314 | z: 0.0
315 | }
316 | rotation {
317 | x: 0.0
318 | y: 0.0
319 | z: 0.0
320 | w: 1.0
321 | }
322 | scale3 {
323 | x: 1.0
324 | y: 1.0
325 | z: 1.0
326 | }
327 | }
328 | embedded_instances {
329 | id: "events"
330 | data: "components {\n"
331 | " id: \"screen_proxy\"\n"
332 | " component: \"/monarch/screen_proxy.script\"\n"
333 | " position {\n"
334 | " x: 0.0\n"
335 | " y: 0.0\n"
336 | " z: 0.0\n"
337 | " }\n"
338 | " rotation {\n"
339 | " x: 0.0\n"
340 | " y: 0.0\n"
341 | " z: 0.0\n"
342 | " w: 1.0\n"
343 | " }\n"
344 | " properties {\n"
345 | " id: \"screen_id\"\n"
346 | " value: \"events\"\n"
347 | " type: PROPERTY_TYPE_HASH\n"
348 | " }\n"
349 | "}\n"
350 | "embedded_components {\n"
351 | " id: \"collectionproxy\"\n"
352 | " type: \"collectionproxy\"\n"
353 | " data: \"collection: \\\"/main/events.collection\\\"\\n"
354 | "exclude: false\\n"
355 | "\"\n"
356 | " position {\n"
357 | " x: 0.0\n"
358 | " y: 0.0\n"
359 | " z: 0.0\n"
360 | " }\n"
361 | " rotation {\n"
362 | " x: 0.0\n"
363 | " y: 0.0\n"
364 | " z: 0.0\n"
365 | " w: 1.0\n"
366 | " }\n"
367 | "}\n"
368 | ""
369 | position {
370 | x: 0.0
371 | y: 0.0
372 | z: 0.0
373 | }
374 | rotation {
375 | x: 0.0
376 | y: 0.0
377 | z: 0.0
378 | w: 1.0
379 | }
380 | scale3 {
381 | x: 1.0
382 | y: 1.0
383 | z: 1.0
384 | }
385 | }
386 |
--------------------------------------------------------------------------------
/main/events.gui:
--------------------------------------------------------------------------------
1 | script: "/main/events.gui_script"
2 | fonts {
3 | name: "larryfont"
4 | font: "/dirtylarry/larryfont.font"
5 | }
6 | textures {
7 | name: "dirtylarry"
8 | texture: "/dirtylarry/dirtylarry.atlas"
9 | }
10 | background_color {
11 | x: 0.0
12 | y: 0.0
13 | z: 0.0
14 | w: 0.0
15 | }
16 | nodes {
17 | position {
18 | x: 170.0
19 | y: 60.0
20 | z: 0.0
21 | w: 1.0
22 | }
23 | rotation {
24 | x: 0.0
25 | y: 0.0
26 | z: 0.0
27 | w: 1.0
28 | }
29 | scale {
30 | x: 1.0
31 | y: 1.0
32 | z: 1.0
33 | w: 1.0
34 | }
35 | size {
36 | x: 200.0
37 | y: 100.0
38 | z: 0.0
39 | w: 1.0
40 | }
41 | color {
42 | x: 1.0
43 | y: 1.0
44 | z: 1.0
45 | w: 1.0
46 | }
47 | type: TYPE_TEMPLATE
48 | id: "back"
49 | layer: ""
50 | inherit_alpha: true
51 | alpha: 1.0
52 | template: "/dirtylarry/button.gui"
53 | template_node_child: false
54 | }
55 | nodes {
56 | position {
57 | x: 0.0
58 | y: 0.0
59 | z: 0.0
60 | w: 1.0
61 | }
62 | rotation {
63 | x: 0.0
64 | y: 0.0
65 | z: 0.0
66 | w: 1.0
67 | }
68 | scale {
69 | x: 1.0
70 | y: 1.0
71 | z: 1.0
72 | w: 1.0
73 | }
74 | size {
75 | x: 300.0
76 | y: 88.0
77 | z: 0.0
78 | w: 1.0
79 | }
80 | color {
81 | x: 1.0
82 | y: 1.0
83 | z: 1.0
84 | w: 1.0
85 | }
86 | type: TYPE_BOX
87 | blend_mode: BLEND_MODE_ALPHA
88 | texture: "button/button_normal"
89 | id: "back/larrybutton"
90 | xanchor: XANCHOR_NONE
91 | yanchor: YANCHOR_NONE
92 | pivot: PIVOT_CENTER
93 | adjust_mode: ADJUST_MODE_FIT
94 | parent: "back"
95 | layer: ""
96 | inherit_alpha: true
97 | slice9 {
98 | x: 32.0
99 | y: 32.0
100 | z: 32.0
101 | w: 32.0
102 | }
103 | clipping_mode: CLIPPING_MODE_NONE
104 | clipping_visible: true
105 | clipping_inverted: false
106 | alpha: 1.0
107 | overridden_fields: 38
108 | template_node_child: true
109 | size_mode: SIZE_MODE_MANUAL
110 | }
111 | nodes {
112 | position {
113 | x: 0.0
114 | y: 0.0
115 | z: 0.0
116 | w: 1.0
117 | }
118 | rotation {
119 | x: 0.0
120 | y: 0.0
121 | z: 0.0
122 | w: 1.0
123 | }
124 | scale {
125 | x: 1.0
126 | y: 1.0
127 | z: 1.0
128 | w: 1.0
129 | }
130 | size {
131 | x: 200.0
132 | y: 100.0
133 | z: 0.0
134 | w: 1.0
135 | }
136 | color {
137 | x: 1.0
138 | y: 1.0
139 | z: 1.0
140 | w: 1.0
141 | }
142 | type: TYPE_TEXT
143 | blend_mode: BLEND_MODE_ALPHA
144 | text: "BACK"
145 | font: "larryfont"
146 | id: "back/larrylabel"
147 | xanchor: XANCHOR_NONE
148 | yanchor: YANCHOR_NONE
149 | pivot: PIVOT_CENTER
150 | outline {
151 | x: 0.0
152 | y: 0.0
153 | z: 0.0
154 | w: 1.0
155 | }
156 | shadow {
157 | x: 1.0
158 | y: 1.0
159 | z: 1.0
160 | w: 1.0
161 | }
162 | adjust_mode: ADJUST_MODE_FIT
163 | line_break: false
164 | parent: "back/larrybutton"
165 | layer: ""
166 | inherit_alpha: true
167 | alpha: 1.0
168 | outline_alpha: 1.0
169 | shadow_alpha: 1.0
170 | overridden_fields: 8
171 | template_node_child: true
172 | text_leading: 1.0
173 | text_tracking: 0.0
174 | }
175 | nodes {
176 | position {
177 | x: 170.0
178 | y: 653.0
179 | z: 0.0
180 | w: 1.0
181 | }
182 | rotation {
183 | x: 0.0
184 | y: 0.0
185 | z: 0.0
186 | w: 1.0
187 | }
188 | scale {
189 | x: 1.0
190 | y: 1.0
191 | z: 1.0
192 | w: 1.0
193 | }
194 | size {
195 | x: 200.0
196 | y: 100.0
197 | z: 0.0
198 | w: 1.0
199 | }
200 | color {
201 | x: 1.0
202 | y: 1.0
203 | z: 1.0
204 | w: 1.0
205 | }
206 | type: TYPE_TEMPLATE
207 | id: "kill_zombie"
208 | layer: ""
209 | inherit_alpha: true
210 | alpha: 1.0
211 | template: "/dirtylarry/button.gui"
212 | template_node_child: false
213 | }
214 | nodes {
215 | position {
216 | x: 0.0
217 | y: 0.0
218 | z: 0.0
219 | w: 1.0
220 | }
221 | rotation {
222 | x: 0.0
223 | y: 0.0
224 | z: 0.0
225 | w: 1.0
226 | }
227 | scale {
228 | x: 1.0
229 | y: 1.0
230 | z: 1.0
231 | w: 1.0
232 | }
233 | size {
234 | x: 300.0
235 | y: 88.0
236 | z: 0.0
237 | w: 1.0
238 | }
239 | color {
240 | x: 1.0
241 | y: 1.0
242 | z: 1.0
243 | w: 1.0
244 | }
245 | type: TYPE_BOX
246 | blend_mode: BLEND_MODE_ALPHA
247 | texture: "button/button_normal"
248 | id: "kill_zombie/larrybutton"
249 | xanchor: XANCHOR_NONE
250 | yanchor: YANCHOR_NONE
251 | pivot: PIVOT_CENTER
252 | adjust_mode: ADJUST_MODE_FIT
253 | parent: "kill_zombie"
254 | layer: ""
255 | inherit_alpha: true
256 | slice9 {
257 | x: 32.0
258 | y: 32.0
259 | z: 32.0
260 | w: 32.0
261 | }
262 | clipping_mode: CLIPPING_MODE_NONE
263 | clipping_visible: true
264 | clipping_inverted: false
265 | alpha: 1.0
266 | overridden_fields: 38
267 | template_node_child: true
268 | size_mode: SIZE_MODE_MANUAL
269 | }
270 | nodes {
271 | position {
272 | x: 0.0
273 | y: 0.0
274 | z: 0.0
275 | w: 1.0
276 | }
277 | rotation {
278 | x: 0.0
279 | y: 0.0
280 | z: 0.0
281 | w: 1.0
282 | }
283 | scale {
284 | x: 1.0
285 | y: 1.0
286 | z: 1.0
287 | w: 1.0
288 | }
289 | size {
290 | x: 200.0
291 | y: 100.0
292 | z: 0.0
293 | w: 1.0
294 | }
295 | color {
296 | x: 1.0
297 | y: 1.0
298 | z: 1.0
299 | w: 1.0
300 | }
301 | type: TYPE_TEXT
302 | blend_mode: BLEND_MODE_ALPHA
303 | text: "Kill Zombie"
304 | font: "larryfont"
305 | id: "kill_zombie/larrylabel"
306 | xanchor: XANCHOR_NONE
307 | yanchor: YANCHOR_NONE
308 | pivot: PIVOT_CENTER
309 | outline {
310 | x: 0.0
311 | y: 0.0
312 | z: 0.0
313 | w: 1.0
314 | }
315 | shadow {
316 | x: 1.0
317 | y: 1.0
318 | z: 1.0
319 | w: 1.0
320 | }
321 | adjust_mode: ADJUST_MODE_FIT
322 | line_break: false
323 | parent: "kill_zombie/larrybutton"
324 | layer: ""
325 | inherit_alpha: true
326 | alpha: 1.0
327 | outline_alpha: 1.0
328 | shadow_alpha: 1.0
329 | overridden_fields: 8
330 | template_node_child: true
331 | text_leading: 1.0
332 | text_tracking: 0.0
333 | }
334 | nodes {
335 | position {
336 | x: 170.0
337 | y: 532.0
338 | z: 0.0
339 | w: 1.0
340 | }
341 | rotation {
342 | x: 0.0
343 | y: 0.0
344 | z: 0.0
345 | w: 1.0
346 | }
347 | scale {
348 | x: 1.0
349 | y: 1.0
350 | z: 1.0
351 | w: 1.0
352 | }
353 | size {
354 | x: 200.0
355 | y: 100.0
356 | z: 0.0
357 | w: 1.0
358 | }
359 | color {
360 | x: 1.0
361 | y: 1.0
362 | z: 1.0
363 | w: 1.0
364 | }
365 | type: TYPE_TEMPLATE
366 | id: "earn_gold"
367 | layer: ""
368 | inherit_alpha: true
369 | alpha: 1.0
370 | template: "/dirtylarry/button.gui"
371 | template_node_child: false
372 | }
373 | nodes {
374 | position {
375 | x: 0.0
376 | y: 0.0
377 | z: 0.0
378 | w: 1.0
379 | }
380 | rotation {
381 | x: 0.0
382 | y: 0.0
383 | z: 0.0
384 | w: 1.0
385 | }
386 | scale {
387 | x: 1.0
388 | y: 1.0
389 | z: 1.0
390 | w: 1.0
391 | }
392 | size {
393 | x: 300.0
394 | y: 88.0
395 | z: 0.0
396 | w: 1.0
397 | }
398 | color {
399 | x: 1.0
400 | y: 1.0
401 | z: 1.0
402 | w: 1.0
403 | }
404 | type: TYPE_BOX
405 | blend_mode: BLEND_MODE_ALPHA
406 | texture: "button/button_normal"
407 | id: "earn_gold/larrybutton"
408 | xanchor: XANCHOR_NONE
409 | yanchor: YANCHOR_NONE
410 | pivot: PIVOT_CENTER
411 | adjust_mode: ADJUST_MODE_FIT
412 | parent: "earn_gold"
413 | layer: ""
414 | inherit_alpha: true
415 | slice9 {
416 | x: 32.0
417 | y: 32.0
418 | z: 32.0
419 | w: 32.0
420 | }
421 | clipping_mode: CLIPPING_MODE_NONE
422 | clipping_visible: true
423 | clipping_inverted: false
424 | alpha: 1.0
425 | overridden_fields: 38
426 | template_node_child: true
427 | size_mode: SIZE_MODE_MANUAL
428 | }
429 | nodes {
430 | position {
431 | x: 0.0
432 | y: 0.0
433 | z: 0.0
434 | w: 1.0
435 | }
436 | rotation {
437 | x: 0.0
438 | y: 0.0
439 | z: 0.0
440 | w: 1.0
441 | }
442 | scale {
443 | x: 1.0
444 | y: 1.0
445 | z: 1.0
446 | w: 1.0
447 | }
448 | size {
449 | x: 200.0
450 | y: 100.0
451 | z: 0.0
452 | w: 1.0
453 | }
454 | color {
455 | x: 1.0
456 | y: 1.0
457 | z: 1.0
458 | w: 1.0
459 | }
460 | type: TYPE_TEXT
461 | blend_mode: BLEND_MODE_ALPHA
462 | text: "Earn Gold"
463 | font: "larryfont"
464 | id: "earn_gold/larrylabel"
465 | xanchor: XANCHOR_NONE
466 | yanchor: YANCHOR_NONE
467 | pivot: PIVOT_CENTER
468 | outline {
469 | x: 0.0
470 | y: 0.0
471 | z: 0.0
472 | w: 1.0
473 | }
474 | shadow {
475 | x: 1.0
476 | y: 1.0
477 | z: 1.0
478 | w: 1.0
479 | }
480 | adjust_mode: ADJUST_MODE_FIT
481 | line_break: false
482 | parent: "earn_gold/larrybutton"
483 | layer: ""
484 | inherit_alpha: true
485 | alpha: 1.0
486 | outline_alpha: 1.0
487 | shadow_alpha: 1.0
488 | overridden_fields: 8
489 | template_node_child: true
490 | text_leading: 1.0
491 | text_tracking: 0.0
492 | }
493 | nodes {
494 | position {
495 | x: 170.0
496 | y: 411.0
497 | z: 0.0
498 | w: 1.0
499 | }
500 | rotation {
501 | x: 0.0
502 | y: 0.0
503 | z: 0.0
504 | w: 1.0
505 | }
506 | scale {
507 | x: 1.0
508 | y: 1.0
509 | z: 1.0
510 | w: 1.0
511 | }
512 | size {
513 | x: 200.0
514 | y: 100.0
515 | z: 0.0
516 | w: 1.0
517 | }
518 | color {
519 | x: 1.0
520 | y: 1.0
521 | z: 1.0
522 | w: 1.0
523 | }
524 | type: TYPE_TEMPLATE
525 | id: "spend_gold"
526 | layer: ""
527 | inherit_alpha: true
528 | alpha: 1.0
529 | template: "/dirtylarry/button.gui"
530 | template_node_child: false
531 | }
532 | nodes {
533 | position {
534 | x: 0.0
535 | y: 0.0
536 | z: 0.0
537 | w: 1.0
538 | }
539 | rotation {
540 | x: 0.0
541 | y: 0.0
542 | z: 0.0
543 | w: 1.0
544 | }
545 | scale {
546 | x: 1.0
547 | y: 1.0
548 | z: 1.0
549 | w: 1.0
550 | }
551 | size {
552 | x: 300.0
553 | y: 88.0
554 | z: 0.0
555 | w: 1.0
556 | }
557 | color {
558 | x: 1.0
559 | y: 1.0
560 | z: 1.0
561 | w: 1.0
562 | }
563 | type: TYPE_BOX
564 | blend_mode: BLEND_MODE_ALPHA
565 | texture: "button/button_normal"
566 | id: "spend_gold/larrybutton"
567 | xanchor: XANCHOR_NONE
568 | yanchor: YANCHOR_NONE
569 | pivot: PIVOT_CENTER
570 | adjust_mode: ADJUST_MODE_FIT
571 | parent: "spend_gold"
572 | layer: ""
573 | inherit_alpha: true
574 | slice9 {
575 | x: 32.0
576 | y: 32.0
577 | z: 32.0
578 | w: 32.0
579 | }
580 | clipping_mode: CLIPPING_MODE_NONE
581 | clipping_visible: true
582 | clipping_inverted: false
583 | alpha: 1.0
584 | overridden_fields: 38
585 | template_node_child: true
586 | size_mode: SIZE_MODE_MANUAL
587 | }
588 | nodes {
589 | position {
590 | x: 0.0
591 | y: 0.0
592 | z: 0.0
593 | w: 1.0
594 | }
595 | rotation {
596 | x: 0.0
597 | y: 0.0
598 | z: 0.0
599 | w: 1.0
600 | }
601 | scale {
602 | x: 1.0
603 | y: 1.0
604 | z: 1.0
605 | w: 1.0
606 | }
607 | size {
608 | x: 200.0
609 | y: 100.0
610 | z: 0.0
611 | w: 1.0
612 | }
613 | color {
614 | x: 1.0
615 | y: 1.0
616 | z: 1.0
617 | w: 1.0
618 | }
619 | type: TYPE_TEXT
620 | blend_mode: BLEND_MODE_ALPHA
621 | text: "Spend Gold"
622 | font: "larryfont"
623 | id: "spend_gold/larrylabel"
624 | xanchor: XANCHOR_NONE
625 | yanchor: YANCHOR_NONE
626 | pivot: PIVOT_CENTER
627 | outline {
628 | x: 0.0
629 | y: 0.0
630 | z: 0.0
631 | w: 1.0
632 | }
633 | shadow {
634 | x: 1.0
635 | y: 1.0
636 | z: 1.0
637 | w: 1.0
638 | }
639 | adjust_mode: ADJUST_MODE_FIT
640 | line_break: false
641 | parent: "spend_gold/larrybutton"
642 | layer: ""
643 | inherit_alpha: true
644 | alpha: 1.0
645 | outline_alpha: 1.0
646 | shadow_alpha: 1.0
647 | overridden_fields: 8
648 | template_node_child: true
649 | text_leading: 1.0
650 | text_tracking: 0.0
651 | }
652 | nodes {
653 | position {
654 | x: 656.0
655 | y: 653.0
656 | z: 0.0
657 | w: 1.0
658 | }
659 | rotation {
660 | x: 0.0
661 | y: 0.0
662 | z: 0.0
663 | w: 1.0
664 | }
665 | scale {
666 | x: 1.0
667 | y: 1.0
668 | z: 1.0
669 | w: 1.0
670 | }
671 | size {
672 | x: 200.0
673 | y: 100.0
674 | z: 0.0
675 | w: 1.0
676 | }
677 | color {
678 | x: 1.0
679 | y: 1.0
680 | z: 1.0
681 | w: 1.0
682 | }
683 | type: TYPE_TEMPLATE
684 | id: "get"
685 | layer: ""
686 | inherit_alpha: true
687 | alpha: 1.0
688 | template: "/dirtylarry/button.gui"
689 | template_node_child: false
690 | }
691 | nodes {
692 | position {
693 | x: 0.0
694 | y: 0.0
695 | z: 0.0
696 | w: 1.0
697 | }
698 | rotation {
699 | x: 0.0
700 | y: 0.0
701 | z: 0.0
702 | w: 1.0
703 | }
704 | scale {
705 | x: 1.0
706 | y: 1.0
707 | z: 1.0
708 | w: 1.0
709 | }
710 | size {
711 | x: 300.0
712 | y: 88.0
713 | z: 0.0
714 | w: 1.0
715 | }
716 | color {
717 | x: 1.0
718 | y: 1.0
719 | z: 1.0
720 | w: 1.0
721 | }
722 | type: TYPE_BOX
723 | blend_mode: BLEND_MODE_ALPHA
724 | texture: "button/button_normal"
725 | id: "get/larrybutton"
726 | xanchor: XANCHOR_NONE
727 | yanchor: YANCHOR_NONE
728 | pivot: PIVOT_CENTER
729 | adjust_mode: ADJUST_MODE_FIT
730 | parent: "get"
731 | layer: ""
732 | inherit_alpha: true
733 | slice9 {
734 | x: 32.0
735 | y: 32.0
736 | z: 32.0
737 | w: 32.0
738 | }
739 | clipping_mode: CLIPPING_MODE_NONE
740 | clipping_visible: true
741 | clipping_inverted: false
742 | alpha: 1.0
743 | overridden_fields: 38
744 | template_node_child: true
745 | size_mode: SIZE_MODE_MANUAL
746 | }
747 | nodes {
748 | position {
749 | x: 0.0
750 | y: 0.0
751 | z: 0.0
752 | w: 1.0
753 | }
754 | rotation {
755 | x: 0.0
756 | y: 0.0
757 | z: 0.0
758 | w: 1.0
759 | }
760 | scale {
761 | x: 1.0
762 | y: 1.0
763 | z: 1.0
764 | w: 1.0
765 | }
766 | size {
767 | x: 200.0
768 | y: 100.0
769 | z: 0.0
770 | w: 1.0
771 | }
772 | color {
773 | x: 1.0
774 | y: 1.0
775 | z: 1.0
776 | w: 1.0
777 | }
778 | type: TYPE_TEXT
779 | blend_mode: BLEND_MODE_ALPHA
780 | text: "Get"
781 | font: "larryfont"
782 | id: "get/larrylabel"
783 | xanchor: XANCHOR_NONE
784 | yanchor: YANCHOR_NONE
785 | pivot: PIVOT_CENTER
786 | outline {
787 | x: 0.0
788 | y: 0.0
789 | z: 0.0
790 | w: 1.0
791 | }
792 | shadow {
793 | x: 1.0
794 | y: 1.0
795 | z: 1.0
796 | w: 1.0
797 | }
798 | adjust_mode: ADJUST_MODE_FIT
799 | line_break: false
800 | parent: "get/larrybutton"
801 | layer: ""
802 | inherit_alpha: true
803 | alpha: 1.0
804 | outline_alpha: 1.0
805 | shadow_alpha: 1.0
806 | overridden_fields: 8
807 | template_node_child: true
808 | text_leading: 1.0
809 | text_tracking: 0.0
810 | }
811 | nodes {
812 | position {
813 | x: 505.0
814 | y: 569.0
815 | z: 0.0
816 | w: 1.0
817 | }
818 | rotation {
819 | x: 0.0
820 | y: 0.0
821 | z: 0.0
822 | w: 1.0
823 | }
824 | scale {
825 | x: 1.0
826 | y: 1.0
827 | z: 1.0
828 | w: 1.0
829 | }
830 | size {
831 | x: 600.0
832 | y: 100.0
833 | z: 0.0
834 | w: 1.0
835 | }
836 | color {
837 | x: 1.0
838 | y: 1.0
839 | z: 1.0
840 | w: 1.0
841 | }
842 | type: TYPE_TEXT
843 | blend_mode: BLEND_MODE_ALPHA
844 | text: ""
845 | font: "larryfont"
846 | id: "events"
847 | xanchor: XANCHOR_NONE
848 | yanchor: YANCHOR_NONE
849 | pivot: PIVOT_NW
850 | outline {
851 | x: 1.0
852 | y: 1.0
853 | z: 1.0
854 | w: 1.0
855 | }
856 | shadow {
857 | x: 1.0
858 | y: 1.0
859 | z: 1.0
860 | w: 1.0
861 | }
862 | adjust_mode: ADJUST_MODE_FIT
863 | line_break: true
864 | layer: ""
865 | inherit_alpha: true
866 | alpha: 1.0
867 | outline_alpha: 1.0
868 | shadow_alpha: 1.0
869 | template_node_child: false
870 | text_leading: 1.0
871 | text_tracking: 0.0
872 | }
873 | material: "/builtins/materials/gui.material"
874 | adjust_reference: ADJUST_REFERENCE_PARENT
875 | max_nodes: 512
876 |
--------------------------------------------------------------------------------
/main/achievements.gui:
--------------------------------------------------------------------------------
1 | script: "/main/achievements.gui_script"
2 | fonts {
3 | name: "larryfont"
4 | font: "/dirtylarry/larryfont.font"
5 | }
6 | textures {
7 | name: "dirtylarry"
8 | texture: "/dirtylarry/dirtylarry.atlas"
9 | }
10 | background_color {
11 | x: 0.0
12 | y: 0.0
13 | z: 0.0
14 | w: 0.0
15 | }
16 | nodes {
17 | position {
18 | x: 170.0
19 | y: 650.0
20 | z: 0.0
21 | w: 1.0
22 | }
23 | rotation {
24 | x: 0.0
25 | y: 0.0
26 | z: 0.0
27 | w: 1.0
28 | }
29 | scale {
30 | x: 1.0
31 | y: 1.0
32 | z: 1.0
33 | w: 1.0
34 | }
35 | size {
36 | x: 200.0
37 | y: 100.0
38 | z: 0.0
39 | w: 1.0
40 | }
41 | color {
42 | x: 1.0
43 | y: 1.0
44 | z: 1.0
45 | w: 1.0
46 | }
47 | type: TYPE_TEMPLATE
48 | id: "reveal"
49 | layer: ""
50 | inherit_alpha: true
51 | alpha: 1.0
52 | template: "/dirtylarry/button.gui"
53 | template_node_child: false
54 | }
55 | nodes {
56 | position {
57 | x: 0.0
58 | y: 0.0
59 | z: 0.0
60 | w: 1.0
61 | }
62 | rotation {
63 | x: 0.0
64 | y: 0.0
65 | z: 0.0
66 | w: 1.0
67 | }
68 | scale {
69 | x: 1.0
70 | y: 1.0
71 | z: 1.0
72 | w: 1.0
73 | }
74 | size {
75 | x: 300.0
76 | y: 88.0
77 | z: 0.0
78 | w: 1.0
79 | }
80 | color {
81 | x: 1.0
82 | y: 1.0
83 | z: 1.0
84 | w: 1.0
85 | }
86 | type: TYPE_BOX
87 | blend_mode: BLEND_MODE_ALPHA
88 | texture: "button/button_normal"
89 | id: "reveal/larrybutton"
90 | xanchor: XANCHOR_NONE
91 | yanchor: YANCHOR_NONE
92 | pivot: PIVOT_CENTER
93 | adjust_mode: ADJUST_MODE_FIT
94 | parent: "reveal"
95 | layer: ""
96 | inherit_alpha: true
97 | slice9 {
98 | x: 32.0
99 | y: 32.0
100 | z: 32.0
101 | w: 32.0
102 | }
103 | clipping_mode: CLIPPING_MODE_NONE
104 | clipping_visible: true
105 | clipping_inverted: false
106 | alpha: 1.0
107 | template_node_child: true
108 | size_mode: SIZE_MODE_MANUAL
109 | }
110 | nodes {
111 | position {
112 | x: 0.0
113 | y: 0.0
114 | z: 0.0
115 | w: 1.0
116 | }
117 | rotation {
118 | x: 0.0
119 | y: 0.0
120 | z: 0.0
121 | w: 1.0
122 | }
123 | scale {
124 | x: 1.0
125 | y: 1.0
126 | z: 1.0
127 | w: 1.0
128 | }
129 | size {
130 | x: 200.0
131 | y: 100.0
132 | z: 0.0
133 | w: 1.0
134 | }
135 | color {
136 | x: 1.0
137 | y: 1.0
138 | z: 1.0
139 | w: 1.0
140 | }
141 | type: TYPE_TEXT
142 | blend_mode: BLEND_MODE_ALPHA
143 | text: "Reveal"
144 | font: "larryfont"
145 | id: "reveal/larrylabel"
146 | xanchor: XANCHOR_NONE
147 | yanchor: YANCHOR_NONE
148 | pivot: PIVOT_CENTER
149 | outline {
150 | x: 0.0
151 | y: 0.0
152 | z: 0.0
153 | w: 1.0
154 | }
155 | shadow {
156 | x: 1.0
157 | y: 1.0
158 | z: 1.0
159 | w: 1.0
160 | }
161 | adjust_mode: ADJUST_MODE_FIT
162 | line_break: false
163 | parent: "reveal/larrybutton"
164 | layer: ""
165 | inherit_alpha: true
166 | alpha: 1.0
167 | outline_alpha: 1.0
168 | shadow_alpha: 1.0
169 | overridden_fields: 8
170 | template_node_child: true
171 | text_leading: 1.0
172 | text_tracking: 0.0
173 | }
174 | nodes {
175 | position {
176 | x: 170.0
177 | y: 530.0
178 | z: 0.0
179 | w: 1.0
180 | }
181 | rotation {
182 | x: 0.0
183 | y: 0.0
184 | z: 0.0
185 | w: 1.0
186 | }
187 | scale {
188 | x: 1.0
189 | y: 1.0
190 | z: 1.0
191 | w: 1.0
192 | }
193 | size {
194 | x: 200.0
195 | y: 100.0
196 | z: 0.0
197 | w: 1.0
198 | }
199 | color {
200 | x: 1.0
201 | y: 1.0
202 | z: 1.0
203 | w: 1.0
204 | }
205 | type: TYPE_TEMPLATE
206 | id: "unlock"
207 | layer: ""
208 | inherit_alpha: true
209 | alpha: 1.0
210 | template: "/dirtylarry/button.gui"
211 | template_node_child: false
212 | }
213 | nodes {
214 | position {
215 | x: 0.0
216 | y: 0.0
217 | z: 0.0
218 | w: 1.0
219 | }
220 | rotation {
221 | x: 0.0
222 | y: 0.0
223 | z: 0.0
224 | w: 1.0
225 | }
226 | scale {
227 | x: 1.0
228 | y: 1.0
229 | z: 1.0
230 | w: 1.0
231 | }
232 | size {
233 | x: 300.0
234 | y: 88.0
235 | z: 0.0
236 | w: 1.0
237 | }
238 | color {
239 | x: 1.0
240 | y: 1.0
241 | z: 1.0
242 | w: 1.0
243 | }
244 | type: TYPE_BOX
245 | blend_mode: BLEND_MODE_ALPHA
246 | texture: "button/button_normal"
247 | id: "unlock/larrybutton"
248 | xanchor: XANCHOR_NONE
249 | yanchor: YANCHOR_NONE
250 | pivot: PIVOT_CENTER
251 | adjust_mode: ADJUST_MODE_FIT
252 | parent: "unlock"
253 | layer: ""
254 | inherit_alpha: true
255 | slice9 {
256 | x: 32.0
257 | y: 32.0
258 | z: 32.0
259 | w: 32.0
260 | }
261 | clipping_mode: CLIPPING_MODE_NONE
262 | clipping_visible: true
263 | clipping_inverted: false
264 | alpha: 1.0
265 | template_node_child: true
266 | size_mode: SIZE_MODE_MANUAL
267 | }
268 | nodes {
269 | position {
270 | x: 0.0
271 | y: 0.0
272 | z: 0.0
273 | w: 1.0
274 | }
275 | rotation {
276 | x: 0.0
277 | y: 0.0
278 | z: 0.0
279 | w: 1.0
280 | }
281 | scale {
282 | x: 1.0
283 | y: 1.0
284 | z: 1.0
285 | w: 1.0
286 | }
287 | size {
288 | x: 200.0
289 | y: 100.0
290 | z: 0.0
291 | w: 1.0
292 | }
293 | color {
294 | x: 1.0
295 | y: 1.0
296 | z: 1.0
297 | w: 1.0
298 | }
299 | type: TYPE_TEXT
300 | blend_mode: BLEND_MODE_ALPHA
301 | text: "Unlock"
302 | font: "larryfont"
303 | id: "unlock/larrylabel"
304 | xanchor: XANCHOR_NONE
305 | yanchor: YANCHOR_NONE
306 | pivot: PIVOT_CENTER
307 | outline {
308 | x: 0.0
309 | y: 0.0
310 | z: 0.0
311 | w: 1.0
312 | }
313 | shadow {
314 | x: 1.0
315 | y: 1.0
316 | z: 1.0
317 | w: 1.0
318 | }
319 | adjust_mode: ADJUST_MODE_FIT
320 | line_break: false
321 | parent: "unlock/larrybutton"
322 | layer: ""
323 | inherit_alpha: true
324 | alpha: 1.0
325 | outline_alpha: 1.0
326 | shadow_alpha: 1.0
327 | overridden_fields: 8
328 | template_node_child: true
329 | text_leading: 1.0
330 | text_tracking: 0.0
331 | }
332 | nodes {
333 | position {
334 | x: 170.0
335 | y: 74.0
336 | z: 0.0
337 | w: 1.0
338 | }
339 | rotation {
340 | x: 0.0
341 | y: 0.0
342 | z: 0.0
343 | w: 1.0
344 | }
345 | scale {
346 | x: 1.0
347 | y: 1.0
348 | z: 1.0
349 | w: 1.0
350 | }
351 | size {
352 | x: 200.0
353 | y: 100.0
354 | z: 0.0
355 | w: 1.0
356 | }
357 | color {
358 | x: 1.0
359 | y: 1.0
360 | z: 1.0
361 | w: 1.0
362 | }
363 | type: TYPE_TEMPLATE
364 | id: "back"
365 | layer: ""
366 | inherit_alpha: true
367 | alpha: 1.0
368 | template: "/dirtylarry/button.gui"
369 | template_node_child: false
370 | }
371 | nodes {
372 | position {
373 | x: 0.0
374 | y: 0.0
375 | z: 0.0
376 | w: 1.0
377 | }
378 | rotation {
379 | x: 0.0
380 | y: 0.0
381 | z: 0.0
382 | w: 1.0
383 | }
384 | scale {
385 | x: 1.0
386 | y: 1.0
387 | z: 1.0
388 | w: 1.0
389 | }
390 | size {
391 | x: 300.0
392 | y: 88.0
393 | z: 0.0
394 | w: 1.0
395 | }
396 | color {
397 | x: 1.0
398 | y: 1.0
399 | z: 1.0
400 | w: 1.0
401 | }
402 | type: TYPE_BOX
403 | blend_mode: BLEND_MODE_ALPHA
404 | texture: "button/button_normal"
405 | id: "back/larrybutton"
406 | xanchor: XANCHOR_NONE
407 | yanchor: YANCHOR_NONE
408 | pivot: PIVOT_CENTER
409 | adjust_mode: ADJUST_MODE_FIT
410 | parent: "back"
411 | layer: ""
412 | inherit_alpha: true
413 | slice9 {
414 | x: 32.0
415 | y: 32.0
416 | z: 32.0
417 | w: 32.0
418 | }
419 | clipping_mode: CLIPPING_MODE_NONE
420 | clipping_visible: true
421 | clipping_inverted: false
422 | alpha: 1.0
423 | template_node_child: true
424 | size_mode: SIZE_MODE_MANUAL
425 | }
426 | nodes {
427 | position {
428 | x: 0.0
429 | y: 0.0
430 | z: 0.0
431 | w: 1.0
432 | }
433 | rotation {
434 | x: 0.0
435 | y: 0.0
436 | z: 0.0
437 | w: 1.0
438 | }
439 | scale {
440 | x: 1.0
441 | y: 1.0
442 | z: 1.0
443 | w: 1.0
444 | }
445 | size {
446 | x: 200.0
447 | y: 100.0
448 | z: 0.0
449 | w: 1.0
450 | }
451 | color {
452 | x: 1.0
453 | y: 1.0
454 | z: 1.0
455 | w: 1.0
456 | }
457 | type: TYPE_TEXT
458 | blend_mode: BLEND_MODE_ALPHA
459 | text: "BACK"
460 | font: "larryfont"
461 | id: "back/larrylabel"
462 | xanchor: XANCHOR_NONE
463 | yanchor: YANCHOR_NONE
464 | pivot: PIVOT_CENTER
465 | outline {
466 | x: 0.0
467 | y: 0.0
468 | z: 0.0
469 | w: 1.0
470 | }
471 | shadow {
472 | x: 1.0
473 | y: 1.0
474 | z: 1.0
475 | w: 1.0
476 | }
477 | adjust_mode: ADJUST_MODE_FIT
478 | line_break: false
479 | parent: "back/larrybutton"
480 | layer: ""
481 | inherit_alpha: true
482 | alpha: 1.0
483 | outline_alpha: 1.0
484 | shadow_alpha: 1.0
485 | overridden_fields: 8
486 | template_node_child: true
487 | text_leading: 1.0
488 | text_tracking: 0.0
489 | }
490 | nodes {
491 | position {
492 | x: 170.0
493 | y: 410.0
494 | z: 0.0
495 | w: 1.0
496 | }
497 | rotation {
498 | x: 0.0
499 | y: 0.0
500 | z: 0.0
501 | w: 1.0
502 | }
503 | scale {
504 | x: 1.0
505 | y: 1.0
506 | z: 1.0
507 | w: 1.0
508 | }
509 | size {
510 | x: 200.0
511 | y: 100.0
512 | z: 0.0
513 | w: 1.0
514 | }
515 | color {
516 | x: 1.0
517 | y: 1.0
518 | z: 1.0
519 | w: 1.0
520 | }
521 | type: TYPE_TEMPLATE
522 | id: "increment"
523 | layer: ""
524 | inherit_alpha: true
525 | alpha: 1.0
526 | template: "/dirtylarry/button.gui"
527 | template_node_child: false
528 | }
529 | nodes {
530 | position {
531 | x: 0.0
532 | y: 0.0
533 | z: 0.0
534 | w: 1.0
535 | }
536 | rotation {
537 | x: 0.0
538 | y: 0.0
539 | z: 0.0
540 | w: 1.0
541 | }
542 | scale {
543 | x: 1.0
544 | y: 1.0
545 | z: 1.0
546 | w: 1.0
547 | }
548 | size {
549 | x: 300.0
550 | y: 88.0
551 | z: 0.0
552 | w: 1.0
553 | }
554 | color {
555 | x: 1.0
556 | y: 1.0
557 | z: 1.0
558 | w: 1.0
559 | }
560 | type: TYPE_BOX
561 | blend_mode: BLEND_MODE_ALPHA
562 | texture: "button/button_normal"
563 | id: "increment/larrybutton"
564 | xanchor: XANCHOR_NONE
565 | yanchor: YANCHOR_NONE
566 | pivot: PIVOT_CENTER
567 | adjust_mode: ADJUST_MODE_FIT
568 | parent: "increment"
569 | layer: ""
570 | inherit_alpha: true
571 | slice9 {
572 | x: 32.0
573 | y: 32.0
574 | z: 32.0
575 | w: 32.0
576 | }
577 | clipping_mode: CLIPPING_MODE_NONE
578 | clipping_visible: true
579 | clipping_inverted: false
580 | alpha: 1.0
581 | template_node_child: true
582 | size_mode: SIZE_MODE_MANUAL
583 | }
584 | nodes {
585 | position {
586 | x: 0.0
587 | y: 0.0
588 | z: 0.0
589 | w: 1.0
590 | }
591 | rotation {
592 | x: 0.0
593 | y: 0.0
594 | z: 0.0
595 | w: 1.0
596 | }
597 | scale {
598 | x: 1.0
599 | y: 1.0
600 | z: 1.0
601 | w: 1.0
602 | }
603 | size {
604 | x: 200.0
605 | y: 100.0
606 | z: 0.0
607 | w: 1.0
608 | }
609 | color {
610 | x: 1.0
611 | y: 1.0
612 | z: 1.0
613 | w: 1.0
614 | }
615 | type: TYPE_TEXT
616 | blend_mode: BLEND_MODE_ALPHA
617 | text: "Increment"
618 | font: "larryfont"
619 | id: "increment/larrylabel"
620 | xanchor: XANCHOR_NONE
621 | yanchor: YANCHOR_NONE
622 | pivot: PIVOT_CENTER
623 | outline {
624 | x: 0.0
625 | y: 0.0
626 | z: 0.0
627 | w: 1.0
628 | }
629 | shadow {
630 | x: 1.0
631 | y: 1.0
632 | z: 1.0
633 | w: 1.0
634 | }
635 | adjust_mode: ADJUST_MODE_FIT
636 | line_break: false
637 | parent: "increment/larrybutton"
638 | layer: ""
639 | inherit_alpha: true
640 | alpha: 1.0
641 | outline_alpha: 1.0
642 | shadow_alpha: 1.0
643 | overridden_fields: 8
644 | template_node_child: true
645 | text_leading: 1.0
646 | text_tracking: 0.0
647 | }
648 | nodes {
649 | position {
650 | x: 170.0
651 | y: 290.0
652 | z: 0.0
653 | w: 1.0
654 | }
655 | rotation {
656 | x: 0.0
657 | y: 0.0
658 | z: 0.0
659 | w: 1.0
660 | }
661 | scale {
662 | x: 1.0
663 | y: 1.0
664 | z: 1.0
665 | w: 1.0
666 | }
667 | size {
668 | x: 200.0
669 | y: 100.0
670 | z: 0.0
671 | w: 1.0
672 | }
673 | color {
674 | x: 1.0
675 | y: 1.0
676 | z: 1.0
677 | w: 1.0
678 | }
679 | type: TYPE_TEMPLATE
680 | id: "set"
681 | layer: ""
682 | inherit_alpha: true
683 | alpha: 1.0
684 | template: "/dirtylarry/button.gui"
685 | template_node_child: false
686 | }
687 | nodes {
688 | position {
689 | x: 0.0
690 | y: 0.0
691 | z: 0.0
692 | w: 1.0
693 | }
694 | rotation {
695 | x: 0.0
696 | y: 0.0
697 | z: 0.0
698 | w: 1.0
699 | }
700 | scale {
701 | x: 1.0
702 | y: 1.0
703 | z: 1.0
704 | w: 1.0
705 | }
706 | size {
707 | x: 300.0
708 | y: 88.0
709 | z: 0.0
710 | w: 1.0
711 | }
712 | color {
713 | x: 1.0
714 | y: 1.0
715 | z: 1.0
716 | w: 1.0
717 | }
718 | type: TYPE_BOX
719 | blend_mode: BLEND_MODE_ALPHA
720 | texture: "button/button_normal"
721 | id: "set/larrybutton"
722 | xanchor: XANCHOR_NONE
723 | yanchor: YANCHOR_NONE
724 | pivot: PIVOT_CENTER
725 | adjust_mode: ADJUST_MODE_FIT
726 | parent: "set"
727 | layer: ""
728 | inherit_alpha: true
729 | slice9 {
730 | x: 32.0
731 | y: 32.0
732 | z: 32.0
733 | w: 32.0
734 | }
735 | clipping_mode: CLIPPING_MODE_NONE
736 | clipping_visible: true
737 | clipping_inverted: false
738 | alpha: 1.0
739 | template_node_child: true
740 | size_mode: SIZE_MODE_MANUAL
741 | }
742 | nodes {
743 | position {
744 | x: 0.0
745 | y: 0.0
746 | z: 0.0
747 | w: 1.0
748 | }
749 | rotation {
750 | x: 0.0
751 | y: 0.0
752 | z: 0.0
753 | w: 1.0
754 | }
755 | scale {
756 | x: 1.0
757 | y: 1.0
758 | z: 1.0
759 | w: 1.0
760 | }
761 | size {
762 | x: 200.0
763 | y: 100.0
764 | z: 0.0
765 | w: 1.0
766 | }
767 | color {
768 | x: 1.0
769 | y: 1.0
770 | z: 1.0
771 | w: 1.0
772 | }
773 | type: TYPE_TEXT
774 | blend_mode: BLEND_MODE_ALPHA
775 | text: "Set"
776 | font: "larryfont"
777 | id: "set/larrylabel"
778 | xanchor: XANCHOR_NONE
779 | yanchor: YANCHOR_NONE
780 | pivot: PIVOT_CENTER
781 | outline {
782 | x: 0.0
783 | y: 0.0
784 | z: 0.0
785 | w: 1.0
786 | }
787 | shadow {
788 | x: 1.0
789 | y: 1.0
790 | z: 1.0
791 | w: 1.0
792 | }
793 | adjust_mode: ADJUST_MODE_FIT
794 | line_break: false
795 | parent: "set/larrybutton"
796 | layer: ""
797 | inherit_alpha: true
798 | alpha: 1.0
799 | outline_alpha: 1.0
800 | shadow_alpha: 1.0
801 | overridden_fields: 8
802 | template_node_child: true
803 | text_leading: 1.0
804 | text_tracking: 0.0
805 | }
806 | nodes {
807 | position {
808 | x: 499.0
809 | y: 650.0
810 | z: 0.0
811 | w: 1.0
812 | }
813 | rotation {
814 | x: 0.0
815 | y: 0.0
816 | z: 0.0
817 | w: 1.0
818 | }
819 | scale {
820 | x: 1.0
821 | y: 1.0
822 | z: 1.0
823 | w: 1.0
824 | }
825 | size {
826 | x: 200.0
827 | y: 100.0
828 | z: 0.0
829 | w: 1.0
830 | }
831 | color {
832 | x: 1.0
833 | y: 1.0
834 | z: 1.0
835 | w: 1.0
836 | }
837 | type: TYPE_TEMPLATE
838 | id: "show"
839 | layer: ""
840 | inherit_alpha: true
841 | alpha: 1.0
842 | template: "/dirtylarry/button.gui"
843 | template_node_child: false
844 | }
845 | nodes {
846 | position {
847 | x: 0.0
848 | y: 0.0
849 | z: 0.0
850 | w: 1.0
851 | }
852 | rotation {
853 | x: 0.0
854 | y: 0.0
855 | z: 0.0
856 | w: 1.0
857 | }
858 | scale {
859 | x: 1.0
860 | y: 1.0
861 | z: 1.0
862 | w: 1.0
863 | }
864 | size {
865 | x: 300.0
866 | y: 88.0
867 | z: 0.0
868 | w: 1.0
869 | }
870 | color {
871 | x: 1.0
872 | y: 1.0
873 | z: 1.0
874 | w: 1.0
875 | }
876 | type: TYPE_BOX
877 | blend_mode: BLEND_MODE_ALPHA
878 | texture: "button/button_normal"
879 | id: "show/larrybutton"
880 | xanchor: XANCHOR_NONE
881 | yanchor: YANCHOR_NONE
882 | pivot: PIVOT_CENTER
883 | adjust_mode: ADJUST_MODE_FIT
884 | parent: "show"
885 | layer: ""
886 | inherit_alpha: true
887 | slice9 {
888 | x: 32.0
889 | y: 32.0
890 | z: 32.0
891 | w: 32.0
892 | }
893 | clipping_mode: CLIPPING_MODE_NONE
894 | clipping_visible: true
895 | clipping_inverted: false
896 | alpha: 1.0
897 | template_node_child: true
898 | size_mode: SIZE_MODE_MANUAL
899 | }
900 | nodes {
901 | position {
902 | x: 0.0
903 | y: 0.0
904 | z: 0.0
905 | w: 1.0
906 | }
907 | rotation {
908 | x: 0.0
909 | y: 0.0
910 | z: 0.0
911 | w: 1.0
912 | }
913 | scale {
914 | x: 1.0
915 | y: 1.0
916 | z: 1.0
917 | w: 1.0
918 | }
919 | size {
920 | x: 200.0
921 | y: 100.0
922 | z: 0.0
923 | w: 1.0
924 | }
925 | color {
926 | x: 1.0
927 | y: 1.0
928 | z: 1.0
929 | w: 1.0
930 | }
931 | type: TYPE_TEXT
932 | blend_mode: BLEND_MODE_ALPHA
933 | text: "Show"
934 | font: "larryfont"
935 | id: "show/larrylabel"
936 | xanchor: XANCHOR_NONE
937 | yanchor: YANCHOR_NONE
938 | pivot: PIVOT_CENTER
939 | outline {
940 | x: 0.0
941 | y: 0.0
942 | z: 0.0
943 | w: 1.0
944 | }
945 | shadow {
946 | x: 1.0
947 | y: 1.0
948 | z: 1.0
949 | w: 1.0
950 | }
951 | adjust_mode: ADJUST_MODE_FIT
952 | line_break: false
953 | parent: "show/larrybutton"
954 | layer: ""
955 | inherit_alpha: true
956 | alpha: 1.0
957 | outline_alpha: 1.0
958 | shadow_alpha: 1.0
959 | overridden_fields: 8
960 | template_node_child: true
961 | text_leading: 1.0
962 | text_tracking: 0.0
963 | }
964 | nodes {
965 | position {
966 | x: 499.0
967 | y: 530.0
968 | z: 0.0
969 | w: 1.0
970 | }
971 | rotation {
972 | x: 0.0
973 | y: 0.0
974 | z: 0.0
975 | w: 1.0
976 | }
977 | scale {
978 | x: 1.0
979 | y: 1.0
980 | z: 1.0
981 | w: 1.0
982 | }
983 | size {
984 | x: 200.0
985 | y: 100.0
986 | z: 0.0
987 | w: 1.0
988 | }
989 | color {
990 | x: 1.0
991 | y: 1.0
992 | z: 1.0
993 | w: 1.0
994 | }
995 | type: TYPE_TEMPLATE
996 | id: "get"
997 | layer: ""
998 | inherit_alpha: true
999 | alpha: 1.0
1000 | template: "/dirtylarry/button.gui"
1001 | template_node_child: false
1002 | }
1003 | nodes {
1004 | position {
1005 | x: 0.0
1006 | y: 0.0
1007 | z: 0.0
1008 | w: 1.0
1009 | }
1010 | rotation {
1011 | x: 0.0
1012 | y: 0.0
1013 | z: 0.0
1014 | w: 1.0
1015 | }
1016 | scale {
1017 | x: 1.0
1018 | y: 1.0
1019 | z: 1.0
1020 | w: 1.0
1021 | }
1022 | size {
1023 | x: 300.0
1024 | y: 88.0
1025 | z: 0.0
1026 | w: 1.0
1027 | }
1028 | color {
1029 | x: 1.0
1030 | y: 1.0
1031 | z: 1.0
1032 | w: 1.0
1033 | }
1034 | type: TYPE_BOX
1035 | blend_mode: BLEND_MODE_ALPHA
1036 | texture: "button/button_normal"
1037 | id: "get/larrybutton"
1038 | xanchor: XANCHOR_NONE
1039 | yanchor: YANCHOR_NONE
1040 | pivot: PIVOT_CENTER
1041 | adjust_mode: ADJUST_MODE_FIT
1042 | parent: "get"
1043 | layer: ""
1044 | inherit_alpha: true
1045 | slice9 {
1046 | x: 32.0
1047 | y: 32.0
1048 | z: 32.0
1049 | w: 32.0
1050 | }
1051 | clipping_mode: CLIPPING_MODE_NONE
1052 | clipping_visible: true
1053 | clipping_inverted: false
1054 | alpha: 1.0
1055 | template_node_child: true
1056 | size_mode: SIZE_MODE_MANUAL
1057 | }
1058 | nodes {
1059 | position {
1060 | x: 0.0
1061 | y: 0.0
1062 | z: 0.0
1063 | w: 1.0
1064 | }
1065 | rotation {
1066 | x: 0.0
1067 | y: 0.0
1068 | z: 0.0
1069 | w: 1.0
1070 | }
1071 | scale {
1072 | x: 1.0
1073 | y: 1.0
1074 | z: 1.0
1075 | w: 1.0
1076 | }
1077 | size {
1078 | x: 200.0
1079 | y: 100.0
1080 | z: 0.0
1081 | w: 1.0
1082 | }
1083 | color {
1084 | x: 1.0
1085 | y: 1.0
1086 | z: 1.0
1087 | w: 1.0
1088 | }
1089 | type: TYPE_TEXT
1090 | blend_mode: BLEND_MODE_ALPHA
1091 | text: "Get"
1092 | font: "larryfont"
1093 | id: "get/larrylabel"
1094 | xanchor: XANCHOR_NONE
1095 | yanchor: YANCHOR_NONE
1096 | pivot: PIVOT_CENTER
1097 | outline {
1098 | x: 0.0
1099 | y: 0.0
1100 | z: 0.0
1101 | w: 1.0
1102 | }
1103 | shadow {
1104 | x: 1.0
1105 | y: 1.0
1106 | z: 1.0
1107 | w: 1.0
1108 | }
1109 | adjust_mode: ADJUST_MODE_FIT
1110 | line_break: false
1111 | parent: "get/larrybutton"
1112 | layer: ""
1113 | inherit_alpha: true
1114 | alpha: 1.0
1115 | outline_alpha: 1.0
1116 | shadow_alpha: 1.0
1117 | overridden_fields: 8
1118 | template_node_child: true
1119 | text_leading: 1.0
1120 | text_tracking: 0.0
1121 | }
1122 | material: "/builtins/materials/gui.material"
1123 | adjust_reference: ADJUST_REFERENCE_PARENT
1124 | max_nodes: 512
1125 |
--------------------------------------------------------------------------------
/main/leaderboards.gui:
--------------------------------------------------------------------------------
1 | script: "/main/leaderboards.gui_script"
2 | fonts {
3 | name: "larryfont"
4 | font: "/dirtylarry/larryfont.font"
5 | }
6 | textures {
7 | name: "dirtylarry"
8 | texture: "/dirtylarry/dirtylarry.atlas"
9 | }
10 | background_color {
11 | x: 0.0
12 | y: 0.0
13 | z: 0.0
14 | w: 0.0
15 | }
16 | nodes {
17 | position {
18 | x: 170.0
19 | y: 74.0
20 | z: 0.0
21 | w: 1.0
22 | }
23 | rotation {
24 | x: 0.0
25 | y: 0.0
26 | z: 0.0
27 | w: 1.0
28 | }
29 | scale {
30 | x: 1.0
31 | y: 1.0
32 | z: 1.0
33 | w: 1.0
34 | }
35 | size {
36 | x: 200.0
37 | y: 100.0
38 | z: 0.0
39 | w: 1.0
40 | }
41 | color {
42 | x: 1.0
43 | y: 1.0
44 | z: 1.0
45 | w: 1.0
46 | }
47 | type: TYPE_TEMPLATE
48 | id: "back"
49 | layer: ""
50 | inherit_alpha: true
51 | alpha: 1.0
52 | template: "/dirtylarry/button.gui"
53 | template_node_child: false
54 | }
55 | nodes {
56 | position {
57 | x: 0.0
58 | y: 0.0
59 | z: 0.0
60 | w: 1.0
61 | }
62 | rotation {
63 | x: 0.0
64 | y: 0.0
65 | z: 0.0
66 | w: 1.0
67 | }
68 | scale {
69 | x: 1.0
70 | y: 1.0
71 | z: 1.0
72 | w: 1.0
73 | }
74 | size {
75 | x: 300.0
76 | y: 88.0
77 | z: 0.0
78 | w: 1.0
79 | }
80 | color {
81 | x: 1.0
82 | y: 1.0
83 | z: 1.0
84 | w: 1.0
85 | }
86 | type: TYPE_BOX
87 | blend_mode: BLEND_MODE_ALPHA
88 | texture: "button/button_normal"
89 | id: "back/larrybutton"
90 | xanchor: XANCHOR_NONE
91 | yanchor: YANCHOR_NONE
92 | pivot: PIVOT_CENTER
93 | adjust_mode: ADJUST_MODE_FIT
94 | parent: "back"
95 | layer: ""
96 | inherit_alpha: true
97 | slice9 {
98 | x: 32.0
99 | y: 32.0
100 | z: 32.0
101 | w: 32.0
102 | }
103 | clipping_mode: CLIPPING_MODE_NONE
104 | clipping_visible: true
105 | clipping_inverted: false
106 | alpha: 1.0
107 | template_node_child: true
108 | size_mode: SIZE_MODE_MANUAL
109 | }
110 | nodes {
111 | position {
112 | x: 0.0
113 | y: 0.0
114 | z: 0.0
115 | w: 1.0
116 | }
117 | rotation {
118 | x: 0.0
119 | y: 0.0
120 | z: 0.0
121 | w: 1.0
122 | }
123 | scale {
124 | x: 1.0
125 | y: 1.0
126 | z: 1.0
127 | w: 1.0
128 | }
129 | size {
130 | x: 200.0
131 | y: 100.0
132 | z: 0.0
133 | w: 1.0
134 | }
135 | color {
136 | x: 1.0
137 | y: 1.0
138 | z: 1.0
139 | w: 1.0
140 | }
141 | type: TYPE_TEXT
142 | blend_mode: BLEND_MODE_ALPHA
143 | text: "BACK"
144 | font: "larryfont"
145 | id: "back/larrylabel"
146 | xanchor: XANCHOR_NONE
147 | yanchor: YANCHOR_NONE
148 | pivot: PIVOT_CENTER
149 | outline {
150 | x: 0.0
151 | y: 0.0
152 | z: 0.0
153 | w: 1.0
154 | }
155 | shadow {
156 | x: 1.0
157 | y: 1.0
158 | z: 1.0
159 | w: 1.0
160 | }
161 | adjust_mode: ADJUST_MODE_FIT
162 | line_break: false
163 | parent: "back/larrybutton"
164 | layer: ""
165 | inherit_alpha: true
166 | alpha: 1.0
167 | outline_alpha: 1.0
168 | shadow_alpha: 1.0
169 | overridden_fields: 8
170 | template_node_child: true
171 | text_leading: 1.0
172 | text_tracking: 0.0
173 | }
174 | nodes {
175 | position {
176 | x: 170.0
177 | y: 656.0
178 | z: 0.0
179 | w: 1.0
180 | }
181 | rotation {
182 | x: 0.0
183 | y: 0.0
184 | z: 0.0
185 | w: 1.0
186 | }
187 | scale {
188 | x: 1.0
189 | y: 1.0
190 | z: 1.0
191 | w: 1.0
192 | }
193 | size {
194 | x: 200.0
195 | y: 100.0
196 | z: 0.0
197 | w: 1.0
198 | }
199 | color {
200 | x: 1.0
201 | y: 1.0
202 | z: 1.0
203 | w: 1.0
204 | }
205 | type: TYPE_TEMPLATE
206 | id: "submit_score"
207 | layer: ""
208 | inherit_alpha: true
209 | alpha: 1.0
210 | template: "/dirtylarry/button.gui"
211 | template_node_child: false
212 | }
213 | nodes {
214 | position {
215 | x: 0.0
216 | y: 0.0
217 | z: 0.0
218 | w: 1.0
219 | }
220 | rotation {
221 | x: 0.0
222 | y: 0.0
223 | z: 0.0
224 | w: 1.0
225 | }
226 | scale {
227 | x: 1.0
228 | y: 1.0
229 | z: 1.0
230 | w: 1.0
231 | }
232 | size {
233 | x: 300.0
234 | y: 88.0
235 | z: 0.0
236 | w: 1.0
237 | }
238 | color {
239 | x: 1.0
240 | y: 1.0
241 | z: 1.0
242 | w: 1.0
243 | }
244 | type: TYPE_BOX
245 | blend_mode: BLEND_MODE_ALPHA
246 | texture: "button/button_normal"
247 | id: "submit_score/larrybutton"
248 | xanchor: XANCHOR_NONE
249 | yanchor: YANCHOR_NONE
250 | pivot: PIVOT_CENTER
251 | adjust_mode: ADJUST_MODE_FIT
252 | parent: "submit_score"
253 | layer: ""
254 | inherit_alpha: true
255 | slice9 {
256 | x: 32.0
257 | y: 32.0
258 | z: 32.0
259 | w: 32.0
260 | }
261 | clipping_mode: CLIPPING_MODE_NONE
262 | clipping_visible: true
263 | clipping_inverted: false
264 | alpha: 1.0
265 | template_node_child: true
266 | size_mode: SIZE_MODE_MANUAL
267 | }
268 | nodes {
269 | position {
270 | x: 0.0
271 | y: 0.0
272 | z: 0.0
273 | w: 1.0
274 | }
275 | rotation {
276 | x: 0.0
277 | y: 0.0
278 | z: 0.0
279 | w: 1.0
280 | }
281 | scale {
282 | x: 1.0
283 | y: 1.0
284 | z: 1.0
285 | w: 1.0
286 | }
287 | size {
288 | x: 200.0
289 | y: 100.0
290 | z: 0.0
291 | w: 1.0
292 | }
293 | color {
294 | x: 1.0
295 | y: 1.0
296 | z: 1.0
297 | w: 1.0
298 | }
299 | type: TYPE_TEXT
300 | blend_mode: BLEND_MODE_ALPHA
301 | text: "Submit Score"
302 | font: "larryfont"
303 | id: "submit_score/larrylabel"
304 | xanchor: XANCHOR_NONE
305 | yanchor: YANCHOR_NONE
306 | pivot: PIVOT_CENTER
307 | outline {
308 | x: 0.0
309 | y: 0.0
310 | z: 0.0
311 | w: 1.0
312 | }
313 | shadow {
314 | x: 1.0
315 | y: 1.0
316 | z: 1.0
317 | w: 1.0
318 | }
319 | adjust_mode: ADJUST_MODE_FIT
320 | line_break: false
321 | parent: "submit_score/larrybutton"
322 | layer: ""
323 | inherit_alpha: true
324 | alpha: 1.0
325 | outline_alpha: 1.0
326 | shadow_alpha: 1.0
327 | overridden_fields: 8
328 | template_node_child: true
329 | text_leading: 1.0
330 | text_tracking: 0.0
331 | }
332 | nodes {
333 | position {
334 | x: 716.0
335 | y: 656.0
336 | z: 0.0
337 | w: 1.0
338 | }
339 | rotation {
340 | x: 0.0
341 | y: 0.0
342 | z: 0.0
343 | w: 1.0
344 | }
345 | scale {
346 | x: 1.0
347 | y: 1.0
348 | z: 1.0
349 | w: 1.0
350 | }
351 | size {
352 | x: 200.0
353 | y: 100.0
354 | z: 0.0
355 | w: 1.0
356 | }
357 | color {
358 | x: 1.0
359 | y: 1.0
360 | z: 1.0
361 | w: 1.0
362 | }
363 | type: TYPE_TEMPLATE
364 | id: "top_scores"
365 | layer: ""
366 | inherit_alpha: true
367 | alpha: 1.0
368 | template: "/dirtylarry/button.gui"
369 | template_node_child: false
370 | }
371 | nodes {
372 | position {
373 | x: 0.0
374 | y: 0.0
375 | z: 0.0
376 | w: 1.0
377 | }
378 | rotation {
379 | x: 0.0
380 | y: 0.0
381 | z: 0.0
382 | w: 1.0
383 | }
384 | scale {
385 | x: 1.0
386 | y: 1.0
387 | z: 1.0
388 | w: 1.0
389 | }
390 | size {
391 | x: 300.0
392 | y: 88.0
393 | z: 0.0
394 | w: 1.0
395 | }
396 | color {
397 | x: 1.0
398 | y: 1.0
399 | z: 1.0
400 | w: 1.0
401 | }
402 | type: TYPE_BOX
403 | blend_mode: BLEND_MODE_ALPHA
404 | texture: "button/button_normal"
405 | id: "top_scores/larrybutton"
406 | xanchor: XANCHOR_NONE
407 | yanchor: YANCHOR_NONE
408 | pivot: PIVOT_CENTER
409 | adjust_mode: ADJUST_MODE_FIT
410 | parent: "top_scores"
411 | layer: ""
412 | inherit_alpha: true
413 | slice9 {
414 | x: 32.0
415 | y: 32.0
416 | z: 32.0
417 | w: 32.0
418 | }
419 | clipping_mode: CLIPPING_MODE_NONE
420 | clipping_visible: true
421 | clipping_inverted: false
422 | alpha: 1.0
423 | template_node_child: true
424 | size_mode: SIZE_MODE_MANUAL
425 | }
426 | nodes {
427 | position {
428 | x: 0.0
429 | y: 0.0
430 | z: 0.0
431 | w: 1.0
432 | }
433 | rotation {
434 | x: 0.0
435 | y: 0.0
436 | z: 0.0
437 | w: 1.0
438 | }
439 | scale {
440 | x: 1.0
441 | y: 1.0
442 | z: 1.0
443 | w: 1.0
444 | }
445 | size {
446 | x: 200.0
447 | y: 100.0
448 | z: 0.0
449 | w: 1.0
450 | }
451 | color {
452 | x: 1.0
453 | y: 1.0
454 | z: 1.0
455 | w: 1.0
456 | }
457 | type: TYPE_TEXT
458 | blend_mode: BLEND_MODE_ALPHA
459 | text: "Top Scores"
460 | font: "larryfont"
461 | id: "top_scores/larrylabel"
462 | xanchor: XANCHOR_NONE
463 | yanchor: YANCHOR_NONE
464 | pivot: PIVOT_CENTER
465 | outline {
466 | x: 0.0
467 | y: 0.0
468 | z: 0.0
469 | w: 1.0
470 | }
471 | shadow {
472 | x: 1.0
473 | y: 1.0
474 | z: 1.0
475 | w: 1.0
476 | }
477 | adjust_mode: ADJUST_MODE_FIT
478 | line_break: false
479 | parent: "top_scores/larrybutton"
480 | layer: ""
481 | inherit_alpha: true
482 | alpha: 1.0
483 | outline_alpha: 1.0
484 | shadow_alpha: 1.0
485 | overridden_fields: 8
486 | template_node_child: true
487 | text_leading: 1.0
488 | text_tracking: 0.0
489 | }
490 | nodes {
491 | position {
492 | x: 1064.0
493 | y: 656.0
494 | z: 0.0
495 | w: 1.0
496 | }
497 | rotation {
498 | x: 0.0
499 | y: 0.0
500 | z: 0.0
501 | w: 1.0
502 | }
503 | scale {
504 | x: 1.0
505 | y: 1.0
506 | z: 1.0
507 | w: 1.0
508 | }
509 | size {
510 | x: 200.0
511 | y: 100.0
512 | z: 0.0
513 | w: 1.0
514 | }
515 | color {
516 | x: 1.0
517 | y: 1.0
518 | z: 1.0
519 | w: 1.0
520 | }
521 | type: TYPE_TEMPLATE
522 | id: "player_centered_scores"
523 | layer: ""
524 | inherit_alpha: true
525 | alpha: 1.0
526 | template: "/dirtylarry/button.gui"
527 | template_node_child: false
528 | }
529 | nodes {
530 | position {
531 | x: 0.0
532 | y: 0.0
533 | z: 0.0
534 | w: 1.0
535 | }
536 | rotation {
537 | x: 0.0
538 | y: 0.0
539 | z: 0.0
540 | w: 1.0
541 | }
542 | scale {
543 | x: 1.0
544 | y: 1.0
545 | z: 1.0
546 | w: 1.0
547 | }
548 | size {
549 | x: 300.0
550 | y: 88.0
551 | z: 0.0
552 | w: 1.0
553 | }
554 | color {
555 | x: 1.0
556 | y: 1.0
557 | z: 1.0
558 | w: 1.0
559 | }
560 | type: TYPE_BOX
561 | blend_mode: BLEND_MODE_ALPHA
562 | texture: "button/button_normal"
563 | id: "player_centered_scores/larrybutton"
564 | xanchor: XANCHOR_NONE
565 | yanchor: YANCHOR_NONE
566 | pivot: PIVOT_CENTER
567 | adjust_mode: ADJUST_MODE_FIT
568 | parent: "player_centered_scores"
569 | layer: ""
570 | inherit_alpha: true
571 | slice9 {
572 | x: 32.0
573 | y: 32.0
574 | z: 32.0
575 | w: 32.0
576 | }
577 | clipping_mode: CLIPPING_MODE_NONE
578 | clipping_visible: true
579 | clipping_inverted: false
580 | alpha: 1.0
581 | template_node_child: true
582 | size_mode: SIZE_MODE_MANUAL
583 | }
584 | nodes {
585 | position {
586 | x: 0.0
587 | y: 0.0
588 | z: 0.0
589 | w: 1.0
590 | }
591 | rotation {
592 | x: 0.0
593 | y: 0.0
594 | z: 0.0
595 | w: 1.0
596 | }
597 | scale {
598 | x: 1.0
599 | y: 1.0
600 | z: 1.0
601 | w: 1.0
602 | }
603 | size {
604 | x: 200.0
605 | y: 100.0
606 | z: 0.0
607 | w: 1.0
608 | }
609 | color {
610 | x: 1.0
611 | y: 1.0
612 | z: 1.0
613 | w: 1.0
614 | }
615 | type: TYPE_TEXT
616 | blend_mode: BLEND_MODE_ALPHA
617 | text: "Player Centered Scores"
618 | font: "larryfont"
619 | id: "player_centered_scores/larrylabel"
620 | xanchor: XANCHOR_NONE
621 | yanchor: YANCHOR_NONE
622 | pivot: PIVOT_CENTER
623 | outline {
624 | x: 0.0
625 | y: 0.0
626 | z: 0.0
627 | w: 1.0
628 | }
629 | shadow {
630 | x: 1.0
631 | y: 1.0
632 | z: 1.0
633 | w: 1.0
634 | }
635 | adjust_mode: ADJUST_MODE_FIT
636 | line_break: true
637 | parent: "player_centered_scores/larrybutton"
638 | layer: ""
639 | inherit_alpha: true
640 | alpha: 1.0
641 | outline_alpha: 1.0
642 | shadow_alpha: 1.0
643 | overridden_fields: 4
644 | overridden_fields: 8
645 | overridden_fields: 18
646 | template_node_child: true
647 | text_leading: 1.0
648 | text_tracking: 0.0
649 | }
650 | nodes {
651 | position {
652 | x: 170.0
653 | y: 531.0
654 | z: 0.0
655 | w: 1.0
656 | }
657 | rotation {
658 | x: 0.0
659 | y: 0.0
660 | z: 0.0
661 | w: 1.0
662 | }
663 | scale {
664 | x: 1.0
665 | y: 1.0
666 | z: 1.0
667 | w: 1.0
668 | }
669 | size {
670 | x: 200.0
671 | y: 100.0
672 | z: 0.0
673 | w: 1.0
674 | }
675 | color {
676 | x: 1.0
677 | y: 1.0
678 | z: 1.0
679 | w: 1.0
680 | }
681 | type: TYPE_TEMPLATE
682 | id: "player_score"
683 | layer: ""
684 | inherit_alpha: true
685 | alpha: 1.0
686 | template: "/dirtylarry/button.gui"
687 | template_node_child: false
688 | }
689 | nodes {
690 | position {
691 | x: 0.0
692 | y: 0.0
693 | z: 0.0
694 | w: 1.0
695 | }
696 | rotation {
697 | x: 0.0
698 | y: 0.0
699 | z: 0.0
700 | w: 1.0
701 | }
702 | scale {
703 | x: 1.0
704 | y: 1.0
705 | z: 1.0
706 | w: 1.0
707 | }
708 | size {
709 | x: 300.0
710 | y: 88.0
711 | z: 0.0
712 | w: 1.0
713 | }
714 | color {
715 | x: 1.0
716 | y: 1.0
717 | z: 1.0
718 | w: 1.0
719 | }
720 | type: TYPE_BOX
721 | blend_mode: BLEND_MODE_ALPHA
722 | texture: "button/button_normal"
723 | id: "player_score/larrybutton"
724 | xanchor: XANCHOR_NONE
725 | yanchor: YANCHOR_NONE
726 | pivot: PIVOT_CENTER
727 | adjust_mode: ADJUST_MODE_FIT
728 | parent: "player_score"
729 | layer: ""
730 | inherit_alpha: true
731 | slice9 {
732 | x: 32.0
733 | y: 32.0
734 | z: 32.0
735 | w: 32.0
736 | }
737 | clipping_mode: CLIPPING_MODE_NONE
738 | clipping_visible: true
739 | clipping_inverted: false
740 | alpha: 1.0
741 | template_node_child: true
742 | size_mode: SIZE_MODE_MANUAL
743 | }
744 | nodes {
745 | position {
746 | x: 0.0
747 | y: 0.0
748 | z: 0.0
749 | w: 1.0
750 | }
751 | rotation {
752 | x: 0.0
753 | y: 0.0
754 | z: 0.0
755 | w: 1.0
756 | }
757 | scale {
758 | x: 1.0
759 | y: 1.0
760 | z: 1.0
761 | w: 1.0
762 | }
763 | size {
764 | x: 240.0
765 | y: 100.0
766 | z: 0.0
767 | w: 1.0
768 | }
769 | color {
770 | x: 1.0
771 | y: 1.0
772 | z: 1.0
773 | w: 1.0
774 | }
775 | type: TYPE_TEXT
776 | blend_mode: BLEND_MODE_ALPHA
777 | text: "Player Score"
778 | font: "larryfont"
779 | id: "player_score/larrylabel"
780 | xanchor: XANCHOR_NONE
781 | yanchor: YANCHOR_NONE
782 | pivot: PIVOT_CENTER
783 | outline {
784 | x: 0.0
785 | y: 0.0
786 | z: 0.0
787 | w: 1.0
788 | }
789 | shadow {
790 | x: 1.0
791 | y: 1.0
792 | z: 1.0
793 | w: 1.0
794 | }
795 | adjust_mode: ADJUST_MODE_FIT
796 | line_break: true
797 | parent: "player_score/larrybutton"
798 | layer: ""
799 | inherit_alpha: true
800 | alpha: 1.0
801 | outline_alpha: 1.0
802 | shadow_alpha: 1.0
803 | overridden_fields: 4
804 | overridden_fields: 8
805 | overridden_fields: 18
806 | template_node_child: true
807 | text_leading: 1.0
808 | text_tracking: 0.0
809 | }
810 | nodes {
811 | position {
812 | x: 331.0
813 | y: 537.0
814 | z: 0.0
815 | w: 1.0
816 | }
817 | rotation {
818 | x: 0.0
819 | y: 0.0
820 | z: 0.0
821 | w: 1.0
822 | }
823 | scale {
824 | x: 1.0
825 | y: 1.0
826 | z: 1.0
827 | w: 1.0
828 | }
829 | size {
830 | x: 200.0
831 | y: 100.0
832 | z: 0.0
833 | w: 1.0
834 | }
835 | color {
836 | x: 1.0
837 | y: 1.0
838 | z: 1.0
839 | w: 1.0
840 | }
841 | type: TYPE_TEXT
842 | blend_mode: BLEND_MODE_ALPHA
843 | text: ""
844 | font: "larryfont"
845 | id: "score"
846 | xanchor: XANCHOR_NONE
847 | yanchor: YANCHOR_NONE
848 | pivot: PIVOT_W
849 | outline {
850 | x: 1.0
851 | y: 1.0
852 | z: 1.0
853 | w: 1.0
854 | }
855 | shadow {
856 | x: 1.0
857 | y: 1.0
858 | z: 1.0
859 | w: 1.0
860 | }
861 | adjust_mode: ADJUST_MODE_FIT
862 | line_break: false
863 | layer: ""
864 | inherit_alpha: true
865 | alpha: 1.0
866 | outline_alpha: 1.0
867 | shadow_alpha: 1.0
868 | template_node_child: false
869 | text_leading: 1.0
870 | text_tracking: 0.0
871 | }
872 | nodes {
873 | position {
874 | x: 331.0
875 | y: 656.0
876 | z: 0.0
877 | w: 1.0
878 | }
879 | rotation {
880 | x: 0.0
881 | y: 0.0
882 | z: 0.0
883 | w: 1.0
884 | }
885 | scale {
886 | x: 1.0
887 | y: 1.0
888 | z: 1.0
889 | w: 1.0
890 | }
891 | size {
892 | x: 200.0
893 | y: 100.0
894 | z: 0.0
895 | w: 1.0
896 | }
897 | color {
898 | x: 1.0
899 | y: 1.0
900 | z: 1.0
901 | w: 1.0
902 | }
903 | type: TYPE_TEXT
904 | blend_mode: BLEND_MODE_ALPHA
905 | text: ""
906 | font: "larryfont"
907 | id: "clicks"
908 | xanchor: XANCHOR_NONE
909 | yanchor: YANCHOR_NONE
910 | pivot: PIVOT_W
911 | outline {
912 | x: 1.0
913 | y: 1.0
914 | z: 1.0
915 | w: 1.0
916 | }
917 | shadow {
918 | x: 1.0
919 | y: 1.0
920 | z: 1.0
921 | w: 1.0
922 | }
923 | adjust_mode: ADJUST_MODE_FIT
924 | line_break: false
925 | layer: ""
926 | inherit_alpha: true
927 | alpha: 1.0
928 | outline_alpha: 1.0
929 | shadow_alpha: 1.0
930 | template_node_child: false
931 | text_leading: 1.0
932 | text_tracking: 0.0
933 | }
934 | nodes {
935 | position {
936 | x: 565.0
937 | y: 537.0
938 | z: 0.0
939 | w: 1.0
940 | }
941 | rotation {
942 | x: 0.0
943 | y: 0.0
944 | z: 0.0
945 | w: 1.0
946 | }
947 | scale {
948 | x: 1.0
949 | y: 1.0
950 | z: 1.0
951 | w: 1.0
952 | }
953 | size {
954 | x: 650.0
955 | y: 100.0
956 | z: 0.0
957 | w: 1.0
958 | }
959 | color {
960 | x: 1.0
961 | y: 1.0
962 | z: 1.0
963 | w: 1.0
964 | }
965 | type: TYPE_TEXT
966 | blend_mode: BLEND_MODE_ALPHA
967 | text: ""
968 | font: "larryfont"
969 | id: "scores"
970 | xanchor: XANCHOR_NONE
971 | yanchor: YANCHOR_NONE
972 | pivot: PIVOT_W
973 | outline {
974 | x: 1.0
975 | y: 1.0
976 | z: 1.0
977 | w: 1.0
978 | }
979 | shadow {
980 | x: 1.0
981 | y: 1.0
982 | z: 1.0
983 | w: 1.0
984 | }
985 | adjust_mode: ADJUST_MODE_FIT
986 | line_break: true
987 | layer: ""
988 | inherit_alpha: true
989 | alpha: 1.0
990 | outline_alpha: 1.0
991 | shadow_alpha: 1.0
992 | template_node_child: false
993 | text_leading: 1.0
994 | text_tracking: 0.0
995 | }
996 | nodes {
997 | position {
998 | x: 170.0
999 | y: 412.0
1000 | z: 0.0
1001 | w: 1.0
1002 | }
1003 | rotation {
1004 | x: 0.0
1005 | y: 0.0
1006 | z: 0.0
1007 | w: 1.0
1008 | }
1009 | scale {
1010 | x: 1.0
1011 | y: 1.0
1012 | z: 1.0
1013 | w: 1.0
1014 | }
1015 | size {
1016 | x: 200.0
1017 | y: 100.0
1018 | z: 0.0
1019 | w: 1.0
1020 | }
1021 | color {
1022 | x: 1.0
1023 | y: 1.0
1024 | z: 1.0
1025 | w: 1.0
1026 | }
1027 | type: TYPE_TEMPLATE
1028 | id: "show_leaderboard"
1029 | layer: ""
1030 | inherit_alpha: true
1031 | alpha: 1.0
1032 | template: "/dirtylarry/button.gui"
1033 | template_node_child: false
1034 | }
1035 | nodes {
1036 | position {
1037 | x: 0.0
1038 | y: 0.0
1039 | z: 0.0
1040 | w: 1.0
1041 | }
1042 | rotation {
1043 | x: 0.0
1044 | y: 0.0
1045 | z: 0.0
1046 | w: 1.0
1047 | }
1048 | scale {
1049 | x: 1.0
1050 | y: 1.0
1051 | z: 1.0
1052 | w: 1.0
1053 | }
1054 | size {
1055 | x: 300.0
1056 | y: 88.0
1057 | z: 0.0
1058 | w: 1.0
1059 | }
1060 | color {
1061 | x: 1.0
1062 | y: 1.0
1063 | z: 1.0
1064 | w: 1.0
1065 | }
1066 | type: TYPE_BOX
1067 | blend_mode: BLEND_MODE_ALPHA
1068 | texture: "button/button_normal"
1069 | id: "show_leaderboard/larrybutton"
1070 | xanchor: XANCHOR_NONE
1071 | yanchor: YANCHOR_NONE
1072 | pivot: PIVOT_CENTER
1073 | adjust_mode: ADJUST_MODE_FIT
1074 | parent: "show_leaderboard"
1075 | layer: ""
1076 | inherit_alpha: true
1077 | slice9 {
1078 | x: 32.0
1079 | y: 32.0
1080 | z: 32.0
1081 | w: 32.0
1082 | }
1083 | clipping_mode: CLIPPING_MODE_NONE
1084 | clipping_visible: true
1085 | clipping_inverted: false
1086 | alpha: 1.0
1087 | template_node_child: true
1088 | size_mode: SIZE_MODE_MANUAL
1089 | }
1090 | nodes {
1091 | position {
1092 | x: 0.0
1093 | y: 0.0
1094 | z: 0.0
1095 | w: 1.0
1096 | }
1097 | rotation {
1098 | x: 0.0
1099 | y: 0.0
1100 | z: 0.0
1101 | w: 1.0
1102 | }
1103 | scale {
1104 | x: 1.0
1105 | y: 1.0
1106 | z: 1.0
1107 | w: 1.0
1108 | }
1109 | size {
1110 | x: 200.0
1111 | y: 100.0
1112 | z: 0.0
1113 | w: 1.0
1114 | }
1115 | color {
1116 | x: 1.0
1117 | y: 1.0
1118 | z: 1.0
1119 | w: 1.0
1120 | }
1121 | type: TYPE_TEXT
1122 | blend_mode: BLEND_MODE_ALPHA
1123 | text: "Show Leaderboard"
1124 | font: "larryfont"
1125 | id: "show_leaderboard/larrylabel"
1126 | xanchor: XANCHOR_NONE
1127 | yanchor: YANCHOR_NONE
1128 | pivot: PIVOT_CENTER
1129 | outline {
1130 | x: 0.0
1131 | y: 0.0
1132 | z: 0.0
1133 | w: 1.0
1134 | }
1135 | shadow {
1136 | x: 1.0
1137 | y: 1.0
1138 | z: 1.0
1139 | w: 1.0
1140 | }
1141 | adjust_mode: ADJUST_MODE_FIT
1142 | line_break: false
1143 | parent: "show_leaderboard/larrybutton"
1144 | layer: ""
1145 | inherit_alpha: true
1146 | alpha: 1.0
1147 | outline_alpha: 1.0
1148 | shadow_alpha: 1.0
1149 | overridden_fields: 8
1150 | template_node_child: true
1151 | text_leading: 1.0
1152 | text_tracking: 0.0
1153 | }
1154 | material: "/builtins/materials/gui.material"
1155 | adjust_reference: ADJUST_REFERENCE_PARENT
1156 | max_nodes: 512
1157 |
--------------------------------------------------------------------------------
/main/snapshot.gui:
--------------------------------------------------------------------------------
1 | script: "/main/snapshot.gui_script"
2 | fonts {
3 | name: "larryfont"
4 | font: "/dirtylarry/larryfont.font"
5 | }
6 | textures {
7 | name: "logo"
8 | texture: "/main/logo.atlas"
9 | }
10 | background_color {
11 | x: 0.0
12 | y: 0.0
13 | z: 0.0
14 | w: 1.0
15 | }
16 | nodes {
17 | position {
18 | x: 170.0
19 | y: 650.0
20 | z: 0.0
21 | w: 1.0
22 | }
23 | rotation {
24 | x: 0.0
25 | y: 0.0
26 | z: 0.0
27 | w: 1.0
28 | }
29 | scale {
30 | x: 1.0
31 | y: 1.0
32 | z: 1.0
33 | w: 1.0
34 | }
35 | size {
36 | x: 200.0
37 | y: 100.0
38 | z: 0.0
39 | w: 1.0
40 | }
41 | color {
42 | x: 1.0
43 | y: 1.0
44 | z: 1.0
45 | w: 1.0
46 | }
47 | type: TYPE_TEMPLATE
48 | id: "snapshot_open"
49 | layer: ""
50 | inherit_alpha: true
51 | alpha: 1.0
52 | template: "/dirtylarry/button.gui"
53 | template_node_child: false
54 | }
55 | nodes {
56 | position {
57 | x: 0.0
58 | y: 0.0
59 | z: 0.0
60 | w: 1.0
61 | }
62 | rotation {
63 | x: 0.0
64 | y: 0.0
65 | z: 0.0
66 | w: 1.0
67 | }
68 | scale {
69 | x: 1.0
70 | y: 1.0
71 | z: 1.0
72 | w: 1.0
73 | }
74 | size {
75 | x: 300.0
76 | y: 88.0
77 | z: 0.0
78 | w: 1.0
79 | }
80 | color {
81 | x: 1.0
82 | y: 1.0
83 | z: 1.0
84 | w: 1.0
85 | }
86 | type: TYPE_BOX
87 | blend_mode: BLEND_MODE_ALPHA
88 | texture: "button/button_normal"
89 | id: "snapshot_open/larrybutton"
90 | xanchor: XANCHOR_NONE
91 | yanchor: YANCHOR_NONE
92 | pivot: PIVOT_CENTER
93 | adjust_mode: ADJUST_MODE_FIT
94 | parent: "snapshot_open"
95 | layer: ""
96 | inherit_alpha: true
97 | slice9 {
98 | x: 32.0
99 | y: 32.0
100 | z: 32.0
101 | w: 32.0
102 | }
103 | clipping_mode: CLIPPING_MODE_NONE
104 | clipping_visible: true
105 | clipping_inverted: false
106 | alpha: 1.0
107 | overridden_fields: 38
108 | template_node_child: true
109 | size_mode: SIZE_MODE_MANUAL
110 | }
111 | nodes {
112 | position {
113 | x: 0.0
114 | y: 0.0
115 | z: 0.0
116 | w: 1.0
117 | }
118 | rotation {
119 | x: 0.0
120 | y: 0.0
121 | z: 0.0
122 | w: 1.0
123 | }
124 | scale {
125 | x: 1.0
126 | y: 1.0
127 | z: 1.0
128 | w: 1.0
129 | }
130 | size {
131 | x: 200.0
132 | y: 100.0
133 | z: 0.0
134 | w: 1.0
135 | }
136 | color {
137 | x: 1.0
138 | y: 1.0
139 | z: 1.0
140 | w: 1.0
141 | }
142 | type: TYPE_TEXT
143 | blend_mode: BLEND_MODE_ALPHA
144 | text: "Open Snapshot"
145 | font: "larryfont"
146 | id: "snapshot_open/larrylabel"
147 | xanchor: XANCHOR_NONE
148 | yanchor: YANCHOR_NONE
149 | pivot: PIVOT_CENTER
150 | outline {
151 | x: 0.0
152 | y: 0.0
153 | z: 0.0
154 | w: 1.0
155 | }
156 | shadow {
157 | x: 1.0
158 | y: 1.0
159 | z: 1.0
160 | w: 1.0
161 | }
162 | adjust_mode: ADJUST_MODE_FIT
163 | line_break: false
164 | parent: "snapshot_open/larrybutton"
165 | layer: ""
166 | inherit_alpha: true
167 | alpha: 1.0
168 | outline_alpha: 1.0
169 | shadow_alpha: 1.0
170 | overridden_fields: 8
171 | template_node_child: true
172 | text_leading: 1.0
173 | text_tracking: 0.0
174 | }
175 | nodes {
176 | position {
177 | x: 170.0
178 | y: 530.0
179 | z: 0.0
180 | w: 1.0
181 | }
182 | rotation {
183 | x: 0.0
184 | y: 0.0
185 | z: 0.0
186 | w: 1.0
187 | }
188 | scale {
189 | x: 1.0
190 | y: 1.0
191 | z: 1.0
192 | w: 1.0
193 | }
194 | size {
195 | x: 200.0
196 | y: 100.0
197 | z: 0.0
198 | w: 1.0
199 | }
200 | color {
201 | x: 1.0
202 | y: 1.0
203 | z: 1.0
204 | w: 1.0
205 | }
206 | type: TYPE_TEMPLATE
207 | id: "snapshot_get_data"
208 | layer: ""
209 | inherit_alpha: true
210 | alpha: 1.0
211 | template: "/dirtylarry/button.gui"
212 | template_node_child: false
213 | }
214 | nodes {
215 | position {
216 | x: 0.0
217 | y: 0.0
218 | z: 0.0
219 | w: 1.0
220 | }
221 | rotation {
222 | x: 0.0
223 | y: 0.0
224 | z: 0.0
225 | w: 1.0
226 | }
227 | scale {
228 | x: 1.0
229 | y: 1.0
230 | z: 1.0
231 | w: 1.0
232 | }
233 | size {
234 | x: 300.0
235 | y: 88.0
236 | z: 0.0
237 | w: 1.0
238 | }
239 | color {
240 | x: 1.0
241 | y: 1.0
242 | z: 1.0
243 | w: 1.0
244 | }
245 | type: TYPE_BOX
246 | blend_mode: BLEND_MODE_ALPHA
247 | texture: "button/button_normal"
248 | id: "snapshot_get_data/larrybutton"
249 | xanchor: XANCHOR_NONE
250 | yanchor: YANCHOR_NONE
251 | pivot: PIVOT_CENTER
252 | adjust_mode: ADJUST_MODE_FIT
253 | parent: "snapshot_get_data"
254 | layer: ""
255 | inherit_alpha: true
256 | slice9 {
257 | x: 32.0
258 | y: 32.0
259 | z: 32.0
260 | w: 32.0
261 | }
262 | clipping_mode: CLIPPING_MODE_NONE
263 | clipping_visible: true
264 | clipping_inverted: false
265 | alpha: 1.0
266 | overridden_fields: 38
267 | template_node_child: true
268 | size_mode: SIZE_MODE_MANUAL
269 | }
270 | nodes {
271 | position {
272 | x: 0.0
273 | y: 0.0
274 | z: 0.0
275 | w: 1.0
276 | }
277 | rotation {
278 | x: 0.0
279 | y: 0.0
280 | z: 0.0
281 | w: 1.0
282 | }
283 | scale {
284 | x: 1.0
285 | y: 1.0
286 | z: 1.0
287 | w: 1.0
288 | }
289 | size {
290 | x: 200.0
291 | y: 100.0
292 | z: 0.0
293 | w: 1.0
294 | }
295 | color {
296 | x: 1.0
297 | y: 1.0
298 | z: 1.0
299 | w: 1.0
300 | }
301 | type: TYPE_TEXT
302 | blend_mode: BLEND_MODE_ALPHA
303 | text: "Get Save Data"
304 | font: "larryfont"
305 | id: "snapshot_get_data/larrylabel"
306 | xanchor: XANCHOR_NONE
307 | yanchor: YANCHOR_NONE
308 | pivot: PIVOT_CENTER
309 | outline {
310 | x: 0.0
311 | y: 0.0
312 | z: 0.0
313 | w: 1.0
314 | }
315 | shadow {
316 | x: 1.0
317 | y: 1.0
318 | z: 1.0
319 | w: 1.0
320 | }
321 | adjust_mode: ADJUST_MODE_FIT
322 | line_break: false
323 | parent: "snapshot_get_data/larrybutton"
324 | layer: ""
325 | inherit_alpha: true
326 | alpha: 1.0
327 | outline_alpha: 1.0
328 | shadow_alpha: 1.0
329 | overridden_fields: 8
330 | template_node_child: true
331 | text_leading: 1.0
332 | text_tracking: 0.0
333 | }
334 | nodes {
335 | position {
336 | x: 170.0
337 | y: 410.0
338 | z: 0.0
339 | w: 1.0
340 | }
341 | rotation {
342 | x: 0.0
343 | y: 0.0
344 | z: 0.0
345 | w: 1.0
346 | }
347 | scale {
348 | x: 1.0
349 | y: 1.0
350 | z: 1.0
351 | w: 1.0
352 | }
353 | size {
354 | x: 200.0
355 | y: 100.0
356 | z: 0.0
357 | w: 1.0
358 | }
359 | color {
360 | x: 1.0
361 | y: 1.0
362 | z: 1.0
363 | w: 1.0
364 | }
365 | type: TYPE_TEMPLATE
366 | id: "snapshot_set_data"
367 | layer: ""
368 | inherit_alpha: true
369 | alpha: 1.0
370 | template: "/dirtylarry/button.gui"
371 | template_node_child: false
372 | }
373 | nodes {
374 | position {
375 | x: 0.0
376 | y: 0.0
377 | z: 0.0
378 | w: 1.0
379 | }
380 | rotation {
381 | x: 0.0
382 | y: 0.0
383 | z: 0.0
384 | w: 1.0
385 | }
386 | scale {
387 | x: 1.0
388 | y: 1.0
389 | z: 1.0
390 | w: 1.0
391 | }
392 | size {
393 | x: 300.0
394 | y: 88.0
395 | z: 0.0
396 | w: 1.0
397 | }
398 | color {
399 | x: 1.0
400 | y: 1.0
401 | z: 1.0
402 | w: 1.0
403 | }
404 | type: TYPE_BOX
405 | blend_mode: BLEND_MODE_ALPHA
406 | texture: "button/button_normal"
407 | id: "snapshot_set_data/larrybutton"
408 | xanchor: XANCHOR_NONE
409 | yanchor: YANCHOR_NONE
410 | pivot: PIVOT_CENTER
411 | adjust_mode: ADJUST_MODE_FIT
412 | parent: "snapshot_set_data"
413 | layer: ""
414 | inherit_alpha: true
415 | slice9 {
416 | x: 32.0
417 | y: 32.0
418 | z: 32.0
419 | w: 32.0
420 | }
421 | clipping_mode: CLIPPING_MODE_NONE
422 | clipping_visible: true
423 | clipping_inverted: false
424 | alpha: 1.0
425 | overridden_fields: 38
426 | template_node_child: true
427 | size_mode: SIZE_MODE_MANUAL
428 | }
429 | nodes {
430 | position {
431 | x: 0.0
432 | y: 0.0
433 | z: 0.0
434 | w: 1.0
435 | }
436 | rotation {
437 | x: 0.0
438 | y: 0.0
439 | z: 0.0
440 | w: 1.0
441 | }
442 | scale {
443 | x: 1.0
444 | y: 1.0
445 | z: 1.0
446 | w: 1.0
447 | }
448 | size {
449 | x: 200.0
450 | y: 100.0
451 | z: 0.0
452 | w: 1.0
453 | }
454 | color {
455 | x: 1.0
456 | y: 1.0
457 | z: 1.0
458 | w: 1.0
459 | }
460 | type: TYPE_TEXT
461 | blend_mode: BLEND_MODE_ALPHA
462 | text: "Set Save Data"
463 | font: "larryfont"
464 | id: "snapshot_set_data/larrylabel"
465 | xanchor: XANCHOR_NONE
466 | yanchor: YANCHOR_NONE
467 | pivot: PIVOT_CENTER
468 | outline {
469 | x: 0.0
470 | y: 0.0
471 | z: 0.0
472 | w: 1.0
473 | }
474 | shadow {
475 | x: 1.0
476 | y: 1.0
477 | z: 1.0
478 | w: 1.0
479 | }
480 | adjust_mode: ADJUST_MODE_FIT
481 | line_break: false
482 | parent: "snapshot_set_data/larrybutton"
483 | layer: ""
484 | inherit_alpha: true
485 | alpha: 1.0
486 | outline_alpha: 1.0
487 | shadow_alpha: 1.0
488 | overridden_fields: 8
489 | template_node_child: true
490 | text_leading: 1.0
491 | text_tracking: 0.0
492 | }
493 | nodes {
494 | position {
495 | x: 490.0
496 | y: 410.0
497 | z: 0.0
498 | w: 1.0
499 | }
500 | rotation {
501 | x: 0.0
502 | y: 0.0
503 | z: 0.0
504 | w: 1.0
505 | }
506 | scale {
507 | x: 1.0
508 | y: 1.0
509 | z: 1.0
510 | w: 1.0
511 | }
512 | size {
513 | x: 200.0
514 | y: 100.0
515 | z: 0.0
516 | w: 1.0
517 | }
518 | color {
519 | x: 1.0
520 | y: 1.0
521 | z: 1.0
522 | w: 1.0
523 | }
524 | type: TYPE_TEMPLATE
525 | id: "save_snapshot"
526 | layer: ""
527 | inherit_alpha: true
528 | alpha: 1.0
529 | template: "/dirtylarry/button.gui"
530 | template_node_child: false
531 | }
532 | nodes {
533 | position {
534 | x: 0.0
535 | y: 0.0
536 | z: 0.0
537 | w: 1.0
538 | }
539 | rotation {
540 | x: 0.0
541 | y: 0.0
542 | z: 0.0
543 | w: 1.0
544 | }
545 | scale {
546 | x: 1.0
547 | y: 1.0
548 | z: 1.0
549 | w: 1.0
550 | }
551 | size {
552 | x: 300.0
553 | y: 88.0
554 | z: 0.0
555 | w: 1.0
556 | }
557 | color {
558 | x: 1.0
559 | y: 1.0
560 | z: 1.0
561 | w: 1.0
562 | }
563 | type: TYPE_BOX
564 | blend_mode: BLEND_MODE_ALPHA
565 | texture: "button/button_normal"
566 | id: "save_snapshot/larrybutton"
567 | xanchor: XANCHOR_NONE
568 | yanchor: YANCHOR_NONE
569 | pivot: PIVOT_CENTER
570 | adjust_mode: ADJUST_MODE_FIT
571 | parent: "save_snapshot"
572 | layer: ""
573 | inherit_alpha: true
574 | slice9 {
575 | x: 32.0
576 | y: 32.0
577 | z: 32.0
578 | w: 32.0
579 | }
580 | clipping_mode: CLIPPING_MODE_NONE
581 | clipping_visible: true
582 | clipping_inverted: false
583 | alpha: 1.0
584 | overridden_fields: 38
585 | template_node_child: true
586 | size_mode: SIZE_MODE_MANUAL
587 | }
588 | nodes {
589 | position {
590 | x: 0.0
591 | y: 0.0
592 | z: 0.0
593 | w: 1.0
594 | }
595 | rotation {
596 | x: 0.0
597 | y: 0.0
598 | z: 0.0
599 | w: 1.0
600 | }
601 | scale {
602 | x: 0.9
603 | y: 0.9
604 | z: 1.0
605 | w: 1.0
606 | }
607 | size {
608 | x: 200.0
609 | y: 100.0
610 | z: 0.0
611 | w: 1.0
612 | }
613 | color {
614 | x: 1.0
615 | y: 1.0
616 | z: 1.0
617 | w: 1.0
618 | }
619 | type: TYPE_TEXT
620 | blend_mode: BLEND_MODE_ALPHA
621 | text: "Commit and Close\n"
622 | "Snapshot"
623 | font: "larryfont"
624 | id: "save_snapshot/larrylabel"
625 | xanchor: XANCHOR_NONE
626 | yanchor: YANCHOR_NONE
627 | pivot: PIVOT_CENTER
628 | outline {
629 | x: 0.0
630 | y: 0.0
631 | z: 0.0
632 | w: 1.0
633 | }
634 | shadow {
635 | x: 1.0
636 | y: 1.0
637 | z: 1.0
638 | w: 1.0
639 | }
640 | adjust_mode: ADJUST_MODE_FIT
641 | line_break: false
642 | parent: "save_snapshot/larrybutton"
643 | layer: ""
644 | inherit_alpha: true
645 | alpha: 1.0
646 | outline_alpha: 1.0
647 | shadow_alpha: 1.0
648 | overridden_fields: 3
649 | overridden_fields: 8
650 | template_node_child: true
651 | text_leading: 1.0
652 | text_tracking: 0.0
653 | }
654 | nodes {
655 | position {
656 | x: 490.0
657 | y: 290.0
658 | z: 0.0
659 | w: 1.0
660 | }
661 | rotation {
662 | x: 0.0
663 | y: 0.0
664 | z: 0.0
665 | w: 1.0
666 | }
667 | scale {
668 | x: 1.0
669 | y: 1.0
670 | z: 1.0
671 | w: 1.0
672 | }
673 | size {
674 | x: 200.0
675 | y: 100.0
676 | z: 0.0
677 | w: 1.0
678 | }
679 | color {
680 | x: 1.0
681 | y: 1.0
682 | z: 1.0
683 | w: 1.0
684 | }
685 | type: TYPE_TEMPLATE
686 | id: "show_snapshots"
687 | layer: ""
688 | inherit_alpha: true
689 | alpha: 1.0
690 | template: "/dirtylarry/button.gui"
691 | template_node_child: false
692 | }
693 | nodes {
694 | position {
695 | x: 0.0
696 | y: 0.0
697 | z: 0.0
698 | w: 1.0
699 | }
700 | rotation {
701 | x: 0.0
702 | y: 0.0
703 | z: 0.0
704 | w: 1.0
705 | }
706 | scale {
707 | x: 1.0
708 | y: 1.0
709 | z: 1.0
710 | w: 1.0
711 | }
712 | size {
713 | x: 300.0
714 | y: 88.0
715 | z: 0.0
716 | w: 1.0
717 | }
718 | color {
719 | x: 1.0
720 | y: 1.0
721 | z: 1.0
722 | w: 1.0
723 | }
724 | type: TYPE_BOX
725 | blend_mode: BLEND_MODE_ALPHA
726 | texture: "button/button_normal"
727 | id: "show_snapshots/larrybutton"
728 | xanchor: XANCHOR_NONE
729 | yanchor: YANCHOR_NONE
730 | pivot: PIVOT_CENTER
731 | adjust_mode: ADJUST_MODE_FIT
732 | parent: "show_snapshots"
733 | layer: ""
734 | inherit_alpha: true
735 | slice9 {
736 | x: 32.0
737 | y: 32.0
738 | z: 32.0
739 | w: 32.0
740 | }
741 | clipping_mode: CLIPPING_MODE_NONE
742 | clipping_visible: true
743 | clipping_inverted: false
744 | alpha: 1.0
745 | template_node_child: true
746 | size_mode: SIZE_MODE_MANUAL
747 | }
748 | nodes {
749 | position {
750 | x: 0.0
751 | y: 0.0
752 | z: 0.0
753 | w: 1.0
754 | }
755 | rotation {
756 | x: 0.0
757 | y: 0.0
758 | z: 0.0
759 | w: 1.0
760 | }
761 | scale {
762 | x: 1.0
763 | y: 1.0
764 | z: 1.0
765 | w: 1.0
766 | }
767 | size {
768 | x: 200.0
769 | y: 100.0
770 | z: 0.0
771 | w: 1.0
772 | }
773 | color {
774 | x: 1.0
775 | y: 1.0
776 | z: 1.0
777 | w: 1.0
778 | }
779 | type: TYPE_TEXT
780 | blend_mode: BLEND_MODE_ALPHA
781 | text: "Show Saves"
782 | font: "larryfont"
783 | id: "show_snapshots/larrylabel"
784 | xanchor: XANCHOR_NONE
785 | yanchor: YANCHOR_NONE
786 | pivot: PIVOT_CENTER
787 | outline {
788 | x: 0.0
789 | y: 0.0
790 | z: 0.0
791 | w: 1.0
792 | }
793 | shadow {
794 | x: 1.0
795 | y: 1.0
796 | z: 1.0
797 | w: 1.0
798 | }
799 | adjust_mode: ADJUST_MODE_FIT
800 | line_break: false
801 | parent: "show_snapshots/larrybutton"
802 | layer: ""
803 | inherit_alpha: true
804 | alpha: 1.0
805 | outline_alpha: 1.0
806 | shadow_alpha: 1.0
807 | overridden_fields: 8
808 | template_node_child: true
809 | text_leading: 1.0
810 | text_tracking: 0.0
811 | }
812 | nodes {
813 | position {
814 | x: 829.0
815 | y: 680.168
816 | z: 0.0
817 | w: 1.0
818 | }
819 | rotation {
820 | x: 0.0
821 | y: 0.0
822 | z: 0.0
823 | w: 1.0
824 | }
825 | scale {
826 | x: 1.0
827 | y: 1.0
828 | z: 1.0
829 | w: 1.0
830 | }
831 | size {
832 | x: 440.0
833 | y: 40.0
834 | z: 0.0
835 | w: 1.0
836 | }
837 | color {
838 | x: 1.0
839 | y: 1.0
840 | z: 1.0
841 | w: 1.0
842 | }
843 | type: TYPE_TEXT
844 | blend_mode: BLEND_MODE_ALPHA
845 | text: ""
846 | font: "larryfont"
847 | id: "snapshotOpened"
848 | xanchor: XANCHOR_NONE
849 | yanchor: YANCHOR_NONE
850 | pivot: PIVOT_W
851 | outline {
852 | x: 1.0
853 | y: 1.0
854 | z: 1.0
855 | w: 1.0
856 | }
857 | shadow {
858 | x: 1.0
859 | y: 1.0
860 | z: 1.0
861 | w: 1.0
862 | }
863 | adjust_mode: ADJUST_MODE_FIT
864 | line_break: true
865 | layer: ""
866 | inherit_alpha: true
867 | alpha: 1.0
868 | outline_alpha: 1.0
869 | shadow_alpha: 1.0
870 | template_node_child: false
871 | text_leading: 1.0
872 | text_tracking: 0.0
873 | }
874 | nodes {
875 | position {
876 | x: 170.0
877 | y: 290.0
878 | z: 0.0
879 | w: 1.0
880 | }
881 | rotation {
882 | x: 0.0
883 | y: 0.0
884 | z: 0.0
885 | w: 1.0
886 | }
887 | scale {
888 | x: 1.0
889 | y: 1.0
890 | z: 1.0
891 | w: 1.0
892 | }
893 | size {
894 | x: 200.0
895 | y: 100.0
896 | z: 0.0
897 | w: 1.0
898 | }
899 | color {
900 | x: 1.0
901 | y: 1.0
902 | z: 1.0
903 | w: 1.0
904 | }
905 | type: TYPE_TEMPLATE
906 | id: "snapshot_get_conflicting_data"
907 | layer: ""
908 | inherit_alpha: true
909 | alpha: 1.0
910 | template: "/dirtylarry/button.gui"
911 | template_node_child: false
912 | }
913 | nodes {
914 | position {
915 | x: 0.0
916 | y: 0.0
917 | z: 0.0
918 | w: 1.0
919 | }
920 | rotation {
921 | x: 0.0
922 | y: 0.0
923 | z: 0.0
924 | w: 1.0
925 | }
926 | scale {
927 | x: 1.0
928 | y: 1.0
929 | z: 1.0
930 | w: 1.0
931 | }
932 | size {
933 | x: 300.0
934 | y: 88.0
935 | z: 0.0
936 | w: 1.0
937 | }
938 | color {
939 | x: 1.0
940 | y: 1.0
941 | z: 1.0
942 | w: 1.0
943 | }
944 | type: TYPE_BOX
945 | blend_mode: BLEND_MODE_ALPHA
946 | texture: "button/button_normal"
947 | id: "snapshot_get_conflicting_data/larrybutton"
948 | xanchor: XANCHOR_NONE
949 | yanchor: YANCHOR_NONE
950 | pivot: PIVOT_CENTER
951 | adjust_mode: ADJUST_MODE_FIT
952 | parent: "snapshot_get_conflicting_data"
953 | layer: ""
954 | inherit_alpha: true
955 | slice9 {
956 | x: 32.0
957 | y: 32.0
958 | z: 32.0
959 | w: 32.0
960 | }
961 | clipping_mode: CLIPPING_MODE_NONE
962 | clipping_visible: true
963 | clipping_inverted: false
964 | alpha: 1.0
965 | overridden_fields: 38
966 | template_node_child: true
967 | size_mode: SIZE_MODE_MANUAL
968 | }
969 | nodes {
970 | position {
971 | x: 0.0
972 | y: 0.0
973 | z: 0.0
974 | w: 1.0
975 | }
976 | rotation {
977 | x: 0.0
978 | y: 0.0
979 | z: 0.0
980 | w: 1.0
981 | }
982 | scale {
983 | x: 1.0
984 | y: 1.0
985 | z: 1.0
986 | w: 1.0
987 | }
988 | size {
989 | x: 200.0
990 | y: 100.0
991 | z: 0.0
992 | w: 1.0
993 | }
994 | color {
995 | x: 1.0
996 | y: 1.0
997 | z: 1.0
998 | w: 1.0
999 | }
1000 | type: TYPE_TEXT
1001 | blend_mode: BLEND_MODE_ALPHA
1002 | text: "Get Conflicting\n"
1003 | "Save Data"
1004 | font: "larryfont"
1005 | id: "snapshot_get_conflicting_data/larrylabel"
1006 | xanchor: XANCHOR_NONE
1007 | yanchor: YANCHOR_NONE
1008 | pivot: PIVOT_CENTER
1009 | outline {
1010 | x: 0.0
1011 | y: 0.0
1012 | z: 0.0
1013 | w: 1.0
1014 | }
1015 | shadow {
1016 | x: 1.0
1017 | y: 1.0
1018 | z: 1.0
1019 | w: 1.0
1020 | }
1021 | adjust_mode: ADJUST_MODE_FIT
1022 | line_break: false
1023 | parent: "snapshot_get_conflicting_data/larrybutton"
1024 | layer: ""
1025 | inherit_alpha: true
1026 | alpha: 1.0
1027 | outline_alpha: 1.0
1028 | shadow_alpha: 1.0
1029 | overridden_fields: 8
1030 | template_node_child: true
1031 | text_leading: 1.0
1032 | text_tracking: 0.0
1033 | }
1034 | nodes {
1035 | position {
1036 | x: 170.0
1037 | y: 182.0
1038 | z: 0.0
1039 | w: 1.0
1040 | }
1041 | rotation {
1042 | x: 0.0
1043 | y: 0.0
1044 | z: 0.0
1045 | w: 1.0
1046 | }
1047 | scale {
1048 | x: 1.0
1049 | y: 1.0
1050 | z: 1.0
1051 | w: 1.0
1052 | }
1053 | size {
1054 | x: 200.0
1055 | y: 100.0
1056 | z: 0.0
1057 | w: 1.0
1058 | }
1059 | color {
1060 | x: 1.0
1061 | y: 1.0
1062 | z: 1.0
1063 | w: 1.0
1064 | }
1065 | type: TYPE_TEMPLATE
1066 | id: "snapshot_resolve_conflict"
1067 | layer: ""
1068 | inherit_alpha: true
1069 | alpha: 1.0
1070 | template: "/dirtylarry/button.gui"
1071 | template_node_child: false
1072 | }
1073 | nodes {
1074 | position {
1075 | x: 0.0
1076 | y: 0.0
1077 | z: 0.0
1078 | w: 1.0
1079 | }
1080 | rotation {
1081 | x: 0.0
1082 | y: 0.0
1083 | z: 0.0
1084 | w: 1.0
1085 | }
1086 | scale {
1087 | x: 1.0
1088 | y: 1.0
1089 | z: 1.0
1090 | w: 1.0
1091 | }
1092 | size {
1093 | x: 300.0
1094 | y: 88.0
1095 | z: 0.0
1096 | w: 1.0
1097 | }
1098 | color {
1099 | x: 1.0
1100 | y: 1.0
1101 | z: 1.0
1102 | w: 1.0
1103 | }
1104 | type: TYPE_BOX
1105 | blend_mode: BLEND_MODE_ALPHA
1106 | texture: "button/button_normal"
1107 | id: "snapshot_resolve_conflict/larrybutton"
1108 | xanchor: XANCHOR_NONE
1109 | yanchor: YANCHOR_NONE
1110 | pivot: PIVOT_CENTER
1111 | adjust_mode: ADJUST_MODE_FIT
1112 | parent: "snapshot_resolve_conflict"
1113 | layer: ""
1114 | inherit_alpha: true
1115 | slice9 {
1116 | x: 32.0
1117 | y: 32.0
1118 | z: 32.0
1119 | w: 32.0
1120 | }
1121 | clipping_mode: CLIPPING_MODE_NONE
1122 | clipping_visible: true
1123 | clipping_inverted: false
1124 | alpha: 1.0
1125 | overridden_fields: 38
1126 | template_node_child: true
1127 | size_mode: SIZE_MODE_MANUAL
1128 | }
1129 | nodes {
1130 | position {
1131 | x: 0.0
1132 | y: 0.0
1133 | z: 0.0
1134 | w: 1.0
1135 | }
1136 | rotation {
1137 | x: 0.0
1138 | y: 0.0
1139 | z: 0.0
1140 | w: 1.0
1141 | }
1142 | scale {
1143 | x: 0.8
1144 | y: 0.8
1145 | z: 1.0
1146 | w: 1.0
1147 | }
1148 | size {
1149 | x: 200.0
1150 | y: 100.0
1151 | z: 0.0
1152 | w: 1.0
1153 | }
1154 | color {
1155 | x: 1.0
1156 | y: 1.0
1157 | z: 1.0
1158 | w: 1.0
1159 | }
1160 | type: TYPE_TEXT
1161 | blend_mode: BLEND_MODE_ALPHA
1162 | text: "Resolve Conflict\n"
1163 | "SNAPSHOT_CURRENT"
1164 | font: "larryfont"
1165 | id: "snapshot_resolve_conflict/larrylabel"
1166 | xanchor: XANCHOR_NONE
1167 | yanchor: YANCHOR_NONE
1168 | pivot: PIVOT_CENTER
1169 | outline {
1170 | x: 0.0
1171 | y: 0.0
1172 | z: 0.0
1173 | w: 1.0
1174 | }
1175 | shadow {
1176 | x: 1.0
1177 | y: 1.0
1178 | z: 1.0
1179 | w: 1.0
1180 | }
1181 | adjust_mode: ADJUST_MODE_FIT
1182 | line_break: false
1183 | parent: "snapshot_resolve_conflict/larrybutton"
1184 | layer: ""
1185 | inherit_alpha: true
1186 | alpha: 1.0
1187 | outline_alpha: 1.0
1188 | shadow_alpha: 1.0
1189 | overridden_fields: 3
1190 | overridden_fields: 8
1191 | template_node_child: true
1192 | text_leading: 1.0
1193 | text_tracking: 0.0
1194 | }
1195 | nodes {
1196 | position {
1197 | x: 488.0
1198 | y: 182.0
1199 | z: 0.0
1200 | w: 1.0
1201 | }
1202 | rotation {
1203 | x: 0.0
1204 | y: 0.0
1205 | z: 0.0
1206 | w: 1.0
1207 | }
1208 | scale {
1209 | x: 1.0
1210 | y: 1.0
1211 | z: 1.0
1212 | w: 1.0
1213 | }
1214 | size {
1215 | x: 200.0
1216 | y: 100.0
1217 | z: 0.0
1218 | w: 1.0
1219 | }
1220 | color {
1221 | x: 1.0
1222 | y: 1.0
1223 | z: 1.0
1224 | w: 1.0
1225 | }
1226 | type: TYPE_TEMPLATE
1227 | id: "snapshot_resolve_conflict_conflicting"
1228 | layer: ""
1229 | inherit_alpha: true
1230 | alpha: 1.0
1231 | template: "/dirtylarry/button.gui"
1232 | template_node_child: false
1233 | }
1234 | nodes {
1235 | position {
1236 | x: 0.0
1237 | y: 0.0
1238 | z: 0.0
1239 | w: 1.0
1240 | }
1241 | rotation {
1242 | x: 0.0
1243 | y: 0.0
1244 | z: 0.0
1245 | w: 1.0
1246 | }
1247 | scale {
1248 | x: 1.0
1249 | y: 1.0
1250 | z: 1.0
1251 | w: 1.0
1252 | }
1253 | size {
1254 | x: 300.0
1255 | y: 88.0
1256 | z: 0.0
1257 | w: 1.0
1258 | }
1259 | color {
1260 | x: 1.0
1261 | y: 1.0
1262 | z: 1.0
1263 | w: 1.0
1264 | }
1265 | type: TYPE_BOX
1266 | blend_mode: BLEND_MODE_ALPHA
1267 | texture: "button/button_normal"
1268 | id: "snapshot_resolve_conflict_conflicting/larrybutton"
1269 | xanchor: XANCHOR_NONE
1270 | yanchor: YANCHOR_NONE
1271 | pivot: PIVOT_CENTER
1272 | adjust_mode: ADJUST_MODE_FIT
1273 | parent: "snapshot_resolve_conflict_conflicting"
1274 | layer: ""
1275 | inherit_alpha: true
1276 | slice9 {
1277 | x: 32.0
1278 | y: 32.0
1279 | z: 32.0
1280 | w: 32.0
1281 | }
1282 | clipping_mode: CLIPPING_MODE_NONE
1283 | clipping_visible: true
1284 | clipping_inverted: false
1285 | alpha: 1.0
1286 | overridden_fields: 38
1287 | template_node_child: true
1288 | size_mode: SIZE_MODE_MANUAL
1289 | }
1290 | nodes {
1291 | position {
1292 | x: 0.0
1293 | y: 0.0
1294 | z: 0.0
1295 | w: 1.0
1296 | }
1297 | rotation {
1298 | x: 0.0
1299 | y: 0.0
1300 | z: 0.0
1301 | w: 1.0
1302 | }
1303 | scale {
1304 | x: 0.7
1305 | y: 0.7
1306 | z: 1.0
1307 | w: 1.0
1308 | }
1309 | size {
1310 | x: 200.0
1311 | y: 100.0
1312 | z: 0.0
1313 | w: 1.0
1314 | }
1315 | color {
1316 | x: 1.0
1317 | y: 1.0
1318 | z: 1.0
1319 | w: 1.0
1320 | }
1321 | type: TYPE_TEXT
1322 | blend_mode: BLEND_MODE_ALPHA
1323 | text: "Resolve conflict\n"
1324 | "SNAPSHOT_CONFLICTING"
1325 | font: "larryfont"
1326 | id: "snapshot_resolve_conflict_conflicting/larrylabel"
1327 | xanchor: XANCHOR_NONE
1328 | yanchor: YANCHOR_NONE
1329 | pivot: PIVOT_CENTER
1330 | outline {
1331 | x: 0.0
1332 | y: 0.0
1333 | z: 0.0
1334 | w: 1.0
1335 | }
1336 | shadow {
1337 | x: 1.0
1338 | y: 1.0
1339 | z: 1.0
1340 | w: 1.0
1341 | }
1342 | adjust_mode: ADJUST_MODE_FIT
1343 | line_break: false
1344 | parent: "snapshot_resolve_conflict_conflicting/larrybutton"
1345 | layer: ""
1346 | inherit_alpha: true
1347 | alpha: 1.0
1348 | outline_alpha: 1.0
1349 | shadow_alpha: 1.0
1350 | overridden_fields: 3
1351 | overridden_fields: 8
1352 | template_node_child: true
1353 | text_leading: 1.0
1354 | text_tracking: 0.0
1355 | }
1356 | nodes {
1357 | position {
1358 | x: 170.0
1359 | y: 60.0
1360 | z: 0.0
1361 | w: 1.0
1362 | }
1363 | rotation {
1364 | x: 0.0
1365 | y: 0.0
1366 | z: 0.0
1367 | w: 1.0
1368 | }
1369 | scale {
1370 | x: 1.0
1371 | y: 1.0
1372 | z: 1.0
1373 | w: 1.0
1374 | }
1375 | size {
1376 | x: 200.0
1377 | y: 100.0
1378 | z: 0.0
1379 | w: 1.0
1380 | }
1381 | color {
1382 | x: 1.0
1383 | y: 1.0
1384 | z: 1.0
1385 | w: 1.0
1386 | }
1387 | type: TYPE_TEMPLATE
1388 | id: "back"
1389 | layer: ""
1390 | inherit_alpha: true
1391 | alpha: 1.0
1392 | template: "/dirtylarry/button.gui"
1393 | template_node_child: false
1394 | }
1395 | nodes {
1396 | position {
1397 | x: 0.0
1398 | y: 0.0
1399 | z: 0.0
1400 | w: 1.0
1401 | }
1402 | rotation {
1403 | x: 0.0
1404 | y: 0.0
1405 | z: 0.0
1406 | w: 1.0
1407 | }
1408 | scale {
1409 | x: 1.0
1410 | y: 1.0
1411 | z: 1.0
1412 | w: 1.0
1413 | }
1414 | size {
1415 | x: 300.0
1416 | y: 88.0
1417 | z: 0.0
1418 | w: 1.0
1419 | }
1420 | color {
1421 | x: 1.0
1422 | y: 1.0
1423 | z: 1.0
1424 | w: 1.0
1425 | }
1426 | type: TYPE_BOX
1427 | blend_mode: BLEND_MODE_ALPHA
1428 | texture: "button/button_normal"
1429 | id: "back/larrybutton"
1430 | xanchor: XANCHOR_NONE
1431 | yanchor: YANCHOR_NONE
1432 | pivot: PIVOT_CENTER
1433 | adjust_mode: ADJUST_MODE_FIT
1434 | parent: "back"
1435 | layer: ""
1436 | inherit_alpha: true
1437 | slice9 {
1438 | x: 32.0
1439 | y: 32.0
1440 | z: 32.0
1441 | w: 32.0
1442 | }
1443 | clipping_mode: CLIPPING_MODE_NONE
1444 | clipping_visible: true
1445 | clipping_inverted: false
1446 | alpha: 1.0
1447 | overridden_fields: 38
1448 | template_node_child: true
1449 | size_mode: SIZE_MODE_MANUAL
1450 | }
1451 | nodes {
1452 | position {
1453 | x: 0.0
1454 | y: 0.0
1455 | z: 0.0
1456 | w: 1.0
1457 | }
1458 | rotation {
1459 | x: 0.0
1460 | y: 0.0
1461 | z: 0.0
1462 | w: 1.0
1463 | }
1464 | scale {
1465 | x: 1.0
1466 | y: 1.0
1467 | z: 1.0
1468 | w: 1.0
1469 | }
1470 | size {
1471 | x: 200.0
1472 | y: 100.0
1473 | z: 0.0
1474 | w: 1.0
1475 | }
1476 | color {
1477 | x: 1.0
1478 | y: 1.0
1479 | z: 1.0
1480 | w: 1.0
1481 | }
1482 | type: TYPE_TEXT
1483 | blend_mode: BLEND_MODE_ALPHA
1484 | text: "BACK"
1485 | font: "larryfont"
1486 | id: "back/larrylabel"
1487 | xanchor: XANCHOR_NONE
1488 | yanchor: YANCHOR_NONE
1489 | pivot: PIVOT_CENTER
1490 | outline {
1491 | x: 0.0
1492 | y: 0.0
1493 | z: 0.0
1494 | w: 1.0
1495 | }
1496 | shadow {
1497 | x: 1.0
1498 | y: 1.0
1499 | z: 1.0
1500 | w: 1.0
1501 | }
1502 | adjust_mode: ADJUST_MODE_FIT
1503 | line_break: false
1504 | parent: "back/larrybutton"
1505 | layer: ""
1506 | inherit_alpha: true
1507 | alpha: 1.0
1508 | outline_alpha: 1.0
1509 | shadow_alpha: 1.0
1510 | overridden_fields: 8
1511 | template_node_child: true
1512 | text_leading: 1.0
1513 | text_tracking: 0.0
1514 | }
1515 | nodes {
1516 | position {
1517 | x: 829.0
1518 | y: 627.168
1519 | z: 0.0
1520 | w: 1.0
1521 | }
1522 | rotation {
1523 | x: 0.0
1524 | y: 0.0
1525 | z: 0.0
1526 | w: 1.0
1527 | }
1528 | scale {
1529 | x: 1.0
1530 | y: 1.0
1531 | z: 1.0
1532 | w: 1.0
1533 | }
1534 | size {
1535 | x: 440.0
1536 | y: 40.0
1537 | z: 0.0
1538 | w: 1.0
1539 | }
1540 | color {
1541 | x: 1.0
1542 | y: 1.0
1543 | z: 1.0
1544 | w: 1.0
1545 | }
1546 | type: TYPE_TEXT
1547 | blend_mode: BLEND_MODE_ALPHA
1548 | text: ""
1549 | font: "larryfont"
1550 | id: "snapshotConflict"
1551 | xanchor: XANCHOR_NONE
1552 | yanchor: YANCHOR_NONE
1553 | pivot: PIVOT_W
1554 | outline {
1555 | x: 1.0
1556 | y: 1.0
1557 | z: 1.0
1558 | w: 1.0
1559 | }
1560 | shadow {
1561 | x: 1.0
1562 | y: 1.0
1563 | z: 1.0
1564 | w: 1.0
1565 | }
1566 | adjust_mode: ADJUST_MODE_FIT
1567 | line_break: true
1568 | layer: ""
1569 | inherit_alpha: true
1570 | alpha: 1.0
1571 | outline_alpha: 1.0
1572 | shadow_alpha: 1.0
1573 | template_node_child: false
1574 | text_leading: 1.0
1575 | text_tracking: 0.0
1576 | }
1577 | material: "/builtins/materials/gui.material"
1578 | adjust_reference: ADJUST_REFERENCE_PARENT
1579 | max_nodes: 512
1580 |
--------------------------------------------------------------------------------
/gpgs/api/gpgs.script_api:
--------------------------------------------------------------------------------
1 | - name: gpgs
2 | type: table
3 | desc: Functions and constants for interacting with Google Play Game Services (GPGS) APIs
4 |
5 | members:
6 |
7 | #*****************************************************************************************************
8 |
9 | - name: is_supported
10 | type: function
11 | desc: Check if Google Play Services are available & ready on the device.
12 |
13 | returns:
14 | - name: is_supported
15 | type: boolean
16 | desc: Status of Google Play Services on the device.
17 |
18 | examples:
19 | - desc: |-
20 | ```lua
21 | if gpgs then
22 | local is_supported = gpgs.is_supported()
23 | end
24 | ```
25 |
26 | #*****************************************************************************************************
27 |
28 | - name: login
29 | type: function
30 | desc: Login to GPGS using a button.
31 |
32 | examples:
33 | - desc: |-
34 | Log in to GPGS using a button:
35 | ```lua
36 | if gpgs then
37 | gpgs.login()
38 | end
39 | ```
40 |
41 | #*****************************************************************************************************
42 |
43 | - name: silent_login
44 | type: function
45 | desc: Silent login to GPGS.
46 |
47 | This function is trying to retrieve the currently signed-in player’s account.
48 |
49 | examples:
50 | - desc: |-
51 | ```lua
52 | function init(self)
53 | if gpgs then
54 | gpgs.silent_login()
55 | end
56 | end
57 | ```
58 |
59 | #*****************************************************************************************************
60 |
61 | - name: get_display_name
62 | type: function
63 | desc: Get the current GPGS player display name.
64 |
65 | returns:
66 | - name: name
67 | type: string
68 | desc: The player's display name.
69 |
70 | examples:
71 | - desc: |-
72 | ```lua
73 | if gpgs then
74 | local name = gpgs.get_display_name()
75 | end
76 | ```
77 |
78 | #*****************************************************************************************************
79 |
80 | - name: get_id
81 | type: function
82 | desc: Get the current GPGS player id.
83 |
84 | returns:
85 | - name: id
86 | type: string
87 | desc: The player ID.
88 |
89 | examples:
90 | - desc: |-
91 | ```lua
92 | if gpgs then
93 | local id = gpgs.get_id()
94 | end
95 | ```
96 |
97 | #*****************************************************************************************************
98 |
99 | - name: get_server_auth_code
100 | type: function
101 | desc: Returns a one-time server auth code to send to your web server which can be exchanged for access token
102 |
103 | Token can be retrieved only if `gpgs.request_server_auth_code` set to 1 and `gpgs.client` is set.
104 |
105 | returns:
106 | - name: server_auth_code
107 | type: string
108 | desc: The server auth code for logged in account. Can be nil if operation is not completed yet.
109 |
110 | Auth token is avaliable after receiving message with id `gpgs.MSG_GET_SERVER_TOKEN`
111 | in callback set via `gpgs.set_callback`.
112 |
113 | examples:
114 | - desc: |-
115 | ```lua
116 | if gpgs then
117 | local server_auth_code = gpgs.get_server_auth_code()
118 | end
119 | ```
120 |
121 | #*****************************************************************************************************
122 |
123 | - name: is_logged_in
124 | type: function
125 | desc: Check if a user is logged in currently.
126 |
127 | returns:
128 | - name: is_loggedin
129 | type: boolean
130 | desc: Current login state.
131 |
132 | examples:
133 | - desc: |-
134 | ```lua
135 | if gpgs then
136 | local is_loggedin = gpgs.is_logged_in()
137 | end
138 | ```
139 |
140 | #*****************************************************************************************************
141 |
142 | - name: set_callback
143 | type: function
144 | desc: Set callback for receiving messages from GPGS.
145 |
146 | parameters:
147 | - name: callback
148 | type: function
149 | desc: A callback taking the following parameters
150 | parameters:
151 | - name: self
152 | type: object
153 | desc: The calling script
154 |
155 | - name: message_id
156 | type: number
157 | desc: An message_id can be one of the predefined constants below
158 |
159 | - `gpgs.MSG_SIGN_IN`
160 |
161 | - `gpgs.MSG_SILENT_SIGN_IN`
162 |
163 | - `gpgs.MSG_SHOW_SNAPSHOTS`
164 |
165 | - `gpgs.MSG_LOAD_SNAPSHOT`
166 |
167 | - `gpgs.MSG_SAVE_SNAPSHOT`
168 |
169 |
170 | - name: message
171 | type: table
172 | desc: Contains information that depends on message_id.
173 | members:
174 | - name: status
175 | type: number
176 | desc: Status of the current operation. It can be one of the predefined constants below
177 |
178 | - `gpgs.STATUS_SUCCESS`
179 |
180 | - `gpgs.STATUS_FAILED`
181 |
182 | - `gpgs.STATUS_CREATE_NEW_SAVE`
183 |
184 | - `gpgs.STATUS_CONFLICT`
185 |
186 | - name: error
187 | type: string
188 | optional: true
189 | desc: The error message. Available only if `status` is `gpgs.STATUS_FAILED`.
190 |
191 | - name: error_status
192 | type: number
193 | optional: true
194 | desc: The error code. Available only if `status` is `gpgs.STATUS_FAILED` and GPGS provide this code.
195 | It can be one of the predefined constants below
196 |
197 | - `gpgs.ERROR_STATUS_SNAPSHOT_COMMIT_FAILED`
198 |
199 | - `gpgs.ERROR_STATUS_SNAPSHOT_CONFLICT_MISSING`
200 |
201 | - `gpgs.ERROR_STATUS_SNAPSHOT_CONTENTS_UNAVAILABLE`
202 |
203 | - `gpgs.ERROR_STATUS_SNAPSHOT_CREATION_FAILED`
204 |
205 | - `gpgs.ERROR_STATUS_SNAPSHOT_FOLDER_UNAVAILABLE`
206 |
207 | - `gpgs.ERROR_STATUS_SNAPSHOT_NOT_FOUND`
208 |
209 | Or it can be ApiException.getStatusCode() (if ApiException was thrown)
210 |
211 | - name: metadata
212 | type: table
213 | optional: true
214 | desc: Metadata of the loaded save. Available only if `message_id` is `gpgs.MSG_LOAD_SNAPSHOT`.
215 |
216 | - name: conflictId
217 | type: string
218 | optional: true
219 | desc: The conflict id. Available only if `status` is `gpgs.STATUS_CONFLICT`.
220 |
221 | - name: conflictMetadata
222 | type: table
223 | optional: true
224 | desc: The conflicting metadata. Available only if `status` is `gpgs.STATUS_CONFLICT`.
225 |
226 | examples:
227 | - desc: |-
228 | ```lua
229 | function callback(self, message_id, message)
230 | if message_id == gpgs.MSG_SIGN_IN or message_id == gpgs.MSG_SILENT_SIGN_IN then
231 | if message.status == gpgs.STATUS_SUCCESS then
232 | -- do something after login
233 | end
234 | elseif message_id == gpgs.MSG_LOAD_SNAPSHOT then
235 | -- do something when a save was loaded
236 | end
237 | end
238 |
239 | function init(self)
240 | gpgs.set_callback(callback)
241 | end
242 |
243 | function init(self)
244 | gpgs.set_callback(nil) -- remove callback
245 | end
246 | ```
247 |
248 | #*****************************************************************************************************
249 |
250 | - name: snapshot_display_saves
251 | type: function
252 | desc: Provides a default saved games selection user interface.
253 |
254 | parameters:
255 | - name: popupTitle
256 | type: string
257 | optional: true
258 | desc: The title to display in the action bar. By default "Game Saves".
259 |
260 | - name: allowAddButton
261 | type: boolean
262 | optional: true
263 | desc: Whether or not to display a "create new snapshot" option in the selection UI. By default `true`.
264 |
265 | - name: allowDelete
266 | type: boolean
267 | optional: true
268 | desc: Whether or not to provide a delete overflow menu option for each snapshot in the selection UI. By default `true`.
269 |
270 | - name: maxNumberOfSavedGamesToShow
271 | type: number
272 | optional: true
273 | desc: The maximum number of snapshots to display in the UI. By default 5.
274 |
275 | examples:
276 | - desc: |-
277 | ```lua
278 | if gpgs then
279 | gpgs.snapshot_display_saves("Choose the save of the game", false, true, 10)
280 | end
281 | ```
282 |
283 | #*****************************************************************************************************
284 |
285 | - name: snapshot_open
286 | type: function
287 | desc: Opens a snapshot with the given `saveName`. If `createIfNotFound` is set to `true`, the specified snapshot will be created if it does not already exist.
288 |
289 | parameters:
290 | - name: saveName
291 | type: string
292 | desc: The name of the snapshot file to open. Must be between 1 and 100 non-URL-reserved characters (a-z, A-Z, 0-9, or the symbols "-", ".", "_", or "~").
293 |
294 | - name: createIfNotFound
295 | type: boolean
296 | optional: true
297 | desc: If `true`, the snapshot will be created if one cannot be found.
298 |
299 | - name: conflictPolicy
300 | type: number
301 | optional: true
302 | desc: The conflict resolution policy to use for this snapshot that can be one of the predefined constants below
303 |
304 | - `gpgs.RESOLUTION_POLICY_MANUAL`
305 |
306 | - `gpgs.RESOLUTION_POLICY_LONGEST_PLAYTIME`
307 |
308 | - `gpgs.RESOLUTION_POLICY_LAST_KNOWN_GOOD`
309 |
310 | - `gpgs.RESOLUTION_POLICY_MOST_RECENTLY_MODIFIED`
311 |
312 | - `gpgs.RESOLUTION_POLICY_HIGHEST_PROGRESS`
313 |
314 |
315 | Default value is `gpgs.RESOLUTION_POLICY_LAST_KNOWN_GOOD`
316 |
317 | examples:
318 | - desc: |-
319 | ```lua
320 | if gpgs then
321 | gpgs.snapshot_open("my_save_1", true, gpgs.RESOLUTION_POLICY_LONGEST_PLAYTIME)
322 | end
323 | ```
324 |
325 | #*****************************************************************************************************
326 |
327 | - name: snapshot_commit_and_close
328 | type: function
329 | desc: Save the currently opened save on the server and close it.
330 |
331 | parameters:
332 | - name: metadata
333 | type: table
334 | optional: true
335 | desc: A table with metadata for a save. It contains the fields below
336 | members:
337 | - name: playedTime
338 | type: number
339 | optional: true
340 | desc: The new played time to set for the snapshot in ms.
341 |
342 | - name: progressValue
343 | type: number
344 | optional: true
345 | desc: The new progress value to set for the snapshot.
346 |
347 | - name: description
348 | type: string
349 | optional: true
350 | desc: The new description to set for the snapshot.
351 |
352 | - name: coverImage
353 | type: object
354 | optional: true
355 | desc: The new cover image to set for the snapshot in `png`.
356 |
357 |
358 | examples:
359 | - desc: |-
360 | ```lua
361 | if gpgs then
362 | local png_img, w, h = screenshot.png()
363 | gpgs.snapshot_commit_and_close({
364 | coverImage = png_img,
365 | description = "LEVEL 31, CAVE",
366 | playedTime = 12345667,
367 | progressValue = 657
368 | })
369 | end
370 | ```
371 |
372 | #*****************************************************************************************************
373 |
374 | - name: snapshot_get_data
375 | type: function
376 | desc: Returns the currently opened snapshot data.
377 |
378 | returns:
379 | - name: bytes
380 | type: string
381 | desc: The byte array data of the currently opened snapshot. `nil` if something goes wrong.
382 |
383 | - name: error_message
384 | type: string
385 | desc: An error message if something goes wrong.
386 |
387 | examples:
388 | - desc: |-
389 | ```lua
390 | if gpgs then
391 | local bytes, error_message = gpgs.snapshot_get_data()
392 | if not bytes then
393 | print("snapshot_get_data ERROR:", error_message)
394 | else
395 | print("snapshot_get_data",bytes)
396 | -- Do something with your data
397 | end
398 | end
399 | ```
400 |
401 | #*****************************************************************************************************
402 |
403 | - name: snapshot_set_data
404 | type: function
405 | desc: Sets the data for the currently opened snapshot.
406 |
407 | parameters:
408 | - name: data
409 | type: string
410 | desc: The data to set.
411 |
412 | returns:
413 | - name: success
414 | type: boolean
415 | desc: True if data was set for the currently opened snapshot.
416 |
417 | - name: error_message
418 | type: string
419 | desc: An error message if something goes wrong.
420 |
421 | examples:
422 | - desc: |-
423 | ```lua
424 | if gpgs then
425 | local success, error_message = gpgs.snapshot_set_data(my_data)
426 | if not success then
427 | print("snapshot_set_data ERROR:", error_message)
428 | end
429 | end
430 | ```
431 |
432 | #*****************************************************************************************************
433 |
434 | - name: snapshot_is_opened
435 | type: function
436 | desc: Check if a snapshot was opened.
437 |
438 | returns:
439 | - name: is_opened
440 | type: boolean
441 | desc: A current snapshot state.
442 |
443 | examples:
444 | - desc: |-
445 | ```lua
446 | if gpgs then
447 | local is_opened = gpgs.snapshot_is_opened()
448 | end
449 | ```
450 |
451 | #*****************************************************************************************************
452 |
453 | - name: snapshot_get_max_image_size
454 | type: function
455 | desc: Returns the maximum data size per snapshot cover image in bytes.
456 |
457 | returns:
458 | - name: image_size
459 | type: number
460 | desc: The maximum data size per snapshot cover image in bytes.
461 |
462 | examples:
463 | - desc: |-
464 | ```lua
465 | if gpgs then
466 | local image_size = gpgs.snapshot_get_max_image_size()
467 | end
468 | ```
469 |
470 | #*****************************************************************************************************
471 |
472 | - name: snapshot_get_max_save_size
473 | type: function
474 | desc: Returns the maximum data size per snapshot in bytes.
475 |
476 | returns:
477 | - name: data_size
478 | type: number
479 | desc: The maximum data size per snapshot in bytes.
480 |
481 | examples:
482 | - desc: |-
483 | ```lua
484 | if gpgs then
485 | local data_size = gpgs.snapshot_get_max_save_size()
486 | end
487 | ```
488 |
489 | #*****************************************************************************************************
490 |
491 | - name: snapshot_get_conflicting_data
492 | type: function
493 | desc: Returns the conflicting snapshot data.
494 |
495 | returns:
496 | - name: bytes
497 | type: string
498 | desc: The byte array data of the conflicting snapshot. `nil` if something goes wrong.
499 |
500 | - name: error_message
501 | type: boolean
502 | desc: An error message if something goes wrong.
503 |
504 | examples:
505 | - desc: |-
506 | ```lua
507 | if gpgs then
508 | local bytes, error_message = gpgs.snapshot_get_conflicting_data()
509 | if not bytes then
510 | print("snapshot_get_conflicting_data ERROR:", error_message)
511 | else
512 | print("snapshot_get_conflicting_data:",bytes)
513 | -- Do something with conflicting data data
514 | end
515 | end
516 | ```
517 |
518 | #*****************************************************************************************************
519 |
520 | - name: snapshot_resolve_conflict
521 | type: function
522 | desc: Resolves a conflict using the data from the provided snapshot.
523 |
524 | parameters:
525 | - name: conflictId
526 | type: string
527 | desc: The conflict id that you want to resolve. Provided in `message` table with `STATUS_CONFLICT` message type.
528 |
529 | - name: snapshotId
530 | type: number
531 | desc: Type of the snapshot you want to use for conflict solving that can be one of the predefined constants below
532 |
533 | - `gpgs.SNAPSHOT_CURRENT`
534 |
535 | - `gpgs.SNAPSHOT_CONFLICTING`
536 |
537 | examples:
538 | - desc: |-
539 | ```lua
540 | if gpgs then
541 | gpgs.snapshot_resolve_conflict(self.conflictId, gpgs.SNAPSHOT_CONFLICTING)
542 | end
543 | ```
544 | #*****************************************************************************************************
545 |
546 | - name: leaderboard_submit_score
547 | type: function
548 | desc: Submit a score to a leaderboard for the currently signed-in player.
549 |
550 | parameters:
551 | - name: leaderboardId
552 | type: string
553 |
554 | - name: score
555 | type: number
556 |
557 | #*****************************************************************************************************
558 |
559 | - name: leaderboard_get_top_scores
560 | type: function
561 | desc: Asynchronously gets the top page of scores for a leaderboard.
562 |
563 | parameters:
564 | - name: leaderboardId
565 | type: string
566 |
567 | - name: time_span
568 | type: number
569 | desc: One of the gpgs.TIME_SPAN_ constants
570 |
571 | - name: collection
572 | type: number
573 | desc: One of the gpgs.COLLECTION_ constants
574 |
575 | - name: max_results
576 | type: number
577 | desc: Between 1-25
578 |
579 | #*****************************************************************************************************
580 |
581 | - name: leaderboard_get_player_centered_scores
582 | type: function
583 | desc: Asynchronously gets a player-centered page of scores for a leaderboard.
584 |
585 | parameters:
586 | - name: leaderboardId
587 | type: string
588 |
589 | - name: time_span
590 | type: number
591 | desc: One of the gpgs.TIME_SPAN_ constants
592 |
593 | - name: collection
594 | type: number
595 | desc: One of the gpgs.COLLECTION_ constants
596 |
597 | - name: max_results
598 | type: number
599 | desc: Between 1-25
600 |
601 | - name: force_reload
602 | type: boolean
603 | desc: If true, this call will clear any locally cached data and attempt to fetch the latest data from the server
604 |
605 | #*****************************************************************************************************
606 |
607 | - name: leaderboard_show
608 | type: function
609 | desc: Show a leaderboard for a game specified by a leaderboardId.
610 |
611 | parameters:
612 | - name: leaderboardId
613 | type: string
614 |
615 | - name: time_span
616 | type: number
617 | desc: One of the gpgs.TIME_SPAN_ constants
618 |
619 | - name: collection
620 | type: number
621 | desc: One of the gpgs.COLLECTION_ constants
622 |
623 | #*****************************************************************************************************
624 |
625 | - name: leaderboard_list
626 | type: function
627 | desc: Show the list of leaderboards.
628 |
629 | #*****************************************************************************************************
630 | - name: leaderboard_get_player_score
631 | type: function
632 | desc: Asynchronously gets a player-centered page of scores for a leaderboard.
633 |
634 | parameters:
635 | - name: leaderboardId
636 | type: string
637 |
638 | - name: time_span
639 | type: number
640 | desc: One of the gpgs.TIME_SPAN_ constants
641 |
642 | - name: collection
643 | type: number
644 | desc: One of the gpgs.COLLECTION_ constants
645 |
646 | #*****************************************************************************************************
647 |
648 | - name: achievement_reveal
649 | type: function
650 | desc: Reveals a hidden achievement to the current player.
651 |
652 | parameters:
653 | - name: achievementId
654 | type: string
655 | desc: Achievement id (from GP console)
656 |
657 | #*****************************************************************************************************
658 | - name: achievement_unlock
659 | type: function
660 | desc: Unlocks an achievement for the current player.
661 |
662 | parameters:
663 | - name: achievementId
664 | type: string
665 | desc: Achievement id (from GP console)
666 |
667 | #*****************************************************************************************************
668 | - name: achievement_set
669 | type: function
670 | desc: Sets an achievement to have at least the given number of steps completed.
671 |
672 | parameters:
673 | - name: achievementId
674 | type: string
675 | desc: Achievement id (from GP console)
676 |
677 | - name: steps
678 | type: number
679 | desc: The number of steps to set the achievement to. Must be greater than 0.
680 |
681 | #*****************************************************************************************************
682 | - name: achievement_increment
683 | type: function
684 | desc: Increments an achievement by the given number of steps.
685 |
686 | parameters:
687 | - name: achievementId
688 | type: string
689 | desc: Achievement id (from GP console)
690 |
691 | - name: steps
692 | type: number
693 | desc: The number of steps to increment by. Must be greater than 0.
694 |
695 | #*****************************************************************************************************
696 | - name: achievement_show
697 | type: function
698 | desc: Show achivements
699 |
700 | #*****************************************************************************************************
701 | - name: achievement_get
702 | type: function
703 | desc: Get information about all achievement's state asynchronously. Result return to callback previously set by
704 | `gpgs.set_callback` with `message_id == gpgs.MSG_ACHIEVEMENTS`. Result is array of tables which contain
705 | following fields
706 |
707 | - `id` - achievement id (from GP console)
708 |
709 | - `name` - achievement name
710 |
711 | - `description` - achievement description
712 |
713 | - `xp` - how much experience points will be added when achievement will be unlocked
714 |
715 | - `steps` - current step of incremental achievement
716 |
717 | - `total_steps` - total amount of steps of incremental achievement
718 |
719 | - `unlocked` - set to `true` if achievement is unlocked. Otherwise field is missed.
720 |
721 | - `hidden` - set to `true if achievement is hidden. Otherwise field is missed.
722 |
723 | - `revealed` - set to `true` if achievement is revealed. Otherwise field is missed.
724 |
725 |
726 | #*****************************************************************************************************
727 | - name: event_increment
728 | type: function
729 | desc: Increments an event specified by `eventId` by the given number of steps
730 |
731 | parameters:
732 | - name: eventId
733 | type: string
734 | desc: Event id (from GP console)
735 |
736 | - name: amount
737 | type: number
738 | desc: The amount increment by. Must be greater than or equal to 0
739 |
740 | #*****************************************************************************************************
741 | - name: event_get
742 | type: function
743 | desc: Get information about all events asynchronously. Result returns to callback previously set by
744 | `gpgs.set_callback` with `message_id == gpgs.MSG_GET_EVENTS`. Result is array of tables which contain
745 | following fields
746 |
747 | - `id` - event id
748 |
749 | - `formatted_value` - sum of all increments have been made to this event
750 |
751 | - `value` - the number of increments this user has made to this event
752 |
753 | - `description` - event's description
754 |
755 | - `image` - URI that can be used to load the event's image icon
756 |
757 | - `name` - event's name
758 |
759 | - `visible` - whether the event should be displayed to the user in any event related UIs
760 |
761 |
762 | #*****************************************************************************************************
763 |
764 | - name: RESOLUTION_POLICY_MANUAL
765 | type: number
766 | desc: Official [GPGS documentation](https://developers.google.com/android/reference/com/google/android/gms/games/SnapshotsClient.html#RESOLUTION_POLICY_MANUAL) for this constant
767 |
768 | - name: RESOLUTION_POLICY_LONGEST_PLAYTIME
769 | type: number
770 | desc: Official [GPGS documentation](https://developers.google.com/android/reference/com/google/android/gms/games/SnapshotsClient.html#RESOLUTION_POLICY_LONGEST_PLAYTIME) for this constant
771 |
772 | - name: RESOLUTION_POLICY_LAST_KNOWN_GOOD
773 | type: number
774 | desc: Official [GPGS documentation](https://developers.google.com/android/reference/com/google/android/gms/games/SnapshotsClient.html#RESOLUTION_POLICY_LAST_KNOWN_GOOD) for this constant
775 |
776 | - name: RESOLUTION_POLICY_MOST_RECENTLY_MODIFIED
777 | type: number
778 | desc: Official [GPGS documentation](https://developers.google.com/android/reference/com/google/android/gms/games/SnapshotsClient.html#RESOLUTION_POLICY_MOST_RECENTLY_MODIFIED) for this constant
779 |
780 | - name: RESOLUTION_POLICY_HIGHEST_PROGRESS
781 | type: number
782 | desc: Official [GPGS documentation](https://developers.google.com/android/reference/com/google/android/gms/games/SnapshotsClient.html#RESOLUTION_POLICY_HIGHEST_PROGRESS) for this constant
783 |
784 | - name: MSG_SIGN_IN
785 | type: number
786 | desc: The message type that GPGS sends when finishing the asynchronous operation
787 | after calling `gpgs.login()`
788 |
789 | - name: MSG_SILENT_SIGN_IN
790 | type: number
791 | desc: The message type that GPGS sends when finishing the asynchronous operation
792 | after calling `gpgs.silent_login()`
793 |
794 | - name: MSG_SHOW_SNAPSHOTS
795 | type: number
796 | desc: The message type that GPGS sends when finishing the asynchronous operation
797 | after calling `gpgs.snapshot_display_saves()`
798 |
799 | - name: MSG_LOAD_SNAPSHOT
800 | type: number
801 | desc: The message type that GPGS sends when finishing the asynchronous operation
802 | after calling `gpgs.snapshot_open()`
803 |
804 | - name: MSG_SAVE_SNAPSHOT
805 | type: number
806 | desc: The message type that GPGS sends when finishing the asynchronous operation
807 | after calling `gpgs.snapshot_commit_and_close()`
808 |
809 | - name: MSG_GET_SERVER_TOKEN
810 | type: number
811 | desc: The message type that GPGS sends when finishing the asynchronous operation
812 | of server token retrieval
813 |
814 | - name: STATUS_SUCCESS
815 | type: number
816 | desc: An operation success.
817 |
818 | - name: STATUS_FAILED
819 | type: number
820 | desc: An operation failed. Check the error field in the massage table.
821 |
822 | - name: STATUS_CREATE_NEW_SAVE
823 | type: number
824 | desc: A user wants to create new save as a result of `gpgs.snapshot_display_saves()` method.
825 | Turn off this button in `gpgs.snapshot_display_saves()` if you don't want to have this functionality.
826 |
827 | - name: STATUS_CONFLICT
828 | type: number
829 | desc: The result of the calling `gpgs.snapshot_open()` or 'gpgs.snapshot_resolve_conflict()' is a conflict.
830 | You need to make decision on how to solve this conflict using 'gpgs.snapshot_resolve_conflict()'.
831 |
832 | - name: SNAPSHOT_CURRENT
833 | type: number
834 | desc: The second parameter for 'gpgs.snapshot_resolve_conflict()' method, which means that you want to choose
835 | the current snapshot as a snapshot for conflict solving.
836 |
837 | - name: SNAPSHOT_CONFLICTING
838 | type: number
839 | desc: The second parameter for 'gpgs.snapshot_resolve_conflict()' method, which means that you want to choose
840 | the conflicting snapshot as a snapshot for conflict solving.
841 |
842 | - name: ERROR_STATUS_SNAPSHOT_NOT_FOUND
843 | type: number
844 | desc: This constant is used in `message.error_status` table when `MSG_LOAD_SNAPSHOT` is `STATUS_FAILED`.
845 | [Official GPGS documentation](https://developers.google.com/android/reference/com/google/android/gms/games/GamesStatusCodes.html#STATUS_SNAPSHOT_NOT_FOUND) for this constant
846 |
847 | - name: ERROR_STATUS_SNAPSHOT_CREATION_FAILED
848 | type: number
849 | desc: This constant is used in `message.error_status` table when `MSG_LOAD_SNAPSHOT` is `STATUS_FAILED`.
850 | [Official GPGS documentation](https://developers.google.com/android/reference/com/google/android/gms/games/GamesStatusCodes.html#STATUS_SNAPSHOT_CREATION_FAILED) for this constant
851 |
852 | - name: ERROR_STATUS_SNAPSHOT_CONTENTS_UNAVAILABLE
853 | type: number
854 | desc: This constant is used in `message.error_status` table when `MSG_LOAD_SNAPSHOT` is `STATUS_FAILED`.
855 | [Official GPGS documentation](https://developers.google.com/android/reference/com/google/android/gms/games/GamesStatusCodes.html#STATUS_SNAPSHOT_CONTENTS_UNAVAILABLE) for this constant
856 |
857 | - name: ERROR_STATUS_SNAPSHOT_COMMIT_FAILED
858 | type: number
859 | desc: This constant is used in `message.error_status` table when `MSG_LOAD_SNAPSHOT` is `STATUS_FAILED`.
860 | [Official GPGS documentation](https://developers.google.com/android/reference/com/google/android/gms/games/GamesStatusCodes.html#STATUS_SNAPSHOT_COMMIT_FAILED) for this constant
861 |
862 | - name: ERROR_STATUS_SNAPSHOT_FOLDER_UNAVAILABLE
863 | type: number
864 | desc: This constant is used in `message.error_status` table when `MSG_LOAD_SNAPSHOT` is `STATUS_FAILED`.
865 | [Official GPGS documentation](https://developers.google.com/android/reference/com/google/android/gms/games/GamesStatusCodes.html#STATUS_SNAPSHOT_FOLDER_UNAVAILABLE) for this constant
866 |
867 | - name: ERROR_STATUS_SNAPSHOT_CONFLICT_MISSING
868 | type: number
869 | desc: This constant is used in `message.error_status` table when `MSG_LOAD_SNAPSHOT` is `STATUS_FAILED`.
870 | [Official GPGS documentation](https://developers.google.com/android/reference/com/google/android/gms/games/GamesStatusCodes.html#STATUS_SNAPSHOT_CONFLICT_MISSING) for this constant
871 |
--------------------------------------------------------------------------------
/gpgs/src/java/com/defold/gpgs/GpgsJNI.java:
--------------------------------------------------------------------------------
1 | package com.defold.gpgs;
2 |
3 | import android.app.Activity;
4 | import android.content.Intent;
5 |
6 | import android.graphics.Bitmap;
7 | import android.graphics.BitmapFactory;
8 | import android.util.Log;
9 |
10 | import com.google.android.gms.games.PlayGames;
11 | import com.google.android.gms.games.GamesSignInClient;
12 | import com.google.android.gms.common.api.ApiException;
13 | import com.google.android.gms.common.ConnectionResult;
14 | import com.google.android.gms.common.GoogleApiAvailability;
15 | import com.google.android.gms.games.Player;
16 | import com.google.android.gms.games.PlayersClient;
17 |
18 | import com.google.android.gms.tasks.OnCompleteListener;
19 | import com.google.android.gms.tasks.OnFailureListener;
20 | import com.google.android.gms.tasks.OnSuccessListener;
21 | import com.google.android.gms.tasks.Task;
22 |
23 | import com.google.android.gms.games.SnapshotsClient;
24 | import com.google.android.gms.games.snapshot.SnapshotMetadata;
25 | import com.google.android.gms.games.snapshot.SnapshotMetadataChange;
26 | import com.google.android.gms.games.snapshot.Snapshot;
27 |
28 | import com.google.android.gms.games.LeaderboardsClient;
29 | import com.google.android.gms.games.leaderboard.LeaderboardScore;
30 | import com.google.android.gms.games.leaderboard.LeaderboardScoreBuffer;
31 |
32 | import com.google.android.gms.games.AchievementsClient;
33 | import com.google.android.gms.games.achievement.Achievement;
34 | import com.google.android.gms.games.achievement.AchievementBuffer;
35 | import com.google.android.gms.games.GamesClientStatusCodes;
36 |
37 | import com.google.android.gms.games.EventsClient;
38 | import com.google.android.gms.games.event.Event;
39 | import com.google.android.gms.games.event.EventBuffer;
40 |
41 | import java.io.IOException;
42 |
43 | import org.json.JSONArray;
44 | import org.json.JSONObject;
45 | import org.json.JSONException;
46 |
47 | public class GpgsJNI {
48 |
49 | private static final String TAG = "GpgsJNI";
50 |
51 | //Internal constants:
52 |
53 | private static final int RC_UNUSED = 5001;
54 | // Request code for listing saved games
55 | private static final int RC_LIST_SAVED_GAMES = 9002;
56 | // Request code for listing achievements
57 | private static final int RC_ACHIEVEMENT_UI = 9003;
58 | private static final int RC_SHOW_LEADERBOARD = 9004;
59 | private static final int RC_SHOW_ALL_LEADERBOARDS = 9005;
60 |
61 | // duplicate of enums from gpgs_extension.h:
62 | private static final int MSG_SIGN_IN = 1;
63 | private static final int MSG_SILENT_SIGN_IN = 2;
64 | private static final int MSG_SHOW_SNAPSHOTS = 4;
65 | private static final int MSG_LOAD_SNAPSHOT = 5;
66 | private static final int MSG_SAVE_SNAPSHOT = 6;
67 | private static final int MSG_ACHIEVEMENTS = 7;
68 | private static final int MSG_GET_TOP_SCORES = 8;
69 | private static final int MSG_GET_PLAYER_CENTERED_SCORES = 9;
70 | private static final int MSG_GET_PLAYER_SCORE = 10;
71 | private static final int MSG_GET_EVENTS = 11;
72 | private static final int MSG_GET_SERVER_TOKEN = 12;
73 |
74 | // duplicate of enums from gpgs_extension.h:
75 | private static final int STATUS_SUCCESS = 1;
76 | private static final int STATUS_FAILED = 2;
77 | private static final int STATUS_CREATE_NEW_SAVE = 3;
78 | private static final int STATUS_CONFLICT = 4;
79 |
80 | // duplicate of enums from gpgs_extension.h:
81 | private static final int SNAPSHOT_CURRENT = 1;
82 | private static final int SNAPSHOT_CONFLICTING = 2;
83 |
84 | //--------------------------------------------------
85 | public static native void gpgsAddToQueue(int msg, String json);
86 |
87 | //--------------------------------------------------
88 | private Activity activity;
89 | private boolean isDiskActive;
90 | private boolean isRequestAuthCode;
91 | private boolean isSupported;
92 | private String mWebClientToken = null; // need for server auth token request
93 | private String mServerAuthCode = null; // can be non-null if isRequestAuthCode == true
94 |
95 | //--------------------------------------------------
96 | // Authorization
97 |
98 | private GamesSignInClient mSignInClient;
99 | private Player mPlayer;
100 |
101 |
102 | private OnFailureListener newOnFailureListener(final int messageId, final String message) {
103 | return e -> sendFailedMessage(messageId, message, e);
104 | }
105 |
106 | private OnSuccessListener newOnSuccessListenerForIntent(final int requestCode) {
107 | return intent -> activity.startActivityForResult(intent, requestCode);
108 | }
109 |
110 | private void sendSimpleMessage(int msg, String key_1, int value_1) {
111 | String message = null;
112 | try {
113 | JSONObject obj = new JSONObject();
114 | obj.put(key_1, value_1);
115 | message = obj.toString();
116 | } catch (JSONException e) {
117 | message = "{ \"error\": \"Error while converting simple message to JSON: " + e.getMessage() + "\" }";
118 | }
119 | gpgsAddToQueue(msg, message);
120 | }
121 |
122 | private void sendSimpleMessage(int msg, String key_1, int value_1, String key_2, String value_2) {
123 | String message = null;
124 | try {
125 | JSONObject obj = new JSONObject();
126 | obj.put(key_1, value_1);
127 | obj.put(key_2, value_2);
128 | message = obj.toString();
129 | } catch (JSONException e) {
130 | message = "{ \"error\": \"Error while converting simple message to JSON: " + e.getMessage() + "\" }";
131 | }
132 | gpgsAddToQueue(msg, message);
133 | }
134 |
135 | private void sendSimpleMessage(int msg, String key_1, int value_1, String key_2, int value_2, String key_3, String value_3) {
136 | String message = null;
137 | try {
138 | JSONObject obj = new JSONObject();
139 | obj.put(key_1, value_1);
140 | obj.put(key_2, value_2);
141 | obj.put(key_3, value_3);
142 | message = obj.toString();
143 | } catch (JSONException e) {
144 | message = "{ \"error\": \"Error while converting simple message to JSON: " + e.getMessage() + "\" }";
145 | }
146 | gpgsAddToQueue(msg, message);
147 | }
148 |
149 | private void sendFailedMessage(int msg, String error_text, Exception e) {
150 | if(e != null) {
151 | if (e instanceof ApiException) {
152 | ApiException apiException = (ApiException) e;
153 | Integer errorStatusCode = apiException.getStatusCode();
154 | error_text += ": " + GamesClientStatusCodes.getStatusCodeString(errorStatusCode) +" ("+errorStatusCode.toString()+")";
155 |
156 | sendSimpleMessage(msg,
157 | "status", STATUS_FAILED,
158 | "error_status", errorStatusCode,
159 | "error", error_text);
160 | } else {
161 | error_text += ": " + e.toString();
162 |
163 | sendSimpleMessage(msg,
164 | "status", STATUS_FAILED,
165 | "error", error_text);
166 | }
167 | } else {
168 |
169 | sendSimpleMessage(msg,
170 | "status", STATUS_FAILED,
171 | "error", error_text);
172 | }
173 | }
174 |
175 | public GpgsJNI(Activity activity, boolean isDiskActive, boolean isRequestAuthCode, String oauthToken) {
176 | this.activity = activity;
177 | this.isDiskActive = isDiskActive;
178 | this.isRequestAuthCode = isRequestAuthCode;
179 | if (isRequestAuthCode) {
180 | this.mWebClientToken = oauthToken;
181 | }
182 |
183 | this.isSupported = GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(activity) == ConnectionResult.SUCCESS;
184 |
185 | mSignInClient = PlayGames.getGamesSignInClient(activity);
186 | if (isDiskActive) {
187 | mPlayerSnapshotsClient = PlayGames.getSnapshotsClient(activity);
188 | }
189 | mLeaderboardsClient = PlayGames.getLeaderboardsClient(activity);
190 | mAchievementsClient = PlayGames.getAchievementsClient(activity);
191 | mEventsClient = PlayGames.getEventsClient(activity);
192 | }
193 |
194 | private void onConnected(final int msg) {
195 | // until we get player information
196 | mPlayer = null;
197 | onAccountChangedDisk();
198 | PlayersClient playersClient = PlayGames.getPlayersClient(activity);
199 | if (this.isRequestAuthCode) {
200 | mSignInClient.requestServerSideAccess(mWebClientToken, false)
201 | .addOnCompleteListener(task -> {
202 | if (task.isSuccessful()) {
203 | mServerAuthCode = task.getResult();
204 | sendSimpleMessage(MSG_GET_SERVER_TOKEN, "status", STATUS_SUCCESS, "token", mServerAuthCode);
205 | } else {
206 | sendFailedMessage(MSG_GET_SERVER_TOKEN, "Can't get server auth token", task.getException());
207 | }
208 | });
209 | }
210 | playersClient.getCurrentPlayer()
211 | .addOnCompleteListener(task -> {
212 | if (task.isSuccessful()) {
213 | mPlayer = task.getResult();
214 | sendSimpleMessage(msg, "status", STATUS_SUCCESS);
215 | } else {
216 | sendFailedMessage(MSG_SIGN_IN, "There was a problem getting the player id!", task.getException());
217 | }
218 | });
219 | }
220 |
221 | public void activityResult(int requestCode, int resultCode, Intent intent) {
222 | if (requestCode == RC_LIST_SAVED_GAMES) {
223 | if (intent != null) {
224 | if (intent.hasExtra(SnapshotsClient.EXTRA_SNAPSHOT_METADATA)) {
225 | SnapshotMetadata snapshotMetadata =
226 | intent.getParcelableExtra(SnapshotsClient.EXTRA_SNAPSHOT_METADATA);
227 | sendSnapshotMetadataMessage(MSG_SHOW_SNAPSHOTS, snapshotMetadata);
228 | } else if (intent.hasExtra(SnapshotsClient.EXTRA_SNAPSHOT_NEW)) {
229 | sendSimpleMessage(MSG_SHOW_SNAPSHOTS, "status", STATUS_CREATE_NEW_SAVE);
230 | }
231 | } else {
232 | // Error message
233 | }
234 | }
235 | }
236 |
237 | public void silentLogin() {
238 | mSignInClient.isAuthenticated().addOnCompleteListener(isAuthenticatedTask -> {
239 | boolean isAuthenticated =
240 | (isAuthenticatedTask.isSuccessful() &&
241 | isAuthenticatedTask.getResult().isAuthenticated());
242 | if (isAuthenticated) {
243 | onConnected(MSG_SILENT_SIGN_IN);
244 | } else {
245 | sendFailedMessage(MSG_SILENT_SIGN_IN, "Silent sign-in failed", isAuthenticatedTask.getException());
246 | }
247 | });
248 | }
249 |
250 | public void login() {
251 | mSignInClient.signIn()
252 | .addOnCompleteListener(task -> {
253 | if (task.isSuccessful() && task.getResult().isAuthenticated()) {
254 | onConnected(MSG_SIGN_IN);
255 | } else {
256 | sendFailedMessage(MSG_SIGN_IN, "Sign-in failed", task.getException());
257 | }
258 | });
259 | }
260 |
261 | public String getDisplayName() {
262 | return isLoggedIn() ? mPlayer.getDisplayName() : null;
263 | }
264 |
265 | public String getId() {
266 | return isLoggedIn() ? mPlayer.getPlayerId() : null;
267 | }
268 |
269 | public String getServerAuthCode() {
270 | return mServerAuthCode;
271 | }
272 |
273 | public boolean isLoggedIn() {
274 | return mPlayer != null;
275 | }
276 |
277 | public boolean isSupported() {
278 | return isSupported;
279 | }
280 |
281 | //--------------------------------------------------
282 | // GoogleDrive (Snapshots)
283 |
284 | // Client used to interact with Google Snapshots.
285 | private SnapshotsClient mPlayerSnapshotsClient = null;
286 | private Snapshot mPlayerSnapshot = null;
287 | private byte[] currentPlayerSave = null;
288 |
289 | private Snapshot mConflictingSnapshot = null;
290 | private byte[] conflictingSave = null;
291 |
292 | // values from the official docs: https://developers.google.com/android/reference/com/google/android/gms/games/SnapshotsClient.html#getMaxCoverImageSize()
293 | private int maxCoverImageSize = 819200;
294 | // https://developers.google.com/android/reference/com/google/android/gms/games/SnapshotsClient.html#getMaxDataSize()
295 | private int maxDataSize = 3145728;
296 |
297 | private void onAccountChangedDisk() {
298 | if (this.isDiskActive) {
299 | mPlayerSnapshotsClient.getMaxCoverImageSize()
300 | .addOnCompleteListener(task -> {
301 | if (task.isSuccessful()) {
302 | maxCoverImageSize = task.getResult();
303 | }
304 | });
305 |
306 | mPlayerSnapshotsClient.getMaxDataSize()
307 | .addOnCompleteListener(task -> {
308 | if (task.isSuccessful()) {
309 | maxDataSize = task.getResult();
310 | }
311 | });
312 | }
313 | }
314 |
315 | private void addSnapshotMetadtaToJson(JSONObject json, String name, SnapshotMetadata metadata) throws JSONException {
316 | JSONObject obj = json;
317 | if (name != null) {
318 | obj = new JSONObject();
319 | json.put(name, obj);
320 | }
321 | obj.put("coverImageAspectRatio", metadata.getCoverImageAspectRatio());
322 | obj.put("coverImageUri", metadata.getCoverImageUri());
323 | obj.put("description", metadata.getDescription());
324 | obj.put("deviceName", metadata.getDeviceName());
325 | obj.put("lastModifiedTimestamp", metadata.getLastModifiedTimestamp());
326 | obj.put("playedTime", metadata.getPlayedTime());
327 | obj.put("progressValue", metadata.getProgressValue());
328 | obj.put("snapshotId", metadata.getSnapshotId());
329 | obj.put("uniqueName", metadata.getUniqueName());
330 | }
331 |
332 | private void sendSnapshotMetadataMessage(int msg, SnapshotMetadata metadata) {
333 | String message = null;
334 | try {
335 | JSONObject obj = new JSONObject();
336 | obj.put("status", STATUS_SUCCESS);
337 | addSnapshotMetadtaToJson(obj, "metadata", metadata);
338 | message = obj.toString();
339 | } catch (JSONException e) {
340 | message = "{ \"error\": \"Error while converting a metadata message to JSON: " + e.getMessage() + "\", \"status\": " + STATUS_FAILED + " }";
341 | }
342 | gpgsAddToQueue(msg, message);
343 | }
344 |
345 | private void sendConflictMessage(int msg, SnapshotMetadata metadata, SnapshotMetadata conflictMetadata, String conflictId) {
346 | String message = null;
347 | try {
348 | JSONObject obj = new JSONObject();
349 | obj.put("status", STATUS_CONFLICT);
350 | obj.put("conflictId", conflictId);
351 | addSnapshotMetadtaToJson(obj, "metadata", metadata);
352 | addSnapshotMetadtaToJson(obj, "conflictMetadata", conflictMetadata);
353 | message = obj.toString();
354 | } catch (JSONException e) {
355 | message = "{ \"error\": \"Error while converting a metadata or a conflict metadata message to JSON: " + e.getMessage() + "\", \"status\": " + STATUS_FAILED + " }";
356 | }
357 | gpgsAddToQueue(msg, message);
358 | }
359 |
360 | private OnCompleteListener> getOnLoadCompleteListener() {
361 | return task -> {
362 | if (!task.isSuccessful()) {
363 | sendFailedMessage(MSG_LOAD_SNAPSHOT, "Error while opening Snapshot", task.getException());
364 | } else {
365 | SnapshotsClient.DataOrConflict result = task.getResult();
366 | if (!result.isConflict()) {
367 | mPlayerSnapshot = result.getData();
368 | try {
369 | currentPlayerSave = mPlayerSnapshot.getSnapshotContents().readFully();
370 | sendSnapshotMetadataMessage(MSG_LOAD_SNAPSHOT, mPlayerSnapshot.getMetadata());
371 | } catch (IOException e) {
372 | sendFailedMessage(MSG_LOAD_SNAPSHOT, "Error while reading Snapshot", e);
373 | } catch (NullPointerException e) {
374 | sendFailedMessage(MSG_LOAD_SNAPSHOT, "Snapshot is null", e);
375 | }
376 | } else {
377 | SnapshotsClient.SnapshotConflict conflict = result.getConflict();
378 | mPlayerSnapshot = conflict.getSnapshot();
379 | mConflictingSnapshot = conflict.getConflictingSnapshot();
380 | try {
381 | currentPlayerSave = mPlayerSnapshot.getSnapshotContents().readFully();
382 | conflictingSave = mConflictingSnapshot.getSnapshotContents().readFully();
383 | sendConflictMessage(MSG_LOAD_SNAPSHOT, mPlayerSnapshot.getMetadata(),
384 | mConflictingSnapshot.getMetadata(), conflict.getConflictId());
385 | } catch (IOException e) {
386 | sendFailedMessage(MSG_LOAD_SNAPSHOT, "Error while reading Snapshot or Conflict", e);
387 | }
388 | }
389 | }
390 | };
391 | }
392 |
393 | public void showSavedGamesUI(String popupTitle, boolean allowAddButton,
394 | boolean allowDelete, int maxNumberOfSavedGamesToShow) {
395 |
396 | if (mPlayerSnapshotsClient == null) {
397 | sendSimpleMessage(MSG_SHOW_SNAPSHOTS,
398 | "status", STATUS_FAILED,
399 | "error",
400 | "Can't start activity for showing saved games. You aren't logged in.");
401 | return;
402 | }
403 |
404 | Task intentTask = mPlayerSnapshotsClient.getSelectSnapshotIntent(
405 | popupTitle, allowAddButton, allowDelete, maxNumberOfSavedGamesToShow);
406 |
407 | intentTask
408 | .addOnSuccessListener(newOnSuccessListenerForIntent(RC_LIST_SAVED_GAMES))
409 | .addOnFailureListener(newOnFailureListener(MSG_SHOW_SNAPSHOTS, "Can't start activity for showing saved games"));
410 | }
411 |
412 | public void loadSnapshot(String saveName, boolean createIfNotFound, int conflictPolicy) {
413 | int conflictResolutionPolicy = SnapshotsClient.RESOLUTION_POLICY_MOST_RECENTLY_MODIFIED;
414 |
415 | if (mPlayerSnapshotsClient == null) {
416 | sendSimpleMessage(MSG_LOAD_SNAPSHOT,
417 | "status", STATUS_FAILED,
418 | "error",
419 | "Failed to open snapshot. You aren't logged in.");
420 | return;
421 | }
422 |
423 | mPlayerSnapshotsClient.open(saveName, createIfNotFound, conflictPolicy)
424 | .addOnCompleteListener(getOnLoadCompleteListener());
425 | }
426 |
427 | public void commitAndCloseSnapshot(long playedTime, long progressValue, String description, byte[] coverImage) {
428 | SnapshotMetadataChange.Builder builder = new SnapshotMetadataChange.Builder();
429 | if (playedTime != -1) {
430 | builder.setPlayedTimeMillis(playedTime);
431 | }
432 | if (progressValue != -1) {
433 | builder.setProgressValue(progressValue);
434 | }
435 | if (description != null) {
436 | builder.setDescription(description);
437 | }
438 | if (coverImage != null) {
439 | Bitmap bitmap = BitmapFactory.decodeByteArray(coverImage, 0, coverImage.length);
440 | builder.setCoverImage(bitmap);
441 | }
442 |
443 | if (mPlayerSnapshot == null) {
444 | sendSimpleMessage(MSG_SAVE_SNAPSHOT,
445 | "status", STATUS_FAILED,
446 | "error",
447 | "A snapshot wasn't opened.");
448 | return;
449 | }
450 |
451 | mPlayerSnapshotsClient.commitAndClose(mPlayerSnapshot, builder.build())
452 | .addOnCompleteListener(task -> {
453 | if (task.isSuccessful()) {
454 | mPlayerSnapshot = null;
455 | currentPlayerSave = null;
456 | sendSimpleMessage(MSG_SAVE_SNAPSHOT,
457 | "status", STATUS_SUCCESS);
458 | } else {
459 | sendFailedMessage(MSG_SAVE_SNAPSHOT, "Failed to save a snapshot", task.getException());
460 | }
461 | });
462 | }
463 |
464 | public void resolveConflict(String conflictId, int metadataId) {
465 | Snapshot snapshot = mPlayerSnapshot;
466 | if (metadataId == SNAPSHOT_CONFLICTING) {
467 | snapshot = mConflictingSnapshot;
468 | }
469 | if (mPlayerSnapshot == null) {
470 | sendSimpleMessage(SNAPSHOT_CONFLICTING,
471 | "status", STATUS_FAILED,
472 | "error",
473 | "Failed to resolve conflict. You aren't logged in.");
474 | return;
475 | }
476 | mPlayerSnapshotsClient.resolveConflict(conflictId, snapshot)
477 | .addOnCompleteListener(getOnLoadCompleteListener());
478 | }
479 |
480 | public byte[] getSave() {
481 | return currentPlayerSave;
482 | }
483 |
484 | public byte[] getConflictingSave() {
485 | return conflictingSave;
486 | }
487 |
488 | public String setSave(byte[] bytes) {
489 | if (mPlayerSnapshot != null) {
490 | mPlayerSnapshot.getSnapshotContents().writeBytes(bytes);
491 | currentPlayerSave = bytes;
492 | return null;
493 | }
494 | return "Can't write data to the snapshot. The snapshot wasn't open.";
495 | }
496 |
497 | public boolean isSnapshotOpened() {
498 | if (mPlayerSnapshot == null || mPlayerSnapshot.getSnapshotContents() == null) {
499 | return false;
500 | }
501 | return !mPlayerSnapshot.getSnapshotContents().isClosed();
502 | }
503 |
504 | public int getMaxCoverImageSize() {
505 | return maxCoverImageSize;
506 | }
507 |
508 | public int getMaxDataSize() {
509 | return maxDataSize;
510 | }
511 |
512 |
513 | //--------------------------------------------------
514 | // Leaderboards
515 |
516 | // Client used to interact with Leaderboards.
517 | private LeaderboardsClient mLeaderboardsClient = null;
518 |
519 | public void submitScore(String leaderboardId, double score) {
520 | mLeaderboardsClient.submitScore(leaderboardId, (long)score);
521 | }
522 |
523 | private static JSONObject scoreToJSON(LeaderboardScore score, String leaderboardId) throws JSONException {
524 | JSONObject json = new JSONObject();
525 | json.put("leaderboard_id", leaderboardId);
526 | json.put("display_rank", score.getDisplayRank());
527 | json.put("display_score", score.getDisplayScore());
528 | json.put("rank", score.getRank());
529 | json.put("score", score.getRawScore());
530 | json.put("tag", score.getScoreTag());
531 | json.put("timestamp", score.getTimestampMillis());
532 | json.put("score_holder_name", score.getScoreHolderDisplayName());
533 | json.put("score_holder_icon", score.getScoreHolderIconImageUri());
534 | json.put("score_holder_image", score.getScoreHolderHiResImageUri());
535 | return json;
536 | }
537 |
538 | public void loadTopScores(final String leaderboardId, int span, int collection, int maxResults) {
539 | mLeaderboardsClient.loadTopScores(leaderboardId, span, collection, maxResults)
540 | .addOnCompleteListener(task -> {
541 | if (task.isSuccessful()) {
542 | LeaderboardsClient.LeaderboardScores scores = task.getResult().get();
543 | LeaderboardScoreBuffer buffer = scores.getScores();
544 | String message = null;
545 | try {
546 | JSONArray result = new JSONArray();
547 | for (LeaderboardScore score : buffer) {
548 | JSONObject json = scoreToJSON(score, leaderboardId);
549 | result.put(json.toString());
550 | }
551 | message = result.toString();
552 | } catch (JSONException e) {
553 | message = "{ \"error\": \"Error while converting leaderboard score to JSON: " + e.getMessage() + "\", \"status\": " + STATUS_FAILED + " }";
554 | }
555 | buffer.release();
556 | gpgsAddToQueue(MSG_GET_TOP_SCORES, message);
557 | } else {
558 | sendFailedMessage(MSG_GET_TOP_SCORES, "Unable to get top scores", task.getException());
559 | }
560 | });
561 | }
562 |
563 | public void loadPlayerCenteredScores(final String leaderboardId, int span, int collection, int maxResults, boolean forceReload) {
564 | mLeaderboardsClient.loadPlayerCenteredScores(leaderboardId, span, collection, maxResults, forceReload)
565 | .addOnCompleteListener(task -> {
566 | if (task.isSuccessful()) {
567 | LeaderboardsClient.LeaderboardScores scores = task.getResult().get();
568 | LeaderboardScoreBuffer buffer = scores.getScores();
569 | String message = null;
570 | try {
571 | JSONArray result = new JSONArray();
572 | for (LeaderboardScore score : buffer) {
573 | JSONObject json = scoreToJSON(score, leaderboardId);
574 | result.put(json.toString());
575 | }
576 | message = result.toString();
577 | } catch (JSONException e) {
578 | message = "{ \"error\": \"Error while converting leaderboard score to JSON: " + e.getMessage() + "\", \"status\": " + STATUS_FAILED + " }";
579 | }
580 | buffer.release();
581 | gpgsAddToQueue(MSG_GET_PLAYER_CENTERED_SCORES, message);
582 | } else {
583 | Exception exception = task.getException();
584 | sendFailedMessage(MSG_GET_PLAYER_CENTERED_SCORES, "Unable to get player centered scores", exception);
585 | }
586 | });
587 | }
588 |
589 | public void loadCurrentPlayerLeaderboardScore(final String leaderboardId, int span, int collection) {
590 | mLeaderboardsClient.loadCurrentPlayerLeaderboardScore(leaderboardId, span, collection)
591 | .addOnCompleteListener(task -> {
592 | if (task.isSuccessful()) {
593 | LeaderboardScore score = task.getResult().get();
594 | String message = null;
595 | if (score == null) {
596 | message = "{ \"error\": \"Player has no score on leaderboard\", \"status\": " + STATUS_FAILED + " }";
597 |
598 | }
599 | else {
600 | try {
601 | JSONObject result = scoreToJSON(score, leaderboardId);
602 | message = result.toString();
603 | } catch (JSONException e) {
604 | message = "{ \"error\": \"Error while converting leaderboard score to JSON: " + e.getMessage() + "\", \"status\": " + STATUS_FAILED + " }";
605 | }
606 | }
607 | gpgsAddToQueue(MSG_GET_PLAYER_SCORE, message);
608 | } else {
609 | Exception exception = task.getException();
610 | sendFailedMessage(MSG_GET_PLAYER_SCORE, "Unable to get player scores", exception);
611 | }
612 | });
613 | }
614 |
615 | public void showLeaderboard(String leaderboardId, int span, int collection) {
616 | mLeaderboardsClient.getLeaderboardIntent(leaderboardId, span, collection)
617 | .addOnSuccessListener(newOnSuccessListenerForIntent(RC_SHOW_LEADERBOARD));
618 | }
619 |
620 | public void showAllLeaderboards() {
621 | mLeaderboardsClient.getAllLeaderboardsIntent()
622 | .addOnSuccessListener(newOnSuccessListenerForIntent(RC_SHOW_ALL_LEADERBOARDS));
623 | }
624 |
625 | //--------------------------------------------------
626 | // Achievements
627 |
628 | // Client used to interact with Achievements.
629 | private AchievementsClient mAchievementsClient = null;
630 |
631 | public void revealAchievement(String achievementId) {
632 | mAchievementsClient.reveal(achievementId);
633 | }
634 |
635 | public void unlockAchievement(String achievementId) {
636 | mAchievementsClient.unlock(achievementId);
637 | }
638 |
639 | public void incrementAchievement(String achievementId, int steps) {
640 | mAchievementsClient.increment(achievementId, steps);
641 | }
642 |
643 | public void setAchievement(String achievementId, int steps) {
644 | mAchievementsClient.setSteps(achievementId, steps);
645 | }
646 |
647 | public void showAchievements() {
648 | mAchievementsClient.getAchievementsIntent()
649 | .addOnSuccessListener(newOnSuccessListenerForIntent(RC_UNUSED));
650 | }
651 |
652 | public void getAchievements() {
653 | mAchievementsClient
654 | .load(false)
655 | .addOnCompleteListener(task -> {
656 | if (task.isSuccessful()) {
657 | AchievementBuffer buffer = task.getResult().get();
658 | String message = null;
659 | try {
660 | JSONArray result = new JSONArray();
661 | for (Achievement a : buffer) {
662 | JSONObject json = new JSONObject();
663 | json.put("id", a.getAchievementId());
664 | json.put("name", a.getName());
665 | json.put("description", a.getDescription());
666 | json.put("xp", a.getXpValue());
667 | if (a.getType() == Achievement.TYPE_INCREMENTAL) {
668 | json.put("steps", a.getCurrentSteps());
669 | json.put("total_steps", a.getTotalSteps());
670 | }
671 | if (a.getState() == Achievement.STATE_UNLOCKED) {
672 | json.put("unlocked", true);
673 | }
674 | else if (a.getState() == Achievement.STATE_HIDDEN) {
675 | json.put("hidden", true);
676 | }
677 | else if (a.getState() == Achievement.STATE_REVEALED) {
678 | json.put("revealed", true);
679 | }
680 | result.put(json.toString());
681 | }
682 | message = result.toString();
683 | buffer.release();
684 | } catch (JSONException e) {
685 | message = "{ \"error\": \"Error while converting achievements to JSON: " + e.getMessage() + "\", \"status\": " + STATUS_FAILED + " }";
686 | }
687 | gpgsAddToQueue(MSG_ACHIEVEMENTS, message);
688 | } else {
689 | Exception exception = task.getException();
690 | sendFailedMessage(MSG_ACHIEVEMENTS, "Unable to get achievements", exception);
691 | }
692 | });
693 | }
694 |
695 | private EventsClient mEventsClient = null;
696 |
697 | public void incrementEvent(String eventId, int amount) {
698 | mEventsClient.increment(eventId, amount);
699 | }
700 |
701 | public void loadEvents() {
702 | mEventsClient
703 | .load(false)
704 | .addOnCompleteListener(task -> {
705 | if (task.isSuccessful()) {
706 | EventBuffer buffer = task.getResult().get();
707 | String message = null;
708 | try {
709 | JSONArray result = new JSONArray();
710 | for (Event e : buffer) {
711 | JSONObject json = new JSONObject();
712 | json.put("id", e.getEventId());
713 | json.put("formatted_value", e.getFormattedValue());
714 | json.put("value", e.getValue());
715 | json.put("description", e.getDescription());
716 | json.put("image", e.getIconImageUri());
717 | json.put("name", e.getName());
718 | json.put("visible", e.isVisible());
719 | result.put(json.toString());
720 | }
721 | message = result.toString();
722 | buffer.release();
723 | } catch (JSONException e) {
724 | message = "{ \"error\": \"Error while converting event to JSON: " + e.getMessage() + "\", \"status\": " + STATUS_FAILED + " }";
725 | }
726 | gpgsAddToQueue(MSG_GET_EVENTS, message);
727 | } else {
728 | Exception exception = task.getException();
729 | sendFailedMessage(MSG_GET_EVENTS, "Unable to get events", exception);
730 | }
731 | });
732 | }
733 |
734 | }
735 |
--------------------------------------------------------------------------------