main 6f5368bf027b cached
276 files
1.7 MB
620.3k tokens
257 symbols
1 requests
Download .txt
Showing preview only (1,807K chars total). Download the full file or copy to clipboard to get everything.
Repository: 3ddelano/epic-online-services-godot
Branch: main
Commit: 6f5368bf027b
Files: 276
Total size: 1.7 MB

Directory structure:
gitextract_ngm7nid4/

├── .clang-format
├── .editorconfig
├── .gitattributes
├── .github/
│   ├── FUNDING.yml
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.md
│   │   └── feature_request.md
│   └── workflows/
│       ├── build.yml
│       └── deploy-docs.yml
├── .gitignore
├── .gitmodules
├── .pre-commit-config.yaml
├── .vscode/
│   ├── c_cpp_properties.json
│   ├── launch.json
│   ├── settings.json
│   └── tasks.json
├── LICENSE.md
├── README.md
├── SConstruct
├── build-ios.sh
├── debug-entitlements.plist
├── debug.cmd
├── debug.sh
├── docs/
│   ├── .gitignore
│   ├── README.md
│   ├── bun.lockb
│   ├── docs/
│   │   ├── installation.md
│   │   ├── introduction.md
│   │   ├── sample-project.md
│   │   ├── topics/
│   │   │   ├── authentication.md
│   │   │   └── initialization.md
│   │   └── update-guide.md
│   ├── docusaurus.config.ts
│   ├── package.json
│   ├── postcss.config.js
│   ├── sidebars.ts
│   ├── src/
│   │   ├── components/
│   │   │   ├── ExampleSection.tsx
│   │   │   ├── FeaturesSection.tsx
│   │   │   ├── HeroSection.tsx
│   │   │   ├── Icons.tsx
│   │   │   ├── InfoSections.tsx
│   │   │   ├── Layout.tsx
│   │   │   ├── MainSystemsSection.tsx
│   │   │   ├── MediaSections.tsx
│   │   │   └── SupportSection.tsx
│   │   ├── css/
│   │   │   └── custom.css
│   │   ├── pages/
│   │   │   ├── index.tsx
│   │   │   └── showcase.md
│   │   └── plugins/
│   │       └── tailwind-config.ts
│   ├── static/
│   │   └── .nojekyll
│   └── tsconfig.json
├── function_analyzer.py
├── sample/
│   ├── .gitignore
│   ├── AntiCheatServerMain.gd
│   ├── AntiCheatServerMain.gd.uid
│   ├── Main.gd
│   ├── Main.gd.uid
│   ├── Main.tscn
│   ├── addons/
│   │   └── epic-online-services-godot/
│   │       ├── base_class.gd
│   │       ├── base_class.gd.uid
│   │       ├── bin/
│   │       │   └── .gitignore
│   │       ├── dataclass.gd
│   │       ├── dataclass.gd.uid
│   │       ├── eos.gd
│   │       ├── eos.gd.uid
│   │       ├── eosg.gdextension
│   │       ├── eosg.gdextension.uid
│   │       ├── export_plugin.gd
│   │       ├── export_plugin.gd.uid
│   │       ├── heos/
│   │       │   ├── hachievement_data.gd
│   │       │   ├── hachievement_data.gd.uid
│   │       │   ├── hachievements.gd
│   │       │   ├── hachievements.gd.uid
│   │       │   ├── hauth.gd
│   │       │   ├── hauth.gd.uid
│   │       │   ├── hcredentials.gd
│   │       │   ├── hcredentials.gd.uid
│   │       │   ├── hfriends.gd
│   │       │   ├── hfriends.gd.uid
│   │       │   ├── hleaderboards.gd
│   │       │   ├── hleaderboards.gd.uid
│   │       │   ├── hlobbies.gd
│   │       │   ├── hlobbies.gd.uid
│   │       │   ├── hlobby.gd
│   │       │   ├── hlobby.gd.uid
│   │       │   ├── hlobbymember.gd
│   │       │   ├── hlobbymember.gd.uid
│   │       │   ├── hlog.gd
│   │       │   ├── hlog.gd.uid
│   │       │   ├── hp2p.gd
│   │       │   ├── hp2p.gd.uid
│   │       │   ├── hplatform.gd
│   │       │   ├── hplatform.gd.uid
│   │       │   ├── hsessions.gd
│   │       │   ├── hsessions.gd.uid
│   │       │   ├── hstats.gd
│   │       │   └── hstats.gd.uid
│   │       ├── plugin.cfg
│   │       ├── plugin.gd
│   │       ├── plugin.gd.uid
│   │       ├── runtime.gd
│   │       └── runtime.gd.uid
│   ├── components/
│   │   └── StyledPopupWindow/
│   │       ├── StyledPopupWindow.gd
│   │       ├── StyledPopupWindow.gd.uid
│   │       ├── StyledPopupWindow.tscn
│   │       └── StyledPopupWindowTheme.tres
│   ├── dedicated_server_example/
│   │   ├── client_main.gd
│   │   ├── client_main.gd.uid
│   │   ├── client_main.tscn
│   │   ├── server_main.gd
│   │   ├── server_main.gd.uid
│   │   └── server_main.tscn
│   ├── default_bus_layout.tres
│   ├── default_env.tres
│   ├── fonts/
│   │   ├── roboto-13r.tres
│   │   ├── roboto-16b.tres
│   │   ├── roboto-16r.tres
│   │   └── roboto-32b.tres
│   ├── game/
│   │   ├── entities/
│   │   │   ├── bullet/
│   │   │   │   ├── bullet.gd
│   │   │   │   ├── bullet.gd.uid
│   │   │   │   └── bullet.tscn
│   │   │   ├── player/
│   │   │   │   ├── player.gd
│   │   │   │   ├── player.gd.uid
│   │   │   │   └── player.tscn
│   │   │   └── wall/
│   │   │       └── wall.tscn
│   │   └── maps/
│   │       ├── map_bellandur.tscn
│   │       ├── map_margao.tscn
│   │       └── map_new_york.tscn
│   ├── project.godot
│   ├── scenes/
│   │   ├── AchievementsView/
│   │   │   ├── AchievementPopup.gd
│   │   │   ├── AchievementPopup.gd.uid
│   │   │   ├── AchievementUnlockNotification.gd
│   │   │   ├── AchievementUnlockNotification.gd.uid
│   │   │   ├── AchievementUnlockNotification.tscn
│   │   │   ├── AchievementsList.gd
│   │   │   ├── AchievementsList.gd.uid
│   │   │   ├── AchievementsListAchievement.gd
│   │   │   ├── AchievementsListAchievement.gd.uid
│   │   │   ├── AchievementsListAchievement.tscn
│   │   │   ├── AchievementsView.gd
│   │   │   ├── AchievementsView.gd.uid
│   │   │   └── AchievementsView.tscn
│   │   ├── CustomInvitesView/
│   │   │   ├── CustomInvitesView.gd
│   │   │   ├── CustomInvitesView.gd.uid
│   │   │   └── CustomInvitesView.tscn
│   │   ├── FriendsView/
│   │   │   ├── FriendsView.gd
│   │   │   ├── FriendsView.gd.uid
│   │   │   └── FriendsView.tscn
│   │   ├── LeaderboardsView/
│   │   │   ├── LeaderboardsView.gd
│   │   │   ├── LeaderboardsView.gd.uid
│   │   │   └── LeaderboardsView.tscn
│   │   ├── LobbiesView/
│   │   │   ├── CreateLobbyPopup.gd
│   │   │   ├── CreateLobbyPopup.gd.uid
│   │   │   ├── CreateLobbyPopup.tscn
│   │   │   ├── CurrentLobby.gd
│   │   │   ├── CurrentLobby.gd.uid
│   │   │   ├── LobbiesView.gd
│   │   │   ├── LobbiesView.gd.uid
│   │   │   ├── LobbiesView.tscn
│   │   │   ├── SearchLobby.gd
│   │   │   ├── SearchLobby.gd.uid
│   │   │   ├── SearchLobbyResults.gd
│   │   │   └── SearchLobbyResults.gd.uid
│   │   ├── LoginView/
│   │   │   ├── EnterCredentials.gd
│   │   │   ├── EnterCredentials.gd.uid
│   │   │   ├── LoginView.gd
│   │   │   ├── LoginView.gd.uid
│   │   │   └── LoginView.tscn
│   │   ├── LogsView/
│   │   │   ├── LogsView.gd
│   │   │   ├── LogsView.gd.uid
│   │   │   └── LogsView.tscn
│   │   ├── MetricsView/
│   │   │   ├── MetricsView.gd
│   │   │   ├── MetricsView.gd.uid
│   │   │   └── MetricsView.tscn
│   │   ├── NotificationsView/
│   │   │   ├── NotificationsView.gd
│   │   │   └── NotificationsView.gd.uid
│   │   ├── StatsView/
│   │   │   ├── StatsView.gd
│   │   │   ├── StatsView.gd.uid
│   │   │   └── StatsView.tscn
│   │   ├── UI/
│   │   │   ├── NetworkImage.gd
│   │   │   ├── NetworkImage.gd.uid
│   │   │   ├── NetworkImage.tscn
│   │   │   ├── PrimaryButton.tscn
│   │   │   ├── joysticks.gd
│   │   │   ├── joysticks.gd.uid
│   │   │   ├── nat_type.gd
│   │   │   ├── nat_type.gd.uid
│   │   │   ├── nat_type.tscn
│   │   │   ├── ping.gd
│   │   │   ├── ping.gd.uid
│   │   │   ├── ping.tscn
│   │   │   ├── players_score.gd
│   │   │   ├── players_score.gd.uid
│   │   │   ├── players_score.tscn
│   │   │   ├── touch_screen_joystick.gd
│   │   │   └── touch_screen_joystick.gd.uid
│   │   └── UIView/
│   │       ├── UIView.gd
│   │       ├── UIView.gd.uid
│   │       └── UIView.tscn
│   ├── scripts/
│   │   ├── Env.gd
│   │   ├── Env.gd.uid
│   │   ├── Store.gd
│   │   ├── Store.gd.uid
│   │   ├── ViewManager.gd
│   │   ├── ViewManager.gd.uid
│   │   ├── network.gd
│   │   └── network.gd.uid
│   ├── styles/
│   │   └── ViewTitleLabelSettings.tres
│   ├── test.gd
│   ├── test.gd.uid
│   ├── test_manual_audio_output.gd
│   └── test_manual_audio_output.gd.uid
├── src/
│   ├── achievements_interface.cpp
│   ├── anticheat_client_interface.cpp
│   ├── anticheat_server_interface.cpp
│   ├── auth_interface.cpp
│   ├── connect_interface.cpp
│   ├── custom_invites_interface.cpp
│   ├── ecom_interface.cpp
│   ├── eosg_active_session.cpp
│   ├── eosg_active_session.h
│   ├── eosg_continuance_token.h
│   ├── eosg_file_transfer_request.h
│   ├── eosg_lobby_details.cpp
│   ├── eosg_lobby_details.h
│   ├── eosg_lobby_modification.cpp
│   ├── eosg_lobby_modification.h
│   ├── eosg_lobby_search.cpp
│   ├── eosg_lobby_search.h
│   ├── eosg_multiplayer_peer.cpp
│   ├── eosg_multiplayer_peer.h
│   ├── eosg_packet_peer_mediator.cpp
│   ├── eosg_packet_peer_mediator.h
│   ├── eosg_playerdatastorage_file_transfer_request.cpp
│   ├── eosg_playerdatastorage_file_transfer_request.h
│   ├── eosg_presence_modification.cpp
│   ├── eosg_presence_modification.h
│   ├── eosg_session_details.cpp
│   ├── eosg_session_details.h
│   ├── eosg_session_modification.cpp
│   ├── eosg_session_modification.h
│   ├── eosg_session_search.cpp
│   ├── eosg_session_search.h
│   ├── eosg_titlestorage_file_transfer_request.cpp
│   ├── eosg_titlestorage_file_transfer_request.h
│   ├── eosg_transaction.cpp
│   ├── eosg_transaction.h
│   ├── friends_interface.cpp
│   ├── ieos.cpp
│   ├── ieos.h
│   ├── kws_interface.cpp
│   ├── leaderboards_interface.cpp
│   ├── lobby_interface.cpp
│   ├── logging_interface.cpp
│   ├── metrics_interface.cpp
│   ├── mods_interface.cpp
│   ├── p2p_interface.cpp
│   ├── platform_interface.cpp
│   ├── playerdatastorage_interface.cpp
│   ├── presence_interface.cpp
│   ├── progression_snapshot_interface.cpp
│   ├── register_types.cpp
│   ├── register_types.h
│   ├── reports_interface.cpp
│   ├── rtc_audio_interface.cpp
│   ├── rtc_data_interface.cpp
│   ├── rtc_interface.cpp
│   ├── sanctions_interface.cpp
│   ├── sessions_interface.cpp
│   ├── stats_interface.cpp
│   ├── titlestorage_interface.cpp
│   ├── ui_interface.cpp
│   ├── user_info_interface.cpp
│   ├── utils.cpp
│   ├── utils.h
│   └── version_interface.cpp
└── thirdparty/
    └── Paste the EOS C SDK here as eos-sdk

================================================
FILE CONTENTS
================================================

================================================
FILE: .clang-format
================================================
# Commented out parameters are those with the same value as base LLVM style.
# We can uncomment them if we want to change their value, or enforce the
# chosen value in case the base style changes (last sync: Clang 14.0).
---
### General config, applies to all languages ###
BasedOnStyle: LLVM
AccessModifierOffset: -4
AlignAfterOpenBracket: DontAlign
AlignOperands:   DontAlign
AlignTrailingComments: false
AllowAllParametersOfDeclarationOnNextLine: false
BreakConstructorInitializers: AfterColon
ColumnLimit:     0
ConstructorInitializerIndentWidth: 8
ContinuationIndentWidth: 8
Cpp11BracedListStyle: false
ConstructorInitializerAllOnOneLineOrOnePerLine: true
IncludeCategories:
  - Regex:           '".*"'
    Priority:        1
  - Regex:           '^<.*\.h>'
    Priority:        2
  - Regex:           '^<.*'
    Priority:        3
IndentCaseLabels: true
IndentWidth:     4
KeepEmptyLinesAtTheStartOfBlocks: false
SpacesInLineCommentPrefix:
  Minimum:         0
  Maximum:         -1
TabWidth:        4
UseTab:          false

---
### C++ specific config ###
Language:        Cpp
Standard:        c++17
---
### ObjC specific config ###
Language:        ObjC
ObjCBlockIndentWidth: 4
---
### Java specific config ###
Language:        Java
JavaImportGroups: ['org.godotengine', 'android', 'androidx', 'com.android', 'com.google', 'java', 'javax']
...


================================================
FILE: .editorconfig
================================================
# EditorConfig is awesome: https://EditorConfig.org

# top-most EditorConfig file
root = true

[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = false
insert_final_newline = false

[*.{h,hpp,cpp,gd}]
indent_style = tab
indent_size = 4

================================================
FILE: .gitattributes
================================================
# Normalize EOL for all files that Git considers text files.
* text=auto eol=lf

================================================
FILE: .github/FUNDING.yml
================================================
github: 3ddelano
custom: https://www.buymeacoffee.com/3ddelano


================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.md
================================================
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: 3ddelano

---

**Describe the bug**
A clear and concise description of what the bug is.

**To Reproduce**
Minimal steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error

(or provide link to minimal reproducible project)

**Expected behavior**
A clear and concise description of what you expected to happen.

**Screenshots**
If applicable, add screenshots to help explain your problem.

**Operating System:**
 - Version: [e.g. iOS 18.2, macOS arm64 15.2]

**Plugin version:**
- Version [e.g. v2.1.5]

**Godot version:**
- Version [e.g. v4.2]

**Additional context**
Add any other context about the problem here.


================================================
FILE: .github/ISSUE_TEMPLATE/feature_request.md
================================================
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''

---

**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

**Describe the solution you'd like**
A clear and concise description of what you want to happen.

**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.

**Additional context**
Add any other context or screenshots about the feature request here.


================================================
FILE: .github/workflows/build.yml
================================================
name: 🛠️ Builds
on:
  workflow_dispatch:
  push:
    branches:
      - "*"
    tags:
      - "*"
jobs:
  build:
    runs-on: ${{ matrix.runner }}
    name: ${{ matrix.name }}
    strategy:
      fail-fast: false
      matrix:
        include:
          - identifier: linux-x86-64-debug
            name: 🐧 Linux x86_64 Debug
            runner: ubuntu-24.04
            target: template_debug
            dev_build: yes
            platform: linux
            arch: x86_64
          - identifier: linux-x86-64-release
            name: 🐧Linux x86_64 Release
            runner: ubuntu-24.04
            target: template_release
            dev_build: no
            platform: linux
            arch: x86_64
          - identifier: linux-arm64-debug
            name: 🐧 Linux arm64 Debug
            runner: ubuntu-24.04-arm
            target: template_debug
            dev_build: yes
            platform: linux
            arch: arm64
          - identifier: linux-arm64-release
            name: 🐧Linux arm64 Release
            runner: ubuntu-24.04-arm
            target: template_release
            dev_build: no
            platform: linux
            arch: arm64
          - identifier: macos-debug
            name: 🍎 macOS (universal) Debug
            runner: macos-latest
            target: template_debug
            dev_build: yes
            platform: macos
            arch: universal
          - identifier: macos-release
            name: 🍎 macOS (universal) Release
            runner: macos-latest
            target: template_release
            dev_build: no
            platform: macos
            arch: universal
          - identifier: windows-debug
            name: 🏁 Windows Debug
            runner: windows-latest
            target: template_debug
            dev_build: yes
            platform: windows
            arch: x86_64
          - identifier: windows-release
            name: 🏁 Windows Release
            runner: windows-latest
            target: template_release
            dev_build: no
            platform: windows
            arch: x86_64
          - identifier: android-arm64-debug
            name: 🤖 Android arm64 Debug
            runner: ubuntu-24.04
            target: template_debug
            dev_build: yes
            platform: android
            arch: arm64
          - identifier: android-arm64-release
            name: 🤖 Android arm64 Release
            runner: ubuntu-24.04
            target: template_release
            dev_build: no
            platform: android
            arch: arm64
          - identifier: android-x86_64-debug
            name: 🤖 Android x86_64 Debug
            runner: ubuntu-24.04
            target: template_debug
            dev_build: yes
            platform: android
            arch: x86_64
          - identifier: android-x86_64-release
            name: 🤖 Android x86_64 Release
            runner: ubuntu-24.04
            target: template_release
            dev_build: no
            platform: android
            arch: x86_64
          - identifier: ios-arm64-all
            name: 🍏 iOS (arm64) All
            runner: macos-latest
            platform: ios
    steps:
      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: "3.x"

      - name: Set up SCons
        shell: bash
        run: |
          python -c "import sys; print(sys.version)"
          python -m pip install scons
          scons --version

      - name: Checkout project
        uses: actions/checkout@v4
        with:
          submodules: false

      - name: Checkout godot-cpp
        uses: actions/checkout@v4
        with:
          repository: godotengine/godot-cpp
          path: godot-cpp
          submodules: recursive
          ref: "godot-4.2-stable"

      - name: Checkout private EOS SDK mirror repo
        uses: actions/checkout@v4
        with:
          token: "${{secrets.EOS_SDK_MIRROR_PAT}}"
          repository: 3ddelano/eos-sdk-mirror
          path: thirdparty/eos-sdk
          ref: "dd294d8d5d175840f61775a527332560ba81afa4"

      - name: (Windows) Install mingw64
        if: ${{ matrix.platform == 'windows' }}
        # change to egor-tensin/setup-mingw@v2 once pr #16 is merged
        uses: 3ddelano/setup-mingw@patch-1

      - name: (Linux) Install dependencies
        if: ${{ matrix.platform == 'linux' }}
        run: |
          sudo apt-get update -qq
          sudo apt-get install -qqq build-essential pkg-config

      - name: (Android) Install dependencies
        if: ${{ matrix.platform == 'android' }}
        uses: nttld/setup-ndk@v1
        with:
          ndk-version: r23c
          link-to-sdk: true

      - name: Setup build cache
        uses: actions/cache@v4
        with:
          path: ${{ github.workspace }}/.scons-cache/
          key: ${{ matrix.identifier }}
          restore-keys: |
            ${{ matrix.identifier }}
        continue-on-error: true

      - name: Compile extension
        shell: sh
        if: ${{ matrix.platform != 'ios' }}
        env:
          SCONS_CACHE: ${{ github.workspace }}/.scons-cache/
          SCONS_CACHE_LIMIT: 7168
        run: |
          scons target='${{ matrix.target }}' platform='${{ matrix.platform }}' arch='${{ matrix.arch }}' dev_build='${{ matrix.dev_build }}'

      - name: (iOS) Compile extension
        shell: sh
        if: ${{ matrix.platform == 'ios' }}
        env:
          SCONS_CACHE: ${{ github.workspace }}/.scons-cache/
          SCONS_CACHE_LIMIT: 7168
        run: |
          chmod +x ./build-ios.sh && ./build-ios.sh

      - name: Copy extra files to addon folder
        shell: sh
        run: |
          cp -n '${{ github.workspace }}/README.md' '${{ github.workspace }}/LICENSE.md' '${{ github.workspace }}/sample/addons/epic-online-services-godot/'

      - name: Create artifact folder
        shell: sh
        run: |
          mkdir -p '${{ github.workspace }}/artifact-${{ matrix.identifier }}/${{ github.event.repository.name }}/'

      - name: Copy addons folder to artifact folder
        shell: sh
        run: |
          cp -n -r '${{ github.workspace }}/sample/addons' '${{ github.workspace }}/artifact-${{ matrix.identifier }}/${{ github.event.repository.name }}/'

      - name: (Windows) Delete compilation files
        if: ${{ matrix.platform == 'windows' }}
        run: |
          Remove-Item ${{ github.workspace }}/artifact-${{ matrix.identifier }}/${{ github.event.repository.name }}/addons/epic-online-services-godot/bin/windows/* -Include *.exp,*.lib,*.ilk -Force

      - name: Upload artifact
        uses: actions/upload-artifact@v4
        with:
          name: ${{ github.event.repository.name }}-${{ matrix.identifier }}-${{ github.sha }}
          path: |
            ${{ github.workspace }}/artifact-${{ matrix.identifier }}/
          compression-level: 9
          retention-days: 14

  merge-platforms:
    runs-on: ubuntu-latest
    needs: build
    strategy:
      fail-fast: false
      matrix:
        include:
          - identifier: linux-x86_64
            name: 🐧 Linux
            matchpattern: linux
          - identifier: macos-universal
            name: 🍎 macOS (universal)
            matchpattern: macos
          - identifier: windows
            name: 🏁 Windows
            matchpattern: windows
          - identifier: android
            name: 🤖 Android
            matchpattern: android
          - identifier: ios
            name: 🍏 iOS
            matchpattern: ios

    steps:
      - name: Merge artifacts for platform
        uses: actions/upload-artifact/merge@v4
        with:
          name: ${{ github.event.repository.name }}-${{ matrix.matchpattern }}-${{ github.sha }}
          pattern: ${{ github.event.repository.name }}-${{ matrix.matchpattern }}*
          compression-level: 9
          retention-days: 14

  merge-all:
    runs-on: ubuntu-latest
    needs: merge-platforms
    steps:
      - name: Merge artifacts into single
        uses: actions/upload-artifact/merge@v4
        with:
          name: ${{ github.event.repository.name }}-all-${{ github.sha }}
          pattern: ${{ github.event.repository.name }}-*
          compression-level: 9
          retention-days: 14

  upload-to-release:
    if: startsWith(github.ref, 'refs/tags/')
    runs-on: ubuntu-latest
    needs: merge-all
    permissions:
      contents: write
    steps:
      - name: Download 'all' artifact
        uses: actions/download-artifact@v4
        with:
          name: ${{ github.event.repository.name }}-all-${{ github.sha }}
          path: artifact-all
      - name: Download 'android' artifact
        uses: actions/download-artifact@v4
        with:
          name: ${{ github.event.repository.name }}-android-${{ github.sha }}
          path: artifact-android
      - name: Download 'macos' artifact
        uses: actions/download-artifact@v4
        with:
          name: ${{ github.event.repository.name }}-macos-${{ github.sha }}
          path: artifact-macos
      - name: Download 'linux' artifact
        uses: actions/download-artifact@v4
        with:
          name: ${{ github.event.repository.name }}-linux-${{ github.sha }}
          path: artifact-linux
      - name: Download 'windows' artifact
        uses: actions/download-artifact@v4
        with:
          name: ${{ github.event.repository.name }}-windows-${{ github.sha }}
          path: artifact-windows
      - name: Download 'ios' artifact
        uses: actions/download-artifact@v4
        with:
          name: ${{ github.event.repository.name }}-ios-${{ github.sha }}
          path: artifact-ios

      - name: Zip 'all' artifact
        run: |
          cd artifact-all
          zip -9 -r ../${{ github.event.repository.name }}-all-${{ github.sha }}.zip .
          cd ..
      - name: Zip 'android' artifact
        run: |
          cd artifact-android
          zip -9 -r ../${{ github.event.repository.name }}-android-${{ github.sha }}.zip .
          cd ..
      - name: Zip 'macos' artifact
        run: |
          cd artifact-macos
          zip -9 -r ../${{ github.event.repository.name }}-macos-${{ github.sha }}.zip .
          cd ..
      - name: Zip 'linux' artifact
        run: |
          cd artifact-linux
          zip -9 -r ../${{ github.event.repository.name }}-linux-${{ github.sha }}.zip .
          cd ..
      - name: Zip 'windows' artifact
        run: |
          cd artifact-windows
          zip -9 -r ../${{ github.event.repository.name }}-windows-${{ github.sha }}.zip .
          cd ..
      - name: Zip 'ios' artifact
        run: |
          cd artifact-ios
          zip -9 -r ../${{ github.event.repository.name }}-ios-${{ github.sha }}.zip .
          cd ..

      - name: Create draft release and upload assets
        uses: softprops/action-gh-release@v2
        if: startsWith(github.ref, 'refs/tags/')
        with:
          tag_name: ${{ github.ref_name }}
          draft: true
          files: |
            ${{github.event.repository.name}}-all-${{ github.sha }}.zip
            ${{github.event.repository.name}}-android-${{ github.sha }}.zip
            ${{github.event.repository.name}}-macos-${{ github.sha }}.zip
            ${{github.event.repository.name}}-linux-${{ github.sha }}.zip
            ${{github.event.repository.name}}-windows-${{ github.sha }}.zip
            ${{github.event.repository.name}}-ios-${{ github.sha }}.zip


================================================
FILE: .github/workflows/deploy-docs.yml
================================================
name: Deploy Docs to GitHub Pages

on:
  push:
    branches:
      - "*"
    # Review gh actions docs if you want to further define triggers, paths, etc
    # https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#on

jobs:
  build:
    name: Build Docusaurus
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - uses: oven-sh/setup-bun@v2

      - name: Install dependencies
        run: cd docs && bun install
      
      - name: Build website
        run: cd docs && bun run build

      - name: Upload Build Artifact
        uses: actions/upload-pages-artifact@v3
        with:
          path: docs/build

  deploy:
    name: Deploy to GitHub Pages
    needs: build
    if: github.ref == 'refs/heads/main'

    # Grant GITHUB_TOKEN the permissions required to make a Pages deployment
    permissions:
      pages: write # to deploy to Pages
      id-token: write # to verify the deployment originates from an appropriate source

    # Deploy to the github-pages environment
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}

    runs-on: ubuntu-latest
    steps:
      - name: Deploy to GitHub Pages
        id: deployment
        uses: actions/deploy-pages@v4

================================================
FILE: .gitignore
================================================
# Godot logs
logs/

cache/
.cache/

sample/android
sample/android_debug.keystore

.DS_Store

.env
vc140.pdb
.sconsign.dblite

*.o
*.obj
*.os

**/*.tmp

temp/

.idea/

compile_commands.json

epic-online-services-godot-addon.zip

================================================
FILE: .gitmodules
================================================
[submodule "godot-cpp"]
	path = godot-cpp
	url = https://github.com/godotengine/godot-cpp
	branch = 4.2
[submodule "thirdparty/eos-sdk"]
	path = thirdparty/eos-sdk
	url = https://github.com/3ddelano/eos-sdk-mirror.git


================================================
FILE: .pre-commit-config.yaml
================================================
repos:
-   repo: https://github.com/ssciwr/clang-format-hook
    rev: v16.0.2
    hooks:
    -   id: clang-format

================================================
FILE: .vscode/c_cpp_properties.json
================================================
{
    "configurations": [
        {
            "name": "Win32",
            "includePath": [
                "${workspaceFolder}/godot-cpp/**",
                "${workspaceFolder}/godot-cpp/gen/include/**",
                "${workspaceFolder}/godot-cpp/include/**",
                "${workspaceFolder}/godot-cpp/gdextension/**",
                "${workspaceFolder}/thirdparty/eos-sdk/SDK/Include/",
                "${workspaceFolder}/thirdparty/eos-sdk/SDK/Include/**",
                "${workspaceFolder}/src/**",
                "${workspaceFolder}/src"
            ],
            "defines": ["_DEBUG", "UNICODE", "_UNICODE"],
            "windowsSdkVersion": "10.0.19041.0",
            "compilerPath": "cl.exe",
            "cStandard": "c17",
            "cppStandard": "c++17",
            "intelliSenseMode": "windows-msvc-x64"
        }
    ],
    "version": 4
}


================================================
FILE: .vscode/launch.json
================================================
{
	"version": "0.2.0",
	"configurations": [
		{
			"name": "Debug Project (Windows)",
			"type": "cppvsdbg",
			"request": "launch",
			"program": "${config:godotTools.editorPath.godot4}",
			"args": ["--debug"],
			"stopAtEntry": false,
			"cwd": "${workspaceFolder}/sample",
			"environment": [],
			"console": "integratedTerminal",
			"preLaunchTask": "build"
		},
		{
			"name": "Debug Project (Macos)",
			"type": "cppdbg",
			"request": "launch",
			"program": "${config:godotTools.editorPath.godot4}",
			"args": ["--debug"],
			"stopAtEntry": false,
			"cwd": "${workspaceFolder}/sample",
			"environment": [],
			"console": "integratedTerminal",
			"MIMode": "lldb",
			"preLaunchTask": "build"
		}
	]
}


================================================
FILE: .vscode/settings.json
================================================
{
  "files.exclude": {
    "**/*.obj": true,
    "**/*.ilk": true,
    "**/*.exp": true,
    "**/*.pdb": true,
    "**/__pycache__": true,
    "**/*.os": true,
    "**/*.o": true
  },
  "godot_tools.editor_path": "d:\\Projects\\Godot\\Godot_v4.exe",
  "files.associations": {
    "*.rmd": "markdown",
    "utility": "cpp",
    "sstream": "cpp",
    "unordered_map": "cpp",
    "algorithm": "cpp",
    "chrono": "cpp",
    "iterator": "cpp",
    "xhash": "cpp",
    "xtree": "cpp",
    "xutility": "cpp",
    "string": "cpp",
    "type_traits": "cpp",
    "deque": "cpp",
    "forward_list": "cpp",
    "list": "cpp",
    "vector": "cpp",
    "initializer_list": "cpp"
  },
  "grammarly.selectors": [
    {
      "language": "cpp",
      "scheme": "file"
    }
  ],
  "cmake.ignoreCMakeListsMissing": true
}


================================================
FILE: .vscode/tasks.json
================================================
{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "build",
            "group": "build",
            "type": "shell",
            "command": "scons",
            "args": ["dev_build=yes"],
            "problemMatcher": "$msCompile"
        },
        {
            "label": "build-release",
            "group": "build",
            "type": "shell",
            "command": "scons",
            "args": ["target=template_release"],
            "problemMatcher": "$msCompile"
        }
    ]
}


================================================
FILE: LICENSE.md
================================================
MIT License

Copyright (c) 2022 Delano Lourenco

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

================================================
FILE: README.md
================================================
# Epic Online Services Godot (EOSG)

<img alt="Project Logo" src="./_media/logo.png" height="150">

### Easiest way to use Epic Online Services in Godot 4.2+ (includes demo project)

<img alt="Godot3" src="https://img.shields.io/badge/-Godot 4.2+-478CBF?style=for-the-badge&logo=godotengine&logoWidth=20&logoColor=white" />
&nbsp;&nbsp;&nbsp;<img alt="Epic Online Services 1.18.1.2" src="https://img.shields.io/badge/-Epic Online Services 1.18.1.2-313131?style=for-the-badge&logo=epic-games&logoWidth=20&logoColor=white" />

> Supports Windows x64, Linux x64/arm64, Android x64/arm64, MacOS, iOS arm64 (iphone/simulator)

> Disclaimer: This project is NOT affiliated with Epic Games Inc or Godot Engine. It doesn't endorse Epic Online
> Services. This project and sample Godot scenes are provided solely for educational purposes and may or may not comply
> with Epic Games' Design Guidelines, if you plan to release a game make sure you read
> the [Guidelines](https://dev.epicgames.com/docs/services/en-US/EpicAccountServices/DesignGuidelines/index.html) and
> any
> other steps needed to release a public game like asking for user consent, option to delete user data, website with
> privacy policy and license, etc.

## This plugin has two main systems:

- ### High Level EOS (Recommended)

  The High Level Epic Online Services provides easy to use methods and signals to interact with EOS recommended for
  beginners.

- ### GDExtension EOS
  The GDExtension EOS provides advanced EOS usage not recommended for beginners. See `EOS` and `IEOS` classes.

## [🚀 Check out out GDAI MCP from the creator of EOSG](https://gdaimcp.com?ref=eosg-readme)

<a href="https://gdaimcp.com?ref=eosg-readme" target="_blank">
<img src="https://gdaimcp.com/images/og/gdai-mcp.png" width="400" />
</a>

Supercharge your Godot 4.2+ workflow with GDAI MCP – the ultimate Godot MCP server that lets AI tools like Claude,
Cursor, Windsurf, VSCode and more automate scene creation, node editing, reading godot errors, creating scripts,
debugging, and more.

Vibe code like never before!

### 🔗 **[https://gdaimcp.com](https://gdaimcp.com?ref=eosg-readme)**

# High Level Epic Online Services

Following are the main classes in High Level Epic Online Services. They also have documentation in the Godot Editor:

- ### HPlatform
- ### HAuth
- ### HAchievements
- ### HFriends
- ### HStats
- ### HLeaderboards
- ### HLobbies
- ### HP2P
- ### HLog

A basic example of using High Level EOS:

```GDScript
# In main script
extends Node

func _ready() -> void:
	# Setup HEOS Logs
	HLog.log_level = HLog.LogLevel.INFO

	var credentials = HCredentials.new()
	credentials.product_name = "PRODUCT_NAME_NAME"
	credentials.product_version = "PRODUCT_VERSION_HERE"
	credentials.product_id = "PRODUCT_ID_HERE"
	credentials.sandbox_id = "SANDBOX_ID_HERE"
	credentials.deployment_id = "DEPLOYMENT_ID_HERE"
	credentials.client_id = "CLIENT_ID_HERE"
	credentials.client_secret = "CLIENT_SECRET_HERE"
	# optional
	#credentials.encryption_key = "ENCRYPTION_KEY_HERE"

	var setup_success := await HPlatform.setup_eos_async(credentials)
	if not setup_success:
	    printerr("Failed to setup EOS. See logs for more details")
	    return

	# Setup Logs from EOS
	HPlatform.log_msg.connect(_on_eos_log_msg)
	var log_res := HPlatform.set_eos_log_level(EOS.Logging.LogCategory.AllCategories, EOS.Logging.LogLevel.Info)
	if not EOS.is_success(log_res):
		printerr("Failed to set logging level")
		return

	HAuth.logged_in.connect(_on_logged_in)

	# During development use the devauth tool to login
	HAuth.login_devtool_async("localhost:4545", "CREDENTIAL_NAME_HERE")

	# Or login without any credentials
	# await HAuth.login_anonymous_async()


func _on_logged_in():
	print("Logged in successfully: product_user_id=%s" % HAuth.product_user_id)

	# Example: Get top records for a leaderboard
	var records := await HLeaderboards.get_leaderboard_records_async("LEADERBOARD_ID_HERE")
	print(records)


func _on_eos_log_msg(msg: EOS.Logging.LogMessage) -> void:
	print("SDK %s | %s" % [msg.category, msg.message])

```

# GDextension Epic Online Services

## Features

- Authentication (Epic Games, Steam, Discord, Anonymous etc)
- Social Overlay on Windows
- Achievements
- Stats & Leaderboards
- Lobby, Sessions and Multiplayer
- Voice
- Metrics
- Mods
- Player/Title data storage
- Progression Snapshot
- Reports and Sanctions
- Ecommerce (Ecom Epic Games Store)
- AntiCheat

#### [View Current Project Status](#current-project-status)

## Simple P2P Example

A simple demo showcasing P2P multiplayer using Epic Online
Services: [Click Here](https://github.com/3ddelano/EOSGP2PInterfaceTestGame)

## Support Development

#### Making this project took a lot of time and effort, reading the Epic Online Services documentation countless times and testing each method in Godot. I would really appreciate if you could support the project in any way.

<a href="https://www.buymeacoffee.com/3ddelano" target="_blank"><img height="41" width="174" src="https://cdn.buymeacoffee.com/buttons/v2/default-red.png" alt="Buy Me A Coffee" width="150" ></a>
<br>
<a href="https://github.com/sponsors/3ddelano" target="_blank">Github Sponsor</a>

#### Want to support in other ways? Contact me on Discord: `@3ddelano`

Join the Discord server for discussing suggestions or bugs: [3ddelano Cafe](https://discord.gg/FZY9TqW)

## [Demo Video (Youtube)](https://www.youtube.com/watch?v=ENyvF4yVjKg)

[Watch the playlist](https://www.youtube.com/playlist?list=PL5t0hR7ADzun5JYF4e2a2FtZEWYHxK83_)

[![Epic Online Services Tutorial series](https://img.youtube.com/vi/ENyvF4yVjKg/0.jpg)](https://www.youtube.com/playlist?list=PL5t0hR7ADzun5JYF4e2a2FtZEWYHxK83_)

## [Documentation](http://localhost:3000/epic-online-services-godot/docs/introduction)

## Screenshots

- Windows
  <img src="./_media/windows_auth_success.png">

- Android
  <img src="./_media/android_auth_success.jpg">

   <img src="./_media/android_p2p_game.jpg">

- iOS
  <img src="./_media/ios_simulator_auth_success.png">

- Cross platform lobbies
  - iOS
    <img src="./_media/ios_simulator_in_lobby.png">
  - macOS
    <img src="./_media/mac_in_lobby.png">

## How does it work

This project uses GDExtension to wrap the `Epic Online Services C SDK` so that it can be easily used in Godot using
GDScript, C#, etc with similar class hierarchy and static type support. It makes use of signals for sending events like
user login, logout, achievement unlock, etc.

## Installation

This is a regular plugin for `Godot 4.2+`. To install the plugin follow the steps below:

#### **Method 1: Install from Asset Library**

1. Asset Library link: [View the plugin on Godot Asset Library](https://godotengine.org/asset-library/asset/2453)
2. In the Godot editor, navigate to the `AssetLib` tab, and in the search bar type `EOSG`.
3. Click on the plugin with name `Epic Online Services Godot (EOSG)` by `3ddelano`
4. In the popup that opens, click the `Download` button.
5. Once the download is done, click the `Install` button.
6. Goto `Project->Project Settings->Plugins` and enable the `Epic Online Services Godot 4.2+ (EOSG)` plugin.
7. Restart the godot editor.
8. You can now use the plugin. Head to the [Documentation](#) for more information on how to use the plugin.

#### **Method 2: Install from GitHub**

1. Goto the Releases section and download
   the [latest release](https://github.com/3ddelano/epic-online-services-godot/releases/latest)
2. Extract the zip file and copy the `addons/epic-online-services-godot` folder into the `res://addons/` folder of your
   project. If the `res://addons` does not exist, create it.
3. In the Godot editor, goto `Project->Project Settings->Plugins` and enable the
   `Epic Online Services Godot 4.2+ (EOSG)` plugin.
4. Restart the godot editor.
5. You can now use the plugin. Head to the [Documentation](#) for more information on how to use the plugin.

## Development Setup

#### Pre-requisites

- Godot Engine 4.2+ (Get it here [Godot Engine Download](https://godotengine.org/download/))
- Epic Online Services C SDK (Download from [Epic Developer Portal](https://dev.epicgames.com/portal/sdk))
- Make sure you have accepted the Terms and Conditions
  for [Epic Online Services](https://www.epicgames.com/site/en-US/tos?lang=en-US)
- A product registered with Epic Games Services (Make one for
  free [Epic Developer Portal](https://dev.epicgames.com/portal))

To develop this plugin, follow the below steps:

1. Download/clone the repository.

1. Run the command:
  ```bash
  git submodule update --init --recursive
  ```

1. Extract the `EOS C SDK` zip downloaded from Epic Games, rename it to `eos-sdk` and paste it in the `thirdparty/`
   folder. Refer to the below folder structure.

   <img src="./_media/eos_folder_structure.png">

1. Build the GDExtension plugin in debug mode (With debug symbols)

   ```shell
   # In root folder
   scons platform=<platform> target=template_debug dev_build=yes
   ```

   Eg. `scons platform=windows target=template_debug dev_build=yes`

1. Build the GDExtension plugin for release (Optimized)

   ```shell
   # In root folder
   scons platform=windows target=template_release
   ```

1. The built GDExtension library will be in the `res://addons/epic-online-services-godot/bin/` folder of the sample
   project.

## Debugging GDExtension on MacOS

If you get an error `Not allowed to attach to process` trying to debug GDExtension on MacOS using LLDB. Run the below
command:

```bash
codesign --entitlements debug-entitlements.plist -f -s - /Applications/Godot.app/Contents/MacOS/Godot
```

### How to run the sample project?

> The sample Godot project is located in the **sample** folder

1. Clone/Download the repo.
2. Download the [latest release](https://github.com/3ddelano/epic-online-services-godot/releases/latest) from the
   Releases section and replace the existing `/addons/epic-online-services-godot` with the one from the Release (this
   includes the built shared libraries).
3. Copy your credentials (`Product Id`, `Sandbox Id`, `Deployment Id`, `Client Id`, `Client Secret`) of your Epic
   Games "Product" from the Epic Games Dev Portal and paste them in `Main.gd` script in the relevant sections. The
   encryption key is a random 64 character long string. These credentials need to be kept as private as possible. One
   way is to make sure to encrypt all scripts when exporting the final game. (
   See [Compiling with script key encryption](https://docs.godotengine.org/en/stable/development/compiling/compiling_with_script_encryption_key.html))

4. Configure your Product on the EOS Dev Portal with the following configuration:

- In the `Client Policies` section in `Product Settings`, for the Client policy type choose `Custom policy`, enable the
  `User is required` and enable every features and action except `Connect` (Trusted Server Required). This will allow
  the sample to access the different services provided by Epic Online Services. In your actual game, the client policy
  is important and you should give minimal permissions to features.
- In the `Permissions` section of `Epic Account Services`, enable all three: `Basic Profile`, `Online Presence` and
  `Friends`.
- (Optional if you want some pre-made achievements)
  In the `Achievements` section in `Game Services`, use the `Bulk Import` option and import the `HelloProduct.zip` file
  located at `res://HelloProduct.zip`

### Bootstrapping Godot executable with Epic Online Services

If you want to use the `Account Portal` login option in Epic Online Services, you need to bootstrap the Godot/Game
executable as needed by `EOS-SDK 1.15` and greater.
See [Redistributable Installer](https://dev.epicgames.com/docs/services/en-US/EpicAccountServices/Crossplayacrossplatforms/RedistributableInstaller/index.html)

A sample of the generated `.ini` file for the Godot Editor is shown below (during game development):

```
ApplicationPath=Godot_v4.2.0-stable_win64.exe
WorkingDirectory=
WaitForExit=0
NoOperation=0
```

Follow the instructions
in [Running the service for local development](https://dev.epicgames.com/docs/services/en-US/EpicAccountServices/Crossplayacrossplatforms/RedistributableInstaller/index.html#runningtheserviceforlocaldevelopment)
and:

- During game development

  Bootstrap the Godot Editor executable (eg. `Godot_v4.2.0-stable_win64.exe`) to test the `Account Portal` login

- After exporting the game

  Bootstrap the exported game executable (eg. `My Amazing Game.exe`)

## Exporting for Android

Use a community created [Android Export Plugin](https://github.com/uno1982/EOSG-android-exporter)

Or follow the steps below to manually export for Android.

### Pre-requisites

1. Setup the `Android Build Template` in your Godot project by following the
   tutorial [Gradle builds for Andriod](https://docs.godotengine.org/en/stable/tutorials/export/android_gradle_build.html).
   This will create an android project in `res://android/build`.

2. Now with reference to the
   tutorial [Add the EOS SDK to Your Android Studio Project](https://dev.epicgames.com/docs/epic-online-services/platforms/android#4-add-the-eos-sdk-to-your-android-studio-project),
   perform the following steps.

3. In the `res://android/build/build.gradle` file, add the following lines after the implementations in the
   `dependencies` section.

   Before

   ```gradle
   dependencies {
       implementation libraries.kotlinStdLib
       implementation libraries.androidxFragment
       ... other code
   ```

   After

   ```gradle
   dependencies {
       implementation libraries.kotlinStdLib
       implementation libraries.androidxFragment

       // EOS SDK dependencies
       implementation 'androidx.appcompat:appcompat:1.5.1'
       implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
       implementation 'androidx.security:security-crypto:1.0.0'
       implementation 'androidx.browser:browser:1.4.0'
       implementation 'androidx.webkit:webkit:1.7.0'
       // Update the path so that it points to eossdk-StaticSTDC-release.aar provided in addons/epic-online-services-godot/bin/android/
       implementation files('../../addons/epic-online-services-godot/bin/android/eossdk-StaticSTDC-release.aar')

       ...other code
   ```

4. In the `res://android/build/build.gradle` file, add the following lines after the `defaultConfig` in the `android`
   section.

   Before

   ```gradle
   android {

       ... other code

       defaultConfig {
           ... other code

           // Feel free to modify the application id to your own.
           applicationId getExportPackageName()
           versionCode getExportVersionCode()
           versionName getExportVersionName()
           minSdkVersion getExportMinSdkVersion()
           targetSdkVersion getExportTargetSdkVersion()

           missingDimensionStrategy 'products', 'template'
       }

       ... other code
   ```

   After

   ```gradle
   android {

       ... other code

       defaultConfig {
           ... other code

           // Feel free to modify the application id to your own.
           applicationId getExportPackageName()
           versionCode getExportVersionCode()
           versionName getExportVersionName()
           minSdkVersion getExportMinSdkVersion()
           targetSdkVersion getExportTargetSdkVersion()

           missingDimensionStrategy 'products', 'template'

           // This is needed by EOS Android SDK
           String ClientId = "PUT YOUR EOS CLIENT ID HERE"
           resValue("string", "eos_login_protocol_scheme", "eos." + ClientId.toLowerCase())
       }

       ... other code
   ```

5. In the `res://android/build/config.gradle` file, update the `minSdk` to `23` to match with the requirements of the
   `EOS Android SDK`.

   Before

   ```gradle
   minSdk             : 21,
   ```

   After

   ```gradle
   minSdk             : 23,
   ```

6. In the `res://android/build/src/com/godot/game/GodotGame.java` file, update it as follows.

   ```java
   package com.godot.game;

   import com.epicgames.mobile.eossdk.EOSSDK;     // added
   import org.godotengine.godot.GodotActivity;

   import android.os.Bundle;

   public class GodotApp extends GodotActivity {
       static {                                   // added
           System.loadLibrary("EOSSDK");          // added
       }                                          // added

       @Override
       public void onCreate(Bundle savedInstanceState) {
           EOSSDK.init(getActivity());  // added

           setTheme(R.style.GodotAppMainTheme);
           super.onCreate(savedInstanceState);

       }
   }

   ```

7. Now open your project in the Godot Editor, and goto `Project -> Export` and create a new Android export profile.

8. In the `Gradle Build` section, enable `Use Gradle Build`. In the `Architectures` section enable `arm64-v8a`. In the
   `Permissions` section ensure that `ACESSS_NETWORK_STATE`, `ACCESS_WIFI_STATE` and `INTERNET` are enabled. These
   permissions are needed for the EOS SDK to work. Fill in the other details such as package name, etc as needed.

9. You can now export the Android APK by clicking the `Export Project` button.

## Exporting for iOS

Export the project from Godot editor for iOS target. You might get a build error during this process, ignore it. Open
the generated iOS project in XCode and build the project. The build should be successful. EOSG has support for iOS arm64
device and iOS arm64 simulator.

## Current Project Status

- Completed with sample
  - Auth Interface
  - Achievements Interface
  - Connect Interface
  - CustomInvites Interface
  - Friends Interface
  - Stats Interface
  - UserInfo Interface
  - Leaderboards Interface
  - Metrics Interface
  - Mods Interface
  - Presence Interface
  - ProgressionSnapshot Interface
  - Reports Interface
  - UI Interface
  - Lobby Interface (Also sample for manual audio input/output)
  - RTC Interface
  - RTCAudio Interface
  - P2P Interface
  - Version Interface

- Completed without sample
  - KWS Interface
  - PlayerDataStorage Interface
  - Sanctions Interface
  - Sessions Interface
  - TitleStorage Interface
  - Ecom Interface
  - AntiCheatServer Interface
  - AntiCheatClient Interface

- Not completed
  - Integrated Platform Interface


================================================
FILE: SConstruct
================================================
#!/usr/bin/env python
import os
import shutil

env = SConscript("godot-cpp/SConstruct")
lib_name = "libeosg"
plugin_bin_folder = "sample/addons/epic-online-services-godot/bin"

eos_sdk_folder = "thirdparty/eos-sdk/SDK/"


# Add source files
env.Append(CPPPATH=["src/", eos_sdk_folder + "Include/"])
sources = Glob("src/*.cpp")
platform = env["platform"]
build_target = env["target"]


def copy_file(from_path, to_path):
	if not os.path.exists(os.path.dirname(to_path)):
		os.makedirs(os.path.dirname(to_path))
	shutil.copyfile(from_path, to_path)

def copy_folder(from_path, to_path):
	if not os.path.exists(to_path):
		os.makedirs(to_path)
	shutil.rmtree(to_path, ignore_errors=True)
	shutil.copytree(from_path, to_path)

def extract_eos_android_libraries():
	libs_path = eos_sdk_folder + "Bin/Android/static-stdc++/libs/"
	aar_file = eos_sdk_folder + "Bin/Android/static-stdc++/aar/eossdk-StaticSTDC-release.aar"
	zip_file = libs_path + "eos-sdk.zip"
	
	# Delete libs folder if exists
	shutil.rmtree(libs_path, ignore_errors=True)
	
	# Copy aar to zip file
	copy_file(aar_file, zip_file)
	
	# Copy aar to plugin bin/android
	copy_file(aar_file, plugin_bin_folder + "/android/eossdk-StaticSTDC-release.aar")
	
	# Create folder if doesnt exist
	if not os.path.exists(libs_path + "extracted"):
		os.makedirs(libs_path + "extracted")

	# Unzip the file
	shutil.unpack_archive(zip_file, libs_path + "extracted")

	# Copy all folders from libs_path+"extracted/jni" to libs_path
	for folder in os.listdir(libs_path + "extracted/jni"):
		shutil.copytree(libs_path + "extracted/jni/" + folder, libs_path + folder)
	
	# Delete extracted folder
	shutil.rmtree(libs_path + "extracted", ignore_errors=True)
	
	# Delete zip file
	os.remove(zip_file)


genv = env
def on_complete(target, source, env):
	if platform == "windows":
		shutil.rmtree(plugin_bin_folder + "/windows/x64", ignore_errors=True)
		shutil.copytree(eos_sdk_folder + "Bin/x64", plugin_bin_folder + "/windows/x64")
		copy_file(eos_sdk_folder + "Bin/EOSSDK-Win64-Shipping.dll", plugin_bin_folder + "/windows/EOSSDK-Win64-Shipping.dll")
	
	elif platform == "linux":
		so_variant = "LinuxArm64" if genv["arch"] == "arm64" else "Linux"
		copy_file(eos_sdk_folder + f"Bin/libEOSSDK-{so_variant}-Shipping.so", plugin_bin_folder + f"/linux/libEOSSDK-{so_variant}-Shipping.so")
	
	elif platform == "macos":
		framework_folder = plugin_bin_folder + f"/macos/{lib_name}.{platform}.{build_target}.framework"
		# Copies EOS dylib inside framework folder
		copy_file(eos_sdk_folder + "Bin/libEOSSDK-Mac-Shipping.dylib", framework_folder + f"/libEOSSDK-Mac-Shipping.dylib")
		lib_path = f"{framework_folder}/{lib_name}.{platform}.{build_target}"
		print(f"Updating libEOSSDK-Mac-Shipping.dylib path in {lib_path}")
		os.system(f"install_name_tool -change @rpath/libEOSSDK-Mac-Shipping.dylib @loader_path/libEOSSDK-Mac-Shipping.dylib {lib_path}")



# For reference:
# - CCFLAGS are compilation flags shared between C and C++
# - CFLAGS are for C-specific compilation flags
# - CXXFLAGS are for C++-specific compilation flags
# - CPPFLAGS are for pre-processor flags
# - CPPDEFINES are for pre-processor defines
# - LINKFLAGS are for linking flags


env.Append(LIBPATH=[eos_sdk_folder + "Lib/"])
env.Append(LIBPATH=[eos_sdk_folder + "Bin/"])
if env["platform"] == "windows":
	# TODO: dont ignore this warning
	# this disables LINK : error LNK1218: warning treated as error;
	# so that it can build in github action with scons cache
	env.Append(LINKFLAGS=["/ignore:4099"])
	
	env.Append(LIBS=["EOSSDK-Win64-Shipping"])

elif env["platform"] == "linux":
	env.Append(LINKFLAGS=["-static-libgcc", "-static-libstdc++"])
	if env["arch"] == "arm64":
		env.Append(LIBS=["EOSSDK-LinuxArm64-Shipping"])
	else:
		env.Append(LIBS=["EOSSDK-Linux-Shipping"])

elif env["platform"] == "macos":
	env.Append(LIBS=["EOSSDK-Mac-Shipping"])

elif env["platform"] == "ios":
	if env["arch"] != "arm64":
		raise Exception("Only arm64 is supported on iOS.")
	copy_folder(eos_sdk_folder + "Bin/IOS/EOSSDK.xcframework", plugin_bin_folder + "/ios/EOSSDK.xcframework")
	
	env.Append(ENV={'IPHONEOS_DEPLOYMENT_TARGET': '15.0'})

	env.Append(LINKFLAGS=[
		"-F", plugin_bin_folder + f"/ios/EOSSDK.xcframework/ios-arm64{"-simulator" if env["ios_simulator"] else ""}",
		'-framework', 'AuthenticationServices',
		'-framework', 'EOSSDK',
	])
	

elif env["platform"] == "android":
	eos_android_arch = "arm64-v8a"
	if env["arch"] == "x86_64":
		eos_android_arch = "x86_64"
		
	extract_eos_android_libraries()
	
	env.Append(LIBPATH=[eos_sdk_folder + "Bin/Android/static-stdc++/libs/" + eos_android_arch + "/"]) 
	env.Append(LIBS=["EOSSDK"])


if env["platform"] == "macos":
	library = env.SharedLibrary(
		f"{plugin_bin_folder}/macos/{lib_name}.{platform}.{build_target}.framework/{lib_name}.{platform}.{build_target}",
		source=sources,)
else:
	library = env.SharedLibrary(
		f"{plugin_bin_folder}/{platform}/{lib_name}{env['suffix']}{env['SHLIBSUFFIX']}",
		source=sources,
	)


# Disable scons cache for source files
# NoCache(sources)

complete_command = Command('complete', library, on_complete)
Depends(complete_command, library)
Default(complete_command)

================================================
FILE: build-ios.sh
================================================
#!/bin/sh

build=yes
if [ "$1" = "build=n" ] || [ "$1" = "build=N" ] || [ "$1" = "build=no" ] || [ "$1" = "build=0" ]; then
    build=no
fi

dev_build=no
dev_build_ext=""
if [ "$2" = "dev_build=y" ] || [ "$2" = "dev_build=Y" ] || [ "$2" = "dev_build=yes" ] || [ "$2" = "dev_build=1" ]; then
	dev_build=yes
	dev_build_ext=".dev"
fi


echo "Config: dev_build=${dev_build}, build=${build}"


if [ "$build" = "yes" ]; then
    echo "\nBuilding for iOS simulator template_debug target"
    scons arch=arm64 ios_simulator=yes platform=ios target=template_debug dev_build=${dev_build}

    echo "\nBuilding for iOS device template_debug target"
    scons arch=arm64 ios_simulator=no platform=ios target=template_debug dev_build=${dev_build}

    echo "\nBuilding for iOS simulator template_release target"
    scons arch=arm64 ios_simulator=yes platform=ios target=template_release dev_build=no
    
    echo "\nBuilding for iOS device template_release target"
    scons arch=arm64 ios_simulator=no platform=ios target=template_release dev_build=no
fi

eosg_ios_bin_dir=./sample/addons/epic-online-services-godot/bin/ios
godotcpp_bin_dir=./godot-cpp/bin

echo "\nDeleting existing libgodot-cpp xcframework(s) if any"
rm -rf ${eosg_ios_bin_dir}/libgodot-cpp.ios.template*

echo "\nCreating libgodot-cpp xcframework for template_debug"
xcodebuild -create-xcframework \
-library ${godotcpp_bin_dir}/libgodot-cpp.ios.template_debug${dev_build_ext}.arm64.a \
-library ${godotcpp_bin_dir}/libgodot-cpp.ios.template_debug${dev_build_ext}.arm64.simulator.a \
-output ${eosg_ios_bin_dir}/libgodot-cpp.ios.template_debug.xcframework

echo "\nCreating libgodot-cpp xcframework for template_release"
xcodebuild -create-xcframework \
-library ${godotcpp_bin_dir}/libgodot-cpp.ios.template_release.arm64.a \
-library ${godotcpp_bin_dir}/libgodot-cpp.ios.template_release.arm64.simulator.a \
-output ${eosg_ios_bin_dir}/libgodot-cpp.ios.template_release.xcframework

echo "\nCreating libeosg xcframework for template_debug"
xcodebuild -create-xcframework \
-library ${eosg_ios_bin_dir}/libeosg.ios.template_debug${dev_build_ext}.arm64.dylib \
-library ${eosg_ios_bin_dir}/libeosg.ios.template_debug${dev_build_ext}.arm64.simulator.dylib \
-output ${eosg_ios_bin_dir}/libeosg.ios.template_debug.xcframework

echo "\nCreating libeosg xcframework for template_release"
xcodebuild -create-xcframework \
-library ${eosg_ios_bin_dir}/libeosg.ios.template_release.arm64.dylib \
-library ${eosg_ios_bin_dir}/libeosg.ios.template_release.arm64.simulator.dylib \
-output ${eosg_ios_bin_dir}/libeosg.ios.template_release.xcframework


echo "\nDeleting all .dylib files from eosg ios bin dir"
rm -rf ${eosg_ios_bin_dir}/*.dylib

================================================
FILE: debug-entitlements.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>com.apple.security.get-task-allow</key>
    <true/>
</dict>
</plist>

================================================
FILE: debug.cmd
================================================
@echo off
scons dev_build=yes && godot4 --path sample

================================================
FILE: debug.sh
================================================
scons dev_build=yes && godot45 --path sample

================================================
FILE: docs/.gitignore
================================================
# Dependencies
/node_modules

# Production
/build

# Generated files
.docusaurus
.cache-loader

# Misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local

npm-debug.log*
yarn-debug.log*
yarn-error.log*


================================================
FILE: docs/README.md
================================================
# Website

This website is built using [Docusaurus](https://docusaurus.io/), a modern static website generator.

### Installation

```
$ yarn
```

### Local Development

```
$ yarn start
```

This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server.

### Build

```
$ yarn build
```

This command generates static content into the `build` directory and can be served using any static contents hosting service.

### Deployment

Using SSH:

```
$ USE_SSH=true yarn deploy
```

Not using SSH:

```
$ GIT_USER=<Your GitHub username> yarn deploy
```

If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch.


================================================
FILE: docs/docs/installation.md
================================================
# Installation

## Method 1: Install from Asset Library (Recommended)

[View the plugin on Godot Asset Library](https://godotengine.org/asset-library/asset/2453)

1. In the Godot editor, navigate to the `AssetLib` tab at the top, and in the search bar type `EOSG`.
2. Click on the plugin with name `Epic Online Services Godot (EOSG)` by `3ddelano`
3. In the popup that opens, click the `Download` button.
4. Once the download is done, click the `Install` button.
5. Goto `Project -> Project Settings -> Plugins` and enable the `Epic Online Services Godot 4.2+ (EOSG)` plugin.
6. **Restart the godot editor.**
7. The plugin is now installeed. Check out the [Initialization](/docs/topics/initialization) guide next.

## Method 2: Install from GitHub

1. Goto the [Releases](https://github.com/3ddelano/epic-online-services-godot/releases) section and download the latest release. Here there are separate zip files for each platform which you can download if you are only looking to release on one platform or download the `epic-online-services-godot-all` that supports all platforms.
2. Extract the zip file and copy the `addons/epic-online-services-godot` folder into the `res://addons/` folder of your project. If the `res://addons` does not exist, create it.
3. In the Godot editor, goto `Project -> Project Settings -> Plugins` and enable the `Epic Online Services Godot 4.2+ (EOSG)` plugin.
4. **Restart the godot editor.**
5. The plugin is now installeed. Check out the [Initialization](/docs/topics/initialization) guide next.

================================================
FILE: docs/docs/introduction.md
================================================
# Introduction

Epic Online Services Godot (EOSG) is the easiest way to integrate Epic Online Services into your Godot project.

The plugin supports the following platforms:

- Windows x64
- Linux x64/arm64
- Android x64/arm64
- MacOS universal
- iOS arm64 (iPhone/simulator)

This plugin has two main ways in which you can interact with Epic Online Services:

1. High Level EOS (Recommended)
2. GDExtension EOS


### High Level EOS (Recommended)

The High Level Epic Online Services provides easy-to-use methods and signals to interact with EOS, making it ideal for beginners. This simplified API abstracts away many of the complexities of the EOS SDK while providing access to its core functionality.


### GDExtension EOS

The GDExtension EOS provides low-level access to the Epic Online Services SDK. This interface is not recommended for beginners but gives you full access to the underlying EOS functionality through the `EOS` and `IEOS` classes in Godot.

<br></br>

Here's the next steps;

- To get started with using the plugin, check out the [Installation](/docs/installation) guide.
- Checkout the [Games Showcase](/showcase)

================================================
FILE: docs/docs/sample-project.md
================================================
# Sample Project

To run the sample project which showcases most of the EOS features, follow these steps:

1. Clone/Download the [plugin repo](https://github.com/3ddelano/epic-online-services-godot)

2. You cannot directly open the ./sample folder and run the project, because the plugin binaries are not included. To include the plugin binaries. Download the [latest release](https://github.com/3ddelano/epic-online-services-godot/releases/latest) from the Releases section and replace the existing `sample/addons/epic-online-services-godot` folder with the one from the Release (this includes the built shared libraries). See the [Installation](/docs/installation) section for more information on how to install the plugin.

3. Copy your credentials (`Product Id`, `Sandbox Id`, `Deployment Id`, `Client Id`, `Client Secret`) of your Epic Games "Product" from the Epic Games Dev Portal and paste them in `./sample/Main.gd` script in the relevant sections. The encryption key is a random 64 character long string. These credentials need to be kept as private as possible. One way is to make sure to encrypt all scripts when exporting the final game. (See [Compiling with script key encryption](https://docs.godotengine.org/en/stable/development/compiling/compiling_with_script_encryption_key.html))

4. Configure your Product on the [EOS Dev Portal](https://dev.epicgames.com/portal) with the following configuration:
  - In the `Client Policies` section in `Product Settings`, for the Client policy type choose `Custom policy`, enable the `User is required` and enable every features and action except `Connect` (Trusted Server Required). This will allow the sample to access the different services provided by Epic Online Services. In your actual game, the client policy is important and you should give minimal permissions to features.
  - In the `Permissions` section of `Epic Account Services`, enable all three: `Basic Profile`, `Online Presence` and `Friends`. 
  - (Optional if you want some pre-made achievements)
  In the `Achievements` section in `Game Services`, use the `Bulk Import` option and import the `HelloProduct.zip` file located at `res://HelloProduct.zip`

5. Finally open the `./sample` folder in Godot.

================================================
FILE: docs/docs/topics/authentication.md
================================================
# Authentication

WIP - Work In Progress

================================================
FILE: docs/docs/topics/initialization.md
================================================
import ReactPlayer from 'react-player'

# Initialization

Follow the steps below to initialize and use the plugin.

Check out the below video for a quick walkthrough.

<ReactPlayer controls url='https://www.youtube.com/watch?v=ENyvF4yVjKg' />

<br></br>

1. You will need the following from the EOS Developer Portal:
- `PRODUCT_ID`
- `SANDBOX_ID`
- `DEPLOYMENT_ID`
- `CLIENT_ID`
- `CLIENT_SECRET`

2. You also need to provide these values yourself:
- `PRODUCT_NAME` - A name chosen by you for the project
- `PRODUCT_VERSION` - A version chosen by you for the project
- `ENCRYPTION_KEY` - A random 64 character long string

Now at the start of your game, or when you want to initialize EOS. Use the following script:

```gdscript
extends Node

func _ready() -> void:
	# This will control which logs you get from EOSG
	HLog.log_level = HLog.LogLevel.INFO

	var init_opts = EOS.Platform.InitializeOptions.new()
	init_opts.product_name = "PRODUCT_NAME_HERE" # Change this
	init_opts.product_version = "PRODUCT_VERSION_HERE" # Change this

	var create_opts = EOS.Platform.CreateOptions.new()
	create_opts.product_id = "PRODUCT_ID_HERE" # Change this
	create_opts.sandbox_id = "SANDBOX_ID_HERE" # Change this
	create_opts.deployment_id = "DEPLOYMENT_ID_HERE" # Change this
	create_opts.client_id = "CLIENT_ID_HERE" # Change this
	create_opts.client_secret = "CLIENT_SECRET_HERE" # Change this
	create_opts.encryption_key = "ENCRYPTION_KEY_HERE" # Change this

	# Enable Social Overlay on Windows
	if OS.get_name() == "Windows":
		HAuth.auth_login_flags = EOS.Auth.LoginFlags.None
		create_opts.flags = EOS.Platform.PlatformFlags.WindowsEnableOverlayOpengl

	# Initialize the SDK
	var init_res := await HPlatform.initialize_async(init_opts)
	if not EOS.is_success(init_res):
		printerr("Failed to initialize EOS SDK: ", EOS.result_str(init_res))
		return
	
	# Create platform
	var create_success := await HPlatform.create_platform_async(create_opts)
	if not create_success:
		printerr("Failed to create EOS Platform")
		return

	# Setup Logs from EOS
	HPlatform.log_msg.connect(_on_eos_log_msg)
	# This will control which logs you get from EOS SDK
	var log_res := HPlatform.set_eos_log_level(EOS.Logging.LogCategory.AllCategories, EOS.Logging.LogLevel.Info)
	if not EOS.is_success(log_res):
		printerr("Failed to set logging level")
		return

	HAuth.logged_in.connect(_on_logged_in)

	# During development use the devauth tool to login
	HAuth.login_devtool_async("localhost:4545", "CREDENTIAL_NAME_HERE")

	# Only on mobile device (Login without any credentials)
	# await HAuth.login_anonymous_async()


func _on_logged_in():
	print("Logged in successfully: product_user_id=%s" % HAuth.product_user_id)

# This method is called when we get a log message from EOS SDK
func _on_eos_log_msg(msg: EOS.Logging.LogMessage) -> void:
	print("SDK %s | %s" % [msg.category, msg.message])
```

## Initialization on Windows

To use the `Account Portal` login option on Windows, you need to bootstrap Godot with EOS. See the steps below.

### Bootstrapping Godot with EOS for Windows

Follow the tutorial at [Redistributable Installer](https://dev.epicgames.com/docs/services/en-US/EpicAccountServices/Crossplayacrossplatforms/RedistributableInstaller/index.html) and also see the below steps.

A sample of the generated `.ini` file for the Godot Editor is shown below (during game development):
```
ApplicationPath=APPLICATION_PATH_HERE
WorkingDirectory=
WaitForExit=0
NoOperation=0
```

In the above `.ini` file, the `APPLICATION_PATH_HERE` can either be the path to your Godot Editor executable (Eg. `Godot_v4.2.0-stable_win64.exe`) when you are in development or the path to the exported game (Eg. `MyAmazingGame.exe`)

## Initialization on Android

The plugin supports the Android platform, but needs a few one-time steps to initialize and configure android exports.

### Pre-requisites

1. Setup the `Android Build Template` in your Godot project by following the tutorial [Gradle builds for Andriod](https://docs.godotengine.org/en/stable/tutorials/export/android_gradle_build.html). This will create an android project in `res://android/build`.

2. Now with reference to the tutorial [Add the EOS SDK to Your Android Studio Project](https://dev.epicgames.com/docs/epic-online-services/platforms/android#4-add-the-eos-sdk-to-your-android-studio-project), perform the following steps.

3. In the `res://android/build/build.gradle` file, add the following lines after the implementations in the `dependencies` section.

    ```gradle
    dependencies {
        implementation libraries.kotlinStdLib
        implementation libraries.androidxFragment
        
        // highlight-start
        // Add these lines
        // EOS SDK dependencies
        implementation 'androidx.appcompat:appcompat:1.5.1'
        implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
        implementation 'androidx.security:security-crypto:1.0.0'
        implementation 'androidx.browser:browser:1.4.0'
        // Update the path so that it points to eossdk-StaticSTDC-release.aar provided in addons/epic-online-services-godot/bin/android/
        implementation files('../../addons/epic-online-services-godot/bin/android/eossdk-StaticSTDC-release.aar')
        // highlight-end

        ...other code
    ```

4. In the `res://android/build/build.gradle` file, add the following lines after the `defaultConfig` in the `android` section.

    ```gradle
    android {

        ... other code

        defaultConfig {
            ... other code
        
            // Feel free to modify the application id to your own.
            applicationId getExportPackageName()
            versionCode getExportVersionCode()
            versionName getExportVersionName()
            minSdkVersion getExportMinSdkVersion()
            targetSdkVersion getExportTargetSdkVersion()

            missingDimensionStrategy 'products', 'template'

            // highlight-start
            // Add these lines
            // This is needed by EOS Android SDK
            String ClientId = "PUT YOUR EOS CLIENT_ID HERE"
            resValue("string", "eos_login_protocol_scheme", "eos." + ClientId.toLowerCase())
            // highlight-end
        }

        ... other code
    ```

5. In the `res://android/build/config.gradle` file, update the `minSdk` to `23` to match with the requirements of the `EOS Android SDK`.

    Before
    ```gradle
    minSdk             : 21,
    ```
    After
    ```gradle
    minSdk             : 23,
    ```

6. In the `res://android/build/src/com/godot/game/GodotGame.java` file, update it as follows.
    ```java
    package com.godot.game;

    // highlight-next-line
    import com.epicgames.mobile.eossdk.EOSSDK;     // added
    import org.godotengine.godot.GodotActivity;

    import android.os.Bundle;

    public class GodotApp extends GodotActivity {
        // highlight-next-line
        static {                                   // added
            // highlight-next-line
            System.loadLibrary("EOSSDK");          // added
        // highlight-next-line
        }                                          // added
        
        @Override
        public void onCreate(Bundle savedInstanceState) {
            EOSSDK.init(getActivity());  // added
            
            setTheme(R.style.GodotAppMainTheme);
            super.onCreate(savedInstanceState);

        }
    }

    ```

7. Now open your project in the Godot Editor, and goto `Project -> Export` and create a new Android export profile.

8. In the `Gradle Build` section, enable `Use Gradle Build`. In the `Architectures` section enable `arm64-v8a`. In the `Permissions` section ensure that `ACESSS_NETWORK_STATE`, `ACCESS_WIFI_STATE` and `INTERNET` are enabled. These permissions are needed for the EOS SDK to work. Fill in the other details such as package name, etc as needed.

9. You can now export the Android APK by clicking the `Export Project` button.


## Initialization on iOS

Export the project from Godot editor for iOS target. **You might get a build error during this process, ignore it.** Open the generated iOS project in XCode and build the project. The build should be successful. EOSG has support for `iOS arm64 device` and `iOS arm64 simulator`.


================================================
FILE: docs/docs/update-guide.md
================================================
# Update Guide

Follow these steps to update to a newer version of the plugin:

1. Disable the plugin in the Editor in `Project -> Project Setings -> Plugins`.
2. Delete the `res://addons/epic-online-services-godot` folder.
3. Now you can install the newer version using any of the methods described in [Installation](/docs/installation) section
4. After installing, enable the plugin and restart the Editor.

================================================
FILE: docs/docusaurus.config.ts
================================================
import { themes as prismThemes } from "prism-react-renderer";
import type { Config } from "@docusaurus/types";
import type * as Preset from "@docusaurus/preset-classic";

// This runs in Node.js - Don't use client-side code here (browser APIs, JSX...)

const config: Config = {
  title: "Epic Online Services Godot",
  tagline: "Easiest way to use Epic Online Services in Godot 4.2+",
  favicon: "img/favicon.ico",

  url: "https://3ddelano.github.io",
  baseUrl: "/epic-online-services-godot/",

  // GitHub pages deployment config
  organizationName: "3ddelano",
  projectName: "epic-online-services-godot",
  deploymentBranch: "gh-pages",

  trailingSlash: false,

  onBrokenLinks: "throw",
  onBrokenMarkdownLinks: "warn",

  i18n: {
    defaultLocale: "en",
    locales: ["en"],
  },

  presets: [
    [
      "classic",
      {
        docs: {
          sidebarPath: "./sidebars.ts",
          editUrl:
            "https://github.com/3ddelano/epic-online-services-godot/tree/main/docs",
        },
        theme: {
          customCss: "./src/css/custom.css",
        },
      } satisfies Preset.Options,
    ],
  ],

  themeConfig: {
    colorMode: {
      defaultMode: "dark",
      disableSwitch: true,
      respectPrefersColorScheme: false,
    },
    image: "img/og-image.jpg",
    navbar: {
      title: "Epic Online Services Godot",
      logo: {
        alt: "EOSG Logo",
        src: "img/eosg-logo.svg",
      },
      items: [
        {
          type: "docSidebar",
          sidebarId: "docsSidebar",
          position: "left",
          label: "Docs",
        },
        {
          to: "showcase",
          position: "left",
          label: "Showcase",
        },
        {
          href: "https://github.com/3ddelano/epic-online-services-godot",
          label: "GitHub",
          position: "right",
        },
      ],
    },
    footer: {
      style: "dark",
      links: [
        {
          title: "Docs",
          items: [
            {
              label: "Docs",
              to: "/docs/introduction",
            },
          ],
        },
        {
          title: "Community",
          items: [
            {
              label: "Discord",
              href: "https://discord.gg/FZY9TqW",
            },
          ],
        },
        {
          title: "More",
          items: [
            {
              label: "GitHub",
              href: "https://github.com/facebook/docusaurus",
            },
            {
              label: "Sponsor",
              href: "https://github.com/sponsors/3ddelano",
            },
          ],
        },
      ],
      copyright: `Copyright © ${new Date().getFullYear()} Delano Lourenco`,
    },
    prism: {
      theme: prismThemes.github,
      darkTheme: prismThemes.dracula,
      additionalLanguages: ["gdscript", "gradle", "java"],
    },
  } satisfies Preset.ThemeConfig,

  plugins: ["./src/plugins/tailwind-config.ts"],
};

export default config;


================================================
FILE: docs/package.json
================================================
{
  "name": "docs",
  "version": "0.0.0",
  "private": true,
  "scripts": {
    "docusaurus": "docusaurus",
    "start": "docusaurus start",
    "dev": "docusaurus start",
    "build": "docusaurus build",
    "swizzle": "docusaurus swizzle",
    "deploy": "docusaurus deploy",
    "clear": "docusaurus clear",
    "serve": "docusaurus serve",
    "write-translations": "docusaurus write-translations",
    "write-heading-ids": "docusaurus write-heading-ids",
    "typecheck": "tsc"
  },
  "dependencies": {
    "@docusaurus/core": "^3.9.2",
    "@docusaurus/preset-classic": "^3.9.2",
    "@mdx-js/react": "^3.0.0",
    "baseline-browser-mapping": "^2.9.19",
    "caniuse-lite": "^1.0.30001769",
    "clsx": "^2.0.0",
    "prism-react-renderer": "^2.3.0",
    "react": "^19.0.0",
    "react-dom": "^19.0.0",
    "react-player": "^2.16.0"
  },
  "devDependencies": {
    "@docusaurus/module-type-aliases": "^3.9.2",
    "@docusaurus/tsconfig": "^3.9.2",
    "@docusaurus/types": "^3.9.2",
    "@tailwindcss/postcss": "^4.1.3",
    "postcss": "^8.5.3",
    "tailwindcss": "^4.1.3",
    "typescript": "~5.6.2"
  },
  "browserslist": {
    "production": [
      ">0.5%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 3 chrome version",
      "last 3 firefox version",
      "last 5 safari version"
    ]
  },
  "engines": {
    "node": ">=18.0"
  }
}


================================================
FILE: docs/postcss.config.js
================================================
module.exports = {
	plugins: {
		'@tailwindcss/postcss': {},
	}
}

================================================
FILE: docs/sidebars.ts
================================================
import type { SidebarsConfig } from '@docusaurus/plugin-content-docs';

// This runs in Node.js - Don't use client-side code here (browser APIs, JSX...)

/**
 * Creating a sidebar enables you to:
 - create an ordered group of docs
 - render a sidebar for each doc of that group
 - provide next/previous navigation

 The sidebars can be generated from the filesystem, or explicitly defined here.

 Create as many sidebars as you want.
 */
const sidebars: SidebarsConfig = {
  // By default, Docusaurus generates a sidebar from the docs folder structure
  // docsSidebar: [{type: 'autogenerated', dirName: '.'}],

  // But you can create a sidebar manually
  docsSidebar: [
    'introduction',
    'installation',
    'update-guide',
    'sample-project',
    {
      type: 'category',
      label: 'Topics',
      items: ['topics/initialization', 'topics/authentication'],
      collapsed: false
    },
  ],
};

export default sidebars;


================================================
FILE: docs/src/components/ExampleSection.tsx
================================================
import CodeBlock from "@theme/CodeBlock";

const codeExample = `
# In main script
extends Node

func _ready() -> void:
    # Setup HEOS Logs
    HLog.log_level = HLog.LogLevel.INFO

    var init_opts = EOS.Platform.InitializeOptions.new()
    init_opts.product_name = "PRODUCT_NAME_HERE"
    init_opts.product_version = "PRODUCT_VERSION_HERE"

    var create_opts = EOS.Platform.CreateOptions.new()
    create_opts.product_id = "PRODUCT_ID_HERE"
    create_opts.sandbox_id = "SANDBOX_ID_HERE"
    create_opts.deployment_id = "DEPLOYMENT_ID_HERE"
    create_opts.client_id = "CLIENT_ID_HERE"
    create_opts.client_secret = "CLIENT_SECRET_HERE"
    create_opts.encryption_key = "ENCRYPTION_KEY_HERE"

    # Enable Social Overlay on Windows
    if OS.get_name() == "Windows":
        HAuth.auth_login_flags = EOS.Auth.LoginFlags.None
        create_opts.flags = EOS.Platform.PlatformFlags.WindowsEnableOverlayOpengl

    # Initialize the SDK
    var init_res := await HPlatform.initialize_async(init_opts)
    if not EOS.is_success(init_res):
        printerr("Failed to initialize EOS SDK: ", EOS.result_str(init_res))
        return

    # Create platform
    var create_success := await HPlatform.create_platform_async(create_opts)
    if not create_success:
        printerr("Failed to create EOS Platform")
        return

    # Setup Logs from EOS
    HPlatform.log_msg.connect(_on_eos_log_msg)
    var log_res := HPlatform.set_eos_log_level(EOS.Logging.LogCategory.AllCategories, EOS.Logging.LogLevel.Info)
    if not EOS.is_success(log_res):
        printerr("Failed to set logging level")
        return

    HAuth.logged_in.connect(_on_logged_in)

    # During development use the devauth tool to login
    HAuth.login_devtool_async("localhost:4545", "CREDENTIAL_NAME_HERE")

    # Only on mobile device (Login without any credentials)
    # await HAuth.login_anonymous_async()


func _on_logged_in():
    print("Logged in successfully: product_user_id=%s" % HAuth.product_user_id)

    # Example: Get top records for a leaderboard
    var records := await HLeaderboards.get_leaderboard_records_async("LEADERBOARD_ID_HERE")
    print(records)


func _on_eos_log_msg(msg: EOS.Logging.LogMessage) -> void:
    print("SDK %s | %s" % [msg.category, msg.message])
`;

export function ExampleSection() {
  return (
    <section id="example" className="py-16 sm:py-20 bg-gray-900">
      <div className="container mx-auto px-6">
        <h2 className="text-3xl font-bold mb-8 text-center text-white">
          Basic Usage Example (GDScript)
        </h2>
        <div className="max-w-4xl mx-auto">
          <CodeBlock language="gdscript">{codeExample}</CodeBlock>
        </div>
      </div>
    </section>
  );
}


================================================
FILE: docs/src/components/FeaturesSection.tsx
================================================
const FEATURES = [
  "Authentication",
  "Social Overlay (Win)",
  "Achievements",
  "Stats & Leaderboards",
  "Lobby & Sessions",
  "Multiplayer (P2P)",
  "Voice",
  "Metrics",
  "Mods",
  "Player/Title Storage",
  "Progression Snapshot",
  "Reports & Sanctions",
  "Ecommerce (EGS)",
  "AntiCheat",
];

const HIGH_LEVEL_CLASSES = [
  "HPlatform",
  "HAuth",
  "HAchievements",
  "HFriends",
  "HStats",
  "HLeaderboards",
  "HLobbies",
  "HP2P",
  "HLog",
];

export function FeaturesSection() {
  return (
    <section id="features" className="py-20 sm:py-24 bg-[#0a0f1e]">
      <div className="container mx-auto px-6">
        <h2 className="text-3xl font-bold mb-4 text-center text-white tracking-tight">
          Core Features
        </h2>
        <p className="text-gray-400 text-center mb-14 max-w-2xl mx-auto font-light">
          All the EOS features you need, wrapped in a clean GDScript API.
        </p>
        <div className="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 gap-3 max-w-6xl mx-auto">
          {FEATURES.map((feature, index) => (
            <div key={index} className="feature-card p-4 rounded-xl">
              <span className="flex items-center text-sm">
                <svg
                  className="w-4 h-4 mr-2 text-emerald-400 flex-shrink-0"
                  fill="currentColor"
                  viewBox="0 0 20 20"
                >
                  <path
                    fillRule="evenodd"
                    d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z"
                    clipRule="evenodd"
                  ></path>
                </svg>
                <span className="text-gray-200 font-medium">{feature}</span>
              </span>
            </div>
          ))}
        </div>
      </div>
    </section>
  );
}

export function HighLevelSection() {
  return (
    <section id="high-level" className="py-16 sm:py-20 bg-gray-950">
      <div className="container mx-auto px-6">
        <h2 className="text-3xl font-bold mb-10 text-center text-white">
          High Level EOS Classes
        </h2>
        <p className="text-gray-300 mb-8 max-w-2xl mx-auto text-center">
          These classes simplify interaction with EOS services. They include
          built-in documentation accessible directly within the Godot Editor.
        </p>
        <div className="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 gap-4 max-w-5xl mx-auto">
          {HIGH_LEVEL_CLASSES.map((cls, index) => (
            <div
              key={index}
              className="bg-blue-900/80 hover:bg-blue-800/80 p-4 rounded-lg text-center shadow transition"
            >
              <span className="font-mono font-medium text-blue-100">{cls}</span>
            </div>
          ))}
        </div>
      </div>
    </section>
  );
}


================================================
FILE: docs/src/components/HeroSection.tsx
================================================
import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
import { GodotIcon, EpicIcon } from "../components/Icons";

const VERSIONS = [
  { label: "Godot", value: "4.2+", icon: GodotIcon },
  { label: "EOS SDK", value: "1.18.1.2", icon: EpicIcon },
];

const PLATFORMS = [
  { label: "Windows x64/arm64", icon: "🖥️" },
  { label: "Linux x64/arm64", icon: "🐧" },
  { label: "Android x64/arm64", icon: "🤖" },
  { label: "MacOS x64/arm64", icon: "🍎" },
  { label: "iOS arm64", icon: "🍏" },
];

const HERO_ACTIONS = [
  {
    label: "Download Latest",
    href: "https://github.com/3ddelano/epic-online-services-godot/releases/latest",
    primary: true,
    target: "_blank",
  },
  {
    label: "Documentation",
    href: "docs/introduction",
    primary: false,
  },
];

export function HeroSection() {
  const { siteConfig } = useDocusaurusContext();
  return (
    <section
      id="hero"
      className="relative bg-[#030712] py-28 sm:py-36 overflow-hidden"
    >
      <div className="absolute inset-0 hero-image opacity-30"></div>
      {/* Glow orbs */}
      <div className="absolute top-20 left-1/4 w-96 h-96 bg-blue-600/20 rounded-full blur-[120px]"></div>
      <div className="absolute bottom-20 right-1/4 w-80 h-80 bg-purple-600/15 rounded-full blur-[100px]"></div>

      <div className="container px-6 relative z-10 grid lg:grid-cols-2 gap-12 items-center">
        {/* Left col */}
        <div className="max-w-xl">
          <h1 className="text-4xl font-bold tracking-tight sm:text-5xl md:text-6xl mb-6 text-white leading-tight">
            {siteConfig.title}
          </h1>
          <p className="text-xl text-gray-400 mb-8 font-light leading-relaxed">
            {siteConfig.tagline}
          </p>
          <div className="flex flex-wrap gap-3 mb-8">
            {VERSIONS.map((v, i) => (
              <span
                key={i}
                className="glass px-4 py-2 rounded-full flex items-center text-sm font-semibold text-gray-200"
              >
                <v.icon className="w-4 h-4 mr-2" />
                {v.label} {v.value}
              </span>
            ))}
          </div>

          <div className="flex flex-wrap gap-4 mb-10">
            {HERO_ACTIONS.map((action, i) => (
              <a
                key={i}
                href={action.href}
                target={action.target}
                rel={action.target === "_blank" ? "noopener noreferrer" : ""}
                className={`${
                  action.primary ? "button-primary" : "button-secondary"
                } px-7 py-3.5 rounded-xl text-sm font-bold uppercase tracking-wider no-underline`}
              >
                {action.label}
              </a>
            ))}
          </div>

          <div className="text-gray-500">
            <p className="mb-3 font-semibold text-gray-400 text-sm uppercase tracking-wider">
              Supported Platforms
            </p>
            <div className="flex flex-wrap gap-2">
              {PLATFORMS.map((platform, i) => (
                <span
                  key={i}
                  className="glass px-3 py-1.5 rounded-full text-xs font-semibold text-gray-300 transition-transform duration-200 hover:scale-105"
                >
                  {platform.icon} {platform.label}
                </span>
              ))}
            </div>
          </div>
        </div>

        {/* Logo Column */}
        <div className="flex-1 flex justify-center items-center">
          <div className="relative">
            <div className="absolute inset-0 bg-blue-500/20 rounded-full blur-[60px] scale-110"></div>
            <img
              src="img/eosg-logo.svg"
              alt="Logo"
              className="w-64 h-64 object-contain rounded-md relative z-10 drop-shadow-2xl"
            />
          </div>
        </div>
      </div>
    </section>
  );
}


================================================
FILE: docs/src/components/Icons.tsx
================================================
export function GodotIcon({ className = "w-4 h-4" }) {
  return (
    <svg
      xmlns="http://www.w3.org/2000/svg"
      className={className}
      viewBox="0 0 1024 1024"
    >
      <g fill="#fff">
        <path d="M417.615 76.875c-42.392 9.424-84.326 22.545-123.642 42.334.899 34.716 3.143 67.98 7.693 101.768-15.268 9.782-31.315 18.177-45.576 29.628-14.49 11.148-29.29 21.813-42.41 34.85-26.212-17.337-53.955-33.63-82.535-48.012C100.337 270.6 71.53 306.383 48 346.428c18.493 29.029 38.33 58.205 56.7 80.959v245.765c.449.005.898.021 1.343.063l150.67 14.527a16.22 16.22 0 0 1 14.627 15.024l4.646 66.51 131.43 9.378 9.055-61.386a16.22 16.22 0 0 1 16.05-13.858h158.961c8.047 0 14.873 5.899 16.047 13.858l9.055 61.386 131.434-9.379 4.642-66.51a16.23 16.23 0 0 1 14.627-15.023l150.611-14.527c.446-.042.89-.058 1.34-.063v-19.611l.063-.02V427.387c21.216-26.71 41.307-56.172 56.699-80.96-23.523-40.044-52.345-75.828-83.152-108.984-28.573 14.382-56.325 30.675-82.537 48.012-13.117-13.037-27.89-23.702-42.4-34.85-14.258-11.45-30.324-19.846-45.563-29.628 4.537-33.788 6.78-67.052 7.683-101.768-39.32-19.79-81.249-32.91-123.662-42.334-16.933 28.46-32.42 59.28-45.906 89.408-15.993-2.672-32.06-3.662-48.149-3.853v-.026c-.112 0-.216.026-.312.026-.1 0-.205-.026-.305-.026v.026c-16.117.191-32.17 1.18-48.168 3.853-13.478-30.129-28.955-60.948-45.914-89.408M298.416 436.398c50.151 0 90.799 40.618 90.799 90.752 0 50.168-40.648 90.809-90.799 90.809-50.126 0-90.787-40.64-90.787-90.809 0-50.134 40.66-90.752 90.787-90.752m427.178 0c50.122 0 90.779 40.618 90.779 90.752 0 50.168-40.657 90.809-90.78 90.809-50.159 0-90.806-40.64-90.806-90.809 0-50.134 40.647-90.752 90.807-90.752m-213.6 53.11c16.143 0 29.254 11.908 29.254 26.56v83.59c0 14.665-13.111 26.563-29.254 26.563-16.142 0-29.226-11.898-29.226-26.563v-83.59c0-14.652 13.084-26.56 29.226-26.56"></path>
        <path d="m784.071 718.723-4.666 66.864c-.562 8.059-6.972 14.474-15.031 15.052l-160.49 11.451q-.587.043-1.17.042c-7.975 0-14.856-5.853-16.034-13.861l-9.203-62.415H446.525l-9.203 62.415c-1.237 8.4-8.746 14.44-17.204 13.82l-160.49-11.452c-8.059-.578-14.469-6.993-15.03-15.052l-4.667-66.864-135.48-13.062c.062 14.56.249 30.512.249 33.688 0 143.085 181.51 211.86 407.024 212.651h.554c225.514-.79 406.962-69.566 406.962-212.651 0-3.234.195-19.119.262-33.688zM367.367 532.537c0 33.276-26.97 60.246-60.27 60.246-33.285 0-60.271-26.97-60.271-60.246s26.986-60.27 60.27-60.27c33.301 0 60.27 26.994 60.27 60.27M656.64 532.537c0 33.276 26.962 60.246 60.238 60.246 33.309 0 60.27-26.97 60.27-60.246s-26.961-60.27-60.27-60.27c-33.276 0-60.237 26.994-60.237 60.27"></path>
      </g>
    </svg>
  );
}

export function EpicIcon({ className = "w-4 h-4" }) {
  return (
    <svg
      xmlns="http://www.w3.org/2000/svg"
      xmlSpace="preserve"
      className={className}
      version="1.1"
      viewBox="0 0 647.167 750.977"
    >
      <defs>
        <clipPath id="a" clipPathUnits="userSpaceOnUse">
          <path d="M0 790.889h900V0H0Z"></path>
        </clipPath>
      </defs>
      <g transform="matrix(1.33333 0 0 -1.33333 -278.052 902.583)">
        <g>
          <g clipPath="url(#a)">
            <g transform="translate(649.836 676.938)">
              <path
                fill="#2f2d2e"
                fillOpacity="1"
                fillRule="evenodd"
                stroke="none"
                d="M0 0h-397.219c-32.196 0-44.078-11.882-44.078-44.093v-388.676c0-3.645.147-7.031.469-10.168.733-7.031.871-13.844 7.41-21.601.639-.76 7.315-5.728 7.315-5.728 3.591-1.761 6.043-3.058 10.093-4.688l195.596-81.948c10.154-4.655 14.4-6.469 21.775-6.323v-.001h.058v.001c7.375-.146 11.621 1.668 21.776 6.323L18.79-474.954c4.051 1.63 6.502 2.927 10.094 4.688 0 0 6.676 4.968 7.314 5.728 6.539 7.757 6.677 14.57 7.41 21.601.322 3.137.47 6.523.47 10.168v388.676C44.078-11.882 32.195 0 0 0"
              ></path>
            </g>
            <g transform="translate(623.23 286.175)">
              <path
                fill="#fff"
                fillOpacity="1"
                fillRule="nonzero"
                stroke="none"
                d="m0 0-.09-.897-.089-.985-.18-.897-.268-.896-.174-.807-.27-.897-.358-.807-.359-.718-.353-.806-.448-.717-.448-.718-.533-.717-.449-.717-.532-.627-.628-.628-.533-.538-.716-.628-.623-.538-.717-.538-.712-.442-.712-.538-.807-.448-.802-.359-.801-.448-.897-.359-.891-.359-.891-.268-.891-.27-.807-.268-.891-.18-.802-.179-.801-.179-.897-.18-.892-.089-.801-.09-.897-.09-.98-.09-.892-.089h-3.749l-.892.089h-.98l-.892.09-.896.09-.981.09-.891.179-.891.09-.897.179-.892.179-.891.18-.891.179-.896.268-.802.18-.891.269-.892.269-.806.359-.891.269-.802.268-.892.359-.806.359-.802.359-.802.442-.806.359-.802.449-.712.447-.807.449-.712.448-.717.448-.712.538-.712.538-.717.538-.713.538-.627.538-.712.627.538.717.622.628.538.718.623.717.538.627.532.717.628.718.532.627.628.717.533.628.627.717.533.718.538.627.622.717.538.718.622.627.538.717.712-.538.802-.538.717-.538.802-.538.717-.448.802-.537.711-.449.808-.358.711-.449.802-.359.807-.358.801-.359.803-.269.806-.358.891-.269.892-.269.801-.269.897-.18.891-.179.891-.179.981-.09.896-.179h.892l.98-.089h1.962l.981.089.897.179.801.18.802.179.717.269.623.358.717.538.532.628.359.718.27.806.088.897v.179l-.088 1.076-.359.897-.449.627-.622.538-.718.538-.712.358-.801.359-.897.359-1.07.447-.623.18-.711.179-.807.27-.802.179-.891.269-.897.179-.98.269-.892.179-.981.269-.891.179-.897.269-.89.18-.892.269-.807.268-.89.18-.803.269-.801.269-.807.269-.981.359-.891.359-.892.358-.896.359-.801.448-.892.448-.717.448-.802.448-.712.538-.717.448-.622.539-.627.627-.623.628-.538.628-.532.627-.449.627-.443.718-.448.806-.359.622-.269.718-.263.807-.269.717-.18.897-.179.807-.09.896-.089.897-.09.985v2.063l.09.896.089.807.09.897.179.806.18.807.269.808.179.806.353.807.359.807.358.806.444.808.447.806.533.718.539.717.622.717.627.627.623.718.717.628.622.448.717.538.713.538.711.448.807.448.802.359.801.448.807.358.891.27.891.358.807.269.712.18.803.179.806.179.891.179.802.18.891.089.897.09.891.09.891.089h3.839l.981-.089.981-.09h.891l.986-.09.891-.179.981-.09.892-.179.807-.179.891-.179.891-.18.802-.179.896-.269.802-.269.802-.18.896-.358.802-.269.801-.358.802-.359.896-.359.802-.448.712-.359.807-.448.802-.448.712-.449.806-.538.713-.447.717-.539.712-.538.711-.537-.532-.718-.448-.717-.533-.717-.538-.718-.532-.806-.449-.717-.538-.718-.533-.717-.447-.717-.534-.718-.537-.717-.449-.717-.532-.807-.539-.717-.532-.717-.448-.717-.533-.717-.717.537-.801.449-.713.448-.717.538-.801.358-.718.449-.801.359-.712.358-.807.359-.712.358-.801.269-.717.359-.982.268-.891.27-.891.268-.897.18-.891.179-.891.18-.891.09-.897.089-.801.09h-1.962l-.981-.179-.897-.18-.801-.179-.712-.359-.628-.358-.802-.718-.538-.807-.352-.807-.091-.896v-.18l.091-1.165.442-.986.359-.538.622-.628.807-.448.712-.448.891-.359.986-.359 1.071-.358.712-.179.712-.269.807-.179.801-.269.891-.18.987-.269.981-.268.981-.27.98-.179.891-.269.981-.269.897-.179.892-.269.891-.269.801-.269.897-.269.802-.269.801-.269.986-.353.891-.449.891-.358.892-.448.807-.449.802-.448.711-.448.717-.538.713-.448.712-.628.717-.627.622-.718.627-.627.533-.718.538-.806.443-.717.449-.808.358-.717.269-.806.264-.807.179-.807.179-.897.179-.897.09-.896.09-.986V.986zm-62.594-17.926h-51.143v65.258h51.587V32.538h-34.543V21.87h31.062V7.979h-31.062V-3.137h34.991v-14.789zm-65.214 0h-16.333v38.589l-.447-.717-.533-.813-.449-.717-.532-.718-.448-.806-.539-.718-.442-.717-.449-.812-.532-.717-.449-.717-.537-.718-.443-.812-.538-.717-.443-.717-.449-.807-.538-.722-.443-.718-.538-.806-.442-.718-.538-.717-.443-.812-.449-.718-.537-.717-.443-.807-.538-.722-.443-.717-.538-.718-.449-.806-.443-.722-.537-.718-.443-.807-.538-.717-.448-.717-.533-.813-.448-.717h-.354l-.537.807-.449.723-.533.807-.448.717-.533.806-.448.723-.532.807-.449.718-.538.806-.443.717-.538.813-.442.717-.538.807-.449.717-.532.812-.449.717-.532.807-.538.717-.448.812-.533.717-.448.807-.533.717-.448.813-.533.717-.448.807-.538.717-.443.807-.538.723-.443.806-.538.718-.448.807-.532.716-.45.813-.532.717v-38.409h-16.96v65.258h18.3l.443-.718.448-.806.532-.712.449-.807.448-.717.443-.808.448-.711.534-.808.447-.717.449-.717.443-.801.448-.718.533-.806.448-.718.448-.801.443-.717.538-.717.449-.803.442-.716.448-.807.444-.718.538-.801.448-.718.442-.806.449-.712.443-.717.538-.807.448-.718.443-.807.448-.712.443-.807.539-.717.448-.801.443-.718.448.718.448.801.533.717.447.807.444.712.448.807.533.718.448.807.449.717.442.712.538.806.443.718.449.801.447.718.533.807.448.716.449.803.442.717.45.717.532.801.448.718.448.806.444.718.537.801.444.717.447.717.449.808.532.711.449.808.442.717.449.807.538.712.443.806.448.718h18.294v-65.258zM-231.367 8.965l-.269.812-.353.897-.359.807-.269.812-.353.807-.358.897-.27.812-.359.807-.352.806-.27.812-.359.897-.263.807-.359.812-.359.807-.268.807-.354.901-.358.808-.269.806-.359.812-.353.897-.269.812-.359.807-.353-.807-.268-.812-.359-.897-.359-.812-.264-.806-.358-.808-.359-.901-.353-.807-.27-.807-.358-.812-.359-.807-.264-.897-.358-.812-.359-.806-.268-.807-.354-.812-.359-.897-.358-.807-.263-.812-.359-.807-.359-.897-.269-.812-.353-.807h15.082zm28.03-26.891h-17.498l-.354.808-.269.807-.358.807-.359.896-.264.802-.358.806-.359.807-.264.807-.358.807-.359.807-.268.807-.354.896-.359.807-.269.807-.359.807h-25.614l-.353-.807-.269-.807-.359-.807-.358-.896-.264-.807-.358-.807-.359-.807-.269-.807-.353-.807-.359-.806-.269-.802-.354-.896-.358-.807-.269-.807-.359-.808h-18.025l.353.808.359.807.358.807.354.896.269.802.359.806.358.807.353.807.359.807.359.897.353.807.359.806.268.807.359.807.353.807.359.896.358.807.354.808.359.806.358.807.269.807.353.897.359.806.359.807.353.807.359.807.359.807.353.897.269.806.359.807.358.807.354.807.358.807.358.896.354.807.358.807.269.807.359.806.353.807.359.897.359.807.353.807.358.807.359.806.269.808.354.801.358.897.358.806.354.808.358.807.359.806.353.807.269.897.359.806.358.807.354.807.359.807.358.807.354.897.358.806.269.807.358.807.354.807.358.807.359.896.353.807.359.807.359.807.263.806.359.808.359.896.359.807.353.807.359.807.358.807.353.806.27.897.358.807.359.807.353.807h16.512l.358-.807.359-.807.354-.807.358-.897.269-.806.353-.807.359-.807.358-.807.359-.807.353-.896.359-.808.359-.806.263-.807.359-.807.359-.807.359-.896.353-.807.358-.807.359-.807.353-.807.269-.806.358-.897.354-.807.359-.807.358-.807.359-.807.353-.806.358-.897.27-.807.353-.806.358-.807.359-.808.359-.806.353-.897.359-.801.358-.808.264-.806.358-.807.359-.807.354-.807.358-.897.359-.807.359-.806.353-.807.269-.807.358-.807.354-.896.358-.807.359-.807.358-.807.354-.807.359-.806.268-.897.354-.807.358-.807.359-.807.353-.807.359-.806.359-.897.359-.807.263-.807.359-.806.359-.808.353-.807.358-.896.359-.807.358-.807.353-.807.27-.806.359-.807.353-.897.358-.807.358-.807.354-.807.358-.806.359-.802.27-.896.352-.807.359-.807.358-.808zm-78.193 8.334-.717-.538-.623-.449-.717-.538-.712-.448-.712-.538-.717-.448-.712-.449-.807-.447-.802-.449-.802-.448-.806-.353-.802-.449-.891-.358-.801-.359-.897-.358-.801-.359-.803-.269-.806-.269-.802-.27-.891-.268-.801-.27-.897-.179-.802-.179-.891-.179-.896-.179-.892-.09-.981-.09-.891-.09-.981-.089-.897-.09-.98-.089h-3.84l-.891.089-.981.09-.891.089-.891.09-.897.09-.891.179-.892.18-.801.179-.896.179-.802.269-.891.179-.807.27-.802.358-.802.269-.89.359-.807.358-.802.358-.801.359-.808.448-.711.444-.802.448-.717.449-.712.447-.717.539-.712.537-.713.538-.627.538-.622.538-.628.628-.622.537-.628.628-.622.628-.538.627-.533.717-.538.628-.448.717-.533.718-.447.716-.444.718-.448.807-.448.717-.353.807-.359.807-.358.807-.354.806-.269.717-.359.808-.179.807-.264.806-.179.896-.269.808-.179.896-.09.807-.18.897-.088.806-.091.897-.084.897-.089.896V15.6l.089.986v.896l.084.897.091.986.179.891.089.897.179.807.269.896.18.897.263.807.269.896.269.807.359.897.354.806.358.807.359.807.353.807.448.807.448.717.444.718.447.717.449.717.532.717.538.717.533.717.538.629.622.627.538.628.623.626.627.629.622.537.717.628.623.538.712.538.717.448.712.538.718.448.711.448.802.449.807.448.801.448.802.359.806.358.892.449.712.268.891.27.808.358.801.18.801.269.896.179.802.269.891.179.892.09.896.179.892.09.89.089.892.09.897.09h3.833l.987-.09.981-.09h.891l.891-.089.981-.18.807-.089.891-.18.892-.179.806-.179.801-.179.803-.18.807-.269.801-.179.712-.269.807-.269.802-.358.801-.359.807-.359.802-.448.801-.359.718-.448.801-.448.712-.448.807-.449.712-.537.712-.449.717-.538.712-.538.717-.627.712-.538-.538-.718-.622-.627-.538-.717-.622-.717-.538-.718-.533-.627-.628-.717-.532-.717-.538-.629-.623-.717-.537-.717-.623-.717-.538-.628-.532-.717-.627-.717-.534-.717-.627-.628-.533-.717-.717.538-.712.627-.717.449-.712.538-.712.448-.717.449-.713.447-.801.449-.717.358-.712.359-.717.269-.802.269-.801.269-.807.179-.891.18-.891.179-.892.089-.981.09-.986.089h-1.872l-.891-.089-.807-.09-.891-.179-.802-.18-.807-.268-.801-.269-.802-.359-.802-.358-.717-.448-.711-.449-.718-.449-.622-.537-.628-.538-.622-.538-.538-.627-.622-.628-.538-.717-.444-.628-.448-.717-.442-.807-.449-.717-.358-.807-.269-.807-.354-.807-.269-.896-.179-.892-.179-.806-.18-.987-.089-.896-.084-.896v-2.063l.084-.896.089-.807.09-.897.179-.806.18-.808.179-.806.269-.807.264-.717.359-.896.358-.808.443-.807.448-.717.448-.717.533-.718.538-.627.622-.628.539-.627.621-.538.718-.538.712-.538.711-.448.717-.448.803-.359.801-.359.806-.358.892-.269.891-.269.897-.18.891-.179.891-.089.981-.09h2.051l.987.09.981.089.891.09.891.18.897.179.891.268.801.18.803.358.717.359.801.359.627.358.713.449v8.158h-13.032v13.084h29.454V-9.055z"
              ></path>
            </g>
            <g transform="translate(312.995 481.16)">
              <path
                fill="#fff"
                fillOpacity="1"
                fillRule="nonzero"
                stroke="none"
                d="M0 0h38.683v29.922H0v61.086h40.223v29.922h-73.072V-95.021h73.684v29.923H0z"
              ></path>
            </g>
            <g transform="translate(590.07 474.677)">
              <path
                fill="#fff"
                fillOpacity="1"
                fillRule="nonzero"
                stroke="none"
                d="M0 0v-48.744c0-8.639-3.993-12.647-12.278-12.647h-6.144c-8.595 0-12.588 4.008-12.588 12.647V87.618c0 8.638 3.993 12.646 12.588 12.646h5.527c8.29 0 12.283-4.008 12.283-12.646V45.349h32.233v44.12c0 26.837-12.895 39.795-39.6 39.795h-15.969c-26.706 0-39.912-13.264-39.912-40.106V-50.284c0-26.843 13.206-40.106 39.912-40.106h16.274c26.712 0 39.911 13.263 39.911 40.106V0z"
              ></path>
            </g>
            <path
              fill="#fff"
              fillOpacity="1"
              fillRule="nonzero"
              stroke="none"
              d="M475.995 386.138h32.854V602.09h-32.854z"
            ></path>
            <g transform="translate(428.326 506.146)">
              <path
                fill="#fff"
                fillOpacity="1"
                fillRule="nonzero"
                stroke="none"
                d="M0 0c0-8.639-3.987-12.652-12.277-12.652h-13.511v79.596h13.511C-3.987 66.944 0 62.935 0 54.298Zm-7.061 95.944h-51.577v-215.952h32.85v78.362h18.727c26.711 0 39.911 13.263 39.911 40.1v57.384c0 26.842-13.2 40.106-39.911 40.106"
              ></path>
            </g>
            <g transform="translate(357.642 190.875)">
              <path
                fill="#fff"
                fillOpacity="1"
                fillRule="evenodd"
                stroke="none"
                d="M0 0h188.054L92.068-31.654Z"
              ></path>
            </g>
          </g>
        </g>
      </g>
    </svg>
  );
}


================================================
FILE: docs/src/components/InfoSections.tsx
================================================
export function HowItWorksSection() {
  return (
    <section id="how-it-works" className="py-16 sm:py-20 bg-gray-950">
      <div className="container mx-auto px-6">
        <div className="max-w-3xl mx-auto text-center">
          <h2 className="text-3xl font-bold mb-6 text-white">How It Works</h2>
          <p className="text-lg text-gray-300 leading-relaxed">
            This project utilizes Godot's{" "}
            <strong className="text-blue-400">GDExtension</strong> system to
            wrap the official Epic Online Services C SDK. This allows seamless
            integration and usage within Godot projects using GDScript, C#, or
            other supported languages. It provides a familiar class hierarchy
            and leverages Godot's signal system for handling asynchronous events
            like user login, achievement unlocks, lobby updates, and more.
          </p>
        </div>
      </div>
    </section>
  );
}

export function InstallationSection() {
  return (
    <section id="installation" className="py-16 sm:py-20 bg-gray-900">
      <div className="container mx-auto px-6">
        <h2 className="text-3xl font-bold mb-12 text-center text-white">
          Installation
        </h2>
        <div className="grid md:grid-cols-2 gap-10 max-w-5xl mx-auto">
          <div className="bg-gray-800 p-6 rounded-lg shadow-md border border-gray-700">
            <h3 className="text-xl font-semibold mb-4 text-white">
              Method 1: Asset Library (Recommended)
            </h3>
            <ol className="list-decimal list-inside space-y-2 text-gray-300">
              <li>
                Open the <strong className="text-white">AssetLib</strong> tab in
                the Godot editor.
              </li>
              <li>
                Search for{" "}
                <code className="bg-gray-700 px-1.5 py-0.5 rounded text-gray-100">
                  EOSG
                </code>{" "}
                or{" "}
                <code className="bg-gray-700 px-1.5 py-0.5 rounded text-gray-100">
                  Epic Online Services Godot
                </code>
                .
              </li>
              <li>
                Find the plugin by{" "}
                <strong className="text-white">3ddelano</strong> and click on
                it.
              </li>
              <li>
                Click <strong className="text-blue-400">Download</strong>, then{" "}
                <strong className="text-blue-400">Install</strong>.
              </li>
              <li>
                Go to{" "}
                <strong className="text-white">
                  Project {"->"} Project Settings {"->"} Plugins
                </strong>
                .
              </li>
              <li>
                Enable the{" "}
                <strong className="text-white">
                  Epic Online Services Godot (EOSG)
                </strong>{" "}
                plugin.
              </li>
              <li>Restart the Godot editor.</li>
            </ol>
            <a
              href="https://godotengine.org/asset-library/asset/2453"
              target="_blank"
              rel="noopener noreferrer"
              className="inline-block mt-4 text-blue-400 hover:text-blue-300 underline"
            >
              View on Godot Asset Library
            </a>
          </div>
          <div className="bg-gray-800 p-6 rounded-lg shadow-md border border-gray-700">
            <h3 className="text-xl font-semibold mb-4 text-white">
              Method 2: GitHub Release
            </h3>
            <ol className="list-decimal list-inside space-y-2 text-gray-300">
              <li>
                Download the latest release{" "}
                <code className="bg-gray-700 px-1.5 py-0.5 rounded text-gray-100">
                  .zip
                </code>{" "}
                file from GitHub.
              </li>
              <li>Extract the zip archive.</li>
              <li>
                Copy the{" "}
                <code className="bg-gray-700 px-1.5 py-0.5 rounded text-gray-100">
                  addons/epic-online-services-godot
                </code>{" "}
                folder into your project's{" "}
                <code className="bg-gray-700 px-1.5 py-0.5 rounded text-gray-100">
                  res://addons/
                </code>{" "}
                folder (create it if needed).
              </li>
              <li>
                Go to{" "}
                <strong className="text-white">
                  Project {"->"} Project Settings {"->"} Plugins
                </strong>
                .
              </li>
              <li>
                Enable the{" "}
                <strong className="text-white">
                  Epic Online Services Godot (EOSG)
                </strong>{" "}
                plugin.
              </li>
              <li>Restart the Godot editor.</li>
            </ol>
            <a
              href="https://github.com/3ddelano/epic-online-services-godot/releases/latest"
              target="_blank"
              rel="noopener noreferrer"
              className="inline-block mt-4 text-blue-400 hover:text-blue-300 underline"
            >
              Download from GitHub Releases
            </a>
          </div>
        </div>
        <p className="text-center mt-8 text-gray-400">
          After installation, you can start using the{" "}
          <code className="bg-gray-700 px-1.5 py-0.5 rounded text-gray-100">
            EOS
          </code>{" "}
          and{" "}
          <code className="bg-gray-700 px-1.5 py-0.5 rounded text-gray-100">
            H
          </code>{" "}
          classes in your scripts.
        </p>
      </div>
    </section>
  );
}


================================================
FILE: docs/src/components/Layout.tsx
================================================
import { useState } from "react";

// Navigation links data
const NAV_LINKS = [
  {
    label: "Docs",
    href: "docs/introduction",
    external: false,
  },
  {
    label: "Showcase",
    href: "showcase",
    external: false,
  },
  {
    label: "GitHub",
    href: "https://github.com/3ddelano/epic-online-services-godot",
    external: true,
    icon: (
      <svg
        xmlns="http://www.w3.org/2000/svg"
        className="w-4 h-4"
        fill="#fff"
        viewBox="0 0 256 256"
      >
        <path
          d="M17.791 46.836A2 2 0 0 0 19 45v-5.4q.002-.297.041-.61L19 39h-3.6c-1.5 0-2.8-.6-3.4-1.8-.7-1.3-1-3.5-2.8-4.7-.3-.2-.1-.5.5-.5.6.1 1.9.9 2.7 2 .9 1.1 1.8 2 3.4 2 2.487 0 3.82-.125 4.622-.555C21.356 34.056 22.649 33 24 33v-.025c-5.668-.182-9.289-2.066-10.975-4.975-3.665.042-6.856.405-8.677.707a22 22 0 0 1-.151-.987c1.797-.296 4.843-.647 8.345-.714a8 8 0 0 1-.291-.849c-3.511-.178-6.541-.039-8.187.097-.02-.332-.047-.663-.051-.999 1.649-.135 4.597-.27 8.018-.111a10 10 0 0 1-.13-1.543c0-1.7.6-3.5 1.7-5-.5-1.7-1.2-5.3.2-6.6 2.7 0 4.6 1.3 5.5 2.1C21 13.4 22.9 13 25 13s4 .4 5.6 1.1c.9-.8 2.8-2.1 5.5-2.1 1.5 1.4.7 5 .2 6.6 1.1 1.5 1.7 3.2 1.6 5 0 .484-.045.951-.11 1.409 3.499-.172 6.527-.034 8.204.102-.002.337-.033.666-.051.999-1.671-.138-4.775-.28-8.359-.089a8 8 0 0 1-.325.98c3.546.046 6.665.389 8.548.689q-.064.498-.151.987c-1.912-.306-5.171-.664-8.879-.682-1.665 2.878-5.22 4.755-10.777 4.974V33c2.6 0 5 3.9 5 6.6V45c0 .823.498 1.53 1.209 1.836C41.37 43.804 48 35.164 48 25 48 12.318 37.683 2 25 2S2 12.318 2 25c0 10.164 6.63 18.804 15.791 21.836"
          fontFamily="none"
          fontSize="none"
          fontWeight="none"
          style={{ mixBlendMode: "normal" }}
          textAnchor="none"
          transform="scale(5.12)"
        ></path>
      </svg>
    ),
  },
];

export function NavBar() {
  const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);

  return (
    <nav className="fixed top-0 left-0 right-0 z-[100] glass py-4 px-6 h-16 navbar">
      <div className="container mx-auto flex items-center justify-between">
        <a
          href="/epic-online-services-godot/"
          className="group flex items-center gap-3 no-underline"
        >
          <img
            src="img/eosg-logo.svg"
            alt="Logo"
            className="w-8 h-8 group-hover:rotate-12 transition-transform duration-500"
          />
          <span className="text-white text-sm font-bold tracking-tight uppercase group-hover:text-blue-400 transition-colors">
            EOS Godot
          </span>
        </a>

        {/* Desktop menu */}
        <div className="hidden sm:flex items-center gap-8">
          {NAV_LINKS.map((link) => (
            <a
              key={link.label}
              href={link.href}
              {...(link.external && {
                rel: "noopener noreferrer",
                target: "_blank",
              })}
              className={
                link.label === "GitHub"
                  ? "button-secondary px-4 py-2 rounded-lg text-xs font-bold uppercase tracking-widest no-underline flex items-center gap-2"
                  : "text-white hover:text-blue-400 active:text-blue-400 text-sm font-semibold uppercase tracking-wider transition-colors no-underline"
              }
            >
              {link.icon}
              {link.label}
            </a>
          ))}
        </div>

        {/* Mobile menu button */}
        <button
          className="sm:hidden p-2 -mr-2"
          onClick={() => setIsMobileMenuOpen(!isMobileMenuOpen)}
          aria-label="Toggle menu"
        >
          <svg
            className="w-6 h-6 text-white"
            fill="none"
            stroke="currentColor"
            viewBox="0 0 24 24"
          >
            {isMobileMenuOpen ? (
              <path
                strokeLinecap="round"
                strokeLinejoin="round"
                strokeWidth="2"
                d="M6 18L18 6M6 6l12 12"
              />
            ) : (
              <path
                strokeLinecap="round"
                strokeLinejoin="round"
                strokeWidth="2"
                d="M4 6h16M4 12h16m-7 6h7"
              />
            )}
          </svg>
        </button>
      </div>

      {/* Mobile menu dropdown */}
      {isMobileMenuOpen && (
        <div className="sm:hidden absolute top-16 left-0 right-0 backdrop-blur-xl bg-gray-900/95 border-t border-b border-white/10 p-4 shadow-lg">
          <div className="container mx-auto px-6 py-4 flex flex-col gap-4">
            {NAV_LINKS.map((link) => (
              <a
                key={link.label}
                href={link.href}
                {...(link.external && {
                  rel: "noopener noreferrer",
                  target: "_blank",
                })}
                className="text-white hover:text-blue-400 active:text-blue-400 text-sm font-semibold uppercase tracking-wider transition-colors no-underline flex items-center gap-2"
                onClick={() => setIsMobileMenuOpen(false)}
              >
                {link.icon}
                {link.label}
              </a>
            ))}
          </div>
        </div>
      )}
    </nav>
  );
}

export function Footer() {
  return (
    <footer className="bg-[#030712] border-t border-white/5 pt-12 pb-8">
      <div className="container px-6">
        <div className="glass rounded-xl text-yellow-300/80 text-xs p-5 max-w-3xl mb-10">
          <p className="leading-relaxed">
            <strong className="text-yellow-200">Disclaimer: </strong>This
            project Epic Online Services Godot (EOSG) is <strong>NOT</strong>{" "}
            affiliated with Epic Games Inc or Godot Engine. It does not endorse
            Epic Online Services. This project and the sample Godot scenes are
            provided solely for educational purposes and may or may not comply
            with Epic Games' Design Guidelines. If you plan to release a game
            using EOS, ensure you read the official{" "}
            <a
              href="https://dev.epicgames.com/docs/services/en-US/EpicAccountServices/DesignGuidelines/index.html"
              target="_blank"
              rel="noopener noreferrer"
              className="underline hover:text-yellow-100 transition-colors"
            >
              Guidelines
            </a>{" "}
            and fulfill all requirements (user consent, data deletion, privacy
            policy, etc.).
          </p>
        </div>

        <p className="text-gray-500 text-sm">
          Copyright &copy; {new Date().getFullYear()}{" "}
          <a
            href="https://github.com/3ddelano"
            target="_blank"
            rel="noopener noreferrer"
            className="text-blue-400/80 hover:text-blue-300 transition-colors"
          >
            Delano Lourenco
          </a>
          . All rights reserved.
        </p>
        <p className="text-gray-600 text-xs mt-2">
          Epic Games, Epic Online Services, Godot Engine, and their respective
          logos are trademarks or registered trademarks of their respective
          owners.
        </p>
      </div>
    </footer>
  );
}


================================================
FILE: docs/src/components/MainSystemsSection.tsx
================================================
const MAIN_SYSTEMS = [
  {
    title: "High Level EOS",
    tag: "Recommended",
    description:
      "Provides easy-to-use methods and signals to interact with EOS. Ideal for most cases and rapid development.",
    link: "docs/introduction",
    icon: (
      <svg
        className="w-6 h-6 text-blue-400"
        fill="none"
        stroke="currentColor"
        viewBox="0 0 24 24"
      >
        <path
          strokeLinecap="round"
          strokeLinejoin="round"
          strokeWidth="2"
          d="M13 10V3L4 14h7v7l9-11h-7z"
        ></path>
      </svg>
    ),
    color: "blue",
  },
  {
    title: "GDExtension EOS",
    tag: "Advanced",
    description:
      "Offers advanced EOS usage with direct access to the C SDK via GDExtension. Suitable for complex needs.",
    extra: (
      <>
        Provides{" "}
        <code className="bg-purple-500/10 px-2 py-0.5 rounded text-purple-300 font-mono text-xs">
          EOS
        </code>{" "}
        and{" "}
        <code className="bg-purple-500/10 px-2 py-0.5 rounded text-purple-300 font-mono text-xs">
          IEOS
        </code>{" "}
        classes.
      </>
    ),
    icon: (
      <svg
        className="w-6 h-6 text-purple-400"
        fill="none"
        stroke="currentColor"
        viewBox="0 0 24 24"
      >
        <path
          strokeLinecap="round"
          strokeLinejoin="round"
          strokeWidth="2"
          d="M10 20l4-16m4 4l4 4-4 4M6 16l-4-4 4-4"
        ></path>
      </svg>
    ),
    color: "purple",
  },
];

export function MainSystemsSection() {
  return (
    <section id="main-systems" className="py-20 sm:py-24 bg-[#030712] relative">
      <div className="container mx-auto px-6">
        <h2 className="text-3xl font-bold mb-4 text-center text-white tracking-tight">
          Two Main Systems
        </h2>
        <p className="text-gray-400 text-center mb-14 max-w-2xl mx-auto font-light">
          Choose the approach that fits your project's complexity.
        </p>
        <div className="grid md:grid-cols-2 gap-8 max-w-5xl mx-auto">
          {MAIN_SYSTEMS.map((system, i) => (
            <div
              key={i}
              className={`glass rounded-2xl p-8 transition-all duration-300 hover:-translate-y-1 hover:shadow-xl hover:shadow-${system.color}-500/5 border-${system.color}-500/20 hover:border-${system.color}-500/40`}
              style={{
                borderColor: `rgba(${
                  system.color === "blue" ? "59,130,246" : "168,85,247"
                },0.2)`,
              }}
            >
              <div
                className={`mb-5 w-12 h-12 rounded-xl bg-${system.color}-500/10 flex items-center justify-center`}
              >
                {system.icon}
              </div>
              <h3 className="text-xl font-bold mb-3 text-white">
                {system.title}
              </h3>
              <span
                className={`inline-block mb-4 text-xs font-bold uppercase tracking-widest text-${system.color}-400 bg-${system.color}-500/10 px-3 py-1 rounded-full`}
              >
                {system.tag}
              </span>
              <p className="text-gray-400 mb-4 font-light leading-relaxed">
                {system.description}
              </p>
              {system.link && (
                <a
                  href={system.link}
                  className={`inline-flex items-center text-${system.color}-400 hover:text-${system.color}-300 font-semibold text-sm no-underline transition-colors`}
                >
                  Learn more
                  <svg
                    className="w-4 h-4 ml-1"
                    fill="none"
                    stroke="currentColor"
                    viewBox="0 0 24 24"
                  >
                    <path
                      strokeLinecap="round"
                      strokeLinejoin="round"
                      strokeWidth="2"
                      d="M9 5l7 7-7 7"
                    ></path>
                  </svg>
                </a>
              )}
              {system.extra && (
                <p className="text-gray-500 text-sm">{system.extra}</p>
              )}
            </div>
          ))}
        </div>
      </div>
    </section>
  );
}


================================================
FILE: docs/src/components/MediaSections.tsx
================================================
const SCREENSHOTS_DATA = [
  {
    category: "Windows",
    images: [
      {
        src: "img/screenshots/windows_auth_success.png",
        alt: "Windows Auth Success Screenshot",
      },
    ],
  },
  {
    category: "Android",
    images: [
      {
        src: "img/screenshots/android_auth_success.jpg",
        alt: "Android Auth Success Screenshot",
      },
      {
        src: "img/screenshots/android_p2p_game.jpg",
        alt: "Android P2P Game Screenshot",
      },
    ],
  },
  {
    category: "iOS / macOS",
    images: [
      {
        src: "img/screenshots/ios_simulator_auth_success.png",
        alt: "iOS Simulator Auth Success Screenshot",
      },
      {
        src: "img/screenshots/ios_simulator_in_lobby.png",
        alt: "iOS Simulator In Lobby Screenshot",
        subtitle: "Cross-Platform Lobbies",
      },
      {
        src: "img/screenshots/mac_in_lobby.png",
        alt: "macOS In Lobby Screenshot",
      },
    ],
  },
];

const TUTORIALS_DATA = {
  playlist_url:
    "https://www.youtube.com/playlist?list=PL5t0hR7ADzun5JYF4e2a2FtZEWYHxK83_",
  thumbnail_url: "https://img.youtube.com/vi/ENyvF4yVjKg/0.jpg",
  thumbnail_alt: "Epic Online Services Tutorial Series Thumbnail",
};

export function ScreenshotsSection() {
  return (
    <section id="screenshots" className="py-20 sm:py-24 bg-[#030712]">
      <div className="container mx-auto px-6">
        <h2 className="text-3xl font-bold mb-4 text-center text-white tracking-tight">
          Screenshots & Demos
        </h2>
        <p className="text-gray-400 text-center mb-14 max-w-2xl mx-auto font-light">
          See the plugin running on multiple platforms.
        </p>
        <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-8">
          {SCREENSHOTS_DATA.map((platform, i) => (
            <div key={i} className="flex items-center flex-col">
              <h3 className="text-lg font-bold mb-4 text-center text-gray-200 uppercase tracking-wider">
                {platform.category}
              </h3>
              {platform.images.map((image, j) => (
                <div key={j} className="flex flex-col items-center w-full">
                  {image.subtitle && (
                    <h4 className="text-sm font-bold my-3 text-center text-gray-400 uppercase tracking-wider">
                      {image.subtitle}
                    </h4>
                  )}
                  <img
                    src={image.src}
                    alt={image.alt}
                    className={`w-full max-w-[800px] h-auto rounded-xl glass border-white/10 hover:brightness-110 transition-all duration-300 ${
                      j < platform.images.length - 1 ? "mb-4" : ""
                    }`}
                  />
                </div>
              ))}
            </div>
          ))}
        </div>
      </div>
    </section>
  );
}

export function DemoSection() {
  return (
    <section id="demo" className="py-20 sm:py-24 bg-[#0a0f1e]">
      <div className="container mx-auto px-6 text-center">
        <h2 className="text-3xl font-bold mb-4 text-white tracking-tight">
          Video Tutorials
        </h2>
        <p className="text-gray-400 mb-10 max-w-2xl mx-auto font-light">
          Watch the tutorial playlist on YouTube for a visual guide and
          examples.
        </p>
        <div className="max-w-3xl mx-auto aspect-video rounded-2xl overflow-hidden glass">
          <a
            href={TUTORIALS_DATA.playlist_url}
            target="_blank"
            rel="noopener noreferrer"
            className="block relative group"
          >
            <img
              src={TUTORIALS_DATA.thumbnail_url}
              alt={TUTORIALS_DATA.thumbnail_alt}
              className="w-full h-full object-cover"
            />
            <div className="absolute inset-0 bg-black/50 flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity duration-300">
              <div className="w-20 h-20 rounded-full bg-white/10 backdrop-blur-sm flex items-center justify-center border border-white/20">
                <svg
                  className="w-10 h-10 text-white ml-1"
                  fill="currentColor"
                  viewBox="0 0 20 20"
                >
                  <path d="M6.5 5.5v9l7-4.5-7-4.5z"></path>
                </svg>
              </div>
            </div>
          </a>
        </div>
        <a
          href={TUTORIALS_DATA.playlist_url}
          target="_blank"
          rel="noopener noreferrer"
          className="inline-block mt-8 text-blue-400 hover:text-blue-300 font-semibold text-sm no-underline transition-colors"
        >
          Watch the playlist on YouTube →
        </a>
      </div>
    </section>
  );
}


================================================
FILE: docs/src/components/SupportSection.tsx
================================================
const SUPPORT_DATA = {
  bmc_url: "https://www.buymeacoffee.com/3ddelano",
  github_sponsor_url: "https://github.com/sponsors/3ddelano",
  discord_url: "https://discord.gg/FZY9TqW",
  username: "@3ddelano",
};

export function SupportSection() {
  return (
    <section
      id="support"
      className="py-20 sm:py-24 bg-[#030712] relative overflow-hidden"
    >
      {/* Background glow */}
      <div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-[600px] h-[400px] bg-blue-600/5 rounded-full blur-[120px]"></div>

      <div className="container mx-auto px-6 text-center relative z-10">
        <h2 className="text-3xl font-bold mb-4 text-white tracking-tight">
          Support Development
        </h2>
        <p className="text-gray-400 mb-10 max-w-2xl mx-auto font-light leading-relaxed">
          Creating and maintaining this plugin requires significant time and
          effort. If you find this project helpful, please consider supporting
          its development.
        </p>
        <div className="flex flex-wrap justify-center items-center gap-6 mb-10">
          <a
            href={SUPPORT_DATA.bmc_url}
            target="_blank"
            rel="noopener noreferrer"
            className="inline-block transition transform hover:scale-105"
          >
            <img
              height="45"
              width="180"
              src="https://cdn.buymeacoffee.com/buttons/v2/default-red.png"
              alt="Buy Me A Coffee"
            />
          </a>
          <a
            href={SUPPORT_DATA.github_sponsor_url}
            target="_blank"
            rel="noopener noreferrer"
            className="button-primary px-6 py-3 rounded-xl text-sm font-bold no-underline inline-flex items-center gap-2"
          >
            <svg className="w-5 h-5" fill="currentColor" viewBox="0 0 16 16">
              <path
                fillRule="evenodd"
                d="M8 1.314C12.438-3.248 23.534 4.735 8 15-7.534 4.736 3.562-3.248 8 1.314z"
              />
            </svg>
            GitHub Sponsor
          </a>
        </div>

        <div className="glass rounded-2xl p-8 max-w-xl mx-auto">
          <p className="text-gray-300 mb-4 font-medium">
            Need help, have suggestions, or found a bug?
          </p>
          <div className="flex flex-wrap justify-center items-center gap-4">
            <a
              href={SUPPORT_DATA.discord_url}
              target="_blank"
              rel="noopener noreferrer"
              className="button-secondary px-5 py-2.5 rounded-xl text-sm font-bold no-underline inline-flex items-center gap-2"
            >
              <svg className="w-5 h-5" fill="currentColor" viewBox="0 0 24 24">
                <path d="M19.27 5.33C17.94 4.71 16.5 4.26 15 4a.09.09 0 0 0-.07.03c-.18.33-.39.76-.53 1.09a16.09 16.09 0 0 0-4.8 0c-.14-.34-.35-.76-.54-1.09a.09.09 0 0 0-.07-.03c-1.5.26-2.93.71-4.27 1.33a.07.07 0 0 0-.05.08c-.67 1.9-.94 3.9-.94 6s.27 4.09.94 6a.07.07 0 0 0 .05.08c1.34.61 2.77 1.07 4.27 1.33a.09.09 0 0 0 .07-.03c.19-.34.4-.77.54-1.1a16.28 16.28 0 0 0 5.34-.01c.14.33.35.76.53 1.1a.09.09 0 0 0 .07.03c1.5-.26 2.93-.71 4.27-1.33a.07.07 0 0 0 .05-.08c.67-1.91.94-3.91.94-6s-.28-4.09-.94-6a.07.07 0 0 0-.05-.08zM8.5 13.5c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5zm7 0c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5z" />
              </svg>
              Join Discord
            </a>
            <span className="text-gray-500 text-sm">
              or DM{" "}
              <code className="glass px-2 py-0.5 rounded text-gray-300 font-mono text-xs">
                {SUPPORT_DATA.username}
              </code>
            </span>
          </div>
        </div>
      </div>
    </section>
  );
}


================================================
FILE: docs/src/css/custom.css
================================================
@import "tailwindcss";

@import url("https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap");

:root {
  --ifm-font-family-base: "Outfit", sans-serif;
  --ifm-font-family-monospace: "JetBrains Mono", monospace;

  --ifm-color-primary: #3b82f6;
  --ifm-color-primary-dark: #2563eb;
  --ifm-color-primary-darker: #1d4ed8;
  --ifm-color-primary-darkest: #1e40af;
  --ifm-color-primary-light: #60a5fa;
  --ifm-color-primary-lighter: #93c5fd;
  --ifm-color-primary-lightest: #bfdbfe;

  --ifm-code-font-size: 90%;
  --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.1);

  --brand-gradient: linear-gradient(135deg, #3b82f6 0%, #8b5cf6 100%);
  --glass-bg: rgba(255, 255, 255, 0.03);
  --glass-border: rgba(255, 255, 255, 0.08);
}

[data-theme='dark'] {
  --ifm-background-color: #030712;
  --ifm-navbar-background-color: rgba(3, 7, 18, 0.8);
  --ifm-footer-background-color: #030712;

  --ifm-color-primary: #60a5fa;
  --ifm-color-primary-dark: #3b82f6;
  --ifm-color-primary-darker: #2563eb;
  --ifm-color-primary-darkest: #1d4ed8;
  --ifm-color-primary-light: #93c5fd;
  --ifm-color-primary-lighter: #bfdbfe;
  --ifm-color-primary-lightest: #dbeafe;

  --docusaurus-highlighted-code-line-bg: rgba(255, 255, 255, 0.1);
}

/* Glassmorphism utility */
.glass {
  background: var(--glass-bg);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border: 1px solid var(--glass-border);
}

.hero-image {
  background-color: #030712;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='192' height='192' viewBox='0 0 192 192'%3E%3Cpath fill='%233b82f6' fill-opacity='0.04' d='M192 15v2a11 11 0 0 0-11 11c0 1.94 1.16 4.75 2.53 6.11l2.36 2.36a6.93 6.93 0 0 1 1.22 7.56l-.43.84a8.08 8.08 0 0 1-6.66 4.13H145v35.02a6.1 6.1 0 0 0 3.03 4.87l.84.43c1.58.79 4 .4 5.24-.85l2.36-2.36a12.04 12.04 0 0 1 7.51-3.11 13 13 0 1 1 .02 26 12 12 0 0 1-7.53-3.11l-2.36-2.36a4.93 4.93 0 0 0-5.24-.85l-.84.43a6.1 6.1 0 0 0-3.03 4.87V143h35.02a8.08 8.08 0 0 1 6.66 4.13l.43.84a6.91 6.91 0 0 1-1.22 7.56l-2.36 2.36A10.06 10.06 0 0 0 181 164a11 11 0 0 0 11 11v2a13 13 0 0 1-13-13 12 12 0 0 1 3.11-7.53l2.36-2.36a4.93 4.93 0 0 0 .85-5.24l-.43-.84a6.1 6.1 0 0 0-4.87-3.03H145v35.02a8.08 8.08 0 0 1-4.13 6.66l-.84.43a6.91 6.91 0 0 1-7.56-1.22l-2.36-2.36A10.06 10.06 0 0 0 124 181a11 11 0 0 0-11 11h-2a13 13 0 0 1 13-13c2.47 0 5.79 1.37 7.53 3.11l2.36 2.36a4.94 4.94 0 0 0 5.24.85l.84-.43a6.1 6.1 0 0 0 3.03-4.87V145h-35.02a8.08 8.08 0 0 1-6.66-4.13l-.43-.84a6.91 6.91 0 0 1 1.22-7.56l2.36-2.36A10.06 10.06 0 0 0 107 124a11 11 0 0 0-22 0c0 1.94 1.16 4.75 2.53 6.11l2.36 2.36a6.93 6.93 0 0 1 1.22 7.56l-.43.84a8.08 8.08 0 0 1-6.66 4.13H49v35.02a6.1 6.1 0 0 0 3.03 4.87l.84.43c1.58.79 4 .4 5.24-.85l2.36-2.36a12.04 12.04 0 0 1 7.51-3.11A13 13 0 0 1 81 192h-2a11 11 0 0 0-11-11c-1.94 0-4.75 1.16-6.11 2.53l-2.36 2.36a6.93 6.93 0 0 1-7.56 1.22l-.84-.43a8.08 8.08 0 0 1-4.13-6.66V145H11.98a6.1 6.1 0 0 0-4.87 3.03l-.43.84c-.79 1.58-.4 4 .85 5.24l2.36 2.36a12.04 12.04 0 0 1 3.11 7.51A13 13 0 0 1 0 177v-2a11 11 0 0 0 11-11c0-1.94-1.16-4.75-2.53-6.11l-2.36-2.36a6.93 6.93 0 0 1-1.22-7.56l.43-.84a8.08 8.08 0 0 1 6.66-4.13H47v-35.02a6.1 6.1 0 0 0-3.03-4.87l-.84-.43c-1.59-.8-4-.4-5.24.85l-2.36 2.36A12 12 0 0 1 28 109a13 13 0 1 1 0-26c2.47 0 5.79 1.37 7.53 3.11l2.36 2.36a4.94 4.94 0 0 0 5.24.85l.84-.43A6.1 6.1 0 0 0 47 84.02V49H11.98a8.08 8.08 0 0 1-6.66-4.13l-.43-.84a6.91 6.91 0 0 1 1.22-7.56l2.36-2.36A10.06 10.06 0 0 0 11 28 11 11 0 0 0 0 17v-2a13 13 0 0 1 13 13c0 2.47-1.37 5.79-3.11 7.53l-2.36 2.36a4.94 4.94 0 0 0-.85 5.24l.43.84A6.1 6.1 0 0 0 11.98 47H47V11.98a8.08 8.08 0 0 1 4.13-6.66l.84-.43a6.91 6.91 0 0 1 7.56 1.22l2.36 2.36A10.06 10.06 0 0 0 68 11 11 11 0 0 0 79 0h2a13 13 0 0 1-13 13 12 12 0 0 1-7.53-3.11l-2.36-2.36a4.93 4.93 0 0 0-5.24-.85l-.84.43A6.1 6.1 0 0 0 49 11.98V47h35.02a8.08 8.08 0 0 1 6.66 4.13l.43.84a6.91 6.91 0 0 1-1.22 7.56l-2.36 2.36A10.06 10.06 0 0 0 85 68a11 11 0 0 0 22 0c0-1.94-1.16-4.75-2.53-6.11l-2.36-2.36a6.93 6.93 0 0 1-1.22-7.56l.43-.84a8.08 8.08 0 0 1 6.66-4.13H143V11.98a6.1 6.1 0 0 0-3.03-4.87l-.84-.43c-1.59-.8-4-.4-5.24.85l-2.36 2.36A12 12 0 0 1 124 13a13 13 0 0 1-13-13h2a11 11 0 0 0 11 11c1.94 0 4.75-1.16 6.11-2.53l2.36-2.36a6.93 6.93 0 0 1 7.56-1.22l.84.43a8.08 8.08 0 0 1 4.13 6.66V47h35.02a6.1 6.1 0 0 0 4.87-3.03l.43-.84c.8-1.59.4-4-.85-5.24l-2.36-2.36A12 12 0 0 1 179 28a13 13 0 0 1 13-13zM84.02 143a6.1 6.1 0 0 0 4.87-3.03l.43-.84c.8-1.59.4-4-.85-5.24l-2.36-2.36A12 12 0 0 1 83 124a13 13 0 1 1 26 0c0 2.47-1.37 5.79-3.11 7.53l-2.36 2.36a4.94 4.94 0 0 0-.85 5.24l.43.84a6.1 6.1 0 0 0 4.87 3.03H143v-35.02a8.08 8.08 0 0 1 4.13-6.66l.84-.43a6.91 6.91 0 0 1 7.56 1.22l2.36 2.36A10.06 10.06 0 0 0 164 107a11 11 0 0 0 0-22c-1.94 0-4.75 1.16-6.11 2.53l-2.36 2.36a6.93 6.93 0 0 1-7.56 1.22l-.84-.43a8.08 8.08 0 0 1-4.13-6.66V49h-35.02a6.1 6.1 0 0 0-4.87 3.03l-.43.84c-.79 1.58-.4 4 .85 5.24l2.36 2.36a12.04 12.04 0 0 1 3.11 7.51A13 13 0 1 1 83 68a12 12 0 0 1 3.11-7.53l2.36-2.36a4.93 4.93 0 0 0 .85-5.24l-.43-.84A6.1 6.1 0 0 0 84.02 49H49v35.02a8.08 8.08 0 0 1-4.13 6.66l-.84.43a6.91 6.91 0 0 1-7.56-1.22l-2.36-2.36A10.06 10.06 0 0 0 28 85a11 11 0 0 0 0 22c1.94 0 4.75-1.16 6.11-2.53l2.36-2.36a6.93 6.93 0 0 1 7.56-1.22l.84.43a8.08 8.08 0 0 1 4.13 6.66V143h35.02z'%3E%3C/path%3E%3C/svg%3E");
}

/* Navbar glassmorphism */
.navbar {
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--glass-border);
  
  /* Override Docusaurus link color variables */
  --ifm-link-color: white;
  --ifm-link-hover-color: #60a5fa;
  --ifm-link-decoration: none;
  --ifm-link-hover-decoration: none;
}

/* Override Docusaurus link colors in navbar */
.navbar a:not(.button-secondary) {
  color: white !important;
}

.navbar a:not(.button-secondary):hover,
.navbar a:not(.button-secondary):active {
  color: #60a5fa !important;
}

/* Button system */
.button-primary {
  background: var(--brand-gradient);
  border: none;
  color: white;
  font-weight: 600;
  transition: all 0.3s ease;
  box-shadow: 0 4px 15px rgba(59, 130, 246, 0.3);
}

.button-primary:hover {
  transform: translateY(-2px);
  box-shadow: 0 8px 25px rgba(59, 130, 246, 0.5);
  color: white !important;
  text-decoration: none;
}

.button-secondary {
  background: var(--glass-bg);
  border: 1px solid var(--glass-border);
  color: white;
  backdrop-filter: blur(8px);
  transition: all 0.3s ease;
}

.button-secondary:hover {
  background: rgba(255, 255, 255, 0.08);
  border-color: rgba(255, 255, 255, 0.2);
  color: white !important;
  text-decoration: none;
}

/* Feature cards */
.feature-card {
  background: var(--glass-bg);
  border: 1px solid var(--glass-border);
  backdrop-filter: blur(8px);
  transition: all 0.3s ease;
}

.feature-card:hover {
  border-color: rgba(255, 255, 255, 0.15);
  transform: translateY(-2px);
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
}

================================================
FILE: docs/src/pages/index.tsx
================================================
import { HeroSection } from "../components/HeroSection";
import { MainSystemsSection } from "../components/MainSystemsSection";
import { FeaturesSection } from "../components/FeaturesSection";
import { ScreenshotsSection, DemoSection } from "../components/MediaSections";
import { SupportSection } from "../components/SupportSection";
import { Footer, NavBar } from "../components/Layout";

export default function App() {
  return (
    <div className="min-h-screen bg-[#030712] text-gray-200 antialiased font-[Outfit,sans-serif]">
      <NavBar />
      <main className="pt-16">
        <HeroSection />
        <MainSystemsSection />
        <FeaturesSection />
        <ScreenshotsSection />
        <DemoSection />
        <SupportSection />
      </main>
      <Footer />
    </div>
  );
}


================================================
FILE: docs/src/pages/showcase.md
================================================
---
---

# Showcase

Here is a list of games using the Epic Online Services Godot plugin. If you are using this plugin and want to list your game in this list. Create an Issue on the [Github Repo](https://github.com/3ddelano/epic-online-services-godot/issues) with your game URL and which features of the plugin you used, or leave a message in the [Discord server](https://discord.gg/FZY9TqW).

- ### Kamaeru: A Frog Refuge

  Foster a sanctuary for frogs and restore the biodiversity of the wetlands in Kamaeru, a cozy frog collecting game, where you take pictures of frogs, play mini-games and decorate your habitat. Hop right to it!

  Links: [Steam](https://store.epicgames.com/en-US/p/kamaeru-0c301e)
  
  ![Kamaeru Logo](/img/showcase/kamaeru-logo.png)
  
  
  > Features Used: Achievements, Cloud Saves / PlayerDataStorage

<br></br>

- ### Kitchen Together
  
  Get ready to stir up some fun in the ultimate cooking challenge! Join your friends in this engaging multiplayer game where teamwork meets culinary creativity. Choose your kitchen role, from chopping and frying to decorating and serving, as you race against the clock to prepare delicious dishes.

  Links: [Android Play Store](https://play.google.com/store/apps/details?id=com.kitchentogether) | [iOS App Store](https://apps.apple.com/us/app/kitchen-together-2/id6748915442)

  ![Kitchen Together Logo](/img/showcase/kitchen-together-logo.webp)

  > Features Used: Voice Chat, P2P, Lobby

<br></br>

- ### Hamsteria
  
  Hamsteria is a short (~1-2 hours) difficult two player co-op game where you're each a hamster in attached wheels. You can only spin your individual wheel forwards or backwards. There is no jump button, and there is no turn action. To escape, you must work together.

  Links: [Itch.io](https://2wheelerdev.itch.io/hamsteria)
  
  ![Hamsteria Logo](/img/showcase/hamsteria-logo.webp)

  > Features Used: P2P, Lobby

================================================
FILE: docs/src/plugins/tailwind-config.ts
================================================
module.exports = function tailwindPlugin(context, options) {
	return {
	  name: 'tailwind-plugin',
	  configurePostCss(postcssOptions) {
		postcssOptions.plugins = [require('@tailwindcss/postcss')]
		return postcssOptions
	  }
	}
  }

================================================
FILE: docs/static/.nojekyll
================================================


================================================
FILE: docs/tsconfig.json
================================================
{
  // This file is not used in compilation. It is here just for a nice editor experience.
  "extends": "@docusaurus/tsconfig",
  "compilerOptions": {
    "baseUrl": "."
  },
  "exclude": [".docusaurus", "build"]
}


================================================
FILE: function_analyzer.py
================================================
# eos_function_usage_checker.py

import os
import re


# Function to extract function names from the EOS C SDK header files
def extract_function_names(sdk_path):
    function_declarations = {}
    pattern = re.compile(r"EOS_DECLARE_FUNC\(\w+\)\s+(EOS_\w+)\(")

    for root, _, files in os.walk(sdk_path):
        for file in files:
            if file.endswith(".h"):
                with open(os.path.join(root, file), 'r', encoding='utf-8') as f:
                    content = f.read()
                    matches = pattern.findall(content)
                    for match in matches:
                        function_declarations[match] = os.path.join(root, file)

    return function_declarations


# Function to search for function names in the src folder
def find_function_calls(src_path, function_names):
    function_usage = {name: [] for name in function_names}
    pattern = re.compile(r"(\bEOS_\w+\b)")

    for root, _, files in os.walk(src_path):
        for file in files:
            if file.endswith(".h") or file.endswith(".cpp"):
                with open(os.path.join(root, file), 'r', encoding='utf-8') as f:
                    content = f.read()
                    matches = pattern.findall(content)
                    for match in matches:
                        if match in function_usage:
                            function_usage[match].append(os.path.join(root, file))

    return function_usage


def main():
    sdk_path = 'thirdparty/eos-sdk/SDK'  # Replace with the actual path to the EOS C SDK folder
    src_path = 'src'  # Replace with the actual path to the src folder

    whitelist = ['EOS_Achievements_CopyAchievementDefinitionByIndex',
                 'EOS_Achievements_CopyAchievementDefinitionByAchievementId',
                 'EOS_Achievements_GetUnlockedAchievementCount',
                 'EOS_Achievements_CopyUnlockedAchievementByIndex',
                 'EOS_Achievements_CopyUnlockedAchievementByAchievementId',
                 'EOS_Achievements_AddNotifyAchievementsUnlocked',
                 'EOS_AntiCheatClient_PollStatus',
                 'EOS_ByteArray_ToString',
                 'EOS_EpicAccountId_IsValid',
                 'EOS_ProductUserId_IsValid',
                 ]

    # Step 1: Extract function names from SDK header files
    function_declarations = extract_function_names(sdk_path)
    function_names = list(function_declarations.keys())
    print(f"Extracted {len(function_names)} function names from SDK headers.")

    # Step 2: Search for these function names in the src folder
    function_usage = find_function_calls(src_path, function_names)

    # Print the results
    print("SDK functions not called by the plugin:")
    uncalled_count = 0
    for function, files in function_usage.items():
        if files: continue
        if function in whitelist: continue
        if "RemoveNotify" in function: continue

        uncalled_count += 1
        print(f"{function} : {function_declarations[function]}")

    print(f"\nTotal number of SDK functions not called by the plugin: {uncalled_count}")


if __name__ == "__main__":
    main()


================================================
FILE: sample/.gitignore
================================================
.import/
export.cfg
export_presets.cfg
*.translation

.godot/

*.env
*.import

================================================
FILE: sample/AntiCheatServerMain.gd
================================================
class_name AntiCheatServerMain
extends Node

@onready var PRODUCT_NAME: String = Env.get_var("PRODUCT_NAME")
@onready var PRODUCT_VERSION: String = Env.get_var("PRODUCT_VERSION")
@onready var PRODUCT_ID: String = Env.get_var("PRODUCT_ID")
@onready var SANDBOX_ID: String = Env.get_var("SANDBOX_ID")
@onready var DEPLOYMENT_ID: String = Env.get_var("DEPLOYMENT_ID")
@onready var CLIENT_ID: String = Env.get_var("CLIENT_ID")
@onready var CLIENT_SECRET: String = Env.get_var("CLIENT_SECRET")
@onready var ENCRYPTION_KEY: String = Env.get_var("ENCRYPTION_KEY")

const PORT = 12345

func _ready() -> void:
	print("AntiCheatServer _ready")

	var init_success = await _load_and_init_sdk()
	if not init_success:
		return

	_begin_session()
	_start_server()

func _load_and_init_sdk() -> bool:
	# -----
	# EOS Setup
	# -----

	# Initialize the SDK
	var init_opts = EOS.Platform.InitializeOptions.new()
	init_opts.product_name = PRODUCT_NAME
	init_opts.product_version = PRODUCT_VERSION
	var init_res := EOS.Platform.PlatformInterface.initialize(init_opts)
	var init_retry_count = 10
	while not EOS.is_success(init_res) and init_retry_count > 0:
		init_res = EOS.Platform.PlatformInterface.initialize(init_opts)
		init_retry_count -= 1
		await get_tree().create_timer(0.2).timeout

	if not EOS.is_success(init_res):
		print("Failed to initialize EOS SDK: ", EOS.result_str(init_res))
		return false
	print("Initialized EOS platform")

	# Create platform
	var create_opts = EOS.Platform.CreateOptions.new()
	create_opts.product_id = PRODUCT_ID
	create_opts.sandbox_id = SANDBOX_ID
	create_opts.deployment_id = DEPLOYMENT_ID
	create_opts.client_id = CLIENT_ID
	create_opts.client_secret = CLIENT_SECRET
	create_opts.encryption_key = ENCRYPTION_KEY
	create_opts.is_server = true
	create_opts.flags = EOS.Platform.PlatformFlags.DisableOverlay
	var create_success: bool = EOS.Platform.PlatformInterface.create(create_opts)
	var create_retry_count = 10
	while not create_success&&create_retry_count > 0:
		create_success = EOS.Platform.PlatformInterface.create(create_opts)
		create_retry_count -= 1
		await get_tree().create_timer(0.2).timeout
	if not create_success:
		print("Failed to create EOS Platform")
		return false
	print("Created EOS platform")

	return true

func _begin_session():
	IEOS.anticheatserver_interface_message_to_client_callback.connect(func(data):
		print("--- AntiCheatServer: message_to_client_callback: ", data)
	)

	IEOS.anticheatserver_interface_client_action_required_callback.connect(func(data):
		print("--- AntiCheatServer: client_action_required_callback: ", data)
	)

	IEOS.anticheatserver_interface_client_auth_status_changed_callback.connect(func(data):
		print("--- AntiCheatServer: client_auth_status_changed_callback: ", data)
	)

	var begin_sess_opts = EOS.AntiCheatServer.BeginSessionOptions.new()
	begin_sess_opts.register_timeout_seconds = 60
	begin_sess_opts.server_name = "Godot 4.2 server"
	begin_sess_opts.enable_gameplay_data = false

	print("--- AntiCheatServer: begin_session: ", EOS.AntiCheatServer.AntiCheatServerInterface.begin_session(begin_sess_opts))

func _verify_id_token(_peer_id: int, product_user_id: String, connect_id_jwt: String):
	var id_token = EOS.Connect.IdToken.new()
	id_token.json_web_token = connect_id_jwt
	id_token.product_user_id = product_user_id

	var verify_token_opts = EOS.Connect.VerifyIdTokenOptions.new()
	verify_token_opts.id_token = id_token

	EOS.Connect.ConnectInterface.verify_id_token(verify_token_opts)
	print("--- AntiCheatServer: verify_id_token: ", await IEOS.connect_interface_verify_id_token_callback)

func _start_server():
	multiplayer.peer_connected.connect(func(id: int):
		print("--- AntiCheatServer:: peer_connected: ", id)
	)
	multiplayer.peer_disconnected.connect(func(id: int):
		print("--- AntiCheatServer:: peer_disconnected: ", id)
	)

	var peer = ENetMultiplayerPeer.new()
	peer.create_server(PORT)
	multiplayer.multiplayer_peer = peer
	print("Listening for clients on port: ", PORT)

func on_client_message_receive(peer_id: int, type: String, data: Dictionary):
	if type == "register":
		_verify_id_token(peer_id, data.local_user_id, data.jwt)


================================================
FILE: sample/AntiCheatServerMain.gd.uid
================================================
uid://clbqhgyalkxuw


================================================
FILE: sample/Main.gd
================================================
extends Control

@onready var PRODUCT_NAME: String = Env.get_var("PRODUCT_NAME") # Paste your own instead of Env.get_var
@onready var PRODUCT_VERSION: String = Env.get_var("PRODUCT_VERSION") # Paste your own
@onready var PRODUCT_ID: String = Env.get_var("PRODUCT_ID") # Paste your own
@onready var SANDBOX_ID: String = Env.get_var("SANDBOX_ID") # Paste your own
@onready var DEPLOYMENT_ID: String = Env.get_var("DEPLOYMENT_ID") # Paste your own
@onready var CLIENT_ID: String = Env.get_var("CLIENT_ID") # Paste your own
@onready var CLIENT_SECRET: String = Env.get_var("CLIENT_SECRET") # Paste your own
@onready var ENCRYPTION_KEY: String = Env.get_var("ENCRYPTION_KEY") # Paste your own

@export var _views_path: NodePath
@onready var views = get_node(_views_path) as VBoxContainer


func _ready() -> void:
	if _check_for_dedicated_server_sample():
		return
	print("Ready!")
	Store._main_node = self
	
	HLog.log_level = HLog.LogLevel.INFO

	# -----
	# EOS Setup
	# -----
	var credentials = HCredentials.new()
	credentials.product_name = PRODUCT_NAME
	credentials.product_version = PRODUCT_VERSION
	credentials.product_id = PRODUCT_ID
	credentials.sandbox_id = SANDBOX_ID
	credentials.deployment_id = DEPLOYMENT_ID
	credentials.client_id = CLIENT_ID
	credentials.client_secret = CLIENT_SECRET
	credentials.encryption_key = ENCRYPTION_KEY
	
	print("Setting up EOS...")
	var setup_success := await HPlatform.setup_eos_async(credentials)
	if not setup_success:
		printerr("Failed to setup EOS. See logs for error details")
		return
	
	var sdk_constants := EOS.Version.VersionInterface.get_constants()
	print("EOS SDK Version: %s (%s)" % [EOS.Version.VersionInterface.get_version(), sdk_constants.copyright_string])

	# See LoginView.gd for the user login flow
	_parse_cmdline_user_args()


func get_view_manager():
	return views


func _notification(what: int) -> void:
	if what == NOTIFICATION_WM_CLOSE_REQUEST:
		print("Shutting down EOS...")
		EOS.Platform.PlatformInterface.release()
		var res := EOS.Platform.PlatformInterface.shutdown()
		if not EOS.is_success(res):
			printerr("Failed to shutdown EOS: ", EOS.result_str(res))


func _check_for_dedicated_server_sample() -> bool:
	# Ignore this method
	# This is for the sample project to dynamically load the
	# dedicated server example when certain cli flags are passed
	
	var args = OS.get_cmdline_user_args()
	for arg in args:
		if arg.begins_with("--screenpos="):
			var rows = 2
			var cols = 2

			var pos := int(arg.replace("--screenpos=", ""))
			var screen_size = DisplayServer.screen_get_size()

			var scale_x = screen_size.x / cols
			var scale_y = screen_size.y / rows

			var x = (pos - 1) % cols
			@warning_ignore("integer_division")
			var y = (pos - 1) / rows

			get_window().position = Vector2(x * scale_x, y * scale_y)
			get_window().size = Vector2(screen_size.x / cols, screen_size.y / rows)
	
	if "--eosg-dedicated-server-example" in args:
		if "--eosg-server" in args:
			_load_dedicated_server_script()
			return true
		if "--eosg-client" in args:
			_load_dedicated_client_script()
			return true
	return false


func _load_dedicated_server_script():
	var SCENE := load("res://dedicated_server_example/server_main.tscn") as PackedScene
	var server = SCENE.instantiate()
	add_child(server)


func _load_dedicated_client_script():
	var SCENE := load("res://dedicated_server_example/client_main.tscn") as PackedScene
	var client = SCENE.instantiate()
	add_child(client)


func _parse_cmdline_user_args():
	var args = OS.get_cmdline_user_args()


	for arg in args:
		if arg.begins_with("--devuser="):
			var login_view = Store.get_view("Login")
			var username = arg.replace("--devuser=", "")
			login_view._set_login_status("Logging in with devtool using cli arg...")
			login_view._set_login_state(LoginView.States.Pending)
			HAuth.login_devtool_async("localhost:4545", username)
		
		if arg.begins_with("--screenpos="):
			var rows = 2
			var cols = 2

			var pos := int(arg.replace("--screenpos=", ""))
			var screen_size = DisplayServer.screen_get_size()

			var scale_x = screen_size.x / cols
			var scale_y = screen_size.y / rows

			var x = (pos - 1) % cols
			@warning_ignore("integer_division")
			var y = (pos - 1) / rows

			get_window().position = Vector2(x * scale_x, y * scale_y)
			get_window().size = Vector2(screen_size.x / cols, screen_size.y / rows)


================================================
FILE: sample/Main.gd.uid
================================================
uid://cf8kvjx2nbysy


================================================
FILE: sample/Main.tscn
================================================
[gd_scene load_steps=25 format=3 uid="uid://gcoi8ld0uvkl"]

[ext_resource type="Theme" uid="uid://dwns7wwoyi1hy" path="res://components/StyledPopupWindow/StyledPopupWindowTheme.tres" id="1_dhxmx"]
[ext_resource type="PackedScene" uid="uid://d3hxdkoy73pf1" path="res://scenes/AchievementsView/AchievementsView.tscn" id="2"]
[ext_resource type="Script" uid="uid://cf8kvjx2nbysy" path="res://Main.gd" id="3"]
[ext_resource type="Script" uid="uid://b8dbhfvrewi8w" path="res://scripts/ViewManager.gd" id="3_j157n"]
[ext_resource type="PackedScene" uid="uid://cl2qvlvdhn2iw" path="res://scenes/LogsView/LogsView.tscn" id="4"]
[ext_resource type="PackedScene" uid="uid://bht0ln2ftshrw" path="res://scenes/LoginView/LoginView.tscn" id="5"]
[ext_resource type="PackedScene" uid="uid://t8s6xh1ax7uy" path="res://scenes/UI/PrimaryButton.tscn" id="6"]
[ext_resource type="PackedScene" uid="uid://d2bkej1dakv6s" path="res://scenes/CustomInvitesView/CustomInvitesView.tscn" id="9"]
[ext_resource type="PackedScene" uid="uid://dgi7j5qx3xt84" path="res://scenes/StatsView/StatsView.tscn" id="10"]
[ext_resource type="PackedScene" uid="uid://5xrk7nvpwosj" path="res://scenes/LeaderboardsView/LeaderboardsView.tscn" id="11"]
[ext_resource type="PackedScene" uid="uid://t016k2yh382d" path="res://scenes/FriendsView/FriendsView.tscn" id="12"]
[ext_resource type="PackedScene" uid="uid://b51w7a6ofuubp" path="res://scenes/UIView/UIView.tscn" id="13"]
[ext_resource type="PackedScene" uid="uid://dsiyt23hnmngd" path="res://scenes/LobbiesView/LobbiesView.tscn" id="13_eyvcp"]
[ext_resource type="PackedScene" uid="uid://bd06h3ufkhfd7" path="res://scenes/MetricsView/MetricsView.tscn" id="14"]
[ext_resource type="Script" uid="uid://6tlvlmuarqub" path="res://scenes/NotificationsView/NotificationsView.gd" id="14_v0jrb"]
[ext_resource type="Script" uid="uid://bb2nerxdrhped" path="res://test.gd" id="16_4rltv"]
[ext_resource type="Script" uid="uid://d0vgtesnrato5" path="res://scripts/network.gd" id="17_ailes"]
[ext_resource type="Script" uid="uid://k3lb65sounwm" path="res://test_manual_audio_output.gd" id="17_bg4s2"]
[ext_resource type="PackedScene" uid="uid://bdlcslag0jdj1" path="res://scenes/UI/nat_type.tscn" id="18_vylep"]
[ext_resource type="PackedScene" uid="uid://c37wtoikc8pgp" path="res://scenes/UI/ping.tscn" id="19_enhih"]
[ext_resource type="PackedScene" uid="uid://8kmyoi08gr22" path="res://scenes/UI/players_score.tscn" id="20_i3cca"]
[ext_resource type="Script" uid="uid://cgmpdyovn5vfm" path="res://scenes/UI/touch_screen_joystick.gd" id="21_5h21x"]
[ext_resource type="Script" uid="uid://dygslh2f7uw40" path="res://scenes/UI/joysticks.gd" id="21_einjf"]

[sub_resource type="StyleBoxEmpty" id="5"]

[node name="Main" type="Control"]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
theme = ExtResource("1_dhxmx")
script = ExtResource("3")
_views_path = NodePath("MC/ViewManager")

[node name="ColorRect" type="ColorRect" parent="."]
layout_mode = 0
anchor_right = 1.0
anchor_bottom = 1.0
color = Color(0.121569, 0.121569, 0.121569, 1)

[node name="MC" type="MarginContainer" parent="."]
layout_mode = 0
anchor_right = 1.0
anchor_bottom = 1.0
theme_override_constants/margin_left = 8
theme_override_constants/margin_top = 8
theme_override_constants/margin_right = 8
theme_override_constants/margin_bottom = 8

[node name="ViewManager" type="VBoxContainer" parent="MC"]
layout_mode = 2
script = ExtResource("3_j157n")

[node name="HB" type="HFlowContainer" parent="MC/ViewManager"]
layout_mode = 2
size_flags_horizontal = 3

[node name="AuthBtn" parent="MC/ViewManager/HB" instance=ExtResource("6")]
unique_name_in_owner = true
layout_mode = 2
text = "Auth"

[node name="NeedsLoginBtns" type="HFlowContainer" parent="MC/ViewManager/HB"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3

[node name="AchievementsBtn" parent="MC/ViewManager/HB/NeedsLoginBtns" instance=ExtResource("6")]
unique_name_in_owner = true
layout_mode = 2
text = "Achievements"

[node name="CustomInvitesBtn" parent="MC/ViewManager/HB/NeedsLoginBtns" instance=ExtResource("6")]
unique_name_in_owner = true
layout_mode = 2
text = "Custom Invites"

[node name="StatsBtn" parent="MC/ViewManager/HB/NeedsLoginBtns" instance=ExtResource("6")]
unique_name_in_owner = true
layout_mode = 2
text = "Stats"

[node name="LeaderboardsBtn" parent="MC/ViewManager/HB/NeedsLoginBtns" instance=ExtResource("6")]
unique_name_in_owner = true
layout_mode = 2
text = "Leaderboards"

[node name="FriendsBtn" parent="MC/ViewManager/HB/NeedsLoginBtns" instance=ExtResource("6")]
unique_name_in_owner = true
layout_mode = 2
text = "Friends"

[node name="UIBtn" parent="MC/ViewManager/HB/NeedsLoginBtns" instance=ExtResource("6")]
unique_name_in_owner = true
layout_mode = 2
text = "UI"

[node name="MetricsBtn" parent="MC/ViewManager/HB/NeedsLoginBtns" instance=ExtResource("6")]
unique_name_in_owner = true
layout_mode = 2
text = "Metrics"

[node name="LobbiesBtn" parent="MC/ViewManager/HB/NeedsLoginBtns" instance=ExtResource("6")]
unique_name_in_owner = true
layout_mode = 2
text = "Lobbies"

[node name="VSC" type="VSplitContainer" parent="MC/ViewManager"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
theme_override_constants/autohide = 0

[node name="VB" type="VBoxContainer" parent="MC/ViewManager/VSC"]
layout_mode = 2
theme_override_constants/separation = 52

[node name="LoginView" parent="MC/ViewManager/VSC/VB" instance=ExtResource("5")]
custom_minimum_size = Vector2(0, 200)
layout_mode = 2

[node name="AchievementsView" parent="MC/ViewManager/VSC/VB" instance=ExtResource("2")]
visible = false
custom_minimum_size = Vector2(0, 200)
layout_mode = 2

[node name="CustomInvitesView" parent="MC/ViewManager/VSC/VB" instance=ExtResource("9")]
visible = false
custom_minimum_size = Vector2(0, 200)
layout_mode = 2

[node name="StatsView" parent="MC/ViewManager/VSC/VB" instance=ExtResource("10")]
visible = false
custom_minimum_size = Vector2(0, 200)
layout_mode = 2

[node name="LeaderboardsView" parent="MC/ViewManager/VSC/VB" instance=ExtResource("11")]
visible = false
custom_minimum_size = Vector2(0, 200)
layout_mode = 2

[node name="FriendsView" parent="MC/ViewManager/VSC/VB" instance=ExtResource("12")]
visible = false
custom_minimum_size = Vector2(0, 200)
layout_mode = 2

[node name="UIView" parent="MC/ViewManager/VSC/VB" instance=ExtResource("13")]
visible = false
custom_minimum_size = Vector2(0, 200)
layout_mode = 2

[node name="MetricsView" parent="MC/ViewManager/VSC/VB" instance=ExtResource("14")]
visible = false
custom_minimum_size = Vector2(0, 200)
layout_mode = 2

[node name="LobbiesView" parent="MC/ViewManager/VSC/VB" instance=ExtResource("13_eyvcp")]
visible = false
custom_minimum_size = Vector2(0, 200)
layout_mode = 2

[node name="NotificationsLayer" type="CanvasLayer" parent="MC/ViewManager/VSC/VB"]

[node name="NotificationsView" type="MarginContainer" parent="MC/ViewManager/VSC/VB/NotificationsLayer"]
offset_top = 270.0
offset_right = 366.0
offset_bottom = 600.0
mouse_filter = 2
script = ExtResource("14_v0jrb")

[node name="SC" type="ScrollContainer" parent="MC/ViewManager/VSC/VB/NotificationsLayer/NotificationsView"]
custom_minimum_size = Vector2(350, 0)
layout_mode = 2
mouse_filter = 2

[node name="PC" type="PanelContainer" parent="MC/ViewManager/VSC/VB/NotificationsLayer/NotificationsView/SC"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 10
mouse_filter = 2
theme_override_styles/panel = SubResource("5")

[node name="MC" type="MarginContainer" parent="MC/ViewManager/VSC/VB/NotificationsLayer/NotificationsView/SC/PC"]
layout_mode = 2
mouse_filter = 2
theme_override_constants/margin_left = 4
theme_override_constants/margin_top = 8
theme_override_constants/margin_right = 4
theme_override_constants/margin_bottom = 8

[node name="VB" type="VBoxContainer" parent="MC/ViewManager/VSC/VB/NotificationsLayer/NotificationsView/SC/PC/MC"]
layout_mode = 2
mouse_filter = 2
theme_override_constants/separation = 8

[node name="LogsView" parent="MC/ViewManager/VSC" instance=ExtResource("4")]
layout_mode = 2

[node name="Test" type="Node" parent="."]
script = ExtResource("16_4rltv")

[node name="ManualAudioOutput" type="Node" parent="Test"]
script = ExtResource("17_bg4s2")

[node name="Network" type="Node2D" parent="."]
script = ExtResource("17_ailes")

[node name="Game" type="Node2D" parent="Network"]

[node name="NetworkSpawn" type="Node2D" parent="Network/Game"]

[node name="MapSpawner" type="MultiplayerSpawner" parent="Network/Game"]
_spawnable_scenes = PackedStringArray("uid://d25abb5oqolnx", "uid://cq20ci5f675b8", "uid://cutu8g5suwurd")
spawn_path = NodePath("../NetworkSpawn")

[node name="PlayerSpawner" type="MultiplayerSpawner" parent="Network/Game"]
_spawnable_scenes = PackedStringArray("uid://d25l4fa1sffqk")
spawn_path = NodePath("../NetworkSpawn")

[node name="CanvasLayer" type="CanvasLayer" parent="Network/Game"]
visible = false

[node name="NatType" parent="Network/Game/CanvasLayer" instance=ExtResource("18_vylep")]
offset_left = -196.0
text = "NAT TYPE: Moderate"

[node name="Ping" parent="Network/Game/CanvasLayer" instance=ExtResource("19_enhih")]
anchors_preset = 3
anchor_left = 1.0
anchor_top = 1.0
anchor_right = 1.0
anchor_bottom = 1.0
offset_left = -305.0
offset_top = -30.0
offset_right = -213.0
offset_bottom = -7.0
grow_horizontal = 0
grow_vertical = 0

[node name="PlayersScore" parent="Network/Game/CanvasLayer" instance=ExtResource("20_i3cca")]

[node name="Joysticks" type="Control" parent="Network/Game/CanvasLayer"]
visible = false
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
script = ExtResource("21_einjf")

[node name="MoveJoystick" type="Control" parent="Network/Game/CanvasLayer/Joysticks"]
anchors_preset = 0
offset_left = 181.0
offset_top = 390.0
offset_right = 221.0
offset_bottom = 430.0
pivot_offset = Vector2(20, 20)
script = ExtResource("21_5h21x")
knob_color = Color(0.560955, 0.560955, 0.560955, 1)
base_color = Color(0.560784, 0.560784, 0.560784, 1)
anti_aliased = true
mode = 1
use_input_actions = true
action_left = "move_left"
action_right = "move_right"
action_up = "move_up"
action_down = "move_down"

[node name="ShootJoystick" type="Control" parent="Network/Game/CanvasLayer/Joysticks"]
anchors_preset = 0
offset_left = 938.0
offset_top = 401.0
offset_right = 978.0
offset_bottom = 441.0
pivot_offset = Vector2(20, 20)
script = ExtResource("21_5h21x")
knob_color = Color(0.560784, 0.560784, 0.560784, 1)
base_color = Color(0.560784, 0.560784, 0.560784, 1)
anti_aliased = true
mode = 1


================================================
FILE: sample/addons/epic-online-services-godot/base_class.gd
================================================
## Copyright (c) 2022-present Delano Lourenco
## https://github.com/3ddelano/dataclasses-godot
## MIT License
## See License.md

class_name BaseClass extends Dataclass

func _init(p_name: String, p_options: Dictionary = {}):
	p_options["print_newline"] = true
	p_options["print_exclude"] = ["base_class.gd", "_log"]
	super._init(p_name, p_options)


================================================
FILE: sample/addons/epic-online-services-godot/base_class.gd.uid
================================================
uid://g1ij604ak57v


================================================
FILE: sample/addons/epic-online-services-godot/bin/.gitignore
================================================
*
!.gitignore

================================================
FILE: sample/addons/epic-online-services-godot/dataclass.gd
================================================
## Copyright (c) 2022-present Delano Lourenco
## https://github.com/3ddelano/dataclasses-godot
## MIT License
## See License.md

class_name Dataclass extends RefCounted

const __DEFAULT_OPTIONS__ = {
	# Whether to sort properties when printing
	"sort_keys": true,

	# Whether to include properties with null values in the to_dict() method
	"include_null_in_dict": true,

	# Whether to include properties with null values when printing
	"include_null_in_print": true,

	# Whether to print properties on newlines when printing
	"print_newline": false,

	# Names of properties to exclude when printing
	"print_exclude": []
}

const __TYPE_STRING_CAPITAL = ["TYPE_NIL", "TYPE_BOOL", "TYPE_INT", "TYPE_FLOAT", "TYPE_STRING", "TYPE_VECTOR2", "TYPE_VECTOR2I", "TYPE_RECT2", "TYPE_RECT2I", "TYPE_VECTOR3", "TYPE_VECTOR3I", "TYPE_TRANSFORM2D", "TYPE_VECTOR4", "TYPE_VECTOR4I", "TYPE_PLANE", "TYPE_QUATERNION", "TYPE_AABB", "TYPE_BASIS", "TYPE_TRANSFORM3D", "TYPE_PROJECTION", "TYPE_COLOR", "TYPE_STRING_NAME", "TYPE_NODE_PATH", "TYPE_RID", "TYPE_OBJECT", "TYPE_CALLABLE", "TYPE_SIGNAL", "TYPE_DICTIONARY", "TYPE_ARRAY", "TYPE_PACKED_BYTE_ARRAY", "TYPE_PACKED_INT32_ARRAY", "TYPE_PACKED_INT64_ARRAY", "TYPE_PACKED_FLOAT32_ARRAY", "TYPE_PACKED_FLOAT64_ARRAY", "TYPE_PACKED_STRING_ARRAY", "TYPE_PACKED_VECTOR2_ARRAY", "TYPE_PACKED_VECTOR3_ARRAY", "TYPE_PACKED_COLOR_ARRAY", "TYPE_MAX"]

const __TYPE_STRING_NORMAL = ["Nil", "Bool", "Int", "Float", "String", "Vector2", "Vector2i", "Rect2", "Rect2i", "Vector3", "Vector3i", "Transform2D", "Vector4", "Vector4i", "Plane", "Quaternion", "AABB", "Basis", "Transform3D", "Projection", "Color", "StringName", "NodePath", "Rid", "Object", "Callable", "Signal", "Dictionary", "Array", "PackedByteArray", "PackedInt32Array", "PackedInt64Array", "PackedFloat32Array", "PackedFloat64Array", "PackedStringArray", "PackedVector2Array", "PackedVector3Array", "PackedColorArray", "Max"]


func from_dict(p_dict: Dictionary):
	for key in p_dict:
		if not key in self:
			printerr("Dataclass:from_dict: Error: Key \"%s\" not found in dataclass \"%s\"" % [key, __name__])
			continue

		# Check for types match
		var typeof_expected = typeof(get(key))
		var typeof_received = typeof(p_dict[key])
		if typeof_expected != TYPE_NIL and typeof_received != typeof_expected and (
			(not typeof_expected in [TYPE_INT, TYPE_FLOAT]) and
			(not typeof_received in [TYPE_INT, TYPE_FLOAT])
		):
			printerr("Dataclass:from_dict: Warning: Key \"%s\" has type %s but expected type %s in dataclass \"%s\"" % [key, __type_to_string(typeof_received), __type_to_string(typeof_expected), __name__])
		set(key, p_dict[key])

	return self


func to_dict() -> Dictionary:
	var ret = {}
	var all_props = __get_props()
	for prop in all_props:
		var value = get(prop.name)
		if value != null or __options__.include_null_in_dict:
			ret[prop.name] = value

	return ret



var __name__: String
var __options__: Dictionary


func _init(p_name: String, p_options: Dictionary = {}):
	__name__ = p_name
	__options__ = __DEFAULT_OPTIONS__.duplicate()
	set_meta("is_dataclass", true)

	# Override options
	for key in p_options:
		__options__[key] = p_options[key]


func get_class() -> String:
	return __name__


func __get_props() -> Array:
	var all_props = get_property_list()
	all_props = all_props.slice(3, all_props.size() - 4)

	if __options__.sort_keys:
		all_props.sort_custom(func sort_ascending(a, b):
			return a.name < b.name)

	return all_props


func __type_to_string(p_type: int, p_capital = true) -> String:
	if p_capital:
		return __TYPE_STRING_CAPITAL[p_type]

	return __TYPE_STRING_NORMAL[p_type]


func __variant_to_string(value, indent_level = 0, visited_objects = []) -> String:
	var type = typeof(value)

	var newline = ""
	var tab = ""
	var dict_join = ", "
	if __options__.print_newline:
		tab = "\t"
		newline = "\n"
		dict_join = ",\n"

	match type:
		TYPE_STRING:
			return "\"" + value.c_escape() + "\""
		TYPE_NIL, TYPE_INT, TYPE_FLOAT, TYPE_BOOL:
			return str(value)
		TYPE_QUATERNION, TYPE_VECTOR2, TYPE_RECT2, TYPE_VECTOR3, TYPE_TRANSFORM2D, TYPE_BASIS:
			return "%s%s" % [__type_to_string(type, false), value]
		TYPE_RID:
			return "RID(%s)" % value.get_id()
		TYPE_OBJECT:
			if value == null:
				return "Object(null)"
			elif (not value is Script) and value.has_meta("is_dataclass") and value.get_meta("is_dataclass"):
				# Check for circular reference to prevent infinite recursion
				if value in visited_objects:
					return "%s(<circular reference>)" % value.__name__

				# Create new visited_objects array with current object added
				visited_objects.append(value)
				
				# Manually construct the string representation to avoid calling _to_string()
				var all_props = value.__get_props()
				var props = PackedStringArray()
				
				for prop in all_props:
					if prop.name in value.__options__.print_exclude:
						continue
					var prop_value = value.get(prop.name)
					var prop_type = typeof(prop_value)
					if prop_value != null or value.__options__.include_null_in_print:
						props.append("%s = %s" % [prop.name, __variant_to_string(prop_value, indent_level + 1, visited_objects)])

				var separator = ", "
				var prop_newline = ""
				var prop_newline_end = ""
				if value.__options__.print_newline:
					prop_newline = "\n\t"
					prop_newline_end = "\n"
				
				var result = value.__name__ + "(" + prop_newline + (separator + prop_newline).join(props) + prop_newline_end + ")"
				return result.indent(tab.repeat(indent_level)).trim_prefix(tab.repeat(indent_level))

			return str(value)
		TYPE_DICTIONARY:
			var keys = value.keys()
			if keys.size() == 0: return "{}"
			var dict_string = PackedStringArray()
			for key in keys:
				dict_string.append("%s: %s" % [key, __variant_to_string(value[key], 0, visited_objects)])

			dict_string = "{" + newline + dict_join.join(dict_string).indent(tab) + newline + "}"

			return dict_string.indent(tab.repeat(indent_level)).trim_prefix(tab.repeat(indent_level))
		TYPE_ARRAY, TYPE_PACKED_BYTE_ARRAY, TYPE_PACKED_INT32_ARRAY, TYPE_PACKED_INT64_ARRAY, TYPE_PACKED_FLOAT32_ARRAY, TYPE_PACKED_FLOAT64_ARRAY, TYPE_PACKED_STRING_ARRAY, TYPE_PACKED_VECTOR2_ARRAY, TYPE_PACKED_VECTOR3_ARRAY, TYPE_PACKED_COLOR_ARRAY:
			var ret = PackedStringArray()
			for elm in value:
				ret.append(__variant_to_string(elm, 1, visited_objects))
			ret = "[" + ", ".join(ret) + "]"
			if type == TYPE_ARRAY: return ret

			return __type_to_string(type, false) + "(" + ret + ")"
		TYPE_COLOR:
			return "%s%s" % [__type_to_string(type, false), value]
		_:
			return "%s(%s)" % [__type_to_string(type, false), value]


func _to_string() -> String:
	var all_props = __get_props()

	var props = PackedStringArray()
	for prop in all_props:
		if prop.name in __options__.print_exclude:
			continue
		var value = get(prop.name)
		var type = typeof(value)
		if value != null or __options__.include_null_in_print:
			props.append("%s = %s" % [prop.name, __variant_to_string(value, 1, [self])])

	var separator = ", "
	var newline = ""
	var newline_end = ""
	if __options__.print_newline:
		newline = "\n\t"
		newline_end = "\n"
	return __name__ + "(" + newline + (separator + newline).join(props) + newline_end + ")"


================================================
FILE: sample/addons/epic-online-services-godot/dataclass.gd.uid
================================================
uid://d4hmupfn3ooqp


================================================
FILE: sample/addons/epic-online-services-godot/eos.gd
================================================
# Copyright (c) 2023-present Delano Lourenco
# https://github.com/3ddelano/epic-online-services-godot/
# MIT License

## The main class to interact with Epic Online Services
class_name EOS
extends RefCounted

static func get_instance():
	return IEOS


## Pretty prints the [enum Result] code and its string representation.[br]
## [code]p_result[/code] is a [enum Result] or a [Dictionary] with a [code]result_code[/code] key
static func print_result(p_result) -> void:
	print_rich("[b]EOS_Result[/b]:%s[code](%s)[/code]" % [result_str(p_result), p_result])


## Returns a string representation of the [enum Result] code.[br]
## [code]p_result[/code] is a [enum Result] or a [Dictionary] with a [code]result_code[/code] key
static func result_str(p_result) -> String:
	if typeof(p_result) == TYPE_DICTIONARY:
		p_result = p_result["result_code"]
	var idx := Result.values().find(p_result)
	return Result.keys()[idx]


## Returns whether the operation was completed.[br]
## [code]p_result[/code] is a [enum Result] or a [Dictionary] with a [code]result_code[/code] key
static func is_operation_complete(p_result) -> bool:
	if typeof(p_result) == TYPE_DICTIONARY:
		p_result = p_result["result_code"]
	return IEOS.is_operation_complete(p_result)


## Returns whether the operation was successful.[br]
## [code]p_result[/code] is a [enum Result] or a [Dictionary] with a [code]result_code[/code] key
static func is_success(p_result) -> bool:
	if typeof(p_result) == TYPE_BOOL:
		return p_result == true
	if typeof(p_result) == TYPE_DICTIONARY:
		p_result = p_result["result_code"]
	return p_result == Result.Success


class Achievements:
	const UNLOCK_TIME_UNDEFINED = -1

	class CopyAchievementDefinitionV2ByAchievementIdOptions extends BaseClass:
		func _init():
			super._init("CopyAchievementDefinitionV2ByAchievementIdOptions")

		var achievement_id: String

	class CopyAchievementDefinitionV2ByIndexOptions extends BaseClass:
		func _init():
			super._init("CopyAchievementDefinitionV2ByIndexOptions")

		var achievement_index: int

	class CopyPlayerAchievementByAchievementIdOptions extends BaseClass:
		func _init():
			super._init("CopyPlayerAchievementByAchievementIdOptions")

		var achievement_id: String
		var local_user_id = EOSGRuntime.local_product_user_id
		var target_user_id = EOSGRuntime.local_product_user_id

	class CopyPlayerAchievementByIndexOptions extends BaseClass:
		func _init():
			super._init("CopyPlayerAchievementByIndexOptions")

		var achievement_index: int
		var local_user_id = EOSGRuntime.local_product_user_id
		var target_user_id: String

	class GetAchievementDefinitionCountOptions extends BaseClass:
		func _init():
			super._init("GetAchievementDefinitionCountOptions")

	class QueryDefinitionsOptions extends BaseClass:
		func _init():
			super._init("QueryDefinitionsOptions")

		var local_user_id = EOSGRuntime.local_product_user_id

		var client_data = null

	class GetPlayerAchievementCountOptions extends BaseClass:
		func _init():
			super._init("GetPlayerAchievementCountOptions")

		var user_id: String

	class QueryPlayerAchievementsOptions extends BaseClass:
		func _init():
			super._init("QueryPlayerAchievementsOptions")

		var local_user_id = EOSGRuntime.local_product_user_id
		var target_user_id = EOSGRuntime.local_product_user_id

		var client_data = null

	class UnlockAchievementsOptions extends BaseClass:
		func _init():
			super._init("UnlockAchievementsOptions")

		var user_id: String
		var achievement_ids: Array # Array[String]
		var client_data = null

	class AchievementsInterface:
		static func query_definitions(options: QueryDefinitionsOptions) -> void:
			IEOS.achievements_interface_query_definitions(options)

		static func get_achievement_definition_count(options: GetAchievementDefinitionCountOptions) -> int:
			return IEOS.achievements_interface_get_achievement_definition_count(options)

		static func copy_achievement_definition_v2_by_achievement_id(
			options: CopyAchievementDefinitionV2ByAchievementIdOptions
		) -> Dictionary:
			return IEOS.achievements_interface_copy_achievement_definition_v2_by_achievement_id(
				options
			)

		static func copy_achievement_definition_v2_by_index(
			options: CopyAchievementDefinitionV2ByIndexOptions
		) -> Dictionary:
			return IEOS.achievements_interface_copy_achievement_definition_v2_by_index(options)

		static func query_player_achievements(options: QueryPlayerAchievementsOptions) -> void:
			IEOS.achievements_interface_query_player_achievements(options)

		static func get_player_achievement_count(options: GetPlayerAchievementCountOptions) -> int:
			return IEOS.achievements_interface_get_player_achievement_count(options)

		static func copy_player_achievement_by_achievement_id(
			options: CopyPlayerAchievementByAchievementIdOptions
		) -> Dictionary:
			return IEOS.achievements_interface_copy_player_achievement_by_achievement_id(options)

		static func copy_player_achievement_by_index(options: CopyPlayerAchievementByIndexOptions) -> Dictionary:
			return IEOS.achievements_interface_copy_player_achievement_by_index(options)

		static func unlock_achievements(options: UnlockAchievementsOptions) -> void:
			IEOS.achievements_interface_unlock_achievements(options)



class Connect:
	const CONNECT_TIME_UNDEFINED = -1
	
	class Credentials extends BaseClass:
		func _init():
			super._init("Credentials")

		var type: ExternalCredentialType = -1
		var token = null

	class UserLoginInfo extends BaseClass:
		func _init():
			super._init("UserLoginInfo")

		var display_name: String
		var nsa_id_token: String

	class LoginOptions extends BaseClass:
		func _init():
			super._init("LoginOptions")

		var credentials: Credentials
		var user_login_info: UserLoginInfo

		var client_data = null

	class LogoutOptions extends BaseClass:
		func _init():
			super._init("LogoutOptions")

		var local_user_id = EOSGRuntime.local_product_user_id

		var client_data = null

	class CopyIdTokenOptions extends BaseClass:
		func _init():
			super._init("CopyIdTokenOptions")

		var local_user_id = EOSGRuntime.local_product_user_id

	class CopyProductUserExternalAccountByAccountIdOptions extends BaseClass:
		func _init():
			super._init("CopyProductUserExternalAccountByAccountIdOptions")

		var target_user_id = EOSGRuntime.local_product_user_id
		var account_id: String

	class CopyProductUserExternalAccountByAccountTypeOptions extends BaseClass:
		func _init():
			super._init("CopyProductUserExternalAccountByAccountTypeOptions")

		var target_user_id = EOSGRuntime.local_product_user_id
		var account_id_type: ExternalAccountType

	class CopyProductUserExternalAccountByIndexOptions extends BaseClass:
		func _init():
			super._init("CopyProductUserExternalAccountByIndexOptions")

		var target_user_id = EOSGRuntime.local_product_user_id
		var external_account_info_index: int

	class CopyProductUserInfoOptions extends BaseClass:
		func _init():
			super._init("CopyProductUserInfoOptions")

		var target_user_id = EOSGRuntime.local_product_user_id

	class CreateDeviceIdOptions extends BaseClass:
		func _init():
			super._init("CreateDeviceIdOptions")

		var device_model: String

		var client_data = null

	class DeleteDeviceIdOptions extends BaseClass:
		func _init():
			super._init("DeleteDeviceIdOptions")

		var client_data = null

	class CreateUserOptions extends BaseClass:
		func _init():
			super._init("CreateUserOptions")

		var continuance_token: EOSGContinuanceToken

		var client_data = null

	class QueryExternalAccountMappingsOptions extends BaseClass:
		func _init():
			super._init("QueryExternalAccountMappingsOptions")

		var local_user_id = EOSGRuntime.local_product_user_id
		var account_id_type: ExternalAccountType
		var external_account_ids: Array # Array[String]

	class GetExternalAccountMappingsOptions extends BaseClass:
		func _init():
			super._init("GetExternalAccountMappingsOptions")

		var account_id_type: ExternalAccountType
		var local_user_id = EOSGRuntime.local_product_user_id
		var target_external_user_id: String

	class GetProductUserExternalAccountCountOptions extends BaseClass:
		func _init():
			super._init("GetProductUserExternalAccountCountOptions")

		var target_user_id = EOSGRuntime.local_product_user_id

	class QueryProductUserIdMappingsOptions extends BaseClass:
		func _init():
			super._init("QueryProductUserIdMappingsOptions")

		var local_user_id = EOSGRuntime.local_product_user_id
		var product_user_ids: Array # Array[String]

	class GetProductUserIdMappingOptions extends BaseClass:
		func _init():
			super._init("GetProductUserIdMappingOptions")

		var account_id_type: ExternalAccountType
		var local_user_id = EOSGRuntime.local_product_user_id
		var target_product_user_id = EOSGRuntime.local_product_user_id

	class LinkAccountOptions extends BaseClass:
		func _init():
			super._init("LinkAccountOptions")

		var continuance_token = null # ContinuanceTokenWrapper
		var local_user_id = EOSGRuntime.local_product_user_id

		var client_data = null

	class IdToken extends BaseClass:
		func _init():
			super._init("IdToken")

		var product_user_id: String
		var json_web_token: String

	class VerifyIdTokenOptions extends BaseClass:
		func _init():
			super._init("VerifyIdTokenOptions")

		var id_token: IdToken

		var client_data = null

	class TransferDeviceIdAccountOptions extends BaseClass:
		func _init():
			super._init("TransferDeviceIdAccountOptions")

		var primary_local_user_id = EOSGRuntime.local_product_user_id
		var local_device_user_id = EOSGRuntime.local_product_user_id
		var product_user_id_to_preserve: String

		var client_data = null

	class UnlinkAccountOptions extends BaseClass:
		func _init():
			super._init("UnlinkAccountOptions")

		var local_user_id = EOSGRuntime.local_product_user_id

		var client_data = null

	class ConnectInterface:
		static func login(options: LoginOptions) -> void:
			IEOS.connect_interface_login(options)

		static func logout(options: LogoutOptions) -> void:
			IEOS.connect_interface_logout(options)

		static func copy_id_token(options: CopyIdTokenOptions) -> Dictionary:
			return IEOS.connect_interface_copy_id_token(options)

		static func copy_product_user_external_account_by_account_id(options: CopyProductUserExternalAccountByAccountIdOptions) -> Dictionary:
			return IEOS.connect_interface_copy_product_user_external_account_by_account_id(options)

		static func copy_product_user_external_account_by_account_type(options: CopyProductUserExternalAccountByAccountTypeOptions) -> Dictionary:
			return IEOS.connect_interface_copy_product_user_external_account_by_account_type(options)

		static func copy_product_user_external_account_by_index(options: CopyProductUserExternalAccountByIndexOptions) -> Dictionary:
			return IEOS.connect_interface_copy_product_user_external_account_by_index(options)

		static func copy_product_user_info(options: CopyProductUserInfoOptions) -> Dictionary:
			return IEOS.connect_interface_copy_product_user_info(options)

		static func create_device_id(options: CreateDeviceIdOptions) -> void:
			IEOS.connect_interface_create_device_id(options)

		static func create_user(options: CreateUserOptions) -> void:
			IEOS.connect_interface_create_user(options)

		static func delete_device_id(options: DeleteDeviceIdOptions) -> void:
			IEOS.connect_interface_delete_device_id(options)

		static func query_external_account_mappings(options: QueryExternalAccountMappingsOptions) -> void:
			IEOS.connect_interface_query_external_account_mappings(options)

		static func get_external_account_mapping(options: GetExternalAccountMappingsOptions) -> String:
			return IEOS.connect_interface_get_external_account_mapping(options)

		static func get_logged_in_user_by_index(index: int) -> String:
			return IEOS.connect_interface_get_logged_in_user_by_index(index)

		static func get_logged_in_users_count() -> int:
			return IEOS.connect_interface_get_logged_in_users_count()

		static func get_login_status(local_user_id := EOSGRuntime.local_product_user_id) -> LoginStatus:
			return IEOS.connect_interface_get_login_status(local_user_id)

		static func get_product_user_external_account_count(options: GetProductUserExternalAccountCountOptions = GetProductUserExternalAccountCountOptions.new()) -> int:
			return IEOS.connect_interface_get_product_user_external_account_count(options)

		static func query_product_user_id_mappings(options: QueryProductUserIdMappingsOptions) -> void:
			IEOS.connect_interface_query_product_user_id_mappings(options)

		static func get_product_user_id_mapping(options: GetProductUserIdMappingOptions) -> Dictionary:
			return IEOS.connect_interface_get_product_user_id_mapping(options)

		static func link_account(options: LinkAccountOptions) -> void:
			IEOS.connect_interface_link_account(options)

		static func verify_id_token(options: VerifyIdTokenOptions) -> void:
			IEOS.connect_interface_verify_id_token(options)

		static func transfer_device_id_account(options: TransferDeviceIdAccountOptions) -> void:
			IEOS.connect_interface_transfer_device_id_account(options)

		static func unlink_account(options: UnlinkAccountOptions) -> void:
			IEOS.connect_interface_unlink_account(options)



class Auth:
	enum ScopeFlags {
		NoFlags = 0x0,
		BasicProfile = 0x1,
		FriendsList = 0x2,
		Presence = 0x4,
		FriendsManagement = 0x8,
		Email = 0x10,
		Country = 0x20,
	}

	enum AuthTokenType {Client = 0, User = 1}

	enum LinkAccountFlags {NoFlags = 0x0, NintendoNsaId = 0x1}

	enum LoginCredentialType {
		None = -1,
		Password = 0,
		ExchangeCode = 1,
		PersistentAuth = 2,
		DeviceCode = 3,
		Developer = 4,
		RefreshToken = 5,
		AccountPortal = 6,
		ExternalAuth = 7
	}

	enum LoginFlags {
		None = 0,
		NoUserInterface = 1
	}

	class Credentials extends BaseClass:
		func _init():
			super._init("Credentials")

		var external_type: ExternalCredentialType = -1
		var id: String
		var token: String
		var type: LoginCredentialType = -1

	class LoginOptions extends BaseClass:
		func _init():
			super._init("LoginOptions")

		var credentials: Credentials
		var login_flags: LoginFlags = LoginFlags.None
		var scope_flags: ScopeFlags = ScopeFlags.NoFlags

		var client_data = null

	class LogoutOptions extends BaseClass:
		func _init():
			super._init("LogoutOptions")

		var local_user_id = EOSGRuntime.local_epic_account_id

		var client_data = null

	class CopyIdTokenOptions extends BaseClass:
		func _init():
			super._init("CopyIdTokenOptions")

		var account_id = EOSGRuntime.local_epic_account_id

	class CopyUserAuthTokenOptions extends BaseClass:
		func _init():
			super._init("CopyUserAuthTokenOptions")

	class DeletePersistentAuthOptions extends BaseClass:
		func _init():
			super._init("DeletePersistentAuthOptions")

		var refresh_token = null

		var client_data = null

	class LinkAccountOptions extends BaseClass:
		func _init():
			super._init("LinkAccountOptions")

		var continuance_token: EOSGContinuanceToken
		var link_account_flags: LinkAccountFlags = LinkAccountFlags.NoFlags
		var local_user_id = EOSGRuntime.local_epic_account_id

		var client_data = null

	class QueryIdTokenOptions extends BaseClass:
		func _init():
			super._init("QueryIdTokenOptions")

		var local_user_id = EOSGRuntime.local_epic_account_id
		var target_account_id = EOSGRuntime.local_epic_account_id

		var client_data = null

	class IdToken extends BaseClass:
		func _init():
			super._init("IdToken")

		var account_id: String
		var json_web_token: String

	class VerifyIdTokenOptions extends BaseClass:
		func _init():
			super._init("VerifyIdTokenOptions")

		var id_token: IdToken

		var client_data = null

	class Token extends BaseClass:
		func _init():
			super._init("Token")

		var access_token: String
		var account_id: String
		var app: String
		var auth_type: int
		var client_id: String
		var expires_at: String
		var expires_in: float
		var refresh_expires_at: String
		var refresh_expires_in: float
		var refresh_token: String

	class VerifyUserAuthOptions extends BaseClass:
		func _init():
			super._init("VerifyUserAuthOptions")

		var auth_token: Token

		var client_data = null

	class AuthInterface:
		static func login(options: LoginOptions) -> void:
			IEOS.auth_interface_login(options)

		static func logout(options: LogoutOptions) -> void:
			IEOS.auth_interface_logout(options)

		static func copy_id_token(options: CopyIdTokenOptions) -> Dictionary:
			return IEOS.auth_interface_copy_id_token(options)

		static func copy_user_auth_token(options: CopyUserAuthTokenOptions, local_user_id := EOSGRuntime.local_epic_account_id) -> Dictionary:
			var func_result: Dictionary = IEOS.auth_interface_copy_user_auth_token(
				options, local_user_id
			)
			var token: Token = Token.new()
			if func_result.token:
				var token_dict = func_result.token
				token.access_token = token_dict.access_token
				token.account_id = token_dict.account_id
				token.app = token_dict.app
				token.auth_type = token_dict.auth_type
				token.client_id = token_dict.client_id
				token.expires_at = token_dict.expires_at
				token.expires_in = token_dict.expires_in
				token.refresh_expires_at = token_dict.refresh_expires_at
				token.refresh_expires_in = token_dict.refresh_expires_in
				token.refresh_token = token_dict.refresh_token

			return {result_code = func_result.result_code, token = token}

		static func delete_persistent_auth(options: DeletePersistentAuthOptions) -> void:
			IEOS.auth_interface_delete_persistent_auth(options)

		static func get_logged_in_account_by_index(index: int) -> String:
			return IEOS.auth_interface_get_logged_in_account_by_index(index)

		static func get_logged_in_accounts_count() -> int:
			return IEOS.auth_interface_get_logged_in_accounts_count()

		static func get_login_status(local_user_id := EOSGRuntime.local_epic_account_id) -> LoginStatus:
			return IEOS.auth_interface_get_login_status(local_user_id)

		static func get_merged_account_by_index(local_user_id: String, index: int) -> String:
			return IEOS.auth_interface_get_merged_account_by_index(local_user_id, index)

		static func get_merged_accounts_count(local_user_id := EOSGRuntime.local_epic_account_id) -> int:
			return IEOS.auth_interface_get_merged_accounts_count(local_user_id)

		static func get_selected_account_id(local_user_id := EOSGRuntime.local_epic_account_id) -> Dictionary:
			return IEOS.auth_interface_get_selected_account_id(local_user_id)

		static func link_account(options: LinkAccountOptions) -> void:
			IEOS.auth_interface_link_account(options)

		static func query_id_token(options: QueryIdTokenOptions) -> void:
			IEOS.auth_interface_query_id_token(options)

		static func verify_id_token(options: VerifyIdTokenOptions) -> void:
			IEOS.auth_interface_verify_id_token(options)

		static func verify_user_auth(options: VerifyUserAuthOptions) -> void:
			IEOS.auth_interface_verify_user_auth(options)



class CustomInvites:
	enum ResquestToJoinResponse {
		Accepted = 0,
		Rejected = 1,
	}

	class SetCustomInviteOptions extends BaseClass:
		func _init():
			super._init("SetCustomInviteOptions")

		var local_user_id = EOSGRuntime.local_product_user_id
		var payload: String

	class SendCustomInviteOptions extends BaseClass:
		func _init():
			super._init("SendCustomInviteOptions")

		var local_user_id = EOSGRuntime.local_product_user_id
		var target_user_ids: Array # Array[String]

		var client_data = null

	class FinalizeInviteOptions extends BaseClass:
		func _init():
			super._init("FinalizeInviteOptions")

		var custom_invite_id: String
		var local_user_id = EOSGRuntime.local_product_user_id
		var processing_result: Result
		var target_user_id: String

	class SendRequestToJoinOptions extends BaseClass:
		func _init():
			super._init("SendRequestToJoinOptions")

		var local_user_id = EOSGRuntime.local_product_user_id
		var target_user_id: String

		var client_data = null

	class AcceptRequestToJoinOptions extends BaseClass:
		func _init():
			super._init("AcceptRequestToJoinOptions")

		var local_user_id = EOSGRuntime.local_product_user_id
		var target_user_id: String

		var client_data = null

	class RejectRequestToJoinOptions extends BaseClass:
		func _init():
			super._init("RejectRequestToJoinOptions")

		var local_user_id = EOSGRuntime.local_product_user_id
		var target_user_id: String

		var client_data = null

	class CustomInvitesInterface:
		static func set_custom_invite(options: SetCustomInviteOptions) -> Result:
			return IEOS.custom_invites_interface_set_custom_invite(options)

		static func send_custom_invite(options: SendCustomInviteOptions) -> void:
			IEOS.custom_invites_interface_send_custom_invite(options)

		static func finalize_invite(options: FinalizeInviteOptions) -> Result:
			return IEOS.custom_invites_interface_finalize_invite(options)

		static func send_request_to_join(options: SendRequestToJoinOptions) -> void:
			IEOS.custom_invites_interface_send_request_to_join(options)

		static func accept_request_to_join(options: SendRequestToJoinOptions) -> void:
			IEOS.custom_invites_interface_accept_request_to_join(options)

		static func reject_request_to_join(options: SendRequestToJoinOptions) -> void:
			IEOS.custom_invites_interface_reject_request_to_join(options)



class Stats:
	const STATS_TIME_UNDEFINED = -1

	class CopyStatByIndexOptions extends BaseClass:
		func _init():
			super._init("CopyStatByIndexOptions")

		var target_user_id = EOSGRuntime.local_product_user_id
		var stat_index: int

	class CopyStatByNameOptions extends BaseClass:
		func _init():
			super._init("CopyStatByNameOptions")

		var target_user_id = EOSGRuntime.local_product_user_id
		var name: String

	class GetStatsCountOptions extends BaseClass:
		func _init():
			super._init("GetStatsCountOptions")

		var target_user_id = EOSGRuntime.local_product_user_id

	class IngestStatOptions extends BaseClass:
		func _init():
			super._init("IngestStatOptions")

		var local_user_id = EOSGRuntime.local_product_user_id
		var stats: Array # Array[Dictionary] {stat_name: String, ingest_amount: int}
		var target_user_id = EOSGRuntime.local_product_user_id

		var client_data = null

	class QueryStatsOptions extends BaseClass:
		func _init():
			super._init("QueryStatsOptions")

		var local_user_id = EOSGRuntime.local_product_user_id
		var target_user_id = EOSGRuntime.local_product_user_id
		var stat_names: Array # Array[String]
		var start_time = STATS_TIME_UNDEFINED
		var end_time = STATS_TIME_UNDEFINED

		var client_data = null

	class StatsInterface:
		static func copy_stat_by_index(options: CopyStatByIndexOptions) -> Dictionary:
			return IEOS.stats_interface_copy_stat_by_index(options)

		static func copy_stat_by_name(options: CopyStatByNameOptions) -> Dictionary:
			return IEOS.stats_interface_copy_stat_by_name(options)

		static func get_stats_count(options: GetStatsCountOptions) -> int:
			return IEOS.stats_interface_get_stats_count(options)

		static func ingest_stat(options: IngestStatOptions) -> void:
			IEOS.stats_interface_ingest_stat(options)

		static func query_stats(options: QueryStatsOptions) -> void:
			IEOS.stats_interface_query_stats(options)



class Platform:
	enum PlatformFlags {
		None = 0x0,
		LoadingInEditor = 0x00001,
		DisableOverlay = 0x00002,
		DisableSocialOverlay = 0x00004,
		Reserved1 = 0x00008,
		WindowsEnableOverlayD3D9 = 0x00010,
		WindowsEnableOverlayD3D10 = 0x00020,
		WindowsEnableOverlayOpengl = 0x00040,
		ConsoleEnableOverlayAutomaticUnloading = 0x00080,
	}

	enum ApplicationStatus {
		BackgroundConstrained = 0,
		BackgroundUnconstrained = 1,
		BackgroundSuspended = 2,
		Foreground = 3
	}

	enum NetworkStatus {
		Disabled = 0,
		Offline = 1,
		Online = 2
	}

	enum DesktopCrossplayStatus {
		OK = 0,
		ApplicationNotBootstrapped = 1,
		ServiceNotInstalled = 2,
		ServiceStartFailed = 3,
		ServiceNotRunning = 4,
		OverlayDisabled = 5,
		OverlayNotInstalled = 6,
		OverlayTrustCheckFailed = 7,
		OverlayLoadFailed = 8
	}

	enum RTCBackgroundMode {
		LeaveRooms = 0,
		KeepRoomsAlive = 1,
	}

	class InitializeOptions extends BaseClass:
		func _init():
			super._init("InitializeOptions")

		var product_name: String
		var product_version: String

	class RTCOptions extends BaseClass:
		func _init():
			super._init("RTCOptions")

		var background_mode = null ## See [enum EOS.Platform.RTCBackgroundMode]

	class CreateOptions extends BaseClass:
		func _init():
			super._init("CreateOptions")

		var client_id: String
		var client_secret: String
		var deployment_id: String
		var encryption_key: String
		var product_id: String
		var sandbox_id: String

		var cache_directory = ProjectSettings.globalize_path("user://eosg-cache")
		var flags: int = 0 ## See [enum EOS.Platform.PlatformFlags]
		var is_server: bool
		var override_country_code: String
		var override_locale_code: String
		var tick_budget_in_milliseconds: int
		var task_network_timeout_seconds = null # float

		var rtc_options := RTCOptions.new()

	class PlatformInterface:
		static func create(options: CreateOptions) -> bool:
			return IEOS.platform_interface_create(options)

		static func get_active_country_code(user_id: String) -> Dictionary:
			return IEOS.platform_interface_get_active_country_code(user_id)

		static func get_active_locale_code(user_id: String) -> Dictionary:
			return IEOS.platform_interface_get_active_locale_code(user_id)

		static func get_override_country_code() -> Dictionary:
			return IEOS.platform_interface_get_override_country_code()

		static func get_override_locale_code() -> Dictionary:
			return IEOS.platform_interface_get_override_locale_code()

		static func set_override_country_code(country_code: String) -> Result:
			return IEOS.platform_interface_set_override_country_code(country_code)

		static func set_override_locale_code(locale_code: String) -> Result:
			return IEOS.platform_interface_set_override_locale_code(locale_code)

		static func check_for_launcher_and_restart() -> Result:
			return IEOS.platform_interface_check_for_launcher_and_restart()

		static func initialize(options: InitializeOptions) -> Result:
			return IEOS.platform_interface_initialize(options)

		static func get_desktop_crossplay_status_info() -> Dictionary:
			return IEOS.platform_interface_get_desktop_crossplay_status_info()

		static func set_application_status(status: ApplicationStatus) -> Result:
			return IEOS.platform_interface_set_application_status(status)

		static func get_application_status() -> ApplicationStatus:
			return IEOS.platform_interface_get_application_status()

		static func set_network_status(status: NetworkStatus) -> Result:
			return IEOS.platform_interface_set_network_status(status)

		static func get_network_status() -> NetworkStatus:
			return IEOS.platform_interface_get_network_status()

		static func release() -> void:
			IEOS.platform_interface_release()

		static func shutdown() -> Result:
			return IEOS.platform_interface_shutdown()



class Ecom:
	enum ItemType { 
		## This entitlement is intended to persist.
		Durable = 0,
		## This entitlement is intended to be transient and redeemed.
		Consumable = 1,
		## This entitlement has a type that is not currently intended for an in-game store.
		Other = 2
	}

	enum OwnershipStatus {
		## The catalog item is not owned by the local user
		NotOwned = 0,
		## The catalog item is owned by the local user
		Owned = 1
	}

	enum CheckoutOrientation {
		## Current orientation will be used
		Default = 0,
		## Portrait orientation
		Portrait = 1,
		## Landscape orientation
		Landscape = 2
	}

	class CheckoutOptions extends BaseClass:
		func _init():
			super._init("CheckoutOptions")

		var local_user_id = EOSGRuntime.local_epic_account_id
		var entries: Array # Array[Dictionary] {offer_id: String}
		var override_catalog_namespace: String
		var preferred_orientation = CheckoutOrientation.Default

	class CopyEntitlementByIdOptions extends BaseClass:
		func _init():
			super._init("CopyEntitlementByIdOptions")

		var local_user_id = EOSGRuntime.local_epic_account_id
		var entitlement_id: String

	class CopyEntitlementByIndexOptions extends BaseClass:
		func _init():
			super._init("CopyEntitlementByIndexOptions")

		var local_user_id = EOSGRuntime.local_epic_account_id
		var entitlement_index: int

	class CopyEntitlementByNameAndIndexOptions extends BaseClass:
		func _init():
			super._init("CopyEntitlementByNameAndIndexOptions")

		var local_user_id = EOSGRuntime.local_epic_account_id
		var entitlement_name: String
		var index: int

	class CopyItemByIdOptions extends BaseClass:
		func _init():
			super._init("CopyItemByIdOptions")

		var local_user_id = EOSGRuntime.local_epic_account_id
		var item_id: String

	class CopyItemImageInfoByIndexOptions extends BaseClass:
		func _init():
			super._init("CopyItemImageInfoByIndexOptions")

		var local_user_id = EOSGRuntime.local_epic_account_id
		var item_id: String
		var image_info_index: int

	class CopyItemReleaseByIndexOptions extends BaseClass:
		func _init():
			super._init("CopyItemReleaseByIndexOptions")

		var local_user_id = EOSGRuntime.local_epic_account_id
		var item_id: String
		var release_index: int

	class CopyOfferByIdOptions extends BaseClass:
		func _init():
			super._init("CopyOfferByIdOptions")

		var local_user_id = EOSGRuntime.local_epic_account_id
		var offer_id: String

	class CopyOfferByIndexOptions extends BaseClass:
		func _init():
			super._init("CopyOfferByIndexOptions")

		var local_user_id = EOSGRuntime.local_epic_account_id
		var offer_index: int

	class CopyOfferImageInfoByIndexOptions extends BaseClass:
		func _init():
			super._init("CopyOfferImageInfoByIndexOptions")

		var local_user_id = EOSGRuntime.local_epic_account_id
		var offer_id: String
		var image_info_index: int

	class CopyOfferItemByIndexOptions extends BaseClass:
		func _init():
			super._init("CopyOfferItemByIndexOptions")

		var local_user_id = EOSGRuntime.local_epic_account_id
		var offer_id: String
		var item_index: int

	class CopyTransactionByIdOptions extends BaseClass:
		func _init():
			super._init("CopyTransactionByIdOptions")

		var local_user_id = EOSGRuntime.local_epic_account_id
		var transaction_id: String

	class CopyTransactionByIndexOptions extends BaseClass:
		func _init():
			super._init("CopyTransactionByIndexOptions")

		var local_user_id = EOSGRuntime.local_epic_account_id
		var transaction_index: int

	class GetEntitlementsByNameCountOptions extends BaseClass:
		func _init():
			super._init("GetEntitlementsByNameCountOptions")

		var local_user_id = EOSGRuntime.local_epic_account_id
		var entitlement_name: String

	class GetEntitlementsCountOptions extends BaseClass:
		func _init():
			super._init("GetEntitlementsCountOptions")

		var local_user_id = EOSGRuntime.local_epic_account_id
		var item_id: String

	class GetItemImageInfoCountOptions extends BaseClass:
		func _init():
			super._init("GetItemImageInfoCountOptions")

		var local_user_id = EOSGRuntime.local_epic_account_id
		var item_id: String

	class GetItemReleaseCountOptions extends BaseClass:
		func _init():
			super._init("GetItemReleaseCountOptions")

		var local_user_id = EOSGRuntime.local_epic_account_id
		var item_id: String

	class GetOfferCountOptions extends BaseClass:
		func _init():
			super._init("GetOfferCountOptions")

		var local_user_id = EOSGRuntime.local_epic_account_id

	class GetOfferImageInfoCountOptions extends BaseClass:
		func _init():
			super._init("GetOfferImageInfoCountOptions")

		var local_user_id = EOSGRuntime.local_epic_account_id
		var offer_id: String

	class GetOfferItemCountOptions extends BaseClass:
		func _init():
			super._init("GetOfferItemCountOptions")

		var local_user_id = EOSGRuntime.local_epic_account_id
		var offer_id: String

	class GetTransactionCountOptions extends BaseClass:
		func _init():
			super._init("GetTransactionCountOptions")

		var local_user_id = EOSGRuntime.local_epic_account_id

	class QueryEntitlementsOptions extends BaseClass:
		func _init():
			super._init("QueryEntitlementsOptions")

		var local_user_id = EOSGRuntime.local_epic_account_id
		var entitlement_names: Array # Array[String]
		var include_redeemed: bool
		var override_catalog_namespace: String

	class QueryOffersOptions extends BaseClass:
		func _init():
			super._init("QueryOffersOptions")

		var local_user_id = EOSGRuntime.local_epic_account_id
		var override_catalog_namespace: String

		var client_data = null

	class QueryOwnershipOptions extends BaseClass:
		func _init():
			super._init("QueryOwnershipOptions")

		var local_user_id = EOSGRuntime.local_epic_account_id
		var catalog_item_ids: Array # Array[String]
		var catalog_namespace: String

		var client_data = null

	class QueryOwnershipTokenOptions extends BaseClass:
		func _init():
			super._init("QueryOwnershipTokenOptions")

		var local_user_id = EOSGRuntime.local_epic_account_id
		var catalog_item_ids: Array # Array[String]
		var catalog_namespace = null # String

		var client_data = null

	class RedeemEntitlementsOptions extends BaseClass:
		func _init():
			super._init("RedeemEntitlementsOptions")

		var local_user_id = EOSGRuntime.local_epic_account_id
		var entitlement_ids: Array # Array[String]

		var client_data = null

	class GetLastRedeemedEntitlementsCountOptions extends BaseClass:
		func _init():
			super._init("GetLastRedeemedEntitlementsCountOptions")

		var local_user_id = EOSGRuntime.local_epic_account_id

	class CopyLastRedeemedEntitlementByIndexOptions extends BaseClass:
		func _init():
			super._init("CopyLastRedeemedEntitlementByIndexOptions")

		var local_user_id = EOSGRuntime.local_epic_account_id
		var redeemed_entitlement_index: String

	class EcomInterface:
		static func checkout(options: CheckoutOptions) -> void:
			IEOS.ecom_interface_checkout(options)

		static func copy_entitlement_by_id(options: CopyEntitlementByIdOptions) -> Dictionary:
			return IEOS.ecom_interface_copy_entitlement_by_id(options)

		static func copy_entitlement_by_index(options: CopyEntitlementByIndexOptions) -> Dictionary:
			return IEOS.ecom_interface_copy_entitlement_by_index(options)

		static func copy_entitlement_by_name_and_index(options: CopyEntitlementByNameAndIndexOptions) -> Dictionary:
			return IEOS.ecom_interface_copy_entitlement_by_name_and_index(options)

		static func copy_item_by_id(options: CopyItemByIdOptions) -> Dictionary:
			return IEOS.ecom_interface_copy_item_by_id(options)

		static func copy_item_image_
Download .txt
gitextract_ngm7nid4/

├── .clang-format
├── .editorconfig
├── .gitattributes
├── .github/
│   ├── FUNDING.yml
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.md
│   │   └── feature_request.md
│   └── workflows/
│       ├── build.yml
│       └── deploy-docs.yml
├── .gitignore
├── .gitmodules
├── .pre-commit-config.yaml
├── .vscode/
│   ├── c_cpp_properties.json
│   ├── launch.json
│   ├── settings.json
│   └── tasks.json
├── LICENSE.md
├── README.md
├── SConstruct
├── build-ios.sh
├── debug-entitlements.plist
├── debug.cmd
├── debug.sh
├── docs/
│   ├── .gitignore
│   ├── README.md
│   ├── bun.lockb
│   ├── docs/
│   │   ├── installation.md
│   │   ├── introduction.md
│   │   ├── sample-project.md
│   │   ├── topics/
│   │   │   ├── authentication.md
│   │   │   └── initialization.md
│   │   └── update-guide.md
│   ├── docusaurus.config.ts
│   ├── package.json
│   ├── postcss.config.js
│   ├── sidebars.ts
│   ├── src/
│   │   ├── components/
│   │   │   ├── ExampleSection.tsx
│   │   │   ├── FeaturesSection.tsx
│   │   │   ├── HeroSection.tsx
│   │   │   ├── Icons.tsx
│   │   │   ├── InfoSections.tsx
│   │   │   ├── Layout.tsx
│   │   │   ├── MainSystemsSection.tsx
│   │   │   ├── MediaSections.tsx
│   │   │   └── SupportSection.tsx
│   │   ├── css/
│   │   │   └── custom.css
│   │   ├── pages/
│   │   │   ├── index.tsx
│   │   │   └── showcase.md
│   │   └── plugins/
│   │       └── tailwind-config.ts
│   ├── static/
│   │   └── .nojekyll
│   └── tsconfig.json
├── function_analyzer.py
├── sample/
│   ├── .gitignore
│   ├── AntiCheatServerMain.gd
│   ├── AntiCheatServerMain.gd.uid
│   ├── Main.gd
│   ├── Main.gd.uid
│   ├── Main.tscn
│   ├── addons/
│   │   └── epic-online-services-godot/
│   │       ├── base_class.gd
│   │       ├── base_class.gd.uid
│   │       ├── bin/
│   │       │   └── .gitignore
│   │       ├── dataclass.gd
│   │       ├── dataclass.gd.uid
│   │       ├── eos.gd
│   │       ├── eos.gd.uid
│   │       ├── eosg.gdextension
│   │       ├── eosg.gdextension.uid
│   │       ├── export_plugin.gd
│   │       ├── export_plugin.gd.uid
│   │       ├── heos/
│   │       │   ├── hachievement_data.gd
│   │       │   ├── hachievement_data.gd.uid
│   │       │   ├── hachievements.gd
│   │       │   ├── hachievements.gd.uid
│   │       │   ├── hauth.gd
│   │       │   ├── hauth.gd.uid
│   │       │   ├── hcredentials.gd
│   │       │   ├── hcredentials.gd.uid
│   │       │   ├── hfriends.gd
│   │       │   ├── hfriends.gd.uid
│   │       │   ├── hleaderboards.gd
│   │       │   ├── hleaderboards.gd.uid
│   │       │   ├── hlobbies.gd
│   │       │   ├── hlobbies.gd.uid
│   │       │   ├── hlobby.gd
│   │       │   ├── hlobby.gd.uid
│   │       │   ├── hlobbymember.gd
│   │       │   ├── hlobbymember.gd.uid
│   │       │   ├── hlog.gd
│   │       │   ├── hlog.gd.uid
│   │       │   ├── hp2p.gd
│   │       │   ├── hp2p.gd.uid
│   │       │   ├── hplatform.gd
│   │       │   ├── hplatform.gd.uid
│   │       │   ├── hsessions.gd
│   │       │   ├── hsessions.gd.uid
│   │       │   ├── hstats.gd
│   │       │   └── hstats.gd.uid
│   │       ├── plugin.cfg
│   │       ├── plugin.gd
│   │       ├── plugin.gd.uid
│   │       ├── runtime.gd
│   │       └── runtime.gd.uid
│   ├── components/
│   │   └── StyledPopupWindow/
│   │       ├── StyledPopupWindow.gd
│   │       ├── StyledPopupWindow.gd.uid
│   │       ├── StyledPopupWindow.tscn
│   │       └── StyledPopupWindowTheme.tres
│   ├── dedicated_server_example/
│   │   ├── client_main.gd
│   │   ├── client_main.gd.uid
│   │   ├── client_main.tscn
│   │   ├── server_main.gd
│   │   ├── server_main.gd.uid
│   │   └── server_main.tscn
│   ├── default_bus_layout.tres
│   ├── default_env.tres
│   ├── fonts/
│   │   ├── roboto-13r.tres
│   │   ├── roboto-16b.tres
│   │   ├── roboto-16r.tres
│   │   └── roboto-32b.tres
│   ├── game/
│   │   ├── entities/
│   │   │   ├── bullet/
│   │   │   │   ├── bullet.gd
│   │   │   │   ├── bullet.gd.uid
│   │   │   │   └── bullet.tscn
│   │   │   ├── player/
│   │   │   │   ├── player.gd
│   │   │   │   ├── player.gd.uid
│   │   │   │   └── player.tscn
│   │   │   └── wall/
│   │   │       └── wall.tscn
│   │   └── maps/
│   │       ├── map_bellandur.tscn
│   │       ├── map_margao.tscn
│   │       └── map_new_york.tscn
│   ├── project.godot
│   ├── scenes/
│   │   ├── AchievementsView/
│   │   │   ├── AchievementPopup.gd
│   │   │   ├── AchievementPopup.gd.uid
│   │   │   ├── AchievementUnlockNotification.gd
│   │   │   ├── AchievementUnlockNotification.gd.uid
│   │   │   ├── AchievementUnlockNotification.tscn
│   │   │   ├── AchievementsList.gd
│   │   │   ├── AchievementsList.gd.uid
│   │   │   ├── AchievementsListAchievement.gd
│   │   │   ├── AchievementsListAchievement.gd.uid
│   │   │   ├── AchievementsListAchievement.tscn
│   │   │   ├── AchievementsView.gd
│   │   │   ├── AchievementsView.gd.uid
│   │   │   └── AchievementsView.tscn
│   │   ├── CustomInvitesView/
│   │   │   ├── CustomInvitesView.gd
│   │   │   ├── CustomInvitesView.gd.uid
│   │   │   └── CustomInvitesView.tscn
│   │   ├── FriendsView/
│   │   │   ├── FriendsView.gd
│   │   │   ├── FriendsView.gd.uid
│   │   │   └── FriendsView.tscn
│   │   ├── LeaderboardsView/
│   │   │   ├── LeaderboardsView.gd
│   │   │   ├── LeaderboardsView.gd.uid
│   │   │   └── LeaderboardsView.tscn
│   │   ├── LobbiesView/
│   │   │   ├── CreateLobbyPopup.gd
│   │   │   ├── CreateLobbyPopup.gd.uid
│   │   │   ├── CreateLobbyPopup.tscn
│   │   │   ├── CurrentLobby.gd
│   │   │   ├── CurrentLobby.gd.uid
│   │   │   ├── LobbiesView.gd
│   │   │   ├── LobbiesView.gd.uid
│   │   │   ├── LobbiesView.tscn
│   │   │   ├── SearchLobby.gd
│   │   │   ├── SearchLobby.gd.uid
│   │   │   ├── SearchLobbyResults.gd
│   │   │   └── SearchLobbyResults.gd.uid
│   │   ├── LoginView/
│   │   │   ├── EnterCredentials.gd
│   │   │   ├── EnterCredentials.gd.uid
│   │   │   ├── LoginView.gd
│   │   │   ├── LoginView.gd.uid
│   │   │   └── LoginView.tscn
│   │   ├── LogsView/
│   │   │   ├── LogsView.gd
│   │   │   ├── LogsView.gd.uid
│   │   │   └── LogsView.tscn
│   │   ├── MetricsView/
│   │   │   ├── MetricsView.gd
│   │   │   ├── MetricsView.gd.uid
│   │   │   └── MetricsView.tscn
│   │   ├── NotificationsView/
│   │   │   ├── NotificationsView.gd
│   │   │   └── NotificationsView.gd.uid
│   │   ├── StatsView/
│   │   │   ├── StatsView.gd
│   │   │   ├── StatsView.gd.uid
│   │   │   └── StatsView.tscn
│   │   ├── UI/
│   │   │   ├── NetworkImage.gd
│   │   │   ├── NetworkImage.gd.uid
│   │   │   ├── NetworkImage.tscn
│   │   │   ├── PrimaryButton.tscn
│   │   │   ├── joysticks.gd
│   │   │   ├── joysticks.gd.uid
│   │   │   ├── nat_type.gd
│   │   │   ├── nat_type.gd.uid
│   │   │   ├── nat_type.tscn
│   │   │   ├── ping.gd
│   │   │   ├── ping.gd.uid
│   │   │   ├── ping.tscn
│   │   │   ├── players_score.gd
│   │   │   ├── players_score.gd.uid
│   │   │   ├── players_score.tscn
│   │   │   ├── touch_screen_joystick.gd
│   │   │   └── touch_screen_joystick.gd.uid
│   │   └── UIView/
│   │       ├── UIView.gd
│   │       ├── UIView.gd.uid
│   │       └── UIView.tscn
│   ├── scripts/
│   │   ├── Env.gd
│   │   ├── Env.gd.uid
│   │   ├── Store.gd
│   │   ├── Store.gd.uid
│   │   ├── ViewManager.gd
│   │   ├── ViewManager.gd.uid
│   │   ├── network.gd
│   │   └── network.gd.uid
│   ├── styles/
│   │   └── ViewTitleLabelSettings.tres
│   ├── test.gd
│   ├── test.gd.uid
│   ├── test_manual_audio_output.gd
│   └── test_manual_audio_output.gd.uid
├── src/
│   ├── achievements_interface.cpp
│   ├── anticheat_client_interface.cpp
│   ├── anticheat_server_interface.cpp
│   ├── auth_interface.cpp
│   ├── connect_interface.cpp
│   ├── custom_invites_interface.cpp
│   ├── ecom_interface.cpp
│   ├── eosg_active_session.cpp
│   ├── eosg_active_session.h
│   ├── eosg_continuance_token.h
│   ├── eosg_file_transfer_request.h
│   ├── eosg_lobby_details.cpp
│   ├── eosg_lobby_details.h
│   ├── eosg_lobby_modification.cpp
│   ├── eosg_lobby_modification.h
│   ├── eosg_lobby_search.cpp
│   ├── eosg_lobby_search.h
│   ├── eosg_multiplayer_peer.cpp
│   ├── eosg_multiplayer_peer.h
│   ├── eosg_packet_peer_mediator.cpp
│   ├── eosg_packet_peer_mediator.h
│   ├── eosg_playerdatastorage_file_transfer_request.cpp
│   ├── eosg_playerdatastorage_file_transfer_request.h
│   ├── eosg_presence_modification.cpp
│   ├── eosg_presence_modification.h
│   ├── eosg_session_details.cpp
│   ├── eosg_session_details.h
│   ├── eosg_session_modification.cpp
│   ├── eosg_session_modification.h
│   ├── eosg_session_search.cpp
│   ├── eosg_session_search.h
│   ├── eosg_titlestorage_file_transfer_request.cpp
│   ├── eosg_titlestorage_file_transfer_request.h
│   ├── eosg_transaction.cpp
│   ├── eosg_transaction.h
│   ├── friends_interface.cpp
│   ├── ieos.cpp
│   ├── ieos.h
│   ├── kws_interface.cpp
│   ├── leaderboards_interface.cpp
│   ├── lobby_interface.cpp
│   ├── logging_interface.cpp
│   ├── metrics_interface.cpp
│   ├── mods_interface.cpp
│   ├── p2p_interface.cpp
│   ├── platform_interface.cpp
│   ├── playerdatastorage_interface.cpp
│   ├── presence_interface.cpp
│   ├── progression_snapshot_interface.cpp
│   ├── register_types.cpp
│   ├── register_types.h
│   ├── reports_interface.cpp
│   ├── rtc_audio_interface.cpp
│   ├── rtc_data_interface.cpp
│   ├── rtc_interface.cpp
│   ├── sanctions_interface.cpp
│   ├── sessions_interface.cpp
│   ├── stats_interface.cpp
│   ├── titlestorage_interface.cpp
│   ├── ui_interface.cpp
│   ├── user_info_interface.cpp
│   ├── utils.cpp
│   ├── utils.h
│   └── version_interface.cpp
└── thirdparty/
    └── Paste the EOS C SDK here as eos-sdk
Download .txt
SYMBOL INDEX (257 symbols across 64 files)

FILE: docs/src/components/ExampleSection.tsx
  function ExampleSection (line 68) | function ExampleSection() {

FILE: docs/src/components/FeaturesSection.tsx
  constant FEATURES (line 1) | const FEATURES = [
  constant HIGH_LEVEL_CLASSES (line 18) | const HIGH_LEVEL_CLASSES = [
  function FeaturesSection (line 30) | function FeaturesSection() {
  function HighLevelSection (line 65) | function HighLevelSection() {

FILE: docs/src/components/HeroSection.tsx
  constant VERSIONS (line 4) | const VERSIONS = [
  constant PLATFORMS (line 9) | const PLATFORMS = [
  constant HERO_ACTIONS (line 17) | const HERO_ACTIONS = [
  function HeroSection (line 31) | function HeroSection() {

FILE: docs/src/components/Icons.tsx
  function GodotIcon (line 1) | function GodotIcon({ className = "w-4 h-4" }) {
  function EpicIcon (line 16) | function EpicIcon({ className = "w-4 h-4" }) {

FILE: docs/src/components/InfoSections.tsx
  function HowItWorksSection (line 1) | function HowItWorksSection() {
  function InstallationSection (line 22) | function InstallationSection() {

FILE: docs/src/components/Layout.tsx
  constant NAV_LINKS (line 4) | const NAV_LINKS = [
  function NavBar (line 40) | function NavBar() {
  function Footer (line 139) | function Footer() {

FILE: docs/src/components/MainSystemsSection.tsx
  constant MAIN_SYSTEMS (line 1) | const MAIN_SYSTEMS = [
  function MainSystemsSection (line 62) | function MainSystemsSection() {

FILE: docs/src/components/MediaSections.tsx
  constant SCREENSHOTS_DATA (line 1) | const SCREENSHOTS_DATA = [
  constant TUTORIALS_DATA (line 44) | const TUTORIALS_DATA = {
  function ScreenshotsSection (line 51) | function ScreenshotsSection() {
  function DemoSection (line 91) | function DemoSection() {

FILE: docs/src/components/SupportSection.tsx
  constant SUPPORT_DATA (line 1) | const SUPPORT_DATA = {
  function SupportSection (line 8) | function SupportSection() {

FILE: docs/src/pages/index.tsx
  function App (line 8) | function App() {

FILE: docs/src/plugins/tailwind-config.ts
  method configurePostCss (line 4) | configurePostCss(postcssOptions) {

FILE: function_analyzer.py
  function extract_function_names (line 8) | def extract_function_names(sdk_path):
  function find_function_calls (line 25) | def find_function_calls(src_path, function_names):
  function main (line 42) | def main():

FILE: src/achievements_interface.cpp
  function Dictionary (line 5) | Dictionary IEOS::achievements_interface_copy_achievement_definition_v2_b...
  function Dictionary (line 23) | Dictionary IEOS::achievements_interface_copy_achievement_definition_v2_b...
  function Dictionary (line 39) | Dictionary IEOS::achievements_interface_copy_player_achievement_by_achie...
  function Dictionary (line 61) | Dictionary IEOS::achievements_interface_copy_player_achievement_by_index...

FILE: src/anticheat_client_interface.cpp
  function Dictionary (line 51) | Dictionary IEOS::anticheat_client_interface_get_protect_message_output_l...
  function Dictionary (line 74) | Dictionary IEOS::anticheat_client_interface_protect_message(Ref<RefCount...
  function Dictionary (line 107) | Dictionary IEOS::anticheat_client_interface_unprotect_message(Ref<RefCou...

FILE: src/anticheat_server_interface.cpp
  function Dictionary (line 123) | Dictionary IEOS::anticheat_server_interface_get_protect_message_output_l...
  function Dictionary (line 146) | Dictionary IEOS::anticheat_server_interface_protect_message(Ref<RefCount...
  function Dictionary (line 179) | Dictionary IEOS::anticheat_server_interface_unprotect_message(Ref<RefCou...

FILE: src/auth_interface.cpp
  function Dictionary (line 79) | Dictionary IEOS::auth_interface_copy_id_token(Ref<RefCounted> p_options) {
  function Dictionary (line 97) | Dictionary IEOS::auth_interface_copy_user_auth_token(Ref<RefCounted> p_o...
  function String (line 139) | String IEOS::auth_interface_get_logged_in_account_by_index(int index) {
  function String (line 157) | String IEOS::auth_interface_get_merged_account_by_index(const String &p_...
  function Dictionary (line 172) | Dictionary IEOS::auth_interface_get_selected_account_id(const String &p_...

FILE: src/connect_interface.cpp
  function Dictionary (line 94) | Dictionary IEOS::connect_interface_copy_id_token(Ref<RefCounted> p_optio...
  function Dictionary (line 112) | Dictionary IEOS::connect_interface_copy_product_user_external_account_by...
  function Dictionary (line 133) | Dictionary IEOS::connect_interface_copy_product_user_external_account_by...
  function Dictionary (line 153) | Dictionary IEOS::connect_interface_copy_product_user_external_account_by...
  function Dictionary (line 172) | Dictionary IEOS::connect_interface_copy_product_user_info(Ref<RefCounted...
  function String (line 251) | String IEOS::connect_interface_get_external_account_mapping(Ref<RefCount...
  function String (line 267) | String IEOS::connect_interface_get_logged_in_user_by_index(int p_index) {
  function Dictionary (line 297) | Dictionary IEOS::connect_interface_get_product_user_id_mapping(Ref<RefCo...

FILE: src/ecom_interface.cpp
  function Dictionary (line 46) | Dictionary IEOS::ecom_interface_copy_entitlement_by_id(Ref<RefCounted> p...
  function Dictionary (line 65) | Dictionary IEOS::ecom_interface_copy_entitlement_by_index(Ref<RefCounted...
  function Dictionary (line 83) | Dictionary IEOS::ecom_interface_copy_entitlement_by_name_and_index(Ref<R...
  function Dictionary (line 103) | Dictionary IEOS::ecom_interface_copy_item_by_id(Ref<RefCounted> p_option...
  function Dictionary (line 122) | Dictionary IEOS::ecom_interface_copy_item_image_info_by_index(Ref<RefCou...
  function Dictionary (line 143) | Dictionary IEOS::ecom_interface_copy_item_release_by_index(Ref<RefCounte...
  function Dictionary (line 164) | Dictionary IEOS::ecom_interface_copy_offer_by_id(Ref<RefCounted> p_optio...
  function Dictionary (line 183) | Dictionary IEOS::ecom_interface_copy_offer_by_index(Ref<RefCounted> p_op...
  function Dictionary (line 202) | Dictionary IEOS::ecom_interface_copy_offer_image_info_by_index(Ref<RefCo...
  function Dictionary (line 223) | Dictionary IEOS::ecom_interface_copy_offer_item_by_index(Ref<RefCounted>...
  function Dictionary (line 244) | Dictionary IEOS::ecom_interface_copy_transaction_by_id(Ref<RefCounted> p...
  function Dictionary (line 263) | Dictionary IEOS::ecom_interface_copy_transaction_by_index(Ref<RefCounted...
  function Dictionary (line 581) | Dictionary IEOS::ecom_interface_copy_last_redeemed_entitlement_by_index(...

FILE: src/eosg_active_session.cpp
  function Dictionary (line 12) | Dictionary EOSGActiveSession::copy_info() {
  function String (line 36) | String EOSGActiveSession::get_registered_player_by_index(int p_player_in...

FILE: src/eosg_active_session.h
  function namespace (line 5) | namespace godot {

FILE: src/eosg_continuance_token.h
  function namespace (line 5) | namespace godot {

FILE: src/eosg_file_transfer_request.h
  function namespace (line 5) | namespace godot {

FILE: src/eosg_lobby_details.cpp
  function String (line 21) | String EOSGLobbyDetails::get_lobby_owner() {
  function Dictionary (line 29) | Dictionary EOSGLobbyDetails::copy_info() {
  function Dictionary (line 52) | Dictionary EOSGLobbyDetails::copy_attribute_by_index(int p_index) {
  function Dictionary (line 68) | Dictionary EOSGLobbyDetails::copy_attribute_by_key(const String &p_key) {
  function String (line 94) | String EOSGLobbyDetails::get_member_by_index(int p_index) {
  function Dictionary (line 115) | Dictionary EOSGLobbyDetails::copy_member_attribute_by_index(const String...
  function Dictionary (line 134) | Dictionary EOSGLobbyDetails::copy_member_attribute_by_key(const String &...
  function Dictionary (line 154) | Dictionary EOSGLobbyDetails::copy_member_info(const String &p_target_use...

FILE: src/eosg_lobby_details.h
  function namespace (line 6) | namespace godot {

FILE: src/eosg_lobby_modification.h
  function namespace (line 5) | namespace godot {

FILE: src/eosg_lobby_search.cpp
  function Dictionary (line 124) | Dictionary EOSGLobbySearch::copy_search_result_by_index(int p_index) {

FILE: src/eosg_lobby_search.h
  function namespace (line 5) | namespace godot {

FILE: src/eosg_multiplayer_peer.cpp
  function Error (line 66) | Error EOSGMultiplayerPeer::create_server(const String &socket_id) {
  function Error (line 102) | Error EOSGMultiplayerPeer::create_client(const String &socket_id, const ...
  function Error (line 152) | Error EOSGMultiplayerPeer::create_mesh(const String &socket_id) {
  function Error (line 186) | Error EOSGMultiplayerPeer::add_mesh_peer(const String &remote_user_id) {
  function String (line 208) | String EOSGMultiplayerPeer::get_socket() const {
  function Array (line 217) | Array EOSGMultiplayerPeer::get_all_connection_requests() {
  function String (line 232) | String EOSGMultiplayerPeer::get_peer_user_id(int p_id) {
  function Dictionary (line 307) | Dictionary EOSGMultiplayerPeer::get_all_peers() {
  function Error (line 466) | Error EOSGMultiplayerPeer::_get_packet(const uint8_t **r_buffer, int32_t...
  function Error (line 486) | Error EOSGMultiplayerPeer::_put_packet(const uint8_t *p_buffer, int32_t ...
  function String (line 853) | String EOSGMultiplayerPeer::get_local_user_id() {
  function Error (line 868) | Error EOSGMultiplayerPeer::_broadcast(const EOSGPacket &packet, int excl...
  function Error (line 905) | Error EOSGMultiplayerPeer::_send_to(const EOS_ProductUserId &remote_peer...
  function EOS_EPacketReliability (line 956) | EOS_EPacketReliability EOSGMultiplayerPeer::_convert_transfer_mode_to_eo...

FILE: src/eosg_multiplayer_peer.h
  function namespace (line 9) | namespace godot {

FILE: src/eosg_packet_peer_mediator.h
  function namespace (line 7) | namespace godot {
  function size (line 25) | int size() {
  function get_channel (line 29) | int get_channel() {
  function String (line 33) | String get_sender() {
  function set_channel (line 37) | void set_channel(int channel) {
  function set_sender (line 41) | void set_sender(EOS_ProductUserId sender) {
  function PackedByteArray (line 45) | PackedByteArray *get_data() {
  function class (line 50) | class EOSGPacketPeerMediator : public Object {
  function get_packet_count_for_socket (line 98) | int get_packet_count_for_socket(const String &socket_id) {
  function Array (line 103) | Array get_sockets() {

FILE: src/eosg_playerdatastorage_file_transfer_request.cpp
  function Dictionary (line 20) | Dictionary EOSGPlayerDataStorageFileTransferRequest::get_filename() {

FILE: src/eosg_playerdatastorage_file_transfer_request.h
  function namespace (line 6) | namespace godot {

FILE: src/eosg_presence_modification.h
  function namespace (line 5) | namespace godot {

FILE: src/eosg_session_details.cpp
  function Dictionary (line 12) | Dictionary EOSGSessionDetails::copy_info() {
  function Dictionary (line 27) | Dictionary EOSGSessionDetails::copy_session_attribute_by_index(int p_att...
  function Dictionary (line 43) | Dictionary EOSGSessionDetails::copy_session_attribute_by_key(const Strin...

FILE: src/eosg_session_details.h
  function namespace (line 5) | namespace godot {

FILE: src/eosg_session_modification.h
  function namespace (line 4) | namespace godot {

FILE: src/eosg_session_search.cpp
  function Dictionary (line 17) | Dictionary EOSGSessionSearch::copy_search_result_by_index(int p_index) {

FILE: src/eosg_session_search.h
  function namespace (line 5) | namespace godot {

FILE: src/eosg_titlestorage_file_transfer_request.cpp
  function Dictionary (line 20) | Dictionary EOSGTitleStorageFileTransferRequest::get_filename() {

FILE: src/eosg_titlestorage_file_transfer_request.h
  function namespace (line 6) | namespace godot {

FILE: src/eosg_transaction.cpp
  function String (line 13) | String EOSGTransaction::get_id() {
  function Dictionary (line 30) | Dictionary EOSGTransaction::copy_entitlement_by_index(int p_entitlement_...

FILE: src/eosg_transaction.h
  function namespace (line 5) | namespace godot {

FILE: src/friends_interface.cpp
  function String (line 28) | String IEOS::friends_interface_get_friend_at_index(Ref<RefCounted> p_opt...
  function String (line 148) | String IEOS::friends_interface_get_blocked_user_at_index(Ref<RefCounted>...

FILE: src/ieos.cpp
  function IEOS (line 534) | IEOS *IEOS::get_singleton() { return singleton; }

FILE: src/ieos.h
  function namespace (line 45) | namespace godot {

FILE: src/kws_interface.cpp
  function Dictionary (line 4) | Dictionary IEOS::kws_interface_copy_permission_by_index(Ref<RefCounted> ...
  function Dictionary (line 50) | Dictionary IEOS::kws_interface_get_permission_by_key(Ref<RefCounted> p_o...

FILE: src/leaderboards_interface.cpp
  function Dictionary (line 4) | Dictionary IEOS::leaderboards_interface_copy_leaderboard_definition_by_i...
  function Dictionary (line 20) | Dictionary IEOS::leaderboards_interface_copy_leaderboard_definition_by_l...
  function Dictionary (line 37) | Dictionary IEOS::leaderboards_interface_copy_leaderboard_record_by_index...
  function Dictionary (line 53) | Dictionary IEOS::leaderboards_interface_copy_leaderboard_record_by_user_...
  function Dictionary (line 71) | Dictionary IEOS::leaderboards_interface_copy_leaderboard_user_score_by_i...
  function Dictionary (line 90) | Dictionary IEOS::leaderboards_interface_copy_leaderboard_user_score_by_u...

FILE: src/lobby_interface.cpp
  function Dictionary (line 229) | Dictionary IEOS::lobby_interface_update_lobby_modification(Ref<RefCounte...
  function Dictionary (line 435) | Dictionary IEOS::lobby_interface_get_invite_id_by_index(Ref<RefCounted> ...
  function Dictionary (line 455) | Dictionary IEOS::lobby_interface_create_lobby_search(Ref<RefCounted> p_o...
  function Dictionary (line 471) | Dictionary IEOS::lobby_interface_copy_lobby_details_by_invite_id(Ref<Ref...
  function Dictionary (line 489) | Dictionary IEOS::lobby_interface_copy_lobby_details_by_ui_event_id(Ref<R...
  function Dictionary (line 505) | Dictionary IEOS::lobby_interface_copy_lobby_details(Ref<RefCounted> p_op...
  function Dictionary (line 527) | Dictionary IEOS::lobby_interface_get_rtc_room_name(Ref<RefCounted> p_opt...
  function Dictionary (line 549) | Dictionary IEOS::lobby_interface_is_rtc_room_connected(Ref<RefCounted> p...
  function Dictionary (line 569) | Dictionary IEOS::lobby_interface_get_connect_string(Ref<RefCounted> p_op...
  function Dictionary (line 594) | Dictionary IEOS::lobby_interface_parse_connect_string(Ref<RefCounted> p_...

FILE: src/mods_interface.cpp
  function Dictionary (line 4) | Dictionary IEOS::mods_interface_copy_mod_info(Ref<RefCounted> p_options) {

FILE: src/p2p_interface.cpp
  function Dictionary (line 15) | Dictionary IEOS::p2p_interface_get_nat_type() {
  function Dictionary (line 43) | Dictionary IEOS::p2p_interface_get_relay_control() {
  function Dictionary (line 71) | Dictionary IEOS::p2p_interface_get_port_range() {
  function Dictionary (line 102) | Dictionary IEOS::p2p_interface_get_packet_queue_info() {
  function EOS_EResult (line 121) | EOS_EResult IEOS::_p2p_send_packet(const EOS_P2P_SendPacketOptions *opti...
  function EOS_EResult (line 127) | EOS_EResult IEOS::_p2p_receive_packet(const EOS_P2P_ReceivePacketOptions...
  function EOS_EResult (line 135) | EOS_EResult IEOS::_p2p_accept_connection(const EOS_P2P_AcceptConnectionO...
  function EOS_EResult (line 141) | EOS_EResult IEOS::_p2p_close_connection(const EOS_P2P_CloseConnectionOpt...
  function EOS_EResult (line 147) | EOS_EResult IEOS::_p2p_close_all_connections(const EOS_P2P_CloseConnecti...
  function EOS_EResult (line 153) | EOS_EResult IEOS::_p2p_get_next_packet_size(const EOS_P2P_GetNextReceive...
  function EOS_EResult (line 159) | EOS_EResult IEOS::_p2p_clear_packet_queue(const EOS_P2P_ClearPacketQueue...
  function EOS_NotificationId (line 165) | EOS_NotificationId IEOS::_p2p_add_notify_peer_connection_established(con...
  function EOS_NotificationId (line 172) | EOS_NotificationId IEOS::_p2p_add_notify_peer_connection_closed(const EO...
  function EOS_NotificationId (line 179) | EOS_NotificationId IEOS::_p2p_add_notify_peer_connection_request(const E...
  function EOS_NotificationId (line 186) | EOS_NotificationId IEOS::_p2p_add_notify_peer_connection_interrupted(con...

FILE: src/platform_interface.cpp
  function Dictionary (line 687) | Dictionary IEOS::platform_interface_get_active_country_code(const String...
  function Dictionary (line 705) | Dictionary IEOS::platform_interface_get_active_locale_code(const String ...
  function Dictionary (line 723) | Dictionary IEOS::platform_interface_get_override_country_code() {
  function Dictionary (line 740) | Dictionary IEOS::platform_interface_get_override_locale_code() {
  function Dictionary (line 808) | Dictionary IEOS::platform_interface_get_desktop_crossplay_status_info() {

FILE: src/playerdatastorage_interface.cpp
  function Dictionary (line 51) | Dictionary IEOS::playerdatastorage_interface_copy_file_metadata_by_filen...
  function Dictionary (line 71) | Dictionary IEOS::playerdatastorage_interface_get_file_metadata_count(Ref...
  function Dictionary (line 89) | Dictionary IEOS::playerdatastorage_interface_copy_file_metadata_at_index...
  function Variant (line 180) | Variant IEOS::playerdatastorage_interface_read_file(Ref<RefCounted> p_op...
  function Variant (line 239) | Variant IEOS::playerdatastorage_interface_write_file(Ref<RefCounted> p_o...

FILE: src/presence_interface.cpp
  function Dictionary (line 4) | Dictionary IEOS::presence_interface_copy_presence(Ref<RefCounted> p_opti...
  function Dictionary (line 24) | Dictionary IEOS::presence_interface_create_presence_modification(Ref<Ref...
  function Dictionary (line 42) | Dictionary IEOS::presence_interface_get_join_info(Ref<RefCounted> p_opti...

FILE: src/progression_snapshot_interface.cpp
  function Dictionary (line 4) | Dictionary IEOS::progression_snapshot_interface_begin_snapshot(Ref<RefCo...

FILE: src/register_types.cpp
  function initialize_eosg_module (line 25) | void initialize_eosg_module(ModuleInitializationLevel p_level) {
  function uninitialize_eosg_module (line 55) | void uninitialize_eosg_module(ModuleInitializationLevel p_level) {
  function GDExtensionBool (line 72) | GDExtensionBool GDE_EXPORT eosg_library_init(GDExtensionInterfaceGetProc...

FILE: src/rtc_audio_interface.cpp
  function Dictionary (line 4) | Dictionary IEOS::rtc_audio_interface_copy_input_device_information_by_in...
  function Dictionary (line 22) | Dictionary IEOS::rtc_audio_interface_copy_output_device_information_by_i...

FILE: src/sanctions_interface.cpp
  function Dictionary (line 41) | Dictionary IEOS::sanctions_interface_copy_player_sanction_by_index(Ref<R...

FILE: src/sessions_interface.cpp
  function Dictionary (line 3) | Dictionary IEOS::sessions_interface_copy_active_session_details(Ref<RefC...
  function Dictionary (line 21) | Dictionary IEOS::sessions_interface_copy_session_details_by_invite_id(Re...
  function Dictionary (line 39) | Dictionary IEOS::sessions_interface_copy_session_details_by_ui_event_id(...
  function Dictionary (line 57) | Dictionary IEOS::sessions_interface_copy_session_details_for_presence(Re...
  function Dictionary (line 75) | Dictionary IEOS::sessions_interface_create_session_modification(Ref<RefC...
  function Dictionary (line 116) | Dictionary IEOS::sessions_interface_create_session_search(Ref<RefCounted...
  function Dictionary (line 146) | Dictionary IEOS::sessions_interface_get_invite_id_by_index(Ref<RefCounte...
  function Dictionary (line 180) | Dictionary IEOS::sessions_interface_update_session_modification(Ref<RefC...

FILE: src/stats_interface.cpp
  function Dictionary (line 4) | Dictionary IEOS::stats_interface_copy_stat_by_index(Ref<RefCounted> p_op...
  function Dictionary (line 23) | Dictionary IEOS::stats_interface_copy_stat_by_name(Ref<RefCounted> p_opt...

FILE: src/titlestorage_interface.cpp
  function Dictionary (line 60) | Dictionary IEOS::titlestorage_interface_copy_file_metadata_by_filename(R...
  function Dictionary (line 92) | Dictionary IEOS::titlestorage_interface_copy_file_metadata_at_index(Ref<...
  function Variant (line 135) | Variant IEOS::titlestorage_interface_read_file(Ref<RefCounted> p_options) {

FILE: src/user_info_interface.cpp
  function Dictionary (line 4) | Dictionary IEOS::user_info_interface_copy_external_user_info_by_account_...
  function Dictionary (line 26) | Dictionary IEOS::user_info_interface_copy_external_user_info_by_account_...
  function Dictionary (line 47) | Dictionary IEOS::user_info_interface_copy_external_user_info_by_index(Re...
  function Dictionary (line 68) | Dictionary IEOS::user_info_interface_copy_user_info(Ref<RefCounted> p_op...
  function Dictionary (line 178) | Dictionary IEOS::user_info_interface_copy_best_display_name(Ref<RefCount...
  function Dictionary (line 198) | Dictionary IEOS::user_info_interface_copy_best_display_name_with_platfor...

FILE: src/utils.cpp
  function String (line 3) | String eosg_epic_account_id_to_string(EOS_EpicAccountId accountId) {
  function String (line 23) | String eosg_product_user_id_to_string(EOS_ProductUserId localUserId) {

FILE: src/utils.h
  function EOS_EpicAccountId (line 53) | static EOS_EpicAccountId eosg_string_to_epic_account_id(const char *p_ac...
  function EOS_ProductUserId (line 60) | static EOS_ProductUserId eosg_string_to_product_user_id(const char *p_ac...
  function Variant (line 65) | static Variant eosg_auth_pin_grant_info_to_dict(const EOS_Auth_PinGrantI...
  function Variant (line 78) | static Variant eosg_continuance_token_to_wrapper(EOS_ContinuanceToken p_...
  function Variant (line 82) | static Variant eosg_auth_id_token_to_dict_and_release(EOS_Auth_IdToken *...
  function Variant (line 93) | static Variant eosg_connect_id_token_to_dict_and_release(EOS_Connect_IdT...
  function Variant (line 104) | static Variant eosg_auth_token_to_dict_and_release(EOS_Auth_Token *authT...
  function Variant (line 123) | static Variant eosg_connect_external_account_info_to_dict_and_release(EO...
  function Variant (line 138) | static Variant eosg_ecom_entitlement_to_dict_and_release(EOS_Ecom_Entitl...
  function Variant (line 154) | static Variant eosg_ecom_catalog_item_to_dict_and_release(EOS_Ecom_Catal...
  function Variant (line 174) | static Variant eosg_ecom_key_image_info_to_dict_and_release(EOS_Ecom_Key...
  function Variant (line 188) | static Variant eosg_ecom_catalog_release_to_dict_and_release(EOS_Ecom_Ca...
  function Variant (line 209) | static Variant eosg_ecom_catalog_offer_to_dict_and_release(EOS_Ecom_Cata...
  function Variant (line 236) | static Variant eosg_ecom_transaction_to_wrapper(EOS_Ecom_HTransaction p_...
  function Variant (line 240) | static Variant eosg_user_info_external_user_info_to_dict_and_release(EOS...
  function Variant (line 254) | static Variant eosg_user_info_user_info_to_dict_and_release(EOS_UserInfo...
  function Variant (line 270) | static Variant eosg_user_info_best_display_name_to_dict_and_release(EOS_...
  function Variant (line 285) | static Variant eosg_mods_mod_info_to_dict_and_release(EOS_Mods_ModInfo *...
  function Variant (line 313) | static Variant eosg_mods_mod_identifier_to_dict(const EOS_Mod_Identifier...
  function Variant (line 326) | static Variant eosg_presence_presence_info_to_dict_and_release(EOS_Prese...
  function Variant (line 355) | static Variant eosg_presence_presence_modification_to_wrapper(EOS_HPrese...
  function Variant (line 359) | static Variant eosg_achievements_definition_to_dict_and_release(EOS_Achi...
  function Variant (line 386) | static Variant eosg_achievements_player_achievement_to_dict_and_release(...
  function Variant (line 411) | static Variant eosg_stats_stat_to_dict_and_release(EOS_Stats_Stat *stat) {
  function Variant (line 424) | static Variant eosg_leaderboards_definition_to_dict_and_release(EOS_Lead...
  function Variant (line 438) | static Variant eosg_leaderboards_leaderboard_record_to_dict_and_release(...
  function Variant (line 451) | static Variant eosg_leaderboards_leaderboard_user_score_to_dict_and_rele...
  function Variant (line 462) | static Variant eosg_kws_permission_status_to_dict_and_release(EOS_KWS_Pe...
  function Variant (line 473) | static Variant eosg_lobby_details_info_to_dict_and_release(EOS_LobbyDeta...
  function Variant (line 499) | static Variant eosg_lobby_details_member_info_to_dict_and_release(EOS_Lo...
  function Variant (line 511) | static Variant eosg_lobby_attribute_data_to_dict(EOS_Lobby_AttributeData...
  function Variant (line 540) | static Variant eosg_lobby_attribute_to_dict_and_release(EOS_Lobby_Attrib...
  function Variant (line 551) | static Variant eosg_lobby_lobby_modification_to_wrapper(EOS_HLobbyModifi...
  function Variant (line 555) | static Variant eosg_lobby_lobby_search_to_wrapper(EOS_HLobbySearch lobby...
  function Variant (line 559) | static Variant eosg_lobby_lobby_details_to_wrapper(EOS_HLobbyDetails lob...
  function EOS_Lobby_LocalRTCOptions (line 563) | static EOS_Lobby_LocalRTCOptions eosg_variant_to_lobby_local_rtc_options...
  function Variant (line 594) | static Variant eosg_playerdatastorage_file_metadata_to_dict_and_release(...
  function Variant (line 609) | static Variant eosg_playerdatastorage_file_tranfer_request_to_wrapper(EO...
  function Variant (line 613) | static Variant eosg_titlestorage_file_metadata_to_dict_and_release(EOS_T...
  function Variant (line 627) | static Variant eosg_titlestorage_file_tranfer_request_to_wrapper(EOS_HTi...
  function Variant (line 631) | static Variant eosg_sanctions_player_sanction_to_dict_and_release(EOS_Sa...
  function Variant (line 645) | static Variant eosg_sessions_session_details_settings_to_dict(const EOS_...
  function Variant (line 666) | static Variant eosg_sessions_session_details_info_to_dict(const EOS_Sess...
  function Variant (line 681) | static Variant eosg_sessions_session_details_info_to_dict_and_release(EO...
  function Variant (line 687) | static Variant eosg_sessions_active_session_info_to_dict_and_release(EOS...
  function Variant (line 701) | static Variant eosg_sessions_attribute_data_to_dict(EOS_Sessions_Attribu...
  function Variant (line 727) | static Variant eosg_sessions_session_details_attribute_to_dict_and_relea...
  function Variant (line 739) | static Variant eosg_sessions_active_session_to_wrapper(EOS_HActiveSessio...
  function Variant (line 743) | static Variant eosg_sessions_session_details_to_wrapper(EOS_HSessionDeta...
  function Variant (line 747) | static Variant eosg_sessions_session_modification_to_wrapper(EOS_HSessio...
  function Variant (line 751) | static Variant eosg_sessions_session_search_to_wrapper(EOS_HSessionSearc...
  function Variant (line 755) | static Variant eosg_rtc_audio_input_device_information_to_dict_and_relea...
  function Variant (line 768) | static Variant eosg_rtc_audio_output_device_information_to_dict_and_rele...
  function Variant (line 781) | static Variant eosg_rtc_audio_audio_buffer_to_dict(EOS_RTCAudio_AudioBuf...

FILE: src/version_interface.cpp
  function String (line 4) | String IEOS::version_interface_get_version() {
  function Dictionary (line 8) | Dictionary IEOS::version_interface_get_constants() {
Condensed preview — 276 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,833K chars).
[
  {
    "path": ".clang-format",
    "chars": 1353,
    "preview": "# Commented out parameters are those with the same value as base LLVM style.\n# We can uncomment them if we want to chang"
  },
  {
    "path": ".editorconfig",
    "chars": 285,
    "preview": "# EditorConfig is awesome: https://EditorConfig.org\n\n# top-most EditorConfig file\nroot = true\n\n[*]\nindent_style = space\n"
  },
  {
    "path": ".gitattributes",
    "chars": 79,
    "preview": "# Normalize EOL for all files that Git considers text files.\n* text=auto eol=lf"
  },
  {
    "path": ".github/FUNDING.yml",
    "chars": 63,
    "preview": "github: 3ddelano\ncustom: https://www.buymeacoffee.com/3ddelano\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "chars": 756,
    "preview": "---\nname: Bug report\nabout: Create a report to help us improve\ntitle: ''\nlabels: ''\nassignees: 3ddelano\n\n---\n\n**Describe"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.md",
    "chars": 595,
    "preview": "---\nname: Feature request\nabout: Suggest an idea for this project\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n**Is your fea"
  },
  {
    "path": ".github/workflows/build.yml",
    "chars": 11418,
    "preview": "name: 🛠️ Builds\non:\n  workflow_dispatch:\n  push:\n    branches:\n      - \"*\"\n    tags:\n      - \"*\"\njobs:\n  build:\n    runs"
  },
  {
    "path": ".github/workflows/deploy-docs.yml",
    "chars": 1274,
    "preview": "name: Deploy Docs to GitHub Pages\n\non:\n  push:\n    branches:\n      - \"*\"\n    # Review gh actions docs if you want to fur"
  },
  {
    "path": ".gitignore",
    "chars": 226,
    "preview": "# Godot logs\nlogs/\n\ncache/\n.cache/\n\nsample/android\nsample/android_debug.keystore\n\n.DS_Store\n\n.env\nvc140.pdb\n.sconsign.db"
  },
  {
    "path": ".gitmodules",
    "chars": 218,
    "preview": "[submodule \"godot-cpp\"]\n\tpath = godot-cpp\n\turl = https://github.com/godotengine/godot-cpp\n\tbranch = 4.2\n[submodule \"thir"
  },
  {
    "path": ".pre-commit-config.yaml",
    "chars": 113,
    "preview": "repos:\n-   repo: https://github.com/ssciwr/clang-format-hook\n    rev: v16.0.2\n    hooks:\n    -   id: clang-format"
  },
  {
    "path": ".vscode/c_cpp_properties.json",
    "chars": 873,
    "preview": "{\n    \"configurations\": [\n        {\n            \"name\": \"Win32\",\n            \"includePath\": [\n                \"${workspa"
  },
  {
    "path": ".vscode/launch.json",
    "chars": 713,
    "preview": "{\n\t\"version\": \"0.2.0\",\n\t\"configurations\": [\n\t\t{\n\t\t\t\"name\": \"Debug Project (Windows)\",\n\t\t\t\"type\": \"cppvsdbg\",\n\t\t\t\"request"
  },
  {
    "path": ".vscode/settings.json",
    "chars": 807,
    "preview": "{\n  \"files.exclude\": {\n    \"**/*.obj\": true,\n    \"**/*.ilk\": true,\n    \"**/*.exp\": true,\n    \"**/*.pdb\": true,\n    \"**/_"
  },
  {
    "path": ".vscode/tasks.json",
    "chars": 514,
    "preview": "{\n    \"version\": \"2.0.0\",\n    \"tasks\": [\n        {\n            \"label\": \"build\",\n            \"group\": \"build\",\n         "
  },
  {
    "path": "LICENSE.md",
    "chars": 1071,
    "preview": "MIT License\n\nCopyright (c) 2022 Delano Lourenco\n\nPermission is hereby granted, free of charge, to any person obtaining a"
  },
  {
    "path": "README.md",
    "chars": 18262,
    "preview": "# Epic Online Services Godot (EOSG)\n\n<img alt=\"Project Logo\" src=\"./_media/logo.png\" height=\"150\">\n\n### Easiest way to u"
  },
  {
    "path": "SConstruct",
    "chars": 5164,
    "preview": "#!/usr/bin/env python\nimport os\nimport shutil\n\nenv = SConscript(\"godot-cpp/SConstruct\")\nlib_name = \"libeosg\"\nplugin_bin_"
  },
  {
    "path": "build-ios.sh",
    "chars": 2693,
    "preview": "#!/bin/sh\n\nbuild=yes\nif [ \"$1\" = \"build=n\" ] || [ \"$1\" = \"build=N\" ] || [ \"$1\" = \"build=no\" ] || [ \"$1\" = \"build=0\" ]; t"
  },
  {
    "path": "debug-entitlements.plist",
    "chars": 248,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "debug.cmd",
    "chars": 53,
    "preview": "@echo off\nscons dev_build=yes && godot4 --path sample"
  },
  {
    "path": "debug.sh",
    "chars": 44,
    "preview": "scons dev_build=yes && godot45 --path sample"
  },
  {
    "path": "docs/.gitignore",
    "chars": 233,
    "preview": "# Dependencies\n/node_modules\n\n# Production\n/build\n\n# Generated files\n.docusaurus\n.cache-loader\n\n# Misc\n.DS_Store\n.env.lo"
  },
  {
    "path": "docs/README.md",
    "chars": 768,
    "preview": "# Website\n\nThis website is built using [Docusaurus](https://docusaurus.io/), a modern static website generator.\n\n### Ins"
  },
  {
    "path": "docs/docs/installation.md",
    "chars": 1531,
    "preview": "# Installation\n\n## Method 1: Install from Asset Library (Recommended)\n\n[View the plugin on Godot Asset Library](https://"
  },
  {
    "path": "docs/docs/introduction.md",
    "chars": 1136,
    "preview": "# Introduction\n\nEpic Online Services Godot (EOSG) is the easiest way to integrate Epic Online Services into your Godot p"
  },
  {
    "path": "docs/docs/sample-project.md",
    "chars": 2228,
    "preview": "# Sample Project\n\nTo run the sample project which showcases most of the EOS features, follow these steps:\n\n1. Clone/Down"
  },
  {
    "path": "docs/docs/topics/authentication.md",
    "chars": 40,
    "preview": "# Authentication\n\nWIP - Work In Progress"
  },
  {
    "path": "docs/docs/topics/initialization.md",
    "chars": 8258,
    "preview": "import ReactPlayer from 'react-player'\n\n# Initialization\n\nFollow the steps below to initialize and use the plugin.\n\nChec"
  },
  {
    "path": "docs/docs/update-guide.md",
    "chars": 408,
    "preview": "# Update Guide\n\nFollow these steps to update to a newer version of the plugin:\n\n1. Disable the plugin in the Editor in `"
  },
  {
    "path": "docs/docusaurus.config.ts",
    "chars": 2951,
    "preview": "import { themes as prismThemes } from \"prism-react-renderer\";\nimport type { Config } from \"@docusaurus/types\";\nimport ty"
  },
  {
    "path": "docs/package.json",
    "chars": 1383,
    "preview": "{\n  \"name\": \"docs\",\n  \"version\": \"0.0.0\",\n  \"private\": true,\n  \"scripts\": {\n    \"docusaurus\": \"docusaurus\",\n    \"start\":"
  },
  {
    "path": "docs/postcss.config.js",
    "chars": 65,
    "preview": "module.exports = {\n\tplugins: {\n\t\t'@tailwindcss/postcss': {},\n\t}\n}"
  },
  {
    "path": "docs/sidebars.ts",
    "chars": 936,
    "preview": "import type { SidebarsConfig } from '@docusaurus/plugin-content-docs';\n\n// This runs in Node.js - Don't use client-side "
  },
  {
    "path": "docs/src/components/ExampleSection.tsx",
    "chars": 2718,
    "preview": "import CodeBlock from \"@theme/CodeBlock\";\n\nconst codeExample = `\n# In main script\nextends Node\n\nfunc _ready() -> void:\n "
  },
  {
    "path": "docs/src/components/FeaturesSection.tsx",
    "chars": 2907,
    "preview": "const FEATURES = [\n  \"Authentication\",\n  \"Social Overlay (Win)\",\n  \"Achievements\",\n  \"Stats & Leaderboards\",\n  \"Lobby & "
  },
  {
    "path": "docs/src/components/HeroSection.tsx",
    "chars": 3872,
    "preview": "import useDocusaurusContext from \"@docusaurus/useDocusaurusContext\";\nimport { GodotIcon, EpicIcon } from \"../components/"
  },
  {
    "path": "docs/src/components/Icons.tsx",
    "chars": 15416,
    "preview": "export function GodotIcon({ className = \"w-4 h-4\" }) {\n  return (\n    <svg\n      xmlns=\"http://www.w3.org/2000/svg\"\n    "
  },
  {
    "path": "docs/src/components/InfoSections.tsx",
    "chars": 5773,
    "preview": "export function HowItWorksSection() {\n  return (\n    <section id=\"how-it-works\" className=\"py-16 sm:py-20 bg-gray-950\">\n"
  },
  {
    "path": "docs/src/components/Layout.tsx",
    "chars": 7177,
    "preview": "import { useState } from \"react\";\n\n// Navigation links data\nconst NAV_LINKS = [\n  {\n    label: \"Docs\",\n    href: \"docs/i"
  },
  {
    "path": "docs/src/components/MainSystemsSection.tsx",
    "chars": 4249,
    "preview": "const MAIN_SYSTEMS = [\n  {\n    title: \"High Level EOS\",\n    tag: \"Recommended\",\n    description:\n      \"Provides easy-to"
  },
  {
    "path": "docs/src/components/MediaSections.tsx",
    "chars": 4759,
    "preview": "const SCREENSHOTS_DATA = [\n  {\n    category: \"Windows\",\n    images: [\n      {\n        src: \"img/screenshots/windows_auth"
  },
  {
    "path": "docs/src/components/SupportSection.tsx",
    "chars": 3797,
    "preview": "const SUPPORT_DATA = {\n  bmc_url: \"https://www.buymeacoffee.com/3ddelano\",\n  github_sponsor_url: \"https://github.com/spo"
  },
  {
    "path": "docs/src/css/custom.css",
    "chars": 6915,
    "preview": "@import \"tailwindcss\";\n\n@import url(\"https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;500;600;700&family=Jet"
  },
  {
    "path": "docs/src/pages/index.tsx",
    "chars": 795,
    "preview": "import { HeroSection } from \"../components/HeroSection\";\nimport { MainSystemsSection } from \"../components/MainSystemsSe"
  },
  {
    "path": "docs/src/pages/showcase.md",
    "chars": 1904,
    "preview": "---\n---\n\n# Showcase\n\nHere is a list of games using the Epic Online Services Godot plugin. If you are using this plugin a"
  },
  {
    "path": "docs/src/plugins/tailwind-config.ts",
    "chars": 233,
    "preview": "module.exports = function tailwindPlugin(context, options) {\n\treturn {\n\t  name: 'tailwind-plugin',\n\t  configurePostCss(p"
  },
  {
    "path": "docs/static/.nojekyll",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "docs/tsconfig.json",
    "chars": 215,
    "preview": "{\n  // This file is not used in compilation. It is here just for a nice editor experience.\n  \"extends\": \"@docusaurus/tsc"
  },
  {
    "path": "function_analyzer.py",
    "chars": 3119,
    "preview": "# eos_function_usage_checker.py\n\nimport os\nimport re\n\n\n# Function to extract function names from the EOS C SDK header fi"
  },
  {
    "path": "sample/.gitignore",
    "chars": 77,
    "preview": ".import/\nexport.cfg\nexport_presets.cfg\n*.translation\n\n.godot/\n\n*.env\n*.import"
  },
  {
    "path": "sample/AntiCheatServerMain.gd",
    "chars": 4139,
    "preview": "class_name AntiCheatServerMain\nextends Node\n\n@onready var PRODUCT_NAME: String = Env.get_var(\"PRODUCT_NAME\")\n@onready va"
  },
  {
    "path": "sample/AntiCheatServerMain.gd.uid",
    "chars": 20,
    "preview": "uid://clbqhgyalkxuw\n"
  },
  {
    "path": "sample/Main.gd",
    "chars": 4349,
    "preview": "extends Control\n\n@onready var PRODUCT_NAME: String = Env.get_var(\"PRODUCT_NAME\") # Paste your own instead of Env.get_var"
  },
  {
    "path": "sample/Main.gd.uid",
    "chars": 20,
    "preview": "uid://cf8kvjx2nbysy\n"
  },
  {
    "path": "sample/Main.tscn",
    "chars": 10648,
    "preview": "[gd_scene load_steps=25 format=3 uid=\"uid://gcoi8ld0uvkl\"]\n\n[ext_resource type=\"Theme\" uid=\"uid://dwns7wwoyi1hy\" path=\"r"
  },
  {
    "path": "sample/addons/epic-online-services-godot/base_class.gd",
    "chars": 348,
    "preview": "## Copyright (c) 2022-present Delano Lourenco\n## https://github.com/3ddelano/dataclasses-godot\n## MIT License\n## See Lic"
  },
  {
    "path": "sample/addons/epic-online-services-godot/base_class.gd.uid",
    "chars": 19,
    "preview": "uid://g1ij604ak57v\n"
  },
  {
    "path": "sample/addons/epic-online-services-godot/bin/.gitignore",
    "chars": 13,
    "preview": "*\n!.gitignore"
  },
  {
    "path": "sample/addons/epic-online-services-godot/dataclass.gd",
    "chars": 7188,
    "preview": "## Copyright (c) 2022-present Delano Lourenco\n## https://github.com/3ddelano/dataclasses-godot\n## MIT License\n## See Lic"
  },
  {
    "path": "sample/addons/epic-online-services-godot/dataclass.gd.uid",
    "chars": 20,
    "preview": "uid://d4hmupfn3ooqp\n"
  },
  {
    "path": "sample/addons/epic-online-services-godot/eos.gd",
    "chars": 136207,
    "preview": "# Copyright (c) 2023-present Delano Lourenco\n# https://github.com/3ddelano/epic-online-services-godot/\n# MIT License\n\n##"
  },
  {
    "path": "sample/addons/epic-online-services-godot/eos.gd.uid",
    "chars": 19,
    "preview": "uid://idtj8sepvkjw\n"
  },
  {
    "path": "sample/addons/epic-online-services-godot/eosg.gdextension",
    "chars": 2084,
    "preview": "[configuration]\n\nentry_symbol = \"eosg_library_init\"\ncompatibility_minimum = 4.1\n\n[libraries]\nlinux.debug.x86_64 = \"bin/l"
  },
  {
    "path": "sample/addons/epic-online-services-godot/eosg.gdextension.uid",
    "chars": 20,
    "preview": "uid://dwyvkkxk32w36\n"
  },
  {
    "path": "sample/addons/epic-online-services-godot/export_plugin.gd",
    "chars": 860,
    "preview": "# Copyright (c) 2023-present Delano Lourenco\n# https://github.com/3ddelano/epic-online-services-godot/\n# MIT License\n@to"
  },
  {
    "path": "sample/addons/epic-online-services-godot/export_plugin.gd.uid",
    "chars": 20,
    "preview": "uid://bydaf5hf76858\n"
  },
  {
    "path": "sample/addons/epic-online-services-godot/heos/hachievement_data.gd",
    "chars": 2598,
    "preview": "## Achievement data from Epic Online Services\nclass_name HAchievementData\nextends BaseClass\n\n\nfunc _init() -> void:\n\tsup"
  },
  {
    "path": "sample/addons/epic-online-services-godot/heos/hachievement_data.gd.uid",
    "chars": 19,
    "preview": "uid://we6ap3yuu378\n"
  },
  {
    "path": "sample/addons/epic-online-services-godot/heos/hachievements.gd",
    "chars": 5810,
    "preview": "extends Node\n\n#region Signals\n\n## Emitted when an achievement is unlocked\n## data has the following keys: achievement_id"
  },
  {
    "path": "sample/addons/epic-online-services-godot/heos/hachievements.gd.uid",
    "chars": 20,
    "preview": "uid://bis404dty5u5c\n"
  },
  {
    "path": "sample/addons/epic-online-services-godot/heos/hauth.gd",
    "chars": 21418,
    "preview": "# Good article about the EOS login flows: https://eoshelp.epicgames.com/s/article/What-is-the-correct-login-flow-for-a-g"
  },
  {
    "path": "sample/addons/epic-online-services-godot/heos/hauth.gd.uid",
    "chars": 19,
    "preview": "uid://786t1jiowvvg\n"
  },
  {
    "path": "sample/addons/epic-online-services-godot/heos/hcredentials.gd",
    "chars": 898,
    "preview": "## Credentials required by Epic Online Services. Get these values from the [url=https://dev.epicgames.com/portal/en-US/]"
  },
  {
    "path": "sample/addons/epic-online-services-godot/heos/hcredentials.gd.uid",
    "chars": 20,
    "preview": "uid://dh3dlxnt075r2\n"
  },
  {
    "path": "sample/addons/epic-online-services-godot/heos/hfriends.gd",
    "chars": 1313,
    "preview": "extends Node\n\n#region Signals\n\n#endregion\n\n\n#region Public vars\n\n#endregion\n\n\n#region Private vars \n\nvar _log = HLog.log"
  },
  {
    "path": "sample/addons/epic-online-services-godot/heos/hfriends.gd.uid",
    "chars": 19,
    "preview": "uid://uumqbey8ji5t\n"
  },
  {
    "path": "sample/addons/epic-online-services-godot/heos/hleaderboards.gd",
    "chars": 3572,
    "preview": "extends Node\n\n#region Signals\n\n#endregion\n\n\n#region Public vars\n\n#endregion\n\n\n#region Private vars \n\nvar _log = HLog.log"
  },
  {
    "path": "sample/addons/epic-online-services-godot/heos/hleaderboards.gd.uid",
    "chars": 20,
    "preview": "uid://b06khhf20mplm\n"
  },
  {
    "path": "sample/addons/epic-online-services-godot/heos/hlobbies.gd",
    "chars": 6769,
    "preview": "extends Node\n\n\n#region Public vars\n\n## The maximum number of lobbies to return in search calls.[br]\n## Except for [metho"
  },
  {
    "path": "sample/addons/epic-online-services-godot/heos/hlobbies.gd.uid",
    "chars": 19,
    "preview": "uid://6iqvm33q0tb1\n"
  },
  {
    "path": "sample/addons/epic-online-services-godot/heos/hlobby.gd",
    "chars": 25390,
    "preview": "## A high-level lobby wrapper for EOSG\nclass_name HLobby\nextends BaseClass\n\n\n#region Signals\n\n## Emitted when anything a"
  },
  {
    "path": "sample/addons/epic-online-services-godot/heos/hlobby.gd.uid",
    "chars": 20,
    "preview": "uid://dk65c5tvqlm1a\n"
  },
  {
    "path": "sample/addons/epic-online-services-godot/heos/hlobbymember.gd",
    "chars": 5900,
    "preview": "## A high-level lobby member wrapper for EOSG\nclass_name HLobbyMember\nextends BaseClass\n\n\n#region Signals\n\n## Emitted wh"
  },
  {
    "path": "sample/addons/epic-online-services-godot/heos/hlobbymember.gd.uid",
    "chars": 20,
    "preview": "uid://brdkf3u56ylbk\n"
  },
  {
    "path": "sample/addons/epic-online-services-godot/heos/hlog.gd",
    "chars": 3113,
    "preview": "## Used for logging by HEOS classes\n##\n## See also [EOS.Logging] for EOS SDK logging\nclass_name HLog\nextends RefCounted\n"
  },
  {
    "path": "sample/addons/epic-online-services-godot/heos/hlog.gd.uid",
    "chars": 20,
    "preview": "uid://cke8udaaf4kka\n"
  },
  {
    "path": "sample/addons/epic-online-services-godot/heos/hp2p.gd",
    "chars": 2727,
    "preview": "extends Node\n\n\n#region Public vars\n\n\n#endregion\n\n\n#region Private vars \n\nvar _log = HLog.logger(\"HP2P\")\n\n#endregion\n\n\n#r"
  },
  {
    "path": "sample/addons/epic-online-services-godot/heos/hp2p.gd.uid",
    "chars": 19,
    "preview": "uid://u6ae5fpm6l8q\n"
  },
  {
    "path": "sample/addons/epic-online-services-godot/heos/hplatform.gd",
    "chars": 6301,
    "preview": "extends Node\n\n#region Signals\n\n## Emitted when the EOS platform was initialized successfully\nsignal platform_initialized"
  },
  {
    "path": "sample/addons/epic-online-services-godot/heos/hplatform.gd.uid",
    "chars": 19,
    "preview": "uid://yl2muvqrdiud\n"
  },
  {
    "path": "sample/addons/epic-online-services-godot/heos/hsessions.gd",
    "chars": 4376,
    "preview": "extends Node\n\n\n#region Public vars\n\nvar max_search_results = 25\n\n#endregion\n\n\n#region Private vars \n\nvar _log = HLog.log"
  },
  {
    "path": "sample/addons/epic-online-services-godot/heos/hsessions.gd.uid",
    "chars": 20,
    "preview": "uid://bieh2rxxahuu2\n"
  },
  {
    "path": "sample/addons/epic-online-services-godot/heos/hstats.gd",
    "chars": 2113,
    "preview": "extends Node\n\n#region Signals\n\n#endregion\n\n\n#region Public vars\n\n#endregion\n\n\n#region Private vars \n\nvar _log = HLog.log"
  },
  {
    "path": "sample/addons/epic-online-services-godot/heos/hstats.gd.uid",
    "chars": 20,
    "preview": "uid://dbckdip83oone\n"
  },
  {
    "path": "sample/addons/epic-online-services-godot/plugin.cfg",
    "chars": 203,
    "preview": "[plugin]\n\nname = \"Epic Online Services Godot 4.2+ (EOSG)\"\ndescription = \"Unofficial Epic Online Services for Godot 4.2+ "
  },
  {
    "path": "sample/addons/epic-online-services-godot/plugin.gd",
    "chars": 1683,
    "preview": "# Copyright (c) 2023-present Delano Lourenco\n# https://github.com/3ddelano/epic-online-services-godot/\n# MIT License\n@to"
  },
  {
    "path": "sample/addons/epic-online-services-godot/plugin.gd.uid",
    "chars": 20,
    "preview": "uid://c2bh2munh5110\n"
  },
  {
    "path": "sample/addons/epic-online-services-godot/runtime.gd",
    "chars": 959,
    "preview": "# Copyright (c) 2023-present Delano Lourenco\n# https://github.com/3ddelano/epic-online-services-godot/\n# MIT License\n## "
  },
  {
    "path": "sample/addons/epic-online-services-godot/runtime.gd.uid",
    "chars": 19,
    "preview": "uid://7saywdx0ipep\n"
  },
  {
    "path": "sample/components/StyledPopupWindow/StyledPopupWindow.gd",
    "chars": 213,
    "preview": "class_name StyledPopupWindow\nextends PopupPanel\n\n\n@onready var _close_btn = %CloseBtn\n@onready var _title = %Title\n\n\nfun"
  },
  {
    "path": "sample/components/StyledPopupWindow/StyledPopupWindow.gd.uid",
    "chars": 19,
    "preview": "uid://467nklflb1n8\n"
  },
  {
    "path": "sample/components/StyledPopupWindow/StyledPopupWindow.tscn",
    "chars": 2191,
    "preview": "[gd_scene load_steps=4 format=3 uid=\"uid://dkprjbptror6n\"]\n\n[ext_resource type=\"Theme\" uid=\"uid://dwns7wwoyi1hy\" path=\"r"
  },
  {
    "path": "sample/components/StyledPopupWindow/StyledPopupWindowTheme.tres",
    "chars": 485208,
    "preview": "[gd_resource type=\"Theme\" load_steps=26 format=4 uid=\"uid://dwns7wwoyi1hy\"]\n\n[ext_resource type=\"Texture2D\" uid=\"uid://b"
  },
  {
    "path": "sample/dedicated_server_example/client_main.gd",
    "chars": 2816,
    "preview": "extends Control\n\n@onready var PRODUCT_NAME: String = Env.get_var(\"PRODUCT_NAME\")\n@onready var PRODUCT_VERSION: String = "
  },
  {
    "path": "sample/dedicated_server_example/client_main.gd.uid",
    "chars": 19,
    "preview": "uid://3nyw0hwkkgmg\n"
  },
  {
    "path": "sample/dedicated_server_example/client_main.tscn",
    "chars": 377,
    "preview": "[gd_scene load_steps=2 format=3 uid=\"uid://dve4hhbpclrm5\"]\n\n[ext_resource type=\"Script\" uid=\"uid://3nyw0hwkkgmg\" path=\"r"
  },
  {
    "path": "sample/dedicated_server_example/server_main.gd",
    "chars": 3242,
    "preview": "extends Control\n\n\n@onready var PRODUCT_NAME: String = Env.get_var(\"PRODUCT_NAME\")\n@onready var PRODUCT_VERSION: String ="
  },
  {
    "path": "sample/dedicated_server_example/server_main.gd.uid",
    "chars": 20,
    "preview": "uid://bneij5syrcl1f\n"
  },
  {
    "path": "sample/dedicated_server_example/server_main.tscn",
    "chars": 378,
    "preview": "[gd_scene load_steps=2 format=3 uid=\"uid://dyuj4qlamg7b5\"]\n\n[ext_resource type=\"Script\" uid=\"uid://bneij5syrcl1f\" path=\""
  },
  {
    "path": "sample/default_bus_layout.tres",
    "chars": 422,
    "preview": "[gd_resource type=\"AudioBusLayout\" load_steps=2 format=3 uid=\"uid://dfiyvl4a8dbhr\"]\n\n[sub_resource type=\"AudioEffectCapt"
  },
  {
    "path": "sample/default_env.tres",
    "chars": 170,
    "preview": "[gd_resource type=\"Environment\" load_steps=2 format=3 uid=\"uid://cdoy56rtiqovw\"]\n\n[sub_resource type=\"Sky\" id=\"1\"]\n\n[res"
  },
  {
    "path": "sample/fonts/roboto-13r.tres",
    "chars": 391,
    "preview": "[gd_resource type=\"FontFile\" load_steps=2 format=3 uid=\"uid://da6bpapjl4a5k\"]\n\n[ext_resource type=\"FontFile\" uid=\"uid://"
  },
  {
    "path": "sample/fonts/roboto-16b.tres",
    "chars": 544,
    "preview": "[gd_resource type=\"FontFile\" load_steps=2 format=3 uid=\"uid://bghbav6kh0lsl\"]\n\n[ext_resource type=\"FontFile\" uid=\"uid://"
  },
  {
    "path": "sample/fonts/roboto-16r.tres",
    "chars": 546,
    "preview": "[gd_resource type=\"FontFile\" load_steps=2 format=3 uid=\"uid://bxcl265jykrk0\"]\n\n[ext_resource type=\"FontFile\" uid=\"uid://"
  },
  {
    "path": "sample/fonts/roboto-32b.tres",
    "chars": 543,
    "preview": "[gd_resource type=\"FontFile\" load_steps=2 format=3 uid=\"uid://njn2rf7rj4ph\"]\n\n[ext_resource type=\"FontFile\" uid=\"uid://d"
  },
  {
    "path": "sample/game/entities/bullet/bullet.gd",
    "chars": 599,
    "preview": "class_name Bullet\nextends Area2D\n\n\nconst SPEED = 2000.0\n\n\nvar dmg_amt = 25\nvar owner_peer_id: int\nvar owner_puid: String"
  },
  {
    "path": "sample/game/entities/bullet/bullet.gd.uid",
    "chars": 19,
    "preview": "uid://83g60od7sqbn\n"
  },
  {
    "path": "sample/game/entities/bullet/bullet.tscn",
    "chars": 1127,
    "preview": "[gd_scene load_steps=4 format=3 uid=\"uid://b8clmnksfigve\"]\n\n[ext_resource type=\"Script\" uid=\"uid://83g60od7sqbn\" path=\"r"
  },
  {
    "path": "sample/game/entities/player/player.gd",
    "chars": 2333,
    "preview": "class_name Player\nextends CharacterBody2D\n\n\nsignal health_changed\nsignal died(player, killing_peer_id: int)\n\n\nconst SPEE"
  },
  {
    "path": "sample/game/entities/player/player.gd.uid",
    "chars": 20,
    "preview": "uid://cwybnfn6dv66t\n"
  },
  {
    "path": "sample/game/entities/player/player.tscn",
    "chars": 1908,
    "preview": "[gd_scene load_steps=6 format=3 uid=\"uid://d25l4fa1sffqk\"]\n\n[ext_resource type=\"Script\" uid=\"uid://cwybnfn6dv66t\" path=\""
  },
  {
    "path": "sample/game/entities/wall/wall.tscn",
    "chars": 785,
    "preview": "[gd_scene load_steps=3 format=3 uid=\"uid://dnt3dorvwuw5y\"]\n\n[sub_resource type=\"RectangleShape2D\" id=\"RectangleShape2D_0"
  },
  {
    "path": "sample/game/maps/map_bellandur.tscn",
    "chars": 3439,
    "preview": "[gd_scene load_steps=4 format=4 uid=\"uid://cq20ci5f675b8\"]\n\n[ext_resource type=\"PackedScene\" uid=\"uid://dnt3dorvwuw5y\" p"
  },
  {
    "path": "sample/game/maps/map_margao.tscn",
    "chars": 3081,
    "preview": "[gd_scene load_steps=4 format=4 uid=\"uid://d25abb5oqolnx\"]\n\n[ext_resource type=\"PackedScene\" uid=\"uid://dnt3dorvwuw5y\" p"
  },
  {
    "path": "sample/game/maps/map_new_york.tscn",
    "chars": 3884,
    "preview": "[gd_scene load_steps=4 format=4 uid=\"uid://cutu8g5suwurd\"]\n\n[ext_resource type=\"PackedScene\" uid=\"uid://dnt3dorvwuw5y\" p"
  },
  {
    "path": "sample/project.godot",
    "chars": 4148,
    "preview": "; Engine configuration file.\n; It's best edited using the editor UI and not directly,\n; since the parameters that go her"
  },
  {
    "path": "sample/scenes/AchievementsView/AchievementPopup.gd",
    "chars": 2345,
    "preview": "class_name AchievementPopup\nextends StyledPopupWindow\n\n@onready var id_label = $VB/MC/VB/GridContainer/IdLabel\n@onready "
  },
  {
    "path": "sample/scenes/AchievementsView/AchievementPopup.gd.uid",
    "chars": 20,
    "preview": "uid://b8fpdhlcd5vf2\n"
  },
  {
    "path": "sample/scenes/AchievementsView/AchievementUnlockNotification.gd",
    "chars": 848,
    "preview": "class_name AchievementUnlockNotification\nextends Control\n\nvar _data: HAchievementData\n\n@onready var id_label = $MC/HB/VB"
  },
  {
    "path": "sample/scenes/AchievementsView/AchievementUnlockNotification.gd.uid",
    "chars": 20,
    "preview": "uid://dnm64cf611a0h\n"
  },
  {
    "path": "sample/scenes/AchievementsView/AchievementUnlockNotification.tscn",
    "chars": 3264,
    "preview": "[gd_scene load_steps=6 format=3 uid=\"uid://b7hrrwwvjqycs\"]\n\n[ext_resource type=\"PackedScene\" uid=\"uid://djhhnis3ksdjk\" p"
  },
  {
    "path": "sample/scenes/AchievementsView/AchievementsList.gd",
    "chars": 766,
    "preview": "class_name AchievementsList\nextends MarginContainer\n\nsignal achievement_pressed(node)\n\nconst ACHIEVEMENTS_LIST_ACHIEVEME"
  },
  {
    "path": "sample/scenes/AchievementsView/AchievementsList.gd.uid",
    "chars": 18,
    "preview": "uid://27jk4xa1yfq\n"
  },
  {
    "path": "sample/scenes/AchievementsView/AchievementsListAchievement.gd",
    "chars": 663,
    "preview": "class_name AchievementsListAchievement\nextends MarginContainer\n\n# warning-ignore:unused_signal\nsignal pressed(_self)\n\n@o"
  },
  {
    "path": "sample/scenes/AchievementsView/AchievementsListAchievement.gd.uid",
    "chars": 20,
    "preview": "uid://cuosdhat5m7tg\n"
  },
  {
    "path": "sample/scenes/AchievementsView/AchievementsListAchievement.tscn",
    "chars": 2215,
    "preview": "[gd_scene load_steps=5 format=3 uid=\"uid://blvi28uiveh0a\"]\n\n[ext_resource type=\"Script\" uid=\"uid://cuosdhat5m7tg\" path=\""
  },
  {
    "path": "sample/scenes/AchievementsView/AchievementsView.gd",
    "chars": 1894,
    "preview": "class_name AchievementsView\nextends VBoxContainer\n\n# Local cache of achievements\nvar achievements = {}\n\n@onready var _ac"
  },
  {
    "path": "sample/scenes/AchievementsView/AchievementsView.gd.uid",
    "chars": 20,
    "preview": "uid://cjhi71075hj1y\n"
  },
  {
    "path": "sample/scenes/AchievementsView/AchievementsView.tscn",
    "chars": 7293,
    "preview": "[gd_scene load_steps=12 format=3 uid=\"uid://d3hxdkoy73pf1\"]\n\n[ext_resource type=\"Script\" uid=\"uid://cjhi71075hj1y\" path="
  },
  {
    "path": "sample/scenes/CustomInvitesView/CustomInvitesView.gd",
    "chars": 3515,
    "preview": "class_name CustomInvitesView\nextends VBoxContainer\n\n@onready var payload_textedit = %PayloadTextEdit\n@onready var send_i"
  },
  {
    "path": "sample/scenes/CustomInvitesView/CustomInvitesView.gd.uid",
    "chars": 20,
    "preview": "uid://ddkxgj5m43swv\n"
  },
  {
    "path": "sample/scenes/CustomInvitesView/CustomInvitesView.tscn",
    "chars": 1182,
    "preview": "[gd_scene load_steps=4 format=3 uid=\"uid://d2bkej1dakv6s\"]\n\n[ext_resource type=\"Script\" uid=\"uid://ddkxgj5m43swv\" path=\""
  },
  {
    "path": "sample/scenes/FriendsView/FriendsView.gd",
    "chars": 1275,
    "preview": "class_name FriendsView\nextends VBoxContainer\n\n# Local cache of friends data\nvar friends = []\n\n@onready var list_title_ri"
  },
  {
    "path": "sample/scenes/FriendsView/FriendsView.gd.uid",
    "chars": 20,
    "preview": "uid://dx8eth83tfuvn\n"
  },
  {
    "path": "sample/scenes/FriendsView/FriendsView.tscn",
    "chars": 1782,
    "preview": "[gd_scene load_steps=5 format=3 uid=\"uid://t016k2yh382d\"]\n\n[ext_resource type=\"Script\" uid=\"uid://dx8eth83tfuvn\" path=\"r"
  },
  {
    "path": "sample/scenes/LeaderboardsView/LeaderboardsView.gd",
    "chars": 2370,
    "preview": "class_name LeaderboardsView\nextends VBoxContainer\n\n# Local cache of leaderboard data\nvar leaderboards = []\n\n@onready var"
  },
  {
    "path": "sample/scenes/LeaderboardsView/LeaderboardsView.gd.uid",
    "chars": 20,
    "preview": "uid://dkhn2a8wdwx21\n"
  },
  {
    "path": "sample/scenes/LeaderboardsView/LeaderboardsView.tscn",
    "chars": 1922,
    "preview": "[gd_scene load_steps=6 format=3 uid=\"uid://5xrk7nvpwosj\"]\n\n[ext_resource type=\"Script\" uid=\"uid://dkhn2a8wdwx21\" path=\"r"
  },
  {
    "path": "sample/scenes/LobbiesView/CreateLobbyPopup.gd",
    "chars": 3131,
    "preview": "class_name CreateLobbyPopup\nextends StyledPopupWindow\n\n\n@onready var _bucket_id: LineEdit = %BucketId\n@onready var _map_"
  },
  {
    "path": "sample/scenes/LobbiesView/CreateLobbyPopup.gd.uid",
    "chars": 20,
    "preview": "uid://csdajb1e07h18\n"
  },
  {
    "path": "sample/scenes/LobbiesView/CreateLobbyPopup.tscn",
    "chars": 2562,
    "preview": "[gd_scene load_steps=4 format=3 uid=\"uid://bmxf7kdhjlip6\"]\n\n[ext_resource type=\"PackedScene\" uid=\"uid://dkprjbptror6n\" p"
  },
  {
    "path": "sample/scenes/LobbiesView/CurrentLobby.gd",
    "chars": 10790,
    "preview": "class_name CurrentLobby\nextends VBoxContainer\n\n@onready var id_label: LineEdit = %IdLabel\n@onready var owner_label: Line"
  },
  {
    "path": "sample/scenes/LobbiesView/CurrentLobby.gd.uid",
    "chars": 20,
    "preview": "uid://dscovu6epeb5t\n"
  },
  {
    "path": "sample/scenes/LobbiesView/LobbiesView.gd",
    "chars": 1589,
    "preview": "class_name LobbiesView\nextends VBoxContainer\n\n\nenum Maps {\n\tMargao,\n\tBellandur,\n\tNewYork,\n}\n\nconst Skins = {\n\tHuman = \"H"
  },
  {
    "path": "sample/scenes/LobbiesView/LobbiesView.gd.uid",
    "chars": 20,
    "preview": "uid://c3mc2b4nqvb5v\n"
  },
  {
    "path": "sample/scenes/LobbiesView/LobbiesView.tscn",
    "chars": 10723,
    "preview": "[gd_scene load_steps=11 format=3 uid=\"uid://dsiyt23hnmngd\"]\n\n[ext_resource type=\"Script\" uid=\"uid://c3mc2b4nqvb5v\" path="
  },
  {
    "path": "sample/scenes/LobbiesView/SearchLobby.gd",
    "chars": 2674,
    "preview": "extends HBoxContainer\n\n#region Enums\n\nconst SearchType = {\n\tMap = \"Map\",\n\tBucketId = \"BucketId\",\n\tLobbyId = \"LobbyId\",\n\t"
  },
  {
    "path": "sample/scenes/LobbiesView/SearchLobby.gd.uid",
    "chars": 20,
    "preview": "uid://bjqvw2f6qq5vu\n"
  },
  {
    "path": "sample/scenes/LobbiesView/SearchLobbyResults.gd",
    "chars": 1944,
    "preview": "class_name SearchLobbyResults\nextends VBoxContainer\n\nconst GRID_CONTAINER_LABELS_COUNT = 4\n\n\nvar search_results: Array[H"
  },
  {
    "path": "sample/scenes/LobbiesView/SearchLobbyResults.gd.uid",
    "chars": 20,
    "preview": "uid://c42grjipjn5g0\n"
  },
  {
    "path": "sample/scenes/LoginView/EnterCredentials.gd",
    "chars": 1214,
    "preview": "extends VBoxContainer\n\n\nsignal perform_login\n\n@onready var id_label = $IdLabel\n@onready var token_label = $TokenLabel\n\n@"
  },
  {
    "path": "sample/scenes/LoginView/EnterCredentials.gd.uid",
    "chars": 20,
    "preview": "uid://bx0bhh73kw3q7\n"
  },
  {
    "path": "sample/scenes/LoginView/LoginView.gd",
    "chars": 5745,
    "preview": "class_name LoginView\nextends CenterContainer\n\n#region Enums\n\nenum States {\n\tChooseMethod,\n\tEnterCredentials,\n\tPending,\n\t"
  },
  {
    "path": "sample/scenes/LoginView/LoginView.gd.uid",
    "chars": 20,
    "preview": "uid://dwpfnhluy8h4e\n"
  },
  {
    "path": "sample/scenes/LoginView/LoginView.tscn",
    "chars": 6514,
    "preview": "[gd_scene load_steps=15 format=3 uid=\"uid://bht0ln2ftshrw\"]\n\n[ext_resource type=\"FontFile\" uid=\"uid://njn2rf7rj4ph\" path"
  },
  {
    "path": "sample/scenes/LogsView/LogsView.gd",
    "chars": 1347,
    "preview": "class_name LogsView\nextends VBoxContainer\n\n@onready var logs_label = %LogsLabel\n\nfunc _ready() -> void:\n\tHPlatform.log_m"
  },
  {
    "path": "sample/scenes/LogsView/LogsView.gd.uid",
    "chars": 20,
    "preview": "uid://b54ebdyvahtmv\n"
  },
  {
    "path": "sample/scenes/LogsView/LogsView.tscn",
    "chars": 1712,
    "preview": "[gd_scene load_steps=6 format=3 uid=\"uid://cl2qvlvdhn2iw\"]\n\n[ext_resource type=\"FontFile\" uid=\"uid://da6bpapjl4a5k\" path"
  },
  {
    "path": "sample/scenes/MetricsView/MetricsView.gd",
    "chars": 1692,
    "preview": "class_name MetricView\nextends VBoxContainer\n\n@onready var begin_player_session_btn = %BeginPlayerSessionBtn\n@onready var"
  },
  {
    "path": "sample/scenes/MetricsView/MetricsView.gd.uid",
    "chars": 20,
    "preview": "uid://b081ugrjtk51r\n"
  },
  {
    "path": "sample/scenes/MetricsView/MetricsView.tscn",
    "chars": 1179,
    "preview": "[gd_scene load_steps=4 format=3 uid=\"uid://bd06h3ufkhfd7\"]\n\n[ext_resource type=\"Script\" uid=\"uid://b081ugrjtk51r\" path=\""
  },
  {
    "path": "sample/scenes/NotificationsView/NotificationsView.gd",
    "chars": 157,
    "preview": "class_name NotificationsView\nextends MarginContainer\n\n@onready var vb = $SC/PC/MC/VB\n\nfunc add_notification(node: Node):"
  },
  {
    "path": "sample/scenes/NotificationsView/NotificationsView.gd.uid",
    "chars": 19,
    "preview": "uid://6tlvlmuarqub\n"
  },
  {
    "path": "sample/scenes/StatsView/StatsView.gd",
    "chars": 2174,
    "preview": "class_name StatsView\nextends VBoxContainer\n\n# Local cache of stats\nvar stats = []\n\n@onready var stat_name = %StatNameLin"
  },
  {
    "path": "sample/scenes/StatsView/StatsView.gd.uid",
    "chars": 19,
    "preview": "uid://svry6i6h3yam\n"
  },
  {
    "path": "sample/scenes/StatsView/StatsView.tscn",
    "chars": 2898,
    "preview": "[gd_scene load_steps=6 format=3 uid=\"uid://dgi7j5qx3xt84\"]\n\n[ext_resource type=\"Script\" uid=\"uid://svry6i6h3yam\" path=\"r"
  },
  {
    "path": "sample/scenes/UI/NetworkImage.gd",
    "chars": 1531,
    "preview": "class_name NetworkImage\nextends MarginContainer\n\nvar LOADING_TEXTURE = preload(\"res://scenes/UI/loading-icon.png\")\n\n@onr"
  },
  {
    "path": "sample/scenes/UI/NetworkImage.gd.uid",
    "chars": 20,
    "preview": "uid://bxtewm8nybcvn\n"
  },
  {
    "path": "sample/scenes/UI/NetworkImage.tscn",
    "chars": 1865,
    "preview": "[gd_scene load_steps=6 format=3 uid=\"uid://djhhnis3ksdjk\"]\n\n[ext_resource type=\"Script\" uid=\"uid://bxtewm8nybcvn\" path=\""
  },
  {
    "path": "sample/scenes/UI/PrimaryButton.tscn",
    "chars": 1500,
    "preview": "[gd_scene load_steps=5 format=3 uid=\"uid://t8s6xh1ax7uy\"]\n\n[sub_resource type=\"StyleBoxFlat\" id=\"6\"]\ncontent_margin_left"
  },
  {
    "path": "sample/scenes/UI/joysticks.gd",
    "chars": 189,
    "preview": "extends Control\n\n@onready var shoot_joystick: TouchScreenJoystick = $ShootJoystick\n\n\nfunc _ready() -> void:\n\thide()\n\t\n\ti"
  },
  {
    "path": "sample/scenes/UI/joysticks.gd.uid",
    "chars": 20,
    "preview": "uid://dygslh2f7uw40\n"
  },
  {
    "path": "sample/scenes/UI/nat_type.gd",
    "chars": 680,
    "preview": "extends RichTextLabel\n\n\n#region built-in methods\n\nfunc _ready() -> void:\n\tHAuth.logged_in.connect(_on_logged_in)\n\tHAuth."
  },
  {
    "path": "sample/scenes/UI/nat_type.gd.uid",
    "chars": 19,
    "preview": "uid://ft2lvpnnwl8k\n"
  },
  {
    "path": "sample/scenes/UI/nat_type.tscn",
    "chars": 494,
    "preview": "[gd_scene load_steps=2 format=3 uid=\"uid://bdlcslag0jdj1\"]\n\n[ext_resource type=\"Script\" uid=\"uid://ft2lvpnnwl8k\" path=\"r"
  },
  {
    "path": "sample/scenes/UI/ping.gd",
    "chars": 948,
    "preview": "extends Label\n\n\nconst COUNT = 5\n\n\nvar _pings = []\nvar _ping_in_progress = false\nvar _last_ping_time = 0\n\n\nfunc _ready() "
  },
  {
    "path": "sample/scenes/UI/ping.gd.uid",
    "chars": 20,
    "preview": "uid://diilhyvdor4ym\n"
  },
  {
    "path": "sample/scenes/UI/ping.tscn",
    "chars": 462,
    "preview": "[gd_scene load_steps=2 format=3 uid=\"uid://c37wtoikc8pgp\"]\n\n[ext_resource type=\"Script\" uid=\"uid://diilhyvdor4ym\" path=\""
  },
  {
    "path": "sample/scenes/UI/players_score.gd",
    "chars": 617,
    "preview": "extends Label\n\n\nfunc _ready() -> void:\n\tStore.player_score_changed.connect(_on_players_score_changed)\n\n\nfunc _on_players"
  },
  {
    "path": "sample/scenes/UI/players_score.gd.uid",
    "chars": 20,
    "preview": "uid://co6ig2d1xliiu\n"
  },
  {
    "path": "sample/scenes/UI/players_score.tscn",
    "chars": 358,
    "preview": "[gd_scene load_steps=2 format=3 uid=\"uid://8kmyoi08gr22\"]\n\n[ext_resource type=\"Script\" uid=\"uid://co6ig2d1xliiu\" path=\"r"
  },
  {
    "path": "sample/scenes/UI/touch_screen_joystick.gd",
    "chars": 14403,
    "preview": "##  RESPONSIVE TOUCHSCREEN JOYSTICK 1.0.2 ##\n\n# From https://github.com/kntCyc1230/TouchScreenJoystick\n# MIT License\n# C"
  },
  {
    "path": "sample/scenes/UI/touch_screen_joystick.gd.uid",
    "chars": 20,
    "preview": "uid://cgmpdyovn5vfm\n"
  },
  {
    "path": "sample/scenes/UIView/UIView.gd",
    "chars": 2875,
    "preview": "class_name UIView\nextends VBoxContainer\n\n@onready var friends_visible_label = %FriendsVisibleLabel\n\n@onready var notific"
  },
  {
    "path": "sample/scenes/UIView/UIView.gd.uid",
    "chars": 20,
    "preview": "uid://dja7fd2sotvig\n"
  },
  {
    "path": "sample/scenes/UIView/UIView.tscn",
    "chars": 2793,
    "preview": "[gd_scene load_steps=4 format=3 uid=\"uid://b51w7a6ofuubp\"]\n\n[ext_resource type=\"Script\" uid=\"uid://dja7fd2sotvig\" path=\""
  },
  {
    "path": "sample/scripts/Env.gd",
    "chars": 612,
    "preview": "extends Node\n\nvar _env = {}\n\n\nfunc load_env(p_path := \"res://.env\"):\n\tif not FileAccess.file_exists(p_path):\n\t\treturn {}"
  },
  {
    "path": "sample/scripts/Env.gd.uid",
    "chars": 20,
    "preview": "uid://bjyq7tcpdc3ac\n"
  },
  {
    "path": "sample/scripts/Store.gd",
    "chars": 1016,
    "preview": "extends Node\n\n\n@warning_ignore(\"unused_signal\")\nsignal player_score_changed\n\n\nconst GAME_SOCKET_NAME = \"EOSGSAMPLE\"\ncons"
  }
]

// ... and 76 more files (download for full content)

About this extraction

This page contains the full source code of the 3ddelano/epic-online-services-godot GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 276 files (1.7 MB), approximately 620.3k tokens, and a symbol index with 257 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!