From 47866078a01aca5e5859d174e0f3cec219c10ccf Mon Sep 17 00:00:00 2001 From: Dorin Date: Thu, 27 Feb 2025 11:24:57 +0200 Subject: [PATCH 01/66] using default argument instead of duplicated function --- include/GameAnalytics/GameAnalytics.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/include/GameAnalytics/GameAnalytics.h b/include/GameAnalytics/GameAnalytics.h index 87845d61..a5b135c7 100644 --- a/include/GameAnalytics/GameAnalytics.h +++ b/include/GameAnalytics/GameAnalytics.h @@ -102,15 +102,13 @@ namespace gameanalytics static void startSession(); static void endSession(); - static std::string getRemoteConfigsValueAsString(std::string const& key); - static std::string getRemoteConfigsValueAsString(std::string const& key, std::string const& defaultValue); + static std::string getRemoteConfigsValueAsString(std::string const& key, std::string const& defaultValue = ""); static bool isRemoteConfigsReady(); static void addRemoteConfigsListener(const std::shared_ptr &listener); static void removeRemoteConfigsListener(const std::shared_ptr &listener); static std::string getRemoteConfigsContentAsString(); - static std::string getRemoteConfigsContentAsJson(); static std::string getABTestingId(); static std::string getABTestingVariantId(); From cec686ec6765f60f877b2344df8586cd154c5bc1 Mon Sep 17 00:00:00 2001 From: Andrei Dabija Date: Thu, 13 Mar 2025 13:20:19 +0200 Subject: [PATCH 02/66] Update Main.cpp --- sample/Main.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/sample/Main.cpp b/sample/Main.cpp index 212589c1..3ed96837 100644 --- a/sample/Main.cpp +++ b/sample/Main.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include "GameAnalytics/GameAnalytics.h" From bcde102271de332029541c66a0791d23c8531b02 Mon Sep 17 00:00:00 2001 From: Andrei Dabija Date: Thu, 13 Mar 2025 15:57:02 +0200 Subject: [PATCH 03/66] set ubuntu-24.04 and clang version to 16 --- .github/workflows/cmake.yml | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 28938db9..21ddadb9 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -31,17 +31,17 @@ jobs: # # To add more build types (Release, Debug, RelWithDebInfo, etc.) customize the build_type list. matrix: - os: [ubuntu-latest, windows-latest, macOS-latest] + os: [ubuntu-24.04, windows-latest, macOS-latest] build_type: ${{ fromJSON(format('[{0}]', inputs.build_type || '"Debug","Release"')) }} c_compiler: [gcc, clang, cl] include: - os: windows-latest c_compiler: cl cpp_compiler: cl - - os: ubuntu-latest + - os: ubuntu-24.04 c_compiler: gcc cpp_compiler: g++ - - os: ubuntu-latest + - os: ubuntu-24.04 c_compiler: clang cpp_compiler: clang++ - os: macOS-latest @@ -52,7 +52,7 @@ jobs: c_compiler: gcc - os: windows-latest c_compiler: clang - - os: ubuntu-latest + - os: ubuntu-24.04 c_compiler: cl - os: macOS-latest c_compiler: cl @@ -71,6 +71,12 @@ jobs: run: | echo "build-output-dir=${{ github.workspace }}/build" >> "$GITHUB_OUTPUT" + - name: Set Clang 16 as default + if: matrix.os == 'ubuntu-24.04' && matrix.c_compiler == 'clang' + run: | + sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-16 100 + sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-16 100 + - name: Configure CMake # Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make. # See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type From 5c6d7e7f72d83a7f14f1cf25f38a44b1a7914bc2 Mon Sep 17 00:00:00 2001 From: Andrei Dabija Date: Thu, 13 Mar 2025 15:59:41 +0200 Subject: [PATCH 04/66] Update cmake.yml --- .github/workflows/cmake.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 21ddadb9..ee3bd697 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -74,8 +74,8 @@ jobs: - name: Set Clang 16 as default if: matrix.os == 'ubuntu-24.04' && matrix.c_compiler == 'clang' run: | - sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-16 100 - sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-16 100 + sudo update-alternatives --set clang /usr/bin/clang-16 + sudo update-alternatives --set clang++ /usr/bin/clang++-16 - name: Configure CMake # Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make. From 5586240ce7b3e2fd406861122b74e0dbdbacfe5e Mon Sep 17 00:00:00 2001 From: Andrei Dabija Date: Thu, 13 Mar 2025 16:12:13 +0200 Subject: [PATCH 05/66] Update cmake.yml --- .github/workflows/cmake.yml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index ee3bd697..9119f059 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -71,11 +71,16 @@ jobs: run: | echo "build-output-dir=${{ github.workspace }}/build" >> "$GITHUB_OUTPUT" - - name: Set Clang 16 as default - if: matrix.os == 'ubuntu-24.04' && matrix.c_compiler == 'clang' + - name: Set Clang 16 as Default run: | + sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-16 100 + sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-16 100 sudo update-alternatives --set clang /usr/bin/clang-16 sudo update-alternatives --set clang++ /usr/bin/clang++-16 + + # Verify the change + clang --version + clang++ --version - name: Configure CMake # Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make. From 2f751e4dc3a40cc94b6afcf861cca9cc8f9b402a Mon Sep 17 00:00:00 2001 From: Andrei Dabija Date: Thu, 13 Mar 2025 16:14:47 +0200 Subject: [PATCH 06/66] Update cmake.yml --- .github/workflows/cmake.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 9119f059..327ba432 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -72,6 +72,7 @@ jobs: echo "build-output-dir=${{ github.workspace }}/build" >> "$GITHUB_OUTPUT" - name: Set Clang 16 as Default + if: matrix.os == 'ubuntu-24.04' && matrix.c_compiler == 'clang' run: | sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-16 100 sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-16 100 From b79e828f26883096cbf425924b1b43da32717536 Mon Sep 17 00:00:00 2001 From: Andrei Dabija Date: Thu, 13 Mar 2025 19:00:38 +0200 Subject: [PATCH 07/66] Update CMakeLists.txt --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3627bdd8..b698d227 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -198,7 +198,7 @@ elseif(LINUX) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DGUID_STDLIB -std=c++17") if(CLANG) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libstdc++") endif() endif() From 2f2c2ebf2d769032a4d361c93030a714d154db4a Mon Sep 17 00:00:00 2001 From: Andrei Dabija Date: Thu, 13 Mar 2025 19:07:54 +0200 Subject: [PATCH 08/66] Update cmake.yml --- .github/workflows/cmake.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 327ba432..25eed345 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -95,7 +95,7 @@ jobs: - name: Build # Build your program with the given configuration. Note that --config is needed because the default Windows generator is a multi-config generator (Visual Studio generator). - run: cmake --build ${{ steps.strings.outputs.build-output-dir }} --config ${{ matrix.build_type }} + run: cmake --build ${{ steps.strings.outputs.build-output-dir }} --config ${{ matrix.build_type }} VERBOSE=1 - name: Test working-directory: ${{ steps.strings.outputs.build-output-dir }} From ebbf72f3546ebdac0166c1daba1a0b42f79422a7 Mon Sep 17 00:00:00 2001 From: Andrei Dabija Date: Thu, 13 Mar 2025 19:08:32 +0200 Subject: [PATCH 09/66] Update cmake.yml --- .github/workflows/cmake.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 25eed345..8190e0e5 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -95,7 +95,7 @@ jobs: - name: Build # Build your program with the given configuration. Note that --config is needed because the default Windows generator is a multi-config generator (Visual Studio generator). - run: cmake --build ${{ steps.strings.outputs.build-output-dir }} --config ${{ matrix.build_type }} VERBOSE=1 + run: cmake --build ${{ steps.strings.outputs.build-output-dir }} --config ${{ matrix.build_type }} --verbose - name: Test working-directory: ${{ steps.strings.outputs.build-output-dir }} From 9a6867a32767f04da439f4b92e85e3d6a4df36f3 Mon Sep 17 00:00:00 2001 From: Andrei Dabija Date: Thu, 13 Mar 2025 19:12:06 +0200 Subject: [PATCH 10/66] Update CMakeLists.txt --- CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b698d227..70053a90 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -209,7 +209,9 @@ endif() add_library(GameAnalytics ${LIB_TYPE} ${CPP_SOURCES}) target_link_libraries(GameAnalytics PRIVATE ${LIBS} PUBLIC ${PUBLIC_LIBS}) - +message(STATUS "CMAKE_CXX_FLAGS: ${CMAKE_CXX_FLAGS}") +message(STATUS "CMAKE_EXE_LINKER_FLAGS: ${CMAKE_EXE_LINKER_FLAGS}") +message(STATUS "CMAKE_SHARED_LINKER_FLAGS: ${CMAKE_SHARED_LINKER_FLAGS}") # --------------------------- Google Test Setup --------------------------- # # Set Project Name From fc62e197c4916ef32c61a5beaefb14a8891ebd78 Mon Sep 17 00:00:00 2001 From: Andrei Dabija Date: Thu, 13 Mar 2025 19:14:07 +0200 Subject: [PATCH 11/66] Update CMakeLists.txt --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 70053a90..2b5e4233 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -198,6 +198,7 @@ elseif(LINUX) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DGUID_STDLIB -std=c++17") if(CLANG) + message(STATUS "Using Linux Clang with libstdc++") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libstdc++") endif() From 122584058606b51aa4d621fbbb3800bb9e21cde0 Mon Sep 17 00:00:00 2001 From: Andrei Dabija Date: Thu, 13 Mar 2025 19:16:49 +0200 Subject: [PATCH 12/66] Update CMakeLists.txt --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2b5e4233..59ab5877 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -198,8 +198,8 @@ elseif(LINUX) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DGUID_STDLIB -std=c++17") if(CLANG) - message(STATUS "Using Linux Clang with libstdc++") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libstdc++") + message(STATUS "Detected Clang compiler: ${CMAKE_CXX_COMPILER}") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") endif() endif() From 691a618769cc71729da9085f3bb75cf47d745d8c Mon Sep 17 00:00:00 2001 From: Andrei Dabija Date: Thu, 13 Mar 2025 19:17:59 +0200 Subject: [PATCH 13/66] Update CMakeLists.txt --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 59ab5877..868c6b1b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -197,7 +197,7 @@ elseif(APPLE) elseif(LINUX) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DGUID_STDLIB -std=c++17") - if(CLANG) + if (CMAKE_CXX_COMPILER MATCHES "clang") message(STATUS "Detected Clang compiler: ${CMAKE_CXX_COMPILER}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") endif() From bd08d61622cff983bd90d2ffedbd2e624e6fbb38 Mon Sep 17 00:00:00 2001 From: Andrei Dabija Date: Thu, 13 Mar 2025 19:21:20 +0200 Subject: [PATCH 14/66] Update CMakeLists.txt --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 868c6b1b..4d5115be 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -199,7 +199,7 @@ elseif(LINUX) if (CMAKE_CXX_COMPILER MATCHES "clang") message(STATUS "Detected Clang compiler: ${CMAKE_CXX_COMPILER}") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++ -nostdinc++") endif() endif() From 792a871ead9bf49d0b20471176dacdf89dbbad16 Mon Sep 17 00:00:00 2001 From: Andrei Dabija Date: Thu, 13 Mar 2025 19:22:37 +0200 Subject: [PATCH 15/66] Update CMakeLists.txt --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4d5115be..e3ffd119 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -199,7 +199,7 @@ elseif(LINUX) if (CMAKE_CXX_COMPILER MATCHES "clang") message(STATUS "Detected Clang compiler: ${CMAKE_CXX_COMPILER}") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++ -nostdinc++") + # set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") endif() endif() From df964bda08eaf78172bbe77fbd9dca3e6a0358ec Mon Sep 17 00:00:00 2001 From: Andrei Dabija Date: Thu, 13 Mar 2025 19:23:29 +0200 Subject: [PATCH 16/66] Update CMakeLists.txt --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e3ffd119..81962bf9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -199,7 +199,7 @@ elseif(LINUX) if (CMAKE_CXX_COMPILER MATCHES "clang") message(STATUS "Detected Clang compiler: ${CMAKE_CXX_COMPILER}") - # set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libstdc++") endif() endif() From 876f32b72b4c8168dfa7c854ab11523e0d5e47d0 Mon Sep 17 00:00:00 2001 From: Andrei Dabija Date: Thu, 13 Mar 2025 19:28:08 +0200 Subject: [PATCH 17/66] Update CMakeLists.txt --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 81962bf9..868c6b1b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -199,7 +199,7 @@ elseif(LINUX) if (CMAKE_CXX_COMPILER MATCHES "clang") message(STATUS "Detected Clang compiler: ${CMAKE_CXX_COMPILER}") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libstdc++") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") endif() endif() From e1b552ecef3a374bf60c7946528a6f3383cc50bc Mon Sep 17 00:00:00 2001 From: Andrei Dabija Date: Thu, 13 Mar 2025 19:33:34 +0200 Subject: [PATCH 18/66] Update guid.cpp --- source/dependencies/crossguid/guid.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/dependencies/crossguid/guid.cpp b/source/dependencies/crossguid/guid.cpp index f3bfe58b..6faa8241 100644 --- a/source/dependencies/crossguid/guid.cpp +++ b/source/dependencies/crossguid/guid.cpp @@ -22,7 +22,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#include +#include #include "guid.h" #ifdef GUID_LIBUUID From cf493e70bc2314254dedf981af303e56af9bc1cf Mon Sep 17 00:00:00 2001 From: Andrei Dabija Date: Thu, 13 Mar 2025 19:36:16 +0200 Subject: [PATCH 19/66] Update guid.cpp --- source/dependencies/crossguid/guid.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/dependencies/crossguid/guid.cpp b/source/dependencies/crossguid/guid.cpp index 6faa8241..f3bfe58b 100644 --- a/source/dependencies/crossguid/guid.cpp +++ b/source/dependencies/crossguid/guid.cpp @@ -22,7 +22,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#include +#include #include "guid.h" #ifdef GUID_LIBUUID From ebca0f4fbf99a064c888763ed2a94f31f3abbbf2 Mon Sep 17 00:00:00 2001 From: Andrei Dabija Date: Thu, 13 Mar 2025 19:41:34 +0200 Subject: [PATCH 20/66] Update CMakeLists.txt --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 868c6b1b..6691b43f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -199,7 +199,7 @@ elseif(LINUX) if (CMAKE_CXX_COMPILER MATCHES "clang") message(STATUS "Detected Clang compiler: ${CMAKE_CXX_COMPILER}") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++ -lc++abi") endif() endif() From 6d771f5786eb53e0acd88fea972fa04b1e9aa842 Mon Sep 17 00:00:00 2001 From: Andrei Dabija Date: Fri, 14 Mar 2025 11:11:08 +0200 Subject: [PATCH 21/66] try and fix libc++ compatibility issues for linux --- .github/workflows/cmake.yml | 2 ++ CMakeLists.txt | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 8190e0e5..be1a878e 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -82,6 +82,8 @@ jobs: # Verify the change clang --version clang++ --version + clang++ -v -E -x c++ /dev/null + clang++ -v -stdlib=libc++ - name: Configure CMake # Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make. diff --git a/CMakeLists.txt b/CMakeLists.txt index 6691b43f..ee6655c7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -199,7 +199,8 @@ elseif(LINUX) if (CMAKE_CXX_COMPILER MATCHES "clang") message(STATUS "Detected Clang compiler: ${CMAKE_CXX_COMPILER}") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++ -lc++abi") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lc++abi") endif() endif() From 0d8ecb4bb872c9d53311b235fc61d32c01c1c3fc Mon Sep 17 00:00:00 2001 From: Andrei Dabija Date: Fri, 14 Mar 2025 11:17:08 +0200 Subject: [PATCH 22/66] Update cmake.yml --- .github/workflows/cmake.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index be1a878e..52441e2c 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -82,8 +82,8 @@ jobs: # Verify the change clang --version clang++ --version + echo "Checking clang headers..." clang++ -v -E -x c++ /dev/null - clang++ -v -stdlib=libc++ - name: Configure CMake # Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make. From 409966ec22edf45b1c8bdd59b310b5d3271212e2 Mon Sep 17 00:00:00 2001 From: Andrei Dabija Date: Fri, 14 Mar 2025 11:36:16 +0200 Subject: [PATCH 23/66] Update cmake.yml --- .github/workflows/cmake.yml | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 52441e2c..be8fb862 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -31,17 +31,17 @@ jobs: # # To add more build types (Release, Debug, RelWithDebInfo, etc.) customize the build_type list. matrix: - os: [ubuntu-24.04, windows-latest, macOS-latest] + os: [ubuntu-22.04, windows-latest, macOS-latest] build_type: ${{ fromJSON(format('[{0}]', inputs.build_type || '"Debug","Release"')) }} c_compiler: [gcc, clang, cl] include: - os: windows-latest c_compiler: cl cpp_compiler: cl - - os: ubuntu-24.04 + - os: ubuntu-22.04 c_compiler: gcc cpp_compiler: g++ - - os: ubuntu-24.04 + - os: ubuntu-22.04 c_compiler: clang cpp_compiler: clang++ - os: macOS-latest @@ -52,7 +52,7 @@ jobs: c_compiler: gcc - os: windows-latest c_compiler: clang - - os: ubuntu-24.04 + - os: ubuntu-22.04 c_compiler: cl - os: macOS-latest c_compiler: cl @@ -78,8 +78,10 @@ jobs: sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-16 100 sudo update-alternatives --set clang /usr/bin/clang-16 sudo update-alternatives --set clang++ /usr/bin/clang++-16 - - # Verify the change + + - name: Check Clang Settings + if: matrix.os == 'ubuntu-22.04' && matrix.c_compiler == 'clang' + run: | clang --version clang++ --version echo "Checking clang headers..." From 4e00501b15c86eb1501e6cf7a716249e6c5c1c17 Mon Sep 17 00:00:00 2001 From: Andrei Dabija Date: Fri, 14 Mar 2025 11:39:14 +0200 Subject: [PATCH 24/66] Update GALinux.cpp --- source/gameanalytics/Platform/GALinux.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/source/gameanalytics/Platform/GALinux.cpp b/source/gameanalytics/Platform/GALinux.cpp index 20154394..d5ec8064 100644 --- a/source/gameanalytics/Platform/GALinux.cpp +++ b/source/gameanalytics/Platform/GALinux.cpp @@ -4,6 +4,7 @@ #include "GAState.h" +#include #include #include #include From 884ae5d132731c3cbc1369cd44706b3739033b4e Mon Sep 17 00:00:00 2001 From: Andrei Dabija Date: Fri, 14 Mar 2025 12:36:05 +0200 Subject: [PATCH 25/66] Update CMakeLists.txt --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ee6655c7..2bedea27 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -210,7 +210,7 @@ if(${GA_BUILD_SAMPLE}) endif() add_library(GameAnalytics ${LIB_TYPE} ${CPP_SOURCES}) -target_link_libraries(GameAnalytics PRIVATE ${LIBS} PUBLIC ${PUBLIC_LIBS}) +target_link_libraries(GameAnalytics PRIVATE ${LIBS} PUBLIC ${PUBLIC_LIBS} -lc) message(STATUS "CMAKE_CXX_FLAGS: ${CMAKE_CXX_FLAGS}") message(STATUS "CMAKE_EXE_LINKER_FLAGS: ${CMAKE_EXE_LINKER_FLAGS}") message(STATUS "CMAKE_SHARED_LINKER_FLAGS: ${CMAKE_SHARED_LINKER_FLAGS}") @@ -240,7 +240,7 @@ add_executable(${UT_PROJECT_NAME} ${TEST_SRC_FILES}) ######################################## # Standard linking to gtest and gmock components ######################################## -target_link_libraries(${UT_PROJECT_NAME} gtest gtest_main gmock_main) +target_link_libraries(${UT_PROJECT_NAME} gtest gtest_main gmock_main -lc) ######################################## # Linking to GA SDK From 2cd685c2f27fa88c82646ad78d3c0a823a0a3117 Mon Sep 17 00:00:00 2001 From: Andrei Dabija Date: Fri, 14 Mar 2025 12:39:32 +0200 Subject: [PATCH 26/66] Update CMakeLists.txt --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ee6655c7..0236eb83 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -200,7 +200,7 @@ elseif(LINUX) if (CMAKE_CXX_COMPILER MATCHES "clang") message(STATUS "Detected Clang compiler: ${CMAKE_CXX_COMPILER}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lc++abi") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lc -lc++abi") endif() endif() From c1dbc7d4f9740f63f4ba5e3482003479a5896076 Mon Sep 17 00:00:00 2001 From: Andrei Dabija Date: Fri, 14 Mar 2025 12:57:44 +0200 Subject: [PATCH 27/66] Update CMakeLists.txt --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f298d238..d95c2397 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -199,7 +199,7 @@ elseif(LINUX) if (CMAKE_CXX_COMPILER MATCHES "clang") message(STATUS "Detected Clang compiler: ${CMAKE_CXX_COMPILER}") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++ -D_FILE_OFFSET_BITS=64") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lc -lc++abi") endif() From 2da61b039f1bebddc5f962ac099a92f2f30272d0 Mon Sep 17 00:00:00 2001 From: Andrei Dabija Date: Fri, 14 Mar 2025 12:59:51 +0200 Subject: [PATCH 28/66] Update cmake.yml --- .github/workflows/cmake.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index be8fb862..2e7ec3c4 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -86,6 +86,8 @@ jobs: clang++ --version echo "Checking clang headers..." clang++ -v -E -x c++ /dev/null + echo "check lld..." + ldd --version - name: Configure CMake # Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make. From 02e23647f6d2aa4ebea49776be7db3f99684e637 Mon Sep 17 00:00:00 2001 From: Andrei Dabija Date: Fri, 14 Mar 2025 15:33:51 +0200 Subject: [PATCH 29/66] use with older ubuntu 20.04 --- .github/workflows/cmake.yml | 18 +++++------------- CMakeLists.txt | 4 ++-- 2 files changed, 7 insertions(+), 15 deletions(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 2e7ec3c4..f1f93185 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -31,17 +31,17 @@ jobs: # # To add more build types (Release, Debug, RelWithDebInfo, etc.) customize the build_type list. matrix: - os: [ubuntu-22.04, windows-latest, macOS-latest] + os: [ubuntu-20.04, windows-latest, macOS-latest] build_type: ${{ fromJSON(format('[{0}]', inputs.build_type || '"Debug","Release"')) }} c_compiler: [gcc, clang, cl] include: - os: windows-latest c_compiler: cl cpp_compiler: cl - - os: ubuntu-22.04 + - os: ubuntu-20.04 c_compiler: gcc cpp_compiler: g++ - - os: ubuntu-22.04 + - os: ubuntu-20.04 c_compiler: clang cpp_compiler: clang++ - os: macOS-latest @@ -52,7 +52,7 @@ jobs: c_compiler: gcc - os: windows-latest c_compiler: clang - - os: ubuntu-22.04 + - os: ubuntu-20.04 c_compiler: cl - os: macOS-latest c_compiler: cl @@ -71,16 +71,8 @@ jobs: run: | echo "build-output-dir=${{ github.workspace }}/build" >> "$GITHUB_OUTPUT" - - name: Set Clang 16 as Default - if: matrix.os == 'ubuntu-24.04' && matrix.c_compiler == 'clang' - run: | - sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-16 100 - sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-16 100 - sudo update-alternatives --set clang /usr/bin/clang-16 - sudo update-alternatives --set clang++ /usr/bin/clang++-16 - - name: Check Clang Settings - if: matrix.os == 'ubuntu-22.04' && matrix.c_compiler == 'clang' + if: matrix.os == 'ubuntu-20.04' && matrix.c_compiler == 'clang' run: | clang --version clang++ --version diff --git a/CMakeLists.txt b/CMakeLists.txt index d95c2397..4b027450 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -210,7 +210,7 @@ if(${GA_BUILD_SAMPLE}) endif() add_library(GameAnalytics ${LIB_TYPE} ${CPP_SOURCES}) -target_link_libraries(GameAnalytics PRIVATE ${LIBS} PUBLIC ${PUBLIC_LIBS} -lc) +target_link_libraries(GameAnalytics PRIVATE ${LIBS} PUBLIC ${PUBLIC_LIBS}) message(STATUS "CMAKE_CXX_FLAGS: ${CMAKE_CXX_FLAGS}") message(STATUS "CMAKE_EXE_LINKER_FLAGS: ${CMAKE_EXE_LINKER_FLAGS}") message(STATUS "CMAKE_SHARED_LINKER_FLAGS: ${CMAKE_SHARED_LINKER_FLAGS}") @@ -240,7 +240,7 @@ add_executable(${UT_PROJECT_NAME} ${TEST_SRC_FILES}) ######################################## # Standard linking to gtest and gmock components ######################################## -target_link_libraries(${UT_PROJECT_NAME} gtest gtest_main gmock_main -lc) +target_link_libraries(${UT_PROJECT_NAME} gtest gtest_main gmock_main) ######################################## # Linking to GA SDK From 2cca217f73e2fd344df1adf416f9df4af5016a2a Mon Sep 17 00:00:00 2001 From: Andrei Dabija Date: Fri, 14 Mar 2025 15:40:39 +0200 Subject: [PATCH 30/66] Update cmake.yml --- .github/workflows/cmake.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index f1f93185..a7a673a3 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -71,6 +71,11 @@ jobs: run: | echo "build-output-dir=${{ github.workspace }}/build" >> "$GITHUB_OUTPUT" + - name: Install Clang and Libraries + run: | + sudo apt-get update + sudo apt-get install -y clang libc++-dev libc++abi-dev + - name: Check Clang Settings if: matrix.os == 'ubuntu-20.04' && matrix.c_compiler == 'clang' run: | From 733ef2a94c0adffd140ef7b9897b48db8a013b29 Mon Sep 17 00:00:00 2001 From: Andrei Dabija Date: Fri, 14 Mar 2025 15:44:16 +0200 Subject: [PATCH 31/66] Update cmake.yml --- .github/workflows/cmake.yml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index a7a673a3..a28e7393 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -31,17 +31,17 @@ jobs: # # To add more build types (Release, Debug, RelWithDebInfo, etc.) customize the build_type list. matrix: - os: [ubuntu-20.04, windows-latest, macOS-latest] + os: [ubuntu-24.04, windows-latest, macOS-latest] build_type: ${{ fromJSON(format('[{0}]', inputs.build_type || '"Debug","Release"')) }} c_compiler: [gcc, clang, cl] include: - os: windows-latest c_compiler: cl cpp_compiler: cl - - os: ubuntu-20.04 + - os: ubuntu-24.04 c_compiler: gcc cpp_compiler: g++ - - os: ubuntu-20.04 + - os: ubuntu-24.04 c_compiler: clang cpp_compiler: clang++ - os: macOS-latest @@ -52,7 +52,7 @@ jobs: c_compiler: gcc - os: windows-latest c_compiler: clang - - os: ubuntu-20.04 + - os: ubuntu-24.04 c_compiler: cl - os: macOS-latest c_compiler: cl @@ -72,12 +72,13 @@ jobs: echo "build-output-dir=${{ github.workspace }}/build" >> "$GITHUB_OUTPUT" - name: Install Clang and Libraries + if: matrix.os == 'ubuntu-24.04' && matrix.c_compiler == 'clang' run: | sudo apt-get update sudo apt-get install -y clang libc++-dev libc++abi-dev - name: Check Clang Settings - if: matrix.os == 'ubuntu-20.04' && matrix.c_compiler == 'clang' + if: matrix.os == 'ubuntu-24.04' && matrix.c_compiler == 'clang' run: | clang --version clang++ --version From 2a4ad72d0c3ced5dc449491ea883d828d577f5f1 Mon Sep 17 00:00:00 2001 From: Andrei Dabija Date: Fri, 14 Mar 2025 16:10:39 +0200 Subject: [PATCH 32/66] Update cmake.yml Update CMakeLists.txt Update cmake.yml fix linux compilation issue --- .github/workflows/cmake.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index a28e7393..15681e38 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -77,6 +77,14 @@ jobs: sudo apt-get update sudo apt-get install -y clang libc++-dev libc++abi-dev + - name: Set Clang 16 as Default + if: matrix.os == 'ubuntu-24.04' && matrix.c_compiler == 'clang' + run: | + sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-16 100 + sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-16 100 + sudo update-alternatives --set clang /usr/bin/clang-16 + sudo update-alternatives --set clang++ /usr/bin/clang++-16 + - name: Check Clang Settings if: matrix.os == 'ubuntu-24.04' && matrix.c_compiler == 'clang' run: | From 72a65adb594d1be58fa5ed82b62613a475b179e3 Mon Sep 17 00:00:00 2001 From: Andrei Dabija Date: Fri, 14 Mar 2025 16:36:14 +0200 Subject: [PATCH 33/66] Update cmake.yml --- .github/workflows/cmake.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index a28e7393..f03da2e9 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -31,17 +31,17 @@ jobs: # # To add more build types (Release, Debug, RelWithDebInfo, etc.) customize the build_type list. matrix: - os: [ubuntu-24.04, windows-latest, macOS-latest] + os: [ubuntu-latest, windows-latest, macOS-latest] build_type: ${{ fromJSON(format('[{0}]', inputs.build_type || '"Debug","Release"')) }} c_compiler: [gcc, clang, cl] include: - os: windows-latest c_compiler: cl cpp_compiler: cl - - os: ubuntu-24.04 + - os: ubuntu-latest c_compiler: gcc cpp_compiler: g++ - - os: ubuntu-24.04 + - os: ubuntu-latest c_compiler: clang cpp_compiler: clang++ - os: macOS-latest @@ -52,7 +52,7 @@ jobs: c_compiler: gcc - os: windows-latest c_compiler: clang - - os: ubuntu-24.04 + - os: ubuntu-latest c_compiler: cl - os: macOS-latest c_compiler: cl @@ -72,13 +72,13 @@ jobs: echo "build-output-dir=${{ github.workspace }}/build" >> "$GITHUB_OUTPUT" - name: Install Clang and Libraries - if: matrix.os == 'ubuntu-24.04' && matrix.c_compiler == 'clang' + if: matrix.os == 'ubuntu-latest' && matrix.c_compiler == 'clang' run: | sudo apt-get update sudo apt-get install -y clang libc++-dev libc++abi-dev - name: Check Clang Settings - if: matrix.os == 'ubuntu-24.04' && matrix.c_compiler == 'clang' + if: matrix.os == 'ubuntu-latest' && matrix.c_compiler == 'clang' run: | clang --version clang++ --version From 43f2de434f3635019b903d47307849d6f5108e55 Mon Sep 17 00:00:00 2001 From: Andrei Dabija Date: Wed, 26 Mar 2025 15:07:45 +0200 Subject: [PATCH 34/66] Update CMakeLists.txt --- CMakeLists.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4b027450..868c6b1b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -199,8 +199,7 @@ elseif(LINUX) if (CMAKE_CXX_COMPILER MATCHES "clang") message(STATUS "Detected Clang compiler: ${CMAKE_CXX_COMPILER}") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++ -D_FILE_OFFSET_BITS=64") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lc -lc++abi") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") endif() endif() From 3a572cf147e15945da3583d7aab4778b146c7ca9 Mon Sep 17 00:00:00 2001 From: Dorin Date: Wed, 26 Mar 2025 15:17:13 +0200 Subject: [PATCH 35/66] expose identifiers --- include/GameAnalytics/GameAnalytics.h | 3 +++ source/gameanalytics/GAState.cpp | 7 ++++++- source/gameanalytics/GAState.h | 3 ++- source/gameanalytics/GameAnalytics.cpp | 12 +++++++++++- 4 files changed, 22 insertions(+), 3 deletions(-) diff --git a/include/GameAnalytics/GameAnalytics.h b/include/GameAnalytics/GameAnalytics.h index a5b135c7..622d30d0 100644 --- a/include/GameAnalytics/GameAnalytics.h +++ b/include/GameAnalytics/GameAnalytics.h @@ -110,6 +110,9 @@ namespace gameanalytics static std::string getRemoteConfigsContentAsString(); + static std::string getUserId(); + static std::string getExternalUserId(); + static std::string getABTestingId(); static std::string getABTestingVariantId(); diff --git a/source/gameanalytics/GAState.cpp b/source/gameanalytics/GAState.cpp index 515655a4..2b8c1745 100644 --- a/source/gameanalytics/GAState.cpp +++ b/source/gameanalytics/GAState.cpp @@ -66,6 +66,11 @@ namespace gameanalytics return getInstance()._identifier; } + std::string GAState::getExternalUserId() + { + return getInstance()._externalUserId; + } + bool GAState::isInitialized() { return getInstance()._initialized; @@ -402,7 +407,7 @@ namespace gameanalytics out["event_uuid"] = utilities::GAUtilities::generateUUID(); // User identifier - out["user_id"] = getInstance().getIdentifier(); + out["user_id"] = getUserId(); // remote configs configurations if(getInstance()._configurations.is_object() && !getInstance()._configurations.empty()) diff --git a/source/gameanalytics/GAState.h b/source/gameanalytics/GAState.h index 490bd3a1..020438ea 100644 --- a/source/gameanalytics/GAState.h +++ b/source/gameanalytics/GAState.h @@ -141,6 +141,8 @@ namespace gameanalytics static std::string getRemoteConfigsContentAsString(); static std::string getAbId(); static std::string getAbVariantId(); + static std::string getUserId(); + static std::string getExternalUserId(); static json getValidatedCustomFields(); static json getValidatedCustomFields(const json& withEventFields); @@ -164,7 +166,6 @@ namespace gameanalytics addErrorEvent(severity, msg); } - std::string getIdentifier(); void setDefaultUserId(std::string const& id); json& getSdkConfig(); void cacheIdentifier(); diff --git a/source/gameanalytics/GameAnalytics.cpp b/source/gameanalytics/GameAnalytics.cpp index dfa373ca..60ec105b 100644 --- a/source/gameanalytics/GameAnalytics.cpp +++ b/source/gameanalytics/GameAnalytics.cpp @@ -475,7 +475,7 @@ namespace gameanalytics { // Send to events json fieldsJson = utilities::parseFields(fields); - events::GAEvents::addProgressionEvent(progressionStatus, progression01, progression02, progression03, score, false, fieldsJson, mergeFields); + events::GAEvents::addProgressionEvent(progressionStatus, progression01, progression02, progression03, score, true, fieldsJson, mergeFields); } catch(const json::exception& e) { @@ -763,6 +763,16 @@ namespace gameanalytics return state::GAState::getRemoteConfigsContentAsString(); } + std::string GameAnalytics::getUserId() + { + return state::GAState::getUserId(); + } + + std::string GameAnalytics::getExternalUserId() + { + return state::GAState::getExternalUserId(); + } + std::string GameAnalytics::getABTestingId() { return state::GAState::getAbId(); From 4eb45a451888a9eef85c706a72523777709ca20d Mon Sep 17 00:00:00 2001 From: Dorin Date: Wed, 26 Mar 2025 15:27:49 +0200 Subject: [PATCH 36/66] renamed getUserId --- source/gameanalytics/GAState.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/gameanalytics/GAState.cpp b/source/gameanalytics/GAState.cpp index 2b8c1745..13fd7a90 100644 --- a/source/gameanalytics/GAState.cpp +++ b/source/gameanalytics/GAState.cpp @@ -61,7 +61,7 @@ namespace gameanalytics getInstance().cacheIdentifier(); } - std::string GAState::getIdentifier() + std::string GAState::getUserId() { return getInstance()._identifier; } From dc8672185288d8d9a7b810353e2a73a5f45736df Mon Sep 17 00:00:00 2001 From: Dorin Date: Thu, 22 May 2025 12:49:54 +0300 Subject: [PATCH 37/66] added gpu model --- source/gameanalytics/GADevice.h | 1 + 1 file changed, 1 insertion(+) diff --git a/source/gameanalytics/GADevice.h b/source/gameanalytics/GADevice.h index 7ab1e825..eca493db 100644 --- a/source/gameanalytics/GADevice.h +++ b/source/gameanalytics/GADevice.h @@ -78,6 +78,7 @@ namespace gameanalytics std::string _osVersion; std::string _deviceModel; std::string _deviceManufacturer; + std::string _gpu; std::string _writablepath; bool _writablepathStatus{false}; From b57c30549442675cdec3eb9623e75b7e99fd4fbc Mon Sep 17 00:00:00 2001 From: Dorin Date: Thu, 22 May 2025 12:51:05 +0300 Subject: [PATCH 38/66] playtime support --- include/GameAnalytics/GameAnalytics.h | 3 ++ source/gameanalytics/GAEvents.cpp | 3 +- source/gameanalytics/GAState.cpp | 41 +++++++++++++++++++++------ source/gameanalytics/GAState.h | 18 ++++++++++-- 4 files changed, 52 insertions(+), 13 deletions(-) diff --git a/include/GameAnalytics/GameAnalytics.h b/include/GameAnalytics/GameAnalytics.h index 622d30d0..5a72cdd3 100644 --- a/include/GameAnalytics/GameAnalytics.h +++ b/include/GameAnalytics/GameAnalytics.h @@ -116,6 +116,9 @@ namespace gameanalytics static std::string getABTestingId(); static std::string getABTestingVariantId(); + static int64_t getElapsedSessionTime(); + static int64_t getElapsedTimeFromAllSessions(); + // game state changes // will affect how session is started / ended static void onResume(); diff --git a/source/gameanalytics/GAEvents.cpp b/source/gameanalytics/GAEvents.cpp index 9cbc710d..64d58ecd 100644 --- a/source/gameanalytics/GAEvents.cpp +++ b/source/gameanalytics/GAEvents.cpp @@ -116,7 +116,8 @@ namespace gameanalytics try { - int64_t sessionLength = state.calculateSessionLength(); + // get session length in seconds + int64_t sessionLength = state.calculateSessionLength(); if(sessionLength < 0ll) { diff --git a/source/gameanalytics/GAState.cpp b/source/gameanalytics/GAState.cpp index 13fd7a90..e1dc80ee 100644 --- a/source/gameanalytics/GAState.cpp +++ b/source/gameanalytics/GAState.cpp @@ -57,7 +57,7 @@ namespace gameanalytics return; } - getInstance()._userId = id; + getInstance()._customUserId = id; getInstance().cacheIdentifier(); } @@ -383,6 +383,7 @@ namespace gameanalytics logging::GALogger::i("Ending session."); if (GAState::isEnabled() && GAState::sessionIsStarted()) { + getInstance().updateTotalSessionTime(); events::GAEvents::addHealthEvent(); events::GAEvents::addSessionEndEvent(); getInstance()._sessionStart = 0; @@ -505,9 +506,9 @@ namespace gameanalytics void GAState::cacheIdentifier() { - if(!_userId.empty()) + if(!_customUserId.empty()) { - _identifier = _userId; + _identifier = _customUserId; } else { @@ -515,7 +516,6 @@ namespace gameanalytics } logging::GALogger::d("identifier, {clean:%s}", _identifier.c_str()); - } std::string setStateFromCache(json& dict, std::string const& key, std::string const& value) @@ -535,6 +535,11 @@ namespace gameanalytics return ""; } + int64_t GAState::getTotalSessionLength() const + { + return _totalElapsedSessionTime + calculateSessionLength(); + } + void GAState::ensurePersistedStates() { try @@ -555,6 +560,9 @@ namespace gameanalytics } } } + + std::string s = state_dict.dump(); + _gaLogger.d("state_dict: %s", s.c_str()); // insert into GAState instance std::string defaultId = utilities::getOptionalValue(state_dict, "default_user_id"); @@ -575,6 +583,20 @@ namespace gameanalytics _currentCustomDimension01 = setStateFromCache(state_dict, "dimension01", _currentCustomDimension01); _currentCustomDimension02 = setStateFromCache(state_dict, "dimension02", _currentCustomDimension02); _currentCustomDimension03 = setStateFromCache(state_dict, "dimension03", _currentCustomDimension03); + + try + { + std::string cachedSessionTime = utilities::getOptionalValue(state_dict, "total_session_time", "0"); + + _totalElapsedSessionTime = std::stoull(cachedSessionTime); + + } + catch(const std::exception& e) + { + _gaLogger.w("Failed to read total_session_time from cache!"); + _totalElapsedSessionTime = 0; + } + // get cached init call values if (state_dict.contains("sdk_config_cached") && state_dict["sdk_config_cached"].is_string()) @@ -856,11 +878,6 @@ namespace gameanalytics return getInstance()._remoteConfigsIsReady; } - int64_t GAState::calculateSessionLength() const - { - return std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - _startTimepoint).count(); - } - void GAState::addRemoteConfigsListener(const std::shared_ptr& listener) { if(std::find(getInstance()._remoteConfigsListeners.begin(), getInstance()._remoteConfigsListeners.end(), listener) == getInstance()._remoteConfigsListeners.end()) @@ -1043,6 +1060,12 @@ namespace gameanalytics return utilities::GAUtilities::timeIntervalSince1970(); } + void GAState::updateTotalSessionTime() + { + int64_t totalSessionTime = getTotalSessionLength(); + _gaStore.setState("total_session_time", std::to_string(totalSessionTime)); + } + std::string GAState::getBuild() { return getInstance()._build; diff --git a/source/gameanalytics/GAState.h b/source/gameanalytics/GAState.h index 020438ea..6ff1d7f0 100644 --- a/source/gameanalytics/GAState.h +++ b/source/gameanalytics/GAState.h @@ -147,7 +147,15 @@ namespace gameanalytics static json getValidatedCustomFields(); static json getValidatedCustomFields(const json& withEventFields); - int64_t calculateSessionLength() const; + int64_t getTotalSessionLength() const; + + template + inline int64_t calculateSessionLength() const + { + return std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - _startTimepoint).count(); + } + + void populateConfigurations(json& sdkConfig); private: @@ -174,8 +182,11 @@ namespace gameanalytics void validateAndFixCurrentDimensions(); std::string getBuild(); + void updateTotalSessionTime(); + int64_t calculateServerTimeOffset(int64_t serverTs); - void populateConfigurations(json& sdkConfig); + + std::chrono::milliseconds getCurrentSessionLength() const; void validateAndCleanCustomFields(const json& fields, json& out); @@ -192,7 +203,7 @@ namespace gameanalytics store::GAStore _gaStore; http::GAHTTPApi _gaHttp; - std::string _userId; + std::string _customUserId; std::string _identifier; bool _initialized = false; @@ -202,6 +213,7 @@ namespace gameanalytics int64_t _sessionNum = 0; int64_t _transactionNum = 0; + int64_t _totalElapsedSessionTime = 0; std::chrono::high_resolution_clock::time_point _startTimepoint; std::string _sessionId; From 22beea33a899b7d9de3dd4fb38b4b1c9d68077b6 Mon Sep 17 00:00:00 2001 From: Dorin Date: Thu, 22 May 2025 12:51:46 +0300 Subject: [PATCH 39/66] playtime support --- source/gameanalytics/GameAnalytics.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/source/gameanalytics/GameAnalytics.cpp b/source/gameanalytics/GameAnalytics.cpp index 60ec105b..0b187dfd 100644 --- a/source/gameanalytics/GameAnalytics.cpp +++ b/source/gameanalytics/GameAnalytics.cpp @@ -988,4 +988,14 @@ namespace gameanalytics } } + int64_t GameAnalytics::getElapsedTimeFromAllSessions() + { + return state::GAState::getInstance().getTotalSessionLength(); + } + + int64_t GameAnalytics::getElapsedSessionTime() + { + return state::GAState::getInstance().calculateSessionLength(); + } + } // namespace gameanalytics From 9a88dce98127916960097e6a41e7c910c2de6cb0 Mon Sep 17 00:00:00 2001 From: Dorin Date: Thu, 22 May 2025 13:00:44 +0300 Subject: [PATCH 40/66] removed redudant function declaration --- source/gameanalytics/GAState.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/source/gameanalytics/GAState.h b/source/gameanalytics/GAState.h index 6ff1d7f0..df375099 100644 --- a/source/gameanalytics/GAState.h +++ b/source/gameanalytics/GAState.h @@ -186,8 +186,6 @@ namespace gameanalytics int64_t calculateServerTimeOffset(int64_t serverTs); - std::chrono::milliseconds getCurrentSessionLength() const; - void validateAndCleanCustomFields(const json& fields, json& out); void setConfigsHash(std::string const& configsHash); From 89048793f13d441a3bec940211767661f26f1705 Mon Sep 17 00:00:00 2001 From: Dorin Date: Fri, 6 Jun 2025 14:29:55 +0300 Subject: [PATCH 41/66] remote configs v3 --- source/gameanalytics/GAHTTPApi.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/gameanalytics/GAHTTPApi.cpp b/source/gameanalytics/GAHTTPApi.cpp index 394a340c..16e5bbe3 100644 --- a/source/gameanalytics/GAHTTPApi.cpp +++ b/source/gameanalytics/GAHTTPApi.cpp @@ -56,7 +56,7 @@ namespace gameanalytics std::string gameKey = state::GAState::getGameKey(); // Generate URL - std::string url = remoteConfigsBaseUrl + "/" + initializeUrlPath + "?game_key=" + gameKey + "&interval_seconds=0&configs_hash=" + configsHash; + std::string url = remoteConfigsBaseUrl + "/" + initializeUrlPath + "?game_key=" + gameKey + "&interval_seconds=0&configs_hash=" + configsHash + "&config_vsn_supported=3"; logging::GALogger::d("Sending 'init' URL: %s", url.c_str()); From bea39258b11967865fd687e3f7aab8bc6b35232e Mon Sep 17 00:00:00 2001 From: Dorin Date: Fri, 6 Jun 2025 14:31:02 +0300 Subject: [PATCH 42/66] remote configs v3 support --- source/gameanalytics/GAState.cpp | 54 +++++++++++++++++++++----------- source/gameanalytics/GAState.h | 24 +++++++++++--- 2 files changed, 56 insertions(+), 22 deletions(-) diff --git a/source/gameanalytics/GAState.cpp b/source/gameanalytics/GAState.cpp index e1dc80ee..01a4c912 100644 --- a/source/gameanalytics/GAState.cpp +++ b/source/gameanalytics/GAState.cpp @@ -413,7 +413,7 @@ namespace gameanalytics // remote configs configurations if(getInstance()._configurations.is_object() && !getInstance()._configurations.empty()) { - out["configurations"] = getInstance()._configurations; + out["configurations_v3"] = getInstance().getRemoteConfigAnnotations(); } out["sdk_version"] = device::GADevice::getRelevantSdkVersion(); @@ -865,14 +865,6 @@ namespace gameanalytics return getInstance()._sessionStart != 0; } - std::string GAState::getRemoteConfigsStringValue(std::string const& key, std::string const& defaultValue) - { - std::lock_guard lg(getInstance()._mtx); - std::string const value = utilities::getOptionalValue(getInstance()._configurations, key, defaultValue); - - return value; - } - bool GAState::isRemoteConfigsReady() { return getInstance()._remoteConfigsIsReady; @@ -900,12 +892,28 @@ namespace gameanalytics std::string GAState::getRemoteConfigsContentAsString() { std::lock_guard lg(getInstance()._mtx); - return getInstance()._configurations.dump(JSON_PRINT_INDENT); + + json contents; + + for(auto& obj : getInstance()._configurations) + { + if(obj.contains("key") && obj.contains("value")) + { + std::string key = utilities::getOptionalValue(obj, "key", ""); + if(!key.empty()) + { + contents[key] = obj["value"]; + } + } + } + + return contents.dump(JSON_PRINT_INDENT); } void GAState::populateConfigurations(json& sdkConfig) { std::lock_guard guard(_mtx); + _configurations = {}; try { @@ -918,21 +926,15 @@ namespace gameanalytics if (!configuration.empty()) { std::string key = utilities::getOptionalValue(configuration, "key", ""); - int64_t start_ts = utilities::getOptionalValue(configuration, "start_ts", std::numeric_limits::min()); - int64_t end_ts = utilities::getOptionalValue(configuration, "end_ts", std::numeric_limits::max()); int64_t client_ts_adjusted = getClientTsAdjusted(); if (!key.empty() && configuration.contains("value") && client_ts_adjusted > start_ts && client_ts_adjusted < end_ts) { - json& value = configuration["value"]; - if (value.is_string() || value.is_number()) - { - _configurations[key] = value; - logging::GALogger::d("configuration added: %s", configuration.dump(JSON_PRINT_INDENT).c_str()); - } + _configurations[key] = configuration; + logging::GALogger::d("configuration added: %s", configuration.dump(JSON_PRINT_INDENT).c_str()); } } } @@ -1155,5 +1157,21 @@ namespace gameanalytics return cleanedFields; } + + json GAState::getRemoteConfigAnnotations() + { + json configs; + for(json& obj : _configurations) + { + json cfg; + cfg["vsn"] = utilities::getOptionalValue(obj, "vsn", 0); + cfg["key"] = utilities::getOptionalValue(obj, "key", ""); + cfg["id"] = utilities::getOptionalValue(obj, "id", ""); + + configs.push_back(cfg); + } + + return configs; + } } } diff --git a/source/gameanalytics/GAState.h b/source/gameanalytics/GAState.h index df375099..b2da9593 100644 --- a/source/gameanalytics/GAState.h +++ b/source/gameanalytics/GAState.h @@ -134,7 +134,6 @@ namespace gameanalytics static void setEnabledEventSubmission(bool flag); static bool isEventSubmissionEnabled(); static bool sessionIsStarted(); - static std::string getRemoteConfigsStringValue(std::string const& key, std::string const& defaultValue); static bool isRemoteConfigsReady(); static void addRemoteConfigsListener(const std::shared_ptr& listener); static void removeRemoteConfigsListener(const std::shared_ptr& listener); @@ -147,16 +146,33 @@ namespace gameanalytics static json getValidatedCustomFields(); static json getValidatedCustomFields(const json& withEventFields); - int64_t getTotalSessionLength() const; + template + inline static T getRemoteConfigsValue(std::string const& key, T const& defaultValue) + { + std::lock_guard lg(getInstance()._mtx); + if(getInstance()._configurations.contains(key)) + { + json& config = getInstance()._configurations[key]; + T value = utilities::getOptionalValue(config, "value", defaultValue); + return value; + } + + return defaultValue; + } template inline int64_t calculateSessionLength() const { - return std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - _startTimepoint).count(); + auto len = std::chrono::high_resolution_clock::now() - _startTimepoint; + return std::chrono::duration_cast(len).count(); } + int64_t getTotalSessionLength() const; + void populateConfigurations(json& sdkConfig); + json getRemoteConfigAnnotations(); + private: GAState(); @@ -184,7 +200,7 @@ namespace gameanalytics void updateTotalSessionTime(); - int64_t calculateServerTimeOffset(int64_t serverTs); + int64_t calculateServerTimeOffset(int64_t serverTs); void validateAndCleanCustomFields(const json& fields, json& out); From f4f36eb096b6960a8cfcc58bc05cabc797587812 Mon Sep 17 00:00:00 2001 From: Dorin Date: Fri, 6 Jun 2025 14:33:39 +0300 Subject: [PATCH 43/66] do not drop fps values outside range --- source/gameanalytics/GAHealth.cpp | 8 +++----- source/gameanalytics/GAHealth.h | 3 ++- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/source/gameanalytics/GAHealth.cpp b/source/gameanalytics/GAHealth.cpp index 6edab39e..a8a93e09 100644 --- a/source/gameanalytics/GAHealth.cpp +++ b/source/gameanalytics/GAHealth.cpp @@ -24,10 +24,9 @@ namespace gameanalytics void GAHealth::doFpsReading(float fps) { int fpsBucket = std::round(fps); - if(fpsBucket >= 0 && fpsBucket < MAX_FPS_COUNT) - { - _fpsReadings[fpsBucket]++; - } + fpsBucket = std::clamp(fpsBucket, 0, MAX_FPS_VALUE); + + _fpsReadings[fpsBucket]++; } int GAHealth::getMemoryPercent(int64_t memory) @@ -169,7 +168,6 @@ namespace gameanalytics } } ); - } } } diff --git a/source/gameanalytics/GAHealth.h b/source/gameanalytics/GAHealth.h index 94361c19..014c2ed3 100644 --- a/source/gameanalytics/GAHealth.h +++ b/source/gameanalytics/GAHealth.h @@ -29,7 +29,8 @@ namespace gameanalytics protected: - static constexpr size_t MAX_FPS_COUNT = 120 + 1; + static constexpr int MAX_FPS_VALUE = 120; + static constexpr size_t MAX_FPS_COUNT = MAX_FPS_VALUE + 1; static constexpr size_t MAX_MEMORY_COUNT = 100 + 1; static constexpr std::chrono::milliseconds MEMORY_TRACK_FREQ {5000}; From 796c6c94b43e7a5627254d26a5fff3908c93c605 Mon Sep 17 00:00:00 2001 From: Dorin Date: Fri, 6 Jun 2025 14:41:12 +0300 Subject: [PATCH 44/66] features for remote configs v3 --- include/GameAnalytics/GameAnalytics.h | 11 ++++ source/gameanalytics/GameAnalytics.cpp | 84 ++++++++++++++++++++++++-- 2 files changed, 89 insertions(+), 6 deletions(-) diff --git a/include/GameAnalytics/GameAnalytics.h b/include/GameAnalytics/GameAnalytics.h index 5a72cdd3..34bf1090 100644 --- a/include/GameAnalytics/GameAnalytics.h +++ b/include/GameAnalytics/GameAnalytics.h @@ -102,7 +102,17 @@ namespace gameanalytics static void startSession(); static void endSession(); + /* + template + static T getRemoteConfigsValue(std::string const& key, T const& defaultValue); + */ + static std::string getRemoteConfigsValueAsString(std::string const& key, std::string const& defaultValue = ""); + static int64_t getRemoteConfigsValueAsInt(std::string const& key, int64_t defaultValue = 0); + static uint64_t getRemoteConfigsValueAsUInt(std::string const& key, uint64_t defaultValue = 0); + static bool getRemoteConfigsValueAsBool(std::string const& key, bool defaultValue = false); + static double getRemoteConfigsValueAsFloat(std::string const& key, double defaultValue = 0.0); + static std::string getRemoteConfigsValueAsJson(std::string const& key); static bool isRemoteConfigsReady(); static void addRemoteConfigsListener(const std::shared_ptr &listener); @@ -134,4 +144,5 @@ namespace gameanalytics static bool isSdkReady(bool needsInitialized, bool warn); static bool isSdkReady(bool needsInitialized, bool warn, std::string const& message); }; + } // namespace gameanalytics diff --git a/source/gameanalytics/GameAnalytics.cpp b/source/gameanalytics/GameAnalytics.cpp index 0b187dfd..dbc4e388 100644 --- a/source/gameanalytics/GameAnalytics.cpp +++ b/source/gameanalytics/GameAnalytics.cpp @@ -740,7 +740,78 @@ namespace gameanalytics std::string GameAnalytics::getRemoteConfigsValueAsString(std::string const& key, std::string const& defaultValue) { - return state::GAState::getRemoteConfigsStringValue(key, defaultValue); + return state::GAState::getRemoteConfigsValue(key, defaultValue); + } + + int64_t GameAnalytics::getRemoteConfigsValueAsInt(std::string const& key, int64_t defaultValue) + { + try + { + std::string s = getRemoteConfigsValueAsString(key); + if(!s.empty()) + { + return std::stoll(s); + } + } + catch(std::exception& e) + { + (void)e; + } + + return defaultValue; + } + + uint64_t GameAnalytics::getRemoteConfigsValueAsUInt(std::string const& key, uint64_t defaultValue) + { + try + { + std::string s = getRemoteConfigsValueAsString(key); + if(!s.empty()) + { + return std::stoull(s); + } + } + catch(std::exception& e) + { + (void)e; + } + + return defaultValue; + } + + double GameAnalytics::getRemoteConfigsValueAsFloat(std::string const& key, double defaultValue) + { + try + { + std::string s = getRemoteConfigsValueAsString(key); + if(!s.empty()) + { + return std::stod(s); + } + } + catch(std::exception& e) + { + (void)e; + } + + return defaultValue; + } + + bool GameAnalytics::getRemoteConfigsValueAsBool(std::string const& key, bool defaultValue) + { + std::string s = getRemoteConfigsValueAsString(key, "false"); + return utilities::toLowerCase(s) == "true"; + } + + std::string GameAnalytics::getRemoteConfigsValueAsJson(std::string const& key) + { + std::string jsonString = getRemoteConfigsValueAsString(key); + if(!json::accept(jsonString)) + { + return ""; + } + + return jsonString; } bool GameAnalytics::isRemoteConfigsReady() @@ -874,8 +945,9 @@ namespace gameanalytics std::this_thread::sleep_for(std::chrono::milliseconds(100)); } } - catch (const std::exception&) + catch (const std::exception& e) { + logging::GALogger::e(e.what()); } } @@ -906,7 +978,7 @@ namespace gameanalytics { if (warn) { - logging::GALogger::w("%sDatastore not initialized", m.c_str()); + logging::GALogger::w("%s; Datastore not initialized", m.c_str()); } return false; } @@ -915,7 +987,7 @@ namespace gameanalytics { if (warn) { - logging::GALogger::w("%sSDK is not initialized", m.c_str()); + logging::GALogger::w("%s; SDK is not initialized", m.c_str()); } return false; } @@ -924,7 +996,7 @@ namespace gameanalytics { if (warn) { - logging::GALogger::w("%s;SDK is disabled", m.c_str()); + logging::GALogger::w("%s; SDK is disabled", m.c_str()); } return false; } @@ -934,7 +1006,7 @@ namespace gameanalytics { if (warn) { - logging::GALogger::w("%s;Session has not started yet", m.c_str()); + logging::GALogger::w("%s; Session has not started yet", m.c_str()); } return false; } From 6d1e591c1fb5980dcf9a43fcf0a07d9e2b4a3449 Mon Sep 17 00:00:00 2001 From: Dorin Date: Fri, 6 Jun 2025 14:48:28 +0300 Subject: [PATCH 45/66] track gpu model --- source/gameanalytics/GAHealth.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/source/gameanalytics/GAHealth.cpp b/source/gameanalytics/GAHealth.cpp index a8a93e09..1f301d3b 100644 --- a/source/gameanalytics/GAHealth.cpp +++ b/source/gameanalytics/GAHealth.cpp @@ -64,6 +64,7 @@ namespace gameanalytics { utilities::addIfNotEmpty(out, "cpu_model", _cpuModel); utilities::addIfNotEmpty(out, "hardware", _hardware); + utilities::addIfNotEmpty(out, "gpu_model", _gpuModel); if(_numCores > 0) { From 01b4543d56e7e2a894f47d873cb9f7a2b172b4b5 Mon Sep 17 00:00:00 2001 From: Dorin Date: Fri, 6 Jun 2025 15:00:28 +0300 Subject: [PATCH 46/66] fixed gpu model retrieval for windows --- source/gameanalytics/Platform/GAWin32.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/source/gameanalytics/Platform/GAWin32.cpp b/source/gameanalytics/Platform/GAWin32.cpp index f63d8320..aaa8e2e0 100644 --- a/source/gameanalytics/Platform/GAWin32.cpp +++ b/source/gameanalytics/Platform/GAWin32.cpp @@ -233,16 +233,18 @@ std::string GAPlatformWin32::getGpuModel() const DISPLAY_DEVICE device; ZeroMemory(&device, sizeof(DISPLAY_DEVICE)); - if(EnumDisplayDevices(NULL, 0, &device, 0)) + device.cb = sizeof(DISPLAY_DEVICE); + + if(EnumDisplayDevices(NULL, 0, &device, EDD_GET_DEVICE_INTERFACE_NAME)) { #ifdef UNICODE - return utilities::GAUtilities::ws2s(device.DeviceName); + return utilities::GAUtilities::ws2s(device.DeviceString); #else - return device.DeviceName; + return device.DeviceString; #endif } - return UNKNOWN_VALUE; + return ""; } int GAPlatformWin32::getNumCpuCores() const From d76234dfcf8fcea56e1e587bd5a266f47da517a0 Mon Sep 17 00:00:00 2001 From: Andrei Dabija Date: Mon, 23 Jun 2025 08:22:23 +0300 Subject: [PATCH 47/66] Fix zlib issues (#28) * create internal compression component * use the new miniz code * Update README.md --- README.md | 2 +- .../miniz/{miniz.c => GA_Zip.cpp} | 22 ++++++------------- source/gameanalytics/GAUtilities.cpp | 4 +++- 3 files changed, 11 insertions(+), 17 deletions(-) rename source/dependencies/miniz/{miniz.c => GA_Zip.cpp} (99%) diff --git a/README.md b/README.md index 04a2cb97..fddbfb38 100644 --- a/README.md +++ b/README.md @@ -123,7 +123,7 @@ Example: Example: ``` c++ - gameanalytics::GameAnalytics::initialize("", "", ""); ``` ### Send events diff --git a/source/dependencies/miniz/miniz.c b/source/dependencies/miniz/GA_Zip.cpp similarity index 99% rename from source/dependencies/miniz/miniz.c rename to source/dependencies/miniz/GA_Zip.cpp index 2b787fbf..31f5841f 100644 --- a/source/dependencies/miniz/miniz.c +++ b/source/dependencies/miniz/GA_Zip.cpp @@ -219,9 +219,9 @@ #define MINIZ_HAS_64BIT_REGISTERS 1 #endif -#ifdef __cplusplus -extern "C" { -#endif +namespace gameanalytics { +namespace utilities { +namespace zip { // ------------------- zlib-style API Definitions. @@ -919,10 +919,6 @@ mz_uint32 tdefl_get_adler32(tdefl_compressor *d); mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits, int strategy); #endif // #ifndef MINIZ_NO_ZLIB_APIS -#ifdef __cplusplus -} -#endif - #endif // MINIZ_HEADER_INCLUDED // ------------------- End of Header: Implementation follows. (If you only want the header, define MINIZ_HEADER_FILE_ONLY.) @@ -968,10 +964,6 @@ typedef unsigned char mz_validate_uint64[sizeof(mz_uint64)==8 ? 1 : -1]; #define MZ_FORCEINLINE inline #endif -#ifdef __cplusplus - extern "C" { -#endif - // ------------------- zlib-style API's mz_ulong mz_adler32(mz_ulong adler, const unsigned char *ptr, size_t buf_len) @@ -4882,12 +4874,12 @@ void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename, const char #endif // #ifndef MINIZ_NO_ARCHIVE_APIS -#ifdef __cplusplus -} -#endif - #endif // MINIZ_HEADER_FILE_ONLY +} // namespace zip +} // namespace utilities +} // namespace gameanalytics + /* This is free and unencumbered software released into the public domain. diff --git a/source/gameanalytics/GAUtilities.cpp b/source/gameanalytics/GAUtilities.cpp index bbb1807c..2f98626e 100644 --- a/source/gameanalytics/GAUtilities.cpp +++ b/source/gameanalytics/GAUtilities.cpp @@ -20,12 +20,14 @@ // From crypto #define MINIZ_HEADER_FILE_ONLY -#include "miniz.c" +#include "GA_Zip.cpp" namespace gameanalytics { namespace utilities { + using namespace zip; + std::string printArray(StringVector const& v, std::string const& delim) { if(v.empty()) From d0ce87328f0c5aa6753599bff89807a2e7829c42 Mon Sep 17 00:00:00 2001 From: Andrei Dabija Date: Fri, 22 Aug 2025 12:00:55 +0300 Subject: [PATCH 48/66] 5.0.0 release prep (#30) * rename remote configs members * split remote configs in game and annotation cfgs * add 5.0.0 release notes --- CHANGELOG.md | 7 +++++ source/gameanalytics/GACommon.h | 2 +- source/gameanalytics/GAState.cpp | 51 +++++++++++++++++++++----------- source/gameanalytics/GAState.h | 10 +++++-- 4 files changed, 48 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4329e0f3..27975727 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## 5.0.0 + +### Added + +- **Remote Configs With JSON**: Remote Configs now support JSON values, allowing for more complex configurations. +- **Playtime Metrics API**: Introduced new API to get total playtime and playtime in the current session. + ## 4.1.0 ### Added diff --git a/source/gameanalytics/GACommon.h b/source/gameanalytics/GACommon.h index e761edb8..37f533c6 100644 --- a/source/gameanalytics/GACommon.h +++ b/source/gameanalytics/GACommon.h @@ -85,7 +85,7 @@ namespace gameanalytics class GAState; } - constexpr const char* GA_VERSION_STR = "cpp 4.1.0"; + constexpr const char* GA_VERSION_STR = "cpp 5.0.0"; constexpr int MAX_CUSTOM_FIELDS_COUNT = 50; constexpr int MAX_CUSTOM_FIELDS_KEY_LENGTH = 64; diff --git a/source/gameanalytics/GAState.cpp b/source/gameanalytics/GAState.cpp index 01a4c912..ae3ba089 100644 --- a/source/gameanalytics/GAState.cpp +++ b/source/gameanalytics/GAState.cpp @@ -411,7 +411,7 @@ namespace gameanalytics out["user_id"] = getUserId(); // remote configs configurations - if(getInstance()._configurations.is_object() && !getInstance()._configurations.empty()) + if(getInstance()._trackingRemoteConfigsJson.is_array() && !getInstance()._trackingRemoteConfigsJson.empty()) { out["configurations_v3"] = getInstance().getRemoteConfigAnnotations(); } @@ -895,7 +895,7 @@ namespace gameanalytics json contents; - for(auto& obj : getInstance()._configurations) + for(auto& obj : getInstance()._gameRemoteConfigsJson) { if(obj.contains("key") && obj.contains("value")) { @@ -910,10 +910,34 @@ namespace gameanalytics return contents.dump(JSON_PRINT_INDENT); } + void GAState::buildRemoteConfigsJsons(const json& remoteCfgs) + { + _gameRemoteConfigsJson = json::array(); + _trackingRemoteConfigsJson = json::array(); + + for (const auto& configuration : remoteCfgs) + { + _gameRemoteConfigsJson.push_back({ + {"key", configuration["key"]}, + {"value", configuration["value"]} + }); + + _trackingRemoteConfigsJson.push_back({ + {"key", configuration["key"]}, + {"id", configuration["id"]}, + {"vsn", configuration["vsn"]} + }); + } + + logging::GALogger::d("Remote configs: %s", _gameRemoteConfigsJson.dump(JSON_PRINT_INDENT).c_str()); + logging::GALogger::d("Remote configs for tracking: %s", _trackingRemoteConfigsJson.dump(JSON_PRINT_INDENT).c_str()); + logging::GALogger::i("Remote configs ready with %zu configurations", _gameRemoteConfigsJson.size()); + } + void GAState::populateConfigurations(json& sdkConfig) { - std::lock_guard guard(_mtx); - _configurations = {}; + + json _tempRemoteConfigsJson = {}; try { @@ -933,16 +957,18 @@ namespace gameanalytics if (!key.empty() && configuration.contains("value") && client_ts_adjusted > start_ts && client_ts_adjusted < end_ts) { - _configurations[key] = configuration; + _tempRemoteConfigsJson[key] = configuration; logging::GALogger::d("configuration added: %s", configuration.dump(JSON_PRINT_INDENT).c_str()); } } } } + buildRemoteConfigsJsons(_tempRemoteConfigsJson); + _remoteConfigsIsReady = true; - std::string const configStr = _configurations.dump(); + std::string const configStr = _gameRemoteConfigsJson.dump(); for (auto& listener : _remoteConfigsListeners) { listener->onRemoteConfigsUpdated(configStr); @@ -1160,18 +1186,7 @@ namespace gameanalytics json GAState::getRemoteConfigAnnotations() { - json configs; - for(json& obj : _configurations) - { - json cfg; - cfg["vsn"] = utilities::getOptionalValue(obj, "vsn", 0); - cfg["key"] = utilities::getOptionalValue(obj, "key", ""); - cfg["id"] = utilities::getOptionalValue(obj, "id", ""); - - configs.push_back(cfg); - } - - return configs; + return _trackingRemoteConfigsJson; } } } diff --git a/source/gameanalytics/GAState.h b/source/gameanalytics/GAState.h index b2da9593..346a0b86 100644 --- a/source/gameanalytics/GAState.h +++ b/source/gameanalytics/GAState.h @@ -150,9 +150,9 @@ namespace gameanalytics inline static T getRemoteConfigsValue(std::string const& key, T const& defaultValue) { std::lock_guard lg(getInstance()._mtx); - if(getInstance()._configurations.contains(key)) + if(getInstance()._gameRemoteConfigsJson.contains(key)) { - json& config = getInstance()._configurations[key]; + json& config = getInstance()._gameRemoteConfigsJson[key]; T value = utilities::getOptionalValue(config, "value", defaultValue); return value; } @@ -210,6 +210,8 @@ namespace gameanalytics void addErrorEvent(EGAErrorSeverity severity, std::string const& message); + void buildRemoteConfigsJsons(const json& remoteCfgs); + threading::GAThreading _gaThread; events::GAEvents _gaEvents; device::GADevice _gaDevice; @@ -271,7 +273,9 @@ namespace gameanalytics bool _enableIdTracking = true; - json _configurations; + json _gameRemoteConfigsJson; + json _trackingRemoteConfigsJson; + bool _remoteConfigsIsReady; std::vector> _remoteConfigsListeners; std::recursive_mutex _mtx; From f7c058f25f71cd9e342b3d0e1f392c6d2addd046 Mon Sep 17 00:00:00 2001 From: Dorin Date: Fri, 22 Aug 2025 14:31:56 +0300 Subject: [PATCH 49/66] use default arguments instead of duplicated functions --- include/GameAnalytics/GameAnalytics.h | 6 ++---- source/gameanalytics/GameAnalytics.cpp | 12 ------------ 2 files changed, 2 insertions(+), 16 deletions(-) diff --git a/include/GameAnalytics/GameAnalytics.h b/include/GameAnalytics/GameAnalytics.h index 34bf1090..eab66a41 100644 --- a/include/GameAnalytics/GameAnalytics.h +++ b/include/GameAnalytics/GameAnalytics.h @@ -138,11 +138,9 @@ namespace gameanalytics static bool isThreadEnding(); private: - static bool _endThread; - static bool isSdkReady(bool needsInitialized); - static bool isSdkReady(bool needsInitialized, bool warn); - static bool isSdkReady(bool needsInitialized, bool warn, std::string const& message); + static bool _endThread; + static bool isSdkReady(bool needsInitialized, bool warn = true, std::string const& message = ""); }; } // namespace gameanalytics diff --git a/source/gameanalytics/GameAnalytics.cpp b/source/gameanalytics/GameAnalytics.cpp index dbc4e388..d00655e8 100644 --- a/source/gameanalytics/GameAnalytics.cpp +++ b/source/gameanalytics/GameAnalytics.cpp @@ -956,18 +956,6 @@ namespace gameanalytics return _endThread || threading::GAThreading::isThreadFinished(); } - // --------------PRIVATE HELPERS -------------- // - - bool GameAnalytics::isSdkReady(bool needsInitialized) - { - return isSdkReady(needsInitialized, true); - } - - bool GameAnalytics::isSdkReady(bool needsInitialized, bool warn) - { - return isSdkReady(needsInitialized, warn, ""); - } - bool GameAnalytics::isSdkReady(bool needsInitialized, bool warn, std::string const& message) { constexpr std::size_t maxMsgLen = 64u; From 855d73171cf8416ffb8b687beb3e18df0cadfd1c Mon Sep 17 00:00:00 2001 From: Dorin Date: Fri, 22 Aug 2025 14:32:53 +0300 Subject: [PATCH 50/66] remove redudndant functions --- include/GameAnalytics/GameAnalytics.h | 4 --- source/gameanalytics/GameAnalytics.cpp | 42 -------------------------- 2 files changed, 46 deletions(-) diff --git a/include/GameAnalytics/GameAnalytics.h b/include/GameAnalytics/GameAnalytics.h index eab66a41..ee0620eb 100644 --- a/include/GameAnalytics/GameAnalytics.h +++ b/include/GameAnalytics/GameAnalytics.h @@ -108,10 +108,6 @@ namespace gameanalytics */ static std::string getRemoteConfigsValueAsString(std::string const& key, std::string const& defaultValue = ""); - static int64_t getRemoteConfigsValueAsInt(std::string const& key, int64_t defaultValue = 0); - static uint64_t getRemoteConfigsValueAsUInt(std::string const& key, uint64_t defaultValue = 0); - static bool getRemoteConfigsValueAsBool(std::string const& key, bool defaultValue = false); - static double getRemoteConfigsValueAsFloat(std::string const& key, double defaultValue = 0.0); static std::string getRemoteConfigsValueAsJson(std::string const& key); static bool isRemoteConfigsReady(); diff --git a/source/gameanalytics/GameAnalytics.cpp b/source/gameanalytics/GameAnalytics.cpp index d00655e8..e47d9d72 100644 --- a/source/gameanalytics/GameAnalytics.cpp +++ b/source/gameanalytics/GameAnalytics.cpp @@ -761,48 +761,6 @@ namespace gameanalytics return defaultValue; } - uint64_t GameAnalytics::getRemoteConfigsValueAsUInt(std::string const& key, uint64_t defaultValue) - { - try - { - std::string s = getRemoteConfigsValueAsString(key); - if(!s.empty()) - { - return std::stoull(s); - } - } - catch(std::exception& e) - { - (void)e; - } - - return defaultValue; - } - - double GameAnalytics::getRemoteConfigsValueAsFloat(std::string const& key, double defaultValue) - { - try - { - std::string s = getRemoteConfigsValueAsString(key); - if(!s.empty()) - { - return std::stod(s); - } - } - catch(std::exception& e) - { - (void)e; - } - - return defaultValue; - } - - bool GameAnalytics::getRemoteConfigsValueAsBool(std::string const& key, bool defaultValue) - { - std::string s = getRemoteConfigsValueAsString(key, "false"); - return utilities::toLowerCase(s) == "true"; - } - std::string GameAnalytics::getRemoteConfigsValueAsJson(std::string const& key) { std::string jsonString = getRemoteConfigsValueAsString(key); From 7f03bd09091cb1f77c0ddd305fa0c2a085749286 Mon Sep 17 00:00:00 2001 From: Dorin Date: Fri, 22 Aug 2025 14:53:45 +0300 Subject: [PATCH 51/66] remove old function --- source/gameanalytics/GameAnalytics.cpp | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/source/gameanalytics/GameAnalytics.cpp b/source/gameanalytics/GameAnalytics.cpp index e47d9d72..76a8604f 100644 --- a/source/gameanalytics/GameAnalytics.cpp +++ b/source/gameanalytics/GameAnalytics.cpp @@ -743,24 +743,6 @@ namespace gameanalytics return state::GAState::getRemoteConfigsValue(key, defaultValue); } - int64_t GameAnalytics::getRemoteConfigsValueAsInt(std::string const& key, int64_t defaultValue) - { - try - { - std::string s = getRemoteConfigsValueAsString(key); - if(!s.empty()) - { - return std::stoll(s); - } - } - catch(std::exception& e) - { - (void)e; - } - - return defaultValue; - } - std::string GameAnalytics::getRemoteConfigsValueAsJson(std::string const& key) { std::string jsonString = getRemoteConfigsValueAsString(key); From def7929f7ec1f532187d3874be5320203b96b46b Mon Sep 17 00:00:00 2001 From: Dorin Date: Wed, 17 Sep 2025 14:57:43 +0300 Subject: [PATCH 52/66] removed memory allocations from the C imports, add prefix --- source/gameanalytics/GameAnalyticsExtern.cpp | 149 ++++++++----------- source/gameanalytics/GameAnalyticsExtern.h | 122 +++++++-------- 2 files changed, 120 insertions(+), 151 deletions(-) diff --git a/source/gameanalytics/GameAnalyticsExtern.cpp b/source/gameanalytics/GameAnalyticsExtern.cpp index cce12908..0b0fef92 100644 --- a/source/gameanalytics/GameAnalyticsExtern.cpp +++ b/source/gameanalytics/GameAnalyticsExtern.cpp @@ -3,32 +3,6 @@ #include "GameAnalytics/GameAnalytics.h" #include "GAUtilities.h" -void ga_string_alloc(GAString* s, unsigned int size) -{ - if(s) - { - s->str = (const char*)std::malloc(size); - if(s->str) - { - s->size = size; - std::memset(s->str, '\0', s->size); - } - } -} - -void ga_string_free(GAString* s) -{ - if(s) - { - if(s->str && s->size) - { - std::free(s->str); - s->str = NULL; - s->size = 0; - } - } -} - StringVector makeStringVector(const char** arr, int size) { if(size > 0 && arr) @@ -48,67 +22,72 @@ StringVector makeStringVector(const char** arr, int size) return {}; } -GAString ga_string_fromString(std::string const& s) +GAErrorCode copyStringBuffer(std::string const& s, char* out, int* size) { - GAString gaStr = {}; - const unsigned int len = s.length() + 1; - ga_string_alloc(&gaStr, len); - - if(gaStr->str && gaStr->size) + if(size && (*size > 0)) { - std::memcpy(gaStr, s.data(), s.length()); - gaStr[len - 1] = '\0'; + if(out && (*size >= s.size())) + { + std::memcpy(out, s.data(), s.size()); + } + else + { + return EGABufferError; + } + + *size = s.size(); + return EGANoError; } - return gaStr; + return EGAFailure; } -void configureAvailableCustomDimensions01(const char **customDimensions, int size) +void gameAnalytics_configureAvailableCustomDimensions01(const char **customDimensions, int size) { StringVector values = makeStringVector(customDimensions, size); gameanalytics::GameAnalytics::configureAvailableCustomDimensions01(values); } -void configureAvailableCustomDimensions02(const char **customDimensions, int size) +void gameAnalytics_configureAvailableCustomDimensions02(const char **customDimensions, int size) { StringVector values = makeStringVector(customDimensions, size); gameanalytics::GameAnalytics::configureAvailableCustomDimensions02(values); } -void configureAvailableCustomDimensions03(const char **customDimensions, int size) +void gameAnalytics_configureAvailableCustomDimensions03(const char **customDimensions, int size) { StringVector values = makeStringVector(customDimensions, size); gameanalytics::GameAnalytics::configureAvailableCustomDimensions03(values); } -void configureAvailableResourceCurrencies(const char** currencies, int size) +void gameAnalytics_configureAvailableResourceCurrencies(const char** currencies, int size) { StringVector values = makeStringVector(currencies, size); gameanalytics::GameAnalytics::configureAvailableResourceCurrencies(values); } -void configureAvailableResourceItemTypes(const char** resources, int size) +void gameAnalytics_configureAvailableResourceItemTypes(const char** resources, int size) { StringVector values = makeStringVector(resources, size); gameanalytics::GameAnalytics::configureAvailableResourceItemTypes(values); } -void configureBuild(const char *build) +void gameAnalytics_configureBuild(const char *build) { gameanalytics::GameAnalytics::configureBuild(build); } -void configureWritablePath(const char *writablePath) +void gameAnalytics_configureWritablePath(const char *writablePath) { gameanalytics::GameAnalytics::configureWritablePath(writablePath); } -void configureDeviceModel(const char *deviceModel) +void gameAnalytics_configureDeviceModel(const char *deviceModel) { gameanalytics::GameAnalytics::configureDeviceModel(deviceModel); } -void configureDeviceManufacturer(const char *deviceManufacturer) +void gameAnalytics_configureDeviceManufacturer(const char *deviceManufacturer) { gameanalytics::GameAnalytics::configureDeviceManufacturer(deviceManufacturer); } @@ -116,177 +95,177 @@ void configureDeviceManufacturer(const char *deviceManufacturer) // the version of SDK code used in an engine. Used for sdk_version field. // !! if set then it will override the SdkWrapperVersion. // example "unity 4.6.9" -void configureSdkGameEngineVersion(const char *sdkGameEngineVersion) +void gameAnalytics_configureSdkGameEngineVersion(const char *sdkGameEngineVersion) { gameanalytics::GameAnalytics::configureSdkGameEngineVersion(sdkGameEngineVersion); } // the version of the game engine (if used and version is available) -void configureGameEngineVersion(const char *engineVersion) +void gameAnalytics_configureGameEngineVersion(const char *engineVersion) { gameanalytics::GameAnalytics::configureGameEngineVersion(engineVersion); } -void configureUserId(const char *uId) +void gameAnalytics_configureUserId(const char *uId) { gameanalytics::GameAnalytics::configureUserId(uId); } -void configureExternalUserId(const char* extId) +void gameAnalytics_configureExternalUserId(const char* extId) { gameanalytics::GameAnalytics::configureExternalUserId(extId); } // initialize - starting SDK (need configuration before starting) -void initialize(const char *gameKey, const char *gameSecret) +void gameAnalytics_initialize(const char *gameKey, const char *gameSecret) { gameanalytics::GameAnalytics::initialize(gameKey, gameSecret); } // add events -void addBusinessEvent(const char *currency, double amount, const char *itemType, const char *itemId, const char *cartType, const char *fields, GA_BOOL mergeFields) +void gameAnalytics_addBusinessEvent(const char *currency, double amount, const char *itemType, const char *itemId, const char *cartType, const char *fields, GAStatus mergeFields) { gameanalytics::GameAnalytics::addBusinessEvent(currency, (int)amount, itemType, itemId, cartType, fields, mergeFields); } -void addResourceEvent(int flowType, const char *currency, double amount, const char *itemType, const char *itemId, const char *fields, GA_BOOL mergeFields) +void gameAnalytics_addResourceEvent(int flowType, const char *currency, double amount, const char *itemType, const char *itemId, const char *fields, GAStatus mergeFields) { gameanalytics::GameAnalytics::addResourceEvent((gameanalytics::EGAResourceFlowType)flowType, currency, (float)amount, itemType, itemId, fields, mergeFields); } -void addProgressionEvent(int progressionStatus, const char *progression01, const char *progression02, const char *progression03, const char *fields, GA_BOOL mergeFields) +void gameAnalytics_addProgressionEvent(int progressionStatus, const char *progression01, const char *progression02, const char *progression03, const char *fields, GAStatus mergeFields) { gameanalytics::GameAnalytics::addProgressionEvent((gameanalytics::EGAProgressionStatus)progressionStatus, progression01, progression02, progression03, fields, mergeFields); } -void addProgressionEventWithScore(int progressionStatus, const char *progression01, const char *progression02, const char *progression03, double score, const char *fields, GA_BOOL mergeFields) +void gameAnalytics_addProgressionEventWithScore(int progressionStatus, const char *progression01, const char *progression02, const char *progression03, double score, const char *fields, GAStatus mergeFields) { gameanalytics::GameAnalytics::addProgressionEvent((gameanalytics::EGAProgressionStatus)progressionStatus, progression01, progression02, progression03, (int)score, fields, mergeFields); } -void addDesignEvent(const char *eventId, const char *fields, GA_BOOL mergeFields) +void gameAnalytics_addDesignEvent(const char *eventId, const char *fields, GAStatus mergeFields) { - gameanalytics::GameAnalytics::addDesignEvent(eventId, fields, mergeFields); + gameanalytics::GameAnalytics::addDesignEvent(eventId, fields, (bool)mergeFields); } -void addDesignEventWithValue(const char *eventId, double value, const char *fields, GA_BOOL mergeFields) +void gameAnalytics_addDesignEventWithValue(const char *eventId, double value, const char *fields, GAStatus mergeFields) { - gameanalytics::GameAnalytics::addDesignEvent(eventId, value, fields, mergeFields); + gameanalytics::GameAnalytics::addDesignEvent(eventId, value, fields, (bool)mergeFields); } -void addErrorEvent(int severity, const char *message, const char *fields, GA_BOOL mergeFields) +void gameAnalytics_addErrorEvent(int severity, const char *message, const char *fields, GAStatus mergeFields) { - gameanalytics::GameAnalytics::addErrorEvent((gameanalytics::EGAErrorSeverity)severity, message, fields, mergeFields); + gameanalytics::GameAnalytics::addErrorEvent((gameanalytics::EGAErrorSeverity)severity, message, fields, (bool)mergeFields); } // set calls can be changed at any time (pre- and post-initialize) // some calls only work after a configure is called (setCustomDimension) -void setEnabledInfoLog(GA_BOOL flag) +void gameAnalytics_setEnabledInfoLog(GAStatus flag) { gameanalytics::GameAnalytics::setEnabledInfoLog(flag); } -void setEnabledVerboseLog(GA_BOOL flag) +void gameAnalytics_setEnabledVerboseLog(GAStatus flag) { gameanalytics::GameAnalytics::setEnabledVerboseLog(flag); } -void setEnabledManualSessionHandling(GA_BOOL flag) +void gameAnalytics_setEnabledManualSessionHandling(GAStatus flag) { gameanalytics::GameAnalytics::setEnabledManualSessionHandling(flag); } -void setEnabledErrorReporting(GA_BOOL flag) +void gameAnalytics_setEnabledErrorReporting(GAStatus flag) { gameanalytics::GameAnalytics::setEnabledErrorReporting(flag); } -void setEnabledEventSubmission(GA_BOOL flag) +void gameAnalytics_setEnabledEventSubmission(GAStatus flag) { gameanalytics::GameAnalytics::setEnabledEventSubmission(flag); } -void setCustomDimension01(const char *dimension01) +void gameAnalytics_setCustomDimension01(const char *dimension01) { gameanalytics::GameAnalytics::setCustomDimension01(dimension01); } -void setCustomDimension02(const char *dimension02) +void gameAnalytics_setCustomDimension02(const char *dimension02) { gameanalytics::GameAnalytics::setCustomDimension02(dimension02); } -void setCustomDimension03(const char *dimension03) +void gameAnalytics_setCustomDimension03(const char *dimension03) { gameanalytics::GameAnalytics::setCustomDimension03(dimension03); } -void setGlobalCustomEventFields(const char *customFields) +void gameAnalytics_setGlobalCustomEventFields(const char *customFields) { gameanalytics::GameAnalytics::setGlobalCustomEventFields(customFields); } -void gameAnalyticsStartSession() +void gameAnalytics_startSession() { gameanalytics::GameAnalytics::startSession(); } -void gameAnalyticsEndSession() +void gameAnalytics_endSession() { gameanalytics::GameAnalytics::endSession(); } // game state changes // will affect how session is started / ended -void onResume() +void gameAnalytics_onResume() { gameanalytics::GameAnalytics::onResume(); } -void onSuspend() +void gameAnalytics_onSuspend() { gameanalytics::GameAnalytics::onSuspend(); } -void onQuit() +void gameAnalytics_onQuit() { gameanalytics::GameAnalytics::onQuit(); } -GAString getRemoteConfigsValueAsString(const char *key) +void gameAnalytics_getRemoteConfigsValueAsString(const char *key, char* out, int* size) { std::string returnValue = gameanalytics::GameAnalytics::getRemoteConfigsValueAsString(key); - return ga_string_fromString(returnValue); + return copyStringBuffer(returnValue, out, size); } -GAString getRemoteConfigsValueAsStringWithDefaultValue(const char *key, const char *defaultValue) +GAErrorCode gameAnalytics_getRemoteConfigsValueAsStringWithDefaultValue(const char *key, const char *defaultValue, char* out, int* size) { std::string returnValue = gameanalytics::GameAnalytics::getRemoteConfigsValueAsString(key, defaultValue); - return ga_string_fromString(returnValue); + return copyStringBuffer(returnValue, out, size); } -GA_BOOL isRemoteConfigsReady() +GAStatus gameAnalytics_isRemoteConfigsReady() { - return gameanalytics::GameAnalytics::isRemoteConfigsReady() ? GA_TRUE : GA_FALSE; + return gameanalytics::GameAnalytics::isRemoteConfigsReady() ? GAEnabled : GADisabled; } -GAString getRemoteConfigsContentAsString() +GAErrorCode gameAnalytics_getRemoteConfigsContentAsString(char* out, int* size) { std::string returnValue = gameanalytics::GameAnalytics::getRemoteConfigsContentAsString(); - return ga_string_fromString(returnValue); + return copyStringBuffer(returnValue, out, size); } -GAString getABTestingId() +GAErrorCode gameAnalytics_getABTestingId(char* out, int* size) { std::string returnValue = gameanalytics::GameAnalytics::getABTestingId(); - return ga_string_fromString(returnValue); + return copyStringBuffer(returnValue, out, size); } -GAString getABTestingVariantId() +GAErrorCode gameAnalytics_getABTestingVariantId(char* out, int* size) { std::string returnValue = gameanalytics::GameAnalytics::getABTestingVariantId(); - return ga_string_fromString(returnValue); + return copyStringBuffer(returnValue, out, size); } #endif diff --git a/source/gameanalytics/GameAnalyticsExtern.h b/source/gameanalytics/GameAnalyticsExtern.h index 24a4d4ad..7ef4009f 100644 --- a/source/gameanalytics/GameAnalyticsExtern.h +++ b/source/gameanalytics/GameAnalyticsExtern.h @@ -8,100 +8,90 @@ extern "C" { #if GA_SHARED_LIB #if defined(_WIN32) - #define EXPORT __declspec(dllexport) + #define GA_EXPORT __declspec(dllexport) #else - #define EXPORT __attribute__((visibility("default"))) + #define GA_EXPORT __attribute__((visibility("default"))) #endif #else - #define EXPORT + #define GA_EXPORT #endif -typedef struct GAString_ +enum GAErrorCode { - const char* str = 0; - unsigned int size = 0; + EGANoError = 0, + EGAFailure, + EGABufferError +}; -} GAString; - -#ifdef __cplusplus - #define GA_BOOL bool - #define GA_TRUE true - #define GA_FALSE false -#else - #define GA_BOOL char - #define GA_TRUE ((char)1) - #define GA_FALSE ((char)0) -#endif - -EXPORT void ga_string_alloc(GAString* s, unsigned int size); -EXPORT void ga_string_free(GAString* s); - -EXPORT void configureAvailableCustomDimensions01(const char **customDimensions, int size); -EXPORT void configureAvailableCustomDimensions02(const char **customDimensions, int size); -EXPORT void configureAvailableCustomDimensions03(const char **customDimensions, int size); -EXPORT void configureAvailableResourceCurrencies(const char **resourceCurrencies, int size); -EXPORT void configureAvailableResourceItemTypes(const char **resourceItemTypes, int size); -EXPORT void configureBuild(const char *build); -EXPORT void configureWritablePath(const char *writablePath); -EXPORT void configureDeviceModel(const char *deviceModel); -EXPORT void configureDeviceManufacturer(const char *deviceManufacturer); +enum GAStatus: char +{ + EGADisabled = 0, + EGAEnabled +}; + +GA_EXPORT void gameAnalytics_configureAvailableCustomDimensions01(const char **customDimensions, int size); +GA_EXPORT void gameAnalytics_configureAvailableCustomDimensions02(const char **customDimensions, int size); +GA_EXPORT void gameAnalytics_configureAvailableCustomDimensions03(const char **customDimensions, int size); +GA_EXPORT void gameAnalytics_configureAvailableResourceCurrencies(const char **resourceCurrencies, int size); +GA_EXPORT void gameAnalytics_configureAvailableResourceItemTypes(const char **resourceItemTypes, int size); +GA_EXPORT void gameAnalytics_configureBuild(const char *build); +GA_EXPORT void gameAnalytics_configureWritablePath(const char *writablePath); +GA_EXPORT void gameAnalytics_configureDeviceModel(const char *deviceModel); +GA_EXPORT void gameAnalytics_configureDeviceManufacturer(const char *deviceManufacturer); // the version of SDK code used in an engine. Used for sdk_version field. // !! if set then it will override the SdkWrapperVersion. // example "unity 4.6.9" -EXPORT void configureSdkGameEngineVersion(const char *sdkGameEngineVersion); +GA_EXPORT void gameAnalytics_configureSdkGameEngineVersion(const char *sdkGameEngineVersion); + // the version of the game engine (if used and version is available) -EXPORT void configureGameEngineVersion(const char *engineVersion); +GA_EXPORT void gameAnalytics_configureGameEngineVersion(const char *engineVersion); -EXPORT void configureUserId(const char *uId); +GA_EXPORT void gameAnalytics_configureUserId(const char *uId); -EXPORT void configureExternalUserId(const char* extId); +GA_EXPORT void gameAnalytics_configureExternalUserId(const char* extId); // initialize - starting SDK (need configuration before starting) -EXPORT void initialize(const char *gameKey, const char *gameSecret); +GA_EXPORT void gameAnalytics_initialize(const char *gameKey, const char *gameSecret); // add events -EXPORT void addBusinessEvent(const char *currency, double amount, const char *itemType, const char *itemId, const char *cartType, const char *customFields, GA_BOOL mergeFields); - -EXPORT void addResourceEvent(int flowType, const char *currency, double amount, const char *itemType, const char *itemId, const char *customFields, GA_BOOL mergeFields); - -EXPORT void addProgressionEvent(int progressionStatus, const char *progression01, const char *progression02, const char *progression03, const char *customFields, GA_BOOL mergeFields); - -EXPORT void addProgressionEventWithScore(int progressionStatus, const char *progression01, const char *progression02, const char *progression03, double score, const char *customFields, GA_BOOL mergeFields); - -EXPORT void addDesignEvent(const char *eventId, const char *customFields, GA_BOOL mergeFields); -EXPORT void addDesignEventWithValue(const char *eventId, double value, const char *customFields, GA_BOOL mergeFields); -EXPORT void addErrorEvent(int severity, const char *message, const char *customFields, GA_BOOL mergeFields); +GA_EXPORT void gameAnalytics_addBusinessEvent(const char *currency, double amount, const char *itemType, const char *itemId, const char *cartType, const char *customFields, GAStatus mergeFields); +GA_EXPORT void gameAnalytics_addResourceEvent(int flowType, const char *currency, double amount, const char *itemType, const char *itemId, const char *customFields, GAStatus mergeFields); +GA_EXPORT void gameAnalytics_addProgressionEvent(int progressionStatus, const char *progression01, const char *progression02, const char *progression03, const char *customFields, GAStatus mergeFields); +GA_EXPORT void gameAnalytics_addProgressionEventWithScore(int progressionStatus, const char *progression01, const char *progression02, const char *progression03, double score, const char *customFields, GAStatus mergeFields); +GA_EXPORT void gameAnalytics_addDesignEvent(const char *eventId, const char *customFields, GAStatus mergeFields); +GA_EXPORT void gameAnalytics_addDesignEventWithValue(const char *eventId, double value, const char *customFields, GAStatus mergeFields); +GA_EXPORT void gameAnalytics_addErrorEvent(int severity, const char *message, const char *customFields, GAStatus mergeFields); // set calls can be changed at any time (pre- and post-initialize) // some calls only work after a configure is called (setCustomDimension) -EXPORT void setEnabledInfoLog(GA_BOOL flag); -EXPORT void setEnabledVerboseLog(GA_BOOL flag); -EXPORT void setEnabledManualSessionHandling(GA_BOOL flag); -EXPORT void setEnabledErrorReporting(GA_BOOL flag); -EXPORT void setEnabledEventSubmission(GA_BOOL flag); -EXPORT void setCustomDimension01(const char *dimension01); -EXPORT void setCustomDimension02(const char *dimension02); -EXPORT void setCustomDimension03(const char *dimension03); +GA_EXPORT void gameAnalytics_setEnabledInfoLog(GAStatus flag); +GA_EXPORT void gameAnalytics_setEnabledVerboseLog(GAStatus flag); +GA_EXPORT void gameAnalytics_setEnabledManualSessionHandling(GAStatus flag); +GA_EXPORT void gameAnalytics_setEnabledErrorReporting(GAStatus flag); +GA_EXPORT void gameAnalytics_setEnabledEventSubmission(GAStatus flag); +GA_EXPORT void gameAnalytics_setCustomDimension01(const char *dimension01); +GA_EXPORT void gameAnalytics_setCustomDimension02(const char *dimension02); +GA_EXPORT void gameAnalytics_setCustomDimension03(const char *dimension03); -EXPORT void setGlobalCustomEventFields(const char *customFields); +GA_EXPORT void gameAnalytics_setGlobalCustomEventFields(const char *customFields); -EXPORT void gameAnalyticsStartSession(); -EXPORT void gameAnalyticsEndSession(); +GA_EXPORT void gameAnalytics_startSession(); +GA_EXPORT void gameAnalytics_endSession(); // game state changes // will affect how session is started / ended -EXPORT void onResume(); -EXPORT void onSuspend(); -EXPORT void onQuit(); +GA_EXPORT void gameAnalytics_onResume(); +GA_EXPORT void gameAnalytics_onSuspend(); +GA_EXPORT void gameAnalytics_onQuit(); -EXPORT GAString getRemoteConfigsValueAsString(const char *key); -EXPORT GAString getRemoteConfigsValueAsStringWithDefaultValue(const char *key, const char *defaultValue); -EXPORT GA_BOOL isRemoteConfigsReady(); -EXPORT GA_BOOL getRemoteConfigsContentAsString(char* out, int size); +GA_EXPORT GAErrorCode gameAnalytics_getRemoteConfigsValueAsString(const char *key, char* out, int* bufferSize); +GA_EXPORT GAErrorCode gameAnalytics_getRemoteConfigsValueAsStringWithDefaultValue(const char *key, const char *defaultValue, char* out, int* bufferSize); +GA_EXPORT GAStatus gameAnalytics_isRemoteConfigsReady(); +GA_EXPORT GAErrorCode gameAnalytics_getRemoteConfigsContentAsString(char* out, int* size); -EXPORT GAString getABTestingId(); -EXPORT GAString getABTestingVariantId(); +GA_EXPORT GAErrorCode gameAnalytics_getABTestingId(char* out, int* size); +GA_EXPORT GAErrorCode gameAnalytics_getABTestingVariantId(char* out, int* size); #ifdef __cplusplus } From 490b7e256641b3cdfa09c487e70e34077047eecf Mon Sep 17 00:00:00 2001 From: Dorin Date: Thu, 18 Sep 2025 13:12:28 +0300 Subject: [PATCH 53/66] detect gpu model for MacOS --- CMakeLists.txt | 2 ++ source/gameanalytics/Platform/GADeviceOSX.h | 1 + source/gameanalytics/Platform/GADeviceOSX.mm | 17 +++++++++++++++++ source/gameanalytics/Platform/GAMacOS.cpp | 7 ++++++- source/gameanalytics/Platform/GAMacOS.h | 1 + 5 files changed, 27 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 868c6b1b..c4072dc3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -190,6 +190,8 @@ elseif(APPLE) "-framework Foundation" "-framework CoreServices" "-framework SystemConfiguration" + "-framework Metal" + "-framework MetalKit" ) create_source_groups(MACOS_SOURCES) diff --git a/source/gameanalytics/Platform/GADeviceOSX.h b/source/gameanalytics/Platform/GADeviceOSX.h index 0d63299f..fe9d6d4e 100644 --- a/source/gameanalytics/Platform/GADeviceOSX.h +++ b/source/gameanalytics/Platform/GADeviceOSX.h @@ -9,6 +9,7 @@ const char* getOSXVersion(); const char* getConnectionType(); int getNumCpuCores(); int64_t getTotalDeviceMemory(); +const char* getGPUName(); #endif diff --git a/source/gameanalytics/Platform/GADeviceOSX.mm b/source/gameanalytics/Platform/GADeviceOSX.mm index df799fc4..7782c860 100644 --- a/source/gameanalytics/Platform/GADeviceOSX.mm +++ b/source/gameanalytics/Platform/GADeviceOSX.mm @@ -16,6 +16,10 @@ #import #import +#import + +#include + typedef struct { NSInteger majorVersion; NSInteger minorVersion; @@ -103,4 +107,17 @@ int64_t getTotalDeviceMemory() return (uint64_t)info.physicalMemory; } +const char* getGPUName() +{ + NSArray* devices = MTLCopyAllDevices(); + if(devices && [devices count]) + { + id device = devices[0]; + NSString* name = [device name]; + return [name UTF8String]; + } + + return ""; +} + #endif // IS_MAC diff --git a/source/gameanalytics/Platform/GAMacOS.cpp b/source/gameanalytics/Platform/GAMacOS.cpp index 1fba913b..3e6f8195 100644 --- a/source/gameanalytics/Platform/GAMacOS.cpp +++ b/source/gameanalytics/Platform/GAMacOS.cpp @@ -193,7 +193,12 @@ std::string gameanalytics::GAPlatformMacOS::getCpuModel() const std::string gameanalytics::GAPlatformMacOS::getGpuModel() const { - return "Apple"; + if(_gpuModel.empty()) + { + _gpuModel = ::getGPUName(); + } + + return _gpuModel; } int gameanalytics::GAPlatformMacOS::getNumCpuCores() const diff --git a/source/gameanalytics/Platform/GAMacOS.h b/source/gameanalytics/Platform/GAMacOS.h index f8f529c3..82d377c3 100644 --- a/source/gameanalytics/Platform/GAMacOS.h +++ b/source/gameanalytics/Platform/GAMacOS.h @@ -38,6 +38,7 @@ namespace gameanalytics private: + mutable std::string _gpuModel; static void signalHandler(int sig, siginfo_t* info, void* context); }; } From a1083036a67c07028b8ca46e1e7eb62bcff87cdb Mon Sep 17 00:00:00 2001 From: Dorin Date: Thu, 18 Sep 2025 13:35:58 +0300 Subject: [PATCH 54/66] return string to avoid dangling ptrs --- source/gameanalytics/Platform/GADeviceOSX.h | 7 ++++--- source/gameanalytics/Platform/GADeviceOSX.mm | 6 +++--- source/gameanalytics/Platform/GAMacOS.cpp | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/source/gameanalytics/Platform/GADeviceOSX.h b/source/gameanalytics/Platform/GADeviceOSX.h index fe9d6d4e..5686019b 100644 --- a/source/gameanalytics/Platform/GADeviceOSX.h +++ b/source/gameanalytics/Platform/GADeviceOSX.h @@ -2,14 +2,15 @@ #define _GADEVICEOSX_H #include "GACommon.h" +#include #if IS_MAC -const char* getOSXVersion(); -const char* getConnectionType(); +std::string getOSXVersion(); +std::string getConnectionType(); int getNumCpuCores(); int64_t getTotalDeviceMemory(); -const char* getGPUName(); +std::string getGPUName(); #endif diff --git a/source/gameanalytics/Platform/GADeviceOSX.mm b/source/gameanalytics/Platform/GADeviceOSX.mm index 7782c860..35443109 100644 --- a/source/gameanalytics/Platform/GADeviceOSX.mm +++ b/source/gameanalytics/Platform/GADeviceOSX.mm @@ -26,7 +26,7 @@ NSInteger patchVersion; } MyOperatingSystemVersion; -const char* getOSXVersion() +std::string getOSXVersion() { if (floor(kCFCoreFoundationVersionNumber) > kCFCoreFoundationVersionNumber10_9) { @@ -64,7 +64,7 @@ SCNetworkReachabilityRef createReachabilityRef() return reachabilityRef; } -const char* getConnectionType() +std::string getConnectionType() { // todo: keep this in a class static SCNetworkReachabilityRef reachabilityRef = createReachabilityRef(); @@ -107,7 +107,7 @@ int64_t getTotalDeviceMemory() return (uint64_t)info.physicalMemory; } -const char* getGPUName() +std::string getGPUName() { NSArray* devices = MTLCopyAllDevices(); if(devices && [devices count]) diff --git a/source/gameanalytics/Platform/GAMacOS.cpp b/source/gameanalytics/Platform/GAMacOS.cpp index 3e6f8195..72d2b983 100644 --- a/source/gameanalytics/Platform/GAMacOS.cpp +++ b/source/gameanalytics/Platform/GAMacOS.cpp @@ -17,7 +17,7 @@ static struct sigaction prevSigAction; std::string gameanalytics::GAPlatformMacOS::getOSVersion() { - const char* osxVersion = getOSXVersion(); + std::string osxVersion = getOSXVersion(); return getBuildPlatform() + " " + osxVersion; } From 5c31b4d963039007f6be1ab2edb7e52e8add7574 Mon Sep 17 00:00:00 2001 From: Dorin Date: Wed, 24 Sep 2025 11:24:42 +0300 Subject: [PATCH 55/66] playtime metrics --- source/gameanalytics/GAState.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/source/gameanalytics/GAState.cpp b/source/gameanalytics/GAState.cpp index ae3ba089..eac0177b 100644 --- a/source/gameanalytics/GAState.cpp +++ b/source/gameanalytics/GAState.cpp @@ -426,6 +426,10 @@ namespace gameanalytics out["session_num"] = getInstance()._sessionNum; out["connection_type"] = device::GADevice::getConnectionType(); + // playtime metrics + out["current_session_length"] = getInstance().calculateSessionLength(); + out["lifetime_session_length"] = getInstance().getTotalSessionLength(); + // ---- OPTIONAL ---- // // A/B testing From a69a65fd3525642554be63347447b498b726d371 Mon Sep 17 00:00:00 2001 From: Dorin Date: Wed, 24 Sep 2025 11:45:58 +0300 Subject: [PATCH 56/66] fix session time with multiple sessions during the same run --- source/gameanalytics/GAState.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/gameanalytics/GAState.cpp b/source/gameanalytics/GAState.cpp index eac0177b..4d649dce 100644 --- a/source/gameanalytics/GAState.cpp +++ b/source/gameanalytics/GAState.cpp @@ -1094,8 +1094,8 @@ namespace gameanalytics void GAState::updateTotalSessionTime() { - int64_t totalSessionTime = getTotalSessionLength(); - _gaStore.setState("total_session_time", std::to_string(totalSessionTime)); + _totalElapsedSessionTime = getTotalSessionLength(); + _gaStore.setState("total_session_time", std::to_string(_totalElapsedSessionTime)); } std::string GAState::getBuild() From fe8d56b1c599cd1e74239c4774f0f59707ab63c2 Mon Sep 17 00:00:00 2001 From: Dorin Date: Wed, 24 Sep 2025 11:54:33 +0300 Subject: [PATCH 57/66] filter info logs --- source/gameanalytics/GALogger.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/source/gameanalytics/GALogger.h b/source/gameanalytics/GALogger.h index 7a1fb097..4f681a14 100644 --- a/source/gameanalytics/GALogger.h +++ b/source/gameanalytics/GALogger.h @@ -26,6 +26,11 @@ namespace gameanalytics return; } + if(logType == LogInfo && !getInstance().infoLogEnabled) + { + return; + } + std::string tag = getInstance().tag; tag += " :"; From 9ec48cd6f6950ebc64fb5e2dd6fe9fa4facca65c Mon Sep 17 00:00:00 2001 From: Dorin Date: Wed, 24 Sep 2025 12:06:03 +0300 Subject: [PATCH 58/66] added previous session time --- include/GameAnalytics/GameAnalytics.h | 1 + source/gameanalytics/GAState.cpp | 17 +++++++++++++---- source/gameanalytics/GAState.h | 3 +++ source/gameanalytics/GameAnalytics.cpp | 5 +++++ 4 files changed, 22 insertions(+), 4 deletions(-) diff --git a/include/GameAnalytics/GameAnalytics.h b/include/GameAnalytics/GameAnalytics.h index c1da53c0..31bbcb49 100644 --- a/include/GameAnalytics/GameAnalytics.h +++ b/include/GameAnalytics/GameAnalytics.h @@ -120,6 +120,7 @@ namespace gameanalytics static int64_t getElapsedSessionTime(); static int64_t getElapsedTimeFromAllSessions(); + static int64_t getElapsedTimeForPreviousSession(); // game state changes // will affect how session is started / ended diff --git a/source/gameanalytics/GAState.cpp b/source/gameanalytics/GAState.cpp index 4d649dce..90278c71 100644 --- a/source/gameanalytics/GAState.cpp +++ b/source/gameanalytics/GAState.cpp @@ -539,6 +539,11 @@ namespace gameanalytics return ""; } + int64_t GAState::getLastSessionLength() const + { + return _lastSessionTime; + } + int64_t GAState::getTotalSessionLength() const { return _totalElapsedSessionTime + calculateSessionLength(); @@ -590,10 +595,11 @@ namespace gameanalytics try { - std::string cachedSessionTime = utilities::getOptionalValue(state_dict, "total_session_time", "0"); + std::string cachedLastSessionTime = utilities::getOptionalValue(state_dict, "last_session_time", "0"); + std::string cachedTotalSessionTime = utilities::getOptionalValue(state_dict, "total_session_time", "0"); - _totalElapsedSessionTime = std::stoull(cachedSessionTime); - + _lastSessionTime = std::stoull(cachedTotalSessionTime); + _totalElapsedSessionTime = std::stoull(cachedTotalSessionTime); } catch(const std::exception& e) { @@ -1094,7 +1100,10 @@ namespace gameanalytics void GAState::updateTotalSessionTime() { - _totalElapsedSessionTime = getTotalSessionLength(); + _lastSessionTime = calculateSessionLength(); + _totalElapsedSessionTime += _lastSessionTime; + + _gaStore.setState("last_session_time", std::to_string(_lastSessionTime)); _gaStore.setState("total_session_time", std::to_string(_totalElapsedSessionTime)); } diff --git a/source/gameanalytics/GAState.h b/source/gameanalytics/GAState.h index 346a0b86..af504e32 100644 --- a/source/gameanalytics/GAState.h +++ b/source/gameanalytics/GAState.h @@ -169,6 +169,8 @@ namespace gameanalytics int64_t getTotalSessionLength() const; + int64_t getLastSessionLength() const; + void populateConfigurations(json& sdkConfig); json getRemoteConfigAnnotations(); @@ -229,6 +231,7 @@ namespace gameanalytics int64_t _sessionNum = 0; int64_t _transactionNum = 0; + int64_t _lastSessionTime = 0; int64_t _totalElapsedSessionTime = 0; std::chrono::high_resolution_clock::time_point _startTimepoint; diff --git a/source/gameanalytics/GameAnalytics.cpp b/source/gameanalytics/GameAnalytics.cpp index 76a8604f..8d524620 100644 --- a/source/gameanalytics/GameAnalytics.cpp +++ b/source/gameanalytics/GameAnalytics.cpp @@ -998,4 +998,9 @@ namespace gameanalytics return state::GAState::getInstance().calculateSessionLength(); } + int64_t GameAnalytics::getElapsedTimeForPreviousSession() + { + return state::GAState::getInstance().getLastSessionLength(); + } + } // namespace gameanalytics From 232a30a88b998b4c79b745263c13dee72f3eb1da Mon Sep 17 00:00:00 2001 From: Dorin Date: Wed, 24 Sep 2025 12:11:50 +0300 Subject: [PATCH 59/66] wrong variable was set --- source/gameanalytics/GAState.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/gameanalytics/GAState.cpp b/source/gameanalytics/GAState.cpp index 90278c71..ff201230 100644 --- a/source/gameanalytics/GAState.cpp +++ b/source/gameanalytics/GAState.cpp @@ -598,7 +598,7 @@ namespace gameanalytics std::string cachedLastSessionTime = utilities::getOptionalValue(state_dict, "last_session_time", "0"); std::string cachedTotalSessionTime = utilities::getOptionalValue(state_dict, "total_session_time", "0"); - _lastSessionTime = std::stoull(cachedTotalSessionTime); + _lastSessionTime = std::stoull(cachedLastSessionTime); _totalElapsedSessionTime = std::stoull(cachedTotalSessionTime); } catch(const std::exception& e) From fa2c2b8a84c1463d11b649389528de7a8e38ce15 Mon Sep 17 00:00:00 2001 From: Dorin Date: Fri, 26 Sep 2025 12:19:51 +0300 Subject: [PATCH 60/66] allow progression2 and progression3 to be empty --- source/gameanalytics/GAValidator.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source/gameanalytics/GAValidator.cpp b/source/gameanalytics/GAValidator.cpp index e6d2b573..c111a422 100644 --- a/source/gameanalytics/GAValidator.cpp +++ b/source/gameanalytics/GAValidator.cpp @@ -275,6 +275,9 @@ namespace gameanalytics bool validateProgressionString(std::string const& progression, ValidationResult& out, int progressionLvl) { + if(progressionLvl > 0 && progression.empty()) + return true; + if (!GAValidator::validateEventPartLength(progression, true)) { logging::GALogger::w("Validation fail - progression event - - progression0%d: Cannot be empty or above 64 characters. String: %s", progressionLvl + 1, progression.c_str()); From 9b1e7afac102442da70e2fc1a83b7aa70edfaa07 Mon Sep 17 00:00:00 2001 From: Dorin Date: Fri, 26 Sep 2025 12:23:22 +0300 Subject: [PATCH 61/66] refactor event part validation --- source/gameanalytics/GAValidator.cpp | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/source/gameanalytics/GAValidator.cpp b/source/gameanalytics/GAValidator.cpp index c111a422..f831836b 100644 --- a/source/gameanalytics/GAValidator.cpp +++ b/source/gameanalytics/GAValidator.cpp @@ -461,17 +461,12 @@ namespace gameanalytics { constexpr uint32_t MAX_SIZE = 64u; - size_t size = eventPart.length(); - if (allowNull == true && size == 0) + if (eventPart.empty()) { - return true; - } - - if (size == 0) - { - return false; + return allowNull; } + size_t size = eventPart.length(); if (size > MAX_SIZE) { return false; From 6b2357dfd8b3e51b5210ee94da6b7806da0d4997 Mon Sep 17 00:00:00 2001 From: Dorin Date: Mon, 29 Sep 2025 15:17:21 +0300 Subject: [PATCH 62/66] add missing functions in the external interface --- source/gameanalytics/GameAnalyticsExtern.cpp | 47 ++++++++++++++++++++ source/gameanalytics/GameAnalyticsExtern.h | 12 +++++ 2 files changed, 59 insertions(+) diff --git a/source/gameanalytics/GameAnalyticsExtern.cpp b/source/gameanalytics/GameAnalyticsExtern.cpp index 0b0fef92..38d306fe 100644 --- a/source/gameanalytics/GameAnalyticsExtern.cpp +++ b/source/gameanalytics/GameAnalyticsExtern.cpp @@ -256,6 +256,12 @@ GAErrorCode gameAnalytics_getRemoteConfigsContentAsString(char* out, int* size) return copyStringBuffer(returnValue, out, size); } +GAErrorCode gameAnalytics_getRemoteConfigsValueAsJson(char* out, int* size) +{ + std::string returnValue = gameanalytics::GameAnalytics::getRemoteConfigsContentAsJson(); + return copyStringBuffer(returnValue, out, size); +} + GAErrorCode gameAnalytics_getABTestingId(char* out, int* size) { std::string returnValue = gameanalytics::GameAnalytics::getABTestingId(); @@ -268,4 +274,45 @@ GAErrorCode gameAnalytics_getABTestingVariantId(char* out, int* size) return copyStringBuffer(returnValue, out, size); } +long long gameAnalytics_getElapsedSessionTime() +{ + return gameanalytics::GameAnalytics::getElapsedSessionTime(); +} + +long long gameAnalytics_getElapsedTimeFromAllSessions() +{ + return gameanalytics::GameAnalytics::getElapsedTimeFromAllSessions(); +} + +long long gameAnalytics_getElapsedTimeForPreviousSession() +{ + return gameanalytics::GameAnalytics::getElapsedTimeForPreviousSession(); +} + +void gameAnalytics_enableSDKInit(GAStatus status) +{ + return gameanalytics::GameAnalytics::enableSDKInit(status); +} + +void gameAnalytics_enableMemoryHistogram(GAStatus status) +{ + return gameanalytics::GameAnalytics::enableMemoryHistogram(status); +} + +void gameAnalytics_enableFPSHistogram(GAFpsTracker tracker, GAStatus status) +{ + gameanaltics::FpsTracker fpsTracker = + [=]() -> float + { + return tracker(); + }; + + return gameanalytics::GameAnalytics::enableFPSHistogram(fpsTracker, status); +} + +void gameAnalytics_enableHardwareTracking(GAStatus status) +{ + return gameanalytics::GameAnalytics::enableHardwareTracking(status); +} + #endif diff --git a/source/gameanalytics/GameAnalyticsExtern.h b/source/gameanalytics/GameAnalyticsExtern.h index 7ef4009f..a8888e73 100644 --- a/source/gameanalytics/GameAnalyticsExtern.h +++ b/source/gameanalytics/GameAnalyticsExtern.h @@ -29,6 +29,8 @@ enum GAStatus: char EGAEnabled }; +typedef float(*GAFpsTracker)(void); + GA_EXPORT void gameAnalytics_configureAvailableCustomDimensions01(const char **customDimensions, int size); GA_EXPORT void gameAnalytics_configureAvailableCustomDimensions02(const char **customDimensions, int size); GA_EXPORT void gameAnalytics_configureAvailableCustomDimensions03(const char **customDimensions, int size); @@ -89,10 +91,20 @@ GA_EXPORT GAErrorCode gameAnalytics_getRemoteConfigsValueAsString(const char *ke GA_EXPORT GAErrorCode gameAnalytics_getRemoteConfigsValueAsStringWithDefaultValue(const char *key, const char *defaultValue, char* out, int* bufferSize); GA_EXPORT GAStatus gameAnalytics_isRemoteConfigsReady(); GA_EXPORT GAErrorCode gameAnalytics_getRemoteConfigsContentAsString(char* out, int* size); +GA_EXPORT GAErrorCode gameAnalytics_getRemoteConfigsValueAsJson(char* out, int* size); GA_EXPORT GAErrorCode gameAnalytics_getABTestingId(char* out, int* size); GA_EXPORT GAErrorCode gameAnalytics_getABTestingVariantId(char* out, int* size); +GA_EXPORT long long gameAnalytics_getElapsedSessionTime(); +GA_EXPORT long long gameAnalytics_getElapsedTimeFromAllSessions(); +GA_EXPORT long long gameAnalytics_getElapsedTimeForPreviousSession(); + +GA_EXPORT void gameAnalytics_enableSDKInit(GAStatus status); +GA_EXPORT void gameAnalytics_enableMemoryHistogram(GAStatus status); +GA_EXPORT void gameAnalytics_enableFPSHistogram(GAFpsTracker tracker, GAStatus status); +GA_EXPORT void gameAnalytics_enableHardwareTracking(GAStatus status); + #ifdef __cplusplus } #endif From b24ac1451302e83e0a95345fffed21586710e84d Mon Sep 17 00:00:00 2001 From: Dorin Date: Mon, 29 Sep 2025 15:43:15 +0300 Subject: [PATCH 63/66] fix extern interface --- source/gameanalytics/GameAnalyticsExtern.cpp | 35 ++++++++++---------- source/gameanalytics/GameAnalyticsExtern.h | 9 ++--- 2 files changed, 23 insertions(+), 21 deletions(-) diff --git a/source/gameanalytics/GameAnalyticsExtern.cpp b/source/gameanalytics/GameAnalyticsExtern.cpp index 38d306fe..86989e77 100644 --- a/source/gameanalytics/GameAnalyticsExtern.cpp +++ b/source/gameanalytics/GameAnalyticsExtern.cpp @@ -2,12 +2,13 @@ #include "GameAnalytics/GameAnalytics.h" #include "GAUtilities.h" +#include "GameAnalyticsExtern.h" -StringVector makeStringVector(const char** arr, int size) +gameanalytics::StringVector makeStringVector(const char** arr, int size) { if(size > 0 && arr) { - StringVector v; + gameanalytics::StringVector v; v.reserve(size); for(int i = 0; i < size; ++i) @@ -35,7 +36,7 @@ GAErrorCode copyStringBuffer(std::string const& s, char* out, int* size) return EGABufferError; } - *size = s.size(); + *size = static_cast(s.size()); return EGANoError; } @@ -44,31 +45,31 @@ GAErrorCode copyStringBuffer(std::string const& s, char* out, int* size) void gameAnalytics_configureAvailableCustomDimensions01(const char **customDimensions, int size) { - StringVector values = makeStringVector(customDimensions, size); + gameanalytics::StringVector values = makeStringVector(customDimensions, size); gameanalytics::GameAnalytics::configureAvailableCustomDimensions01(values); } void gameAnalytics_configureAvailableCustomDimensions02(const char **customDimensions, int size) { - StringVector values = makeStringVector(customDimensions, size); + gameanalytics::StringVector values = makeStringVector(customDimensions, size); gameanalytics::GameAnalytics::configureAvailableCustomDimensions02(values); } void gameAnalytics_configureAvailableCustomDimensions03(const char **customDimensions, int size) { - StringVector values = makeStringVector(customDimensions, size); + gameanalytics::StringVector values = makeStringVector(customDimensions, size); gameanalytics::GameAnalytics::configureAvailableCustomDimensions03(values); } void gameAnalytics_configureAvailableResourceCurrencies(const char** currencies, int size) { - StringVector values = makeStringVector(currencies, size); + gameanalytics::StringVector values = makeStringVector(currencies, size); gameanalytics::GameAnalytics::configureAvailableResourceCurrencies(values); } void gameAnalytics_configureAvailableResourceItemTypes(const char** resources, int size) { - StringVector values = makeStringVector(resources, size); + gameanalytics::StringVector values = makeStringVector(resources, size); gameanalytics::GameAnalytics::configureAvailableResourceItemTypes(values); } @@ -138,9 +139,9 @@ void gameAnalytics_addProgressionEvent(int progressionStatus, const char *progre gameanalytics::GameAnalytics::addProgressionEvent((gameanalytics::EGAProgressionStatus)progressionStatus, progression01, progression02, progression03, fields, mergeFields); } -void gameAnalytics_addProgressionEventWithScore(int progressionStatus, const char *progression01, const char *progression02, const char *progression03, double score, const char *fields, GAStatus mergeFields) +void gameAnalytics_addProgressionEventWithScore(int progressionStatus, const char *progression01, const char *progression02, const char *progression03, int score, const char *fields, GAStatus mergeFields) { - gameanalytics::GameAnalytics::addProgressionEvent((gameanalytics::EGAProgressionStatus)progressionStatus, progression01, progression02, progression03, (int)score, fields, mergeFields); + gameanalytics::GameAnalytics::addProgressionEvent((gameanalytics::EGAProgressionStatus)progressionStatus, score, progression01, progression02, progression03, fields, mergeFields); } void gameAnalytics_addDesignEvent(const char *eventId, const char *fields, GAStatus mergeFields) @@ -233,7 +234,7 @@ void gameAnalytics_onQuit() gameanalytics::GameAnalytics::onQuit(); } -void gameAnalytics_getRemoteConfigsValueAsString(const char *key, char* out, int* size) +GAErrorCode gameAnalytics_getRemoteConfigsValueAsString(const char *key, char* out, int* size) { std::string returnValue = gameanalytics::GameAnalytics::getRemoteConfigsValueAsString(key); return copyStringBuffer(returnValue, out, size); @@ -247,7 +248,7 @@ GAErrorCode gameAnalytics_getRemoteConfigsValueAsStringWithDefaultValue(const ch GAStatus gameAnalytics_isRemoteConfigsReady() { - return gameanalytics::GameAnalytics::isRemoteConfigsReady() ? GAEnabled : GADisabled; + return gameanalytics::GameAnalytics::isRemoteConfigsReady() ? EGAEnabled : EGADisabled; } GAErrorCode gameAnalytics_getRemoteConfigsContentAsString(char* out, int* size) @@ -256,9 +257,9 @@ GAErrorCode gameAnalytics_getRemoteConfigsContentAsString(char* out, int* size) return copyStringBuffer(returnValue, out, size); } -GAErrorCode gameAnalytics_getRemoteConfigsValueAsJson(char* out, int* size) +GAErrorCode gameAnalytics_getRemoteConfigsValueAsJson(const char* key, char* out, int* size) { - std::string returnValue = gameanalytics::GameAnalytics::getRemoteConfigsContentAsJson(); + std::string returnValue = gameanalytics::GameAnalytics::getRemoteConfigsValueAsJson(key); return copyStringBuffer(returnValue, out, size); } @@ -289,9 +290,9 @@ long long gameAnalytics_getElapsedTimeForPreviousSession() return gameanalytics::GameAnalytics::getElapsedTimeForPreviousSession(); } -void gameAnalytics_enableSDKInit(GAStatus status) +void gameAnalytics_enableSDKInitEvent(GAStatus status) { - return gameanalytics::GameAnalytics::enableSDKInit(status); + return gameanalytics::GameAnalytics::enableSDKInitEvent(status); } void gameAnalytics_enableMemoryHistogram(GAStatus status) @@ -301,7 +302,7 @@ void gameAnalytics_enableMemoryHistogram(GAStatus status) void gameAnalytics_enableFPSHistogram(GAFpsTracker tracker, GAStatus status) { - gameanaltics::FpsTracker fpsTracker = + gameanalytics::FPSTracker fpsTracker = [=]() -> float { return tracker(); diff --git a/source/gameanalytics/GameAnalyticsExtern.h b/source/gameanalytics/GameAnalyticsExtern.h index a8888e73..0d60af7d 100644 --- a/source/gameanalytics/GameAnalyticsExtern.h +++ b/source/gameanalytics/GameAnalyticsExtern.h @@ -60,7 +60,7 @@ GA_EXPORT void gameAnalytics_initialize(const char *gameKey, const char *gameSec GA_EXPORT void gameAnalytics_addBusinessEvent(const char *currency, double amount, const char *itemType, const char *itemId, const char *cartType, const char *customFields, GAStatus mergeFields); GA_EXPORT void gameAnalytics_addResourceEvent(int flowType, const char *currency, double amount, const char *itemType, const char *itemId, const char *customFields, GAStatus mergeFields); GA_EXPORT void gameAnalytics_addProgressionEvent(int progressionStatus, const char *progression01, const char *progression02, const char *progression03, const char *customFields, GAStatus mergeFields); -GA_EXPORT void gameAnalytics_addProgressionEventWithScore(int progressionStatus, const char *progression01, const char *progression02, const char *progression03, double score, const char *customFields, GAStatus mergeFields); +GA_EXPORT void gameAnalytics_addProgressionEventWithScore(int progressionStatus, const char *progression01, const char *progression02, const char *progression03, int score, const char *customFields, GAStatus mergeFields); GA_EXPORT void gameAnalytics_addDesignEvent(const char *eventId, const char *customFields, GAStatus mergeFields); GA_EXPORT void gameAnalytics_addDesignEventWithValue(const char *eventId, double value, const char *customFields, GAStatus mergeFields); GA_EXPORT void gameAnalytics_addErrorEvent(int severity, const char *message, const char *customFields, GAStatus mergeFields); @@ -87,11 +87,12 @@ GA_EXPORT void gameAnalytics_onResume(); GA_EXPORT void gameAnalytics_onSuspend(); GA_EXPORT void gameAnalytics_onQuit(); -GA_EXPORT GAErrorCode gameAnalytics_getRemoteConfigsValueAsString(const char *key, char* out, int* bufferSize); +GA_EXPORT GAErrorCode gameAnalytics_getRemoteConfigsValueAsString(const char *key, char* out, int* size); GA_EXPORT GAErrorCode gameAnalytics_getRemoteConfigsValueAsStringWithDefaultValue(const char *key, const char *defaultValue, char* out, int* bufferSize); +GA_EXPORT GAErrorCode gameAnalytics_getRemoteConfigsValueAsJson(const char* key, char* out, int* size); + GA_EXPORT GAStatus gameAnalytics_isRemoteConfigsReady(); GA_EXPORT GAErrorCode gameAnalytics_getRemoteConfigsContentAsString(char* out, int* size); -GA_EXPORT GAErrorCode gameAnalytics_getRemoteConfigsValueAsJson(char* out, int* size); GA_EXPORT GAErrorCode gameAnalytics_getABTestingId(char* out, int* size); GA_EXPORT GAErrorCode gameAnalytics_getABTestingVariantId(char* out, int* size); @@ -100,7 +101,7 @@ GA_EXPORT long long gameAnalytics_getElapsedSessionTime(); GA_EXPORT long long gameAnalytics_getElapsedTimeFromAllSessions(); GA_EXPORT long long gameAnalytics_getElapsedTimeForPreviousSession(); -GA_EXPORT void gameAnalytics_enableSDKInit(GAStatus status); +GA_EXPORT void gameAnalytics_enableSDKInitEvent(GAStatus status); GA_EXPORT void gameAnalytics_enableMemoryHistogram(GAStatus status); GA_EXPORT void gameAnalytics_enableFPSHistogram(GAFpsTracker tracker, GAStatus status); GA_EXPORT void gameAnalytics_enableHardwareTracking(GAStatus status); From accc628c3bc68d1d5cae45016d959065200cc2a0 Mon Sep 17 00:00:00 2001 From: Dorin Date: Thu, 9 Oct 2025 15:53:11 +0300 Subject: [PATCH 64/66] remove patch --- source/gameanalytics/GAStore.cpp | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/source/gameanalytics/GAStore.cpp b/source/gameanalytics/GAStore.cpp index 69e463b5..2a2c5e09 100644 --- a/source/gameanalytics/GAStore.cpp +++ b/source/gameanalytics/GAStore.cpp @@ -206,30 +206,6 @@ namespace gameanalytics { return sqlDatabase; } - - bool GAStore::fixOldDatabase() - { - std::filesystem::path oldPath = dbPath; - std::filesystem::path filename = oldPath.filename(); - - oldPath = oldPath.parent_path() / ".." / filename; - - if(std::filesystem::exists(oldPath) && !std::filesystem::exists(dbPath)) - { - try - { - std::filesystem::rename(oldPath, dbPath); - } - catch(...) - { - return false; - } - - return true; - } - - return false; - } bool GAStore::initDatabaseLocation() { @@ -244,8 +220,6 @@ namespace gameanalytics { if(!std::filesystem::create_directory(p)) return false; - - fixOldDatabase(); } return true; From 8fabc1c67ba8d75dba594266b26b188b0a3cd717 Mon Sep 17 00:00:00 2001 From: Dorin Date: Thu, 9 Oct 2025 16:17:38 +0300 Subject: [PATCH 65/66] increase version --- source/gameanalytics/GACommon.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/gameanalytics/GACommon.h b/source/gameanalytics/GACommon.h index 37f533c6..c6890c34 100644 --- a/source/gameanalytics/GACommon.h +++ b/source/gameanalytics/GACommon.h @@ -85,7 +85,7 @@ namespace gameanalytics class GAState; } - constexpr const char* GA_VERSION_STR = "cpp 5.0.0"; + constexpr const char* GA_VERSION_STR = "cpp 5.1.0"; constexpr int MAX_CUSTOM_FIELDS_COUNT = 50; constexpr int MAX_CUSTOM_FIELDS_KEY_LENGTH = 64; From d8d84d247f72e87d567b9efc1bd49304e8c325f9 Mon Sep 17 00:00:00 2001 From: Dorin Date: Thu, 9 Oct 2025 16:24:10 +0300 Subject: [PATCH 66/66] 5.1.0 changelog --- CHANGELOG.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b26b7b13..b9f80700 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,16 @@ # Changelog +# 5.1.0 + +### Added + +- **Previous session time**: functionality to get the last session time + +### Fixed + +- **Playtime Metrics**: Fixed annotations for session time and total session time +- **MacOS**: GPU model detection + ## 5.0.0 ### Added