43 Commits

Author SHA1 Message Date
a4fb6c19fd crash fix for missing party invite resources 2025-03-28 00:48:21 +01:00
6edd50d9c2 improved auto_token_manage, added invites and some more stuff 2025-03-28 00:36:01 +01:00
98a4b4783c implemented rich presences and better naming 2025-03-27 15:22:43 +01:00
bd7a102d3d kind of fixed the lobby 2025-03-26 22:33:57 +01:00
8b37af48b1 Merge branch 'discord-social-sdk' of https://github.com/vaporvee/discord-rpc-godot into discord-social-sdk 2025-03-26 22:07:09 +01:00
ce0aef8dc0 activity resource and fixed connection ready signal 2025-03-26 22:06:11 +01:00
Duskitten
9ec8019915 Added Lobby + Linked Channel Nodes 2025-03-26 16:44:32 -04:00
b363a11b3a a lot of changes 2025-03-26 19:48:49 +01:00
295601c7f6 fixed reparenting error 2025-03-26 02:32:59 +01:00
9ce43ef5ce better classes 2025-03-26 00:29:17 +01:00
d78f2ca856 got root connector node saved as variable 2025-03-26 00:11:28 +01:00
d07acbb149 fixed token loading crash 2025-03-25 22:58:22 +01:00
44685b12e8 more doc generation stuff 2025-03-25 22:08:45 +01:00
ff62edb36b continued working on discord connector 2025-03-25 14:07:51 +01:00
3f6e695c77 finished discord connector node 2025-03-25 11:43:16 +01:00
41b62a248c more signals 2025-03-25 10:56:56 +01:00
3c1d5c9e8f fixed fileaccess error 2025-03-25 10:20:08 +01:00
91d592c484 added option to manage token automatically 2025-03-24 17:45:00 +01:00
8e029178cd added signal and cleaned up old code 2025-03-24 14:42:20 +01:00
70969b5a19 fixed app id type and DiscordConnector node 2025-03-23 23:33:38 +01:00
e9a48bba97 a lot of social sdk progress 2025-03-23 22:36:54 +01:00
80bcfbd98d added TODO 2025-03-22 03:11:23 +01:00
27eafb1511 simple richpresence 2025-03-22 02:48:49 +01:00
7cd67693cc FINALLY fixed the build error 2025-03-22 01:33:28 +01:00
7621e73174 yeah no it was never fixed 2025-03-22 00:42:07 +01:00
115cf4c8c0 fixed import errors 2025-03-22 00:13:17 +01:00
bcb3cb95a0 more towards building 2025-03-19 16:53:37 +01:00
185f295ffb implemented scons for social sdk 2025-03-19 13:38:33 +01:00
8edabeddf8 new setup script 2025-03-19 02:37:08 +01:00
ac8c67b387 removed old sdk code 2025-03-19 02:18:04 +01:00
302c039171 began porting discord social sdk (insanely broken) 2025-03-18 18:06:09 +01:00
Yannik
1d14de9cf4 Update README.md 2025-03-18 11:29:43 +01:00
Yannik
aaccf765d0 Update BUG.yml 2024-12-20 10:33:37 +01:00
Yannik
1a7c3fab99 Update README.md 2024-10-22 02:49:52 +02:00
Yannik
5bd25877b2 Delete .github/ISSUE_TEMPLATE/custom.md 2024-09-26 00:48:24 +02:00
Yannik
ddc87a03a8 Update issue templates 2024-09-26 00:47:15 +02:00
3411e9a870 Merge branch 'main' of https://github.com/vaporvee/discord-sdk-godot 2024-08-08 22:17:12 +02:00
12e61f30e1 fixed static typing and some other stuff 2024-08-08 22:17:10 +02:00
412aec1210 added a needed gitignore 2024-08-08 22:16:58 +02:00
Yannik
a22533ea49 Delete project/addons/discord-rpc-gd/bin/windows/~discord_game_sdk_binding_debug.dll 2024-08-08 22:16:21 +02:00
Yannik
47324cbba5 Update README.md 2024-05-15 19:52:28 +02:00
Yannik
edf6b8caed already fixed 2024-04-25 14:13:19 +02:00
0bac00b3a4 reverts shipping the game sdk unpacked 2024-04-18 15:43:46 +02:00
117 changed files with 2482 additions and 6341 deletions

View File

@@ -21,7 +21,7 @@ body:
id: version
attributes:
label: Version
description: What version of the Discord RPC Godot plugin are you running?
description: What version of the Discord Social SDK Godot plugin are you running?
options:
- 1.3.1
- 1.3.0
@@ -96,5 +96,5 @@ body:
required: true
- label: I tried restarting Discord and Godot completely.
required: true
- label: I did read the documentation https://vaporvee.com/docs/discord-rpc-godot/
- label: I did read the documentation and its troubleshooting guide https://docs.vaporvee.com/discord-rpc-godot/
required: true

View File

@@ -1,65 +0,0 @@
name: Auto Wontfix Issues
on:
issues:
types: [opened, edited]
jobs:
auto_wontfix:
runs-on: ubuntu-latest
steps:
- name: Check for specific word in the issue
uses: actions/github-script@v4
with:
github-token: ${{ secrets.WONTFIX_TOKEN }}
script: |
const wordToCheck = 'mac';
const issue = context.payload.issue;
if (issue.body && issue.body.toLowerCase().includes(wordToCheck)) {
const repo = context.repo.repo;
const owner = context.repo.owner;
const number = issue.number;
const issueComment = "macOS is not supported, because loading libraries in Godot from third-party sources requires a paid developer certificate from Apple. You are welcome to compile and sign the library yourself.";
// Mark the issue as "wontfix"
await octokit.issues.update({
owner,
repo,
issue_number: number,
state: 'closed',
labels: ['wontfix']
});
// Post a comment on the issue
await octokit.issues.createComment({
owner,
repo,
issue_number: number,
body: issueComment
});
}
if (issue.title && issue.title.toLowerCase().includes(wordToCheck)) {
const repo = context.repo.repo;
const owner = context.repo.owner;
const number = issue.number;
const issueComment = "macOS is not supported, because loading libraries in Godot from third-party sources requires a paid developer certificate from Apple. You are welcome to compile and sign the library yourself.";
// Mark the issue as "wontfix"
await octokit.issues.update({
owner,
repo,
issue_number: number,
state: 'closed',
labels: ['wontfix']
});
// Post a comment on the issue
await octokit.issues.createComment({
owner,
repo,
issue_number: number,
body: issueComment
});
}

11
.gitignore vendored
View File

@@ -22,7 +22,14 @@ build/
*.a
#Clean files from setup.py
src/lib/discord_rpc/
src/lib/discord_social_sdk/*
src/lib/godot-cpp/*
discordpp.h
cdiscord.h
*.zip
*.so
*.dll
*.dylib
# release
release/
@@ -31,3 +38,5 @@ project/export/
# venv
venv/
# docs
src/gen/

2
.gitmodules vendored
View File

@@ -1,4 +1,4 @@
[submodule "src/lib/godot-cpp"]
path = src/lib/godot-cpp
url = https://github.com/godotengine/godot-cpp
branch = 4.1
branch = 4.4

View File

@@ -7,7 +7,8 @@
"${workspaceFolder}/src/lib/godot-cpp/gen/include",
"${workspaceFolder}/src/lib/godot-cpp/include",
"${workspaceFolder}/src/lib/godot-cpp/gdextension",
"${workspaceFolder}/src/lib/godot-cpp/gen/include"
"${workspaceFolder}/src/lib/godot-cpp/gen/include",
"${workspaceFolder}/src/lib/discord_social_sdk/include"
],
"defines": [
"_DEBUG",

73
.vscode/settings.json vendored
View File

@@ -4,10 +4,79 @@
"${workspaceFolder}/src/lib/godot-cpp/include"
],
"files.associations": {
"*.gdextension": "ini"
"*.gdextension": "ini",
"charconv": "cpp",
"chrono": "cpp",
"optional": "cpp",
"format": "cpp",
"ratio": "cpp",
"system_error": "cpp",
"array": "cpp",
"functional": "cpp",
"tuple": "cpp",
"type_traits": "cpp",
"utility": "cpp",
"any": "cpp",
"atomic": "cpp",
"bit": "cpp",
"*.tcc": "cpp",
"cctype": "cpp",
"clocale": "cpp",
"cmath": "cpp",
"compare": "cpp",
"concepts": "cpp",
"cstdarg": "cpp",
"cstddef": "cpp",
"cstdint": "cpp",
"cstdio": "cpp",
"cstdlib": "cpp",
"cstring": "cpp",
"ctime": "cpp",
"cwchar": "cpp",
"cwctype": "cpp",
"deque": "cpp",
"list": "cpp",
"map": "cpp",
"set": "cpp",
"string": "cpp",
"unordered_map": "cpp",
"vector": "cpp",
"exception": "cpp",
"algorithm": "cpp",
"iterator": "cpp",
"memory": "cpp",
"memory_resource": "cpp",
"numeric": "cpp",
"random": "cpp",
"string_view": "cpp",
"fstream": "cpp",
"initializer_list": "cpp",
"iomanip": "cpp",
"iosfwd": "cpp",
"iostream": "cpp",
"istream": "cpp",
"limits": "cpp",
"new": "cpp",
"numbers": "cpp",
"ostream": "cpp",
"ranges": "cpp",
"semaphore": "cpp",
"span": "cpp",
"sstream": "cpp",
"stdexcept": "cpp",
"stop_token": "cpp",
"streambuf": "cpp",
"text_encoding": "cpp",
"thread": "cpp",
"cinttypes": "cpp",
"typeinfo": "cpp",
"variant": "cpp",
"condition_variable": "cpp",
"mutex": "cpp"
},
"[python]": {
"editor.defaultFormatter": "ms-python.black-formatter"
},
"python.formatting.provider": "none"
"python.formatting.provider": "none",
"cmake.ignoreCMakeListsMissing": true
}

View File

@@ -1,10 +1,15 @@
<img src="/project/assets/discordgodot_banner.png" alt="Project Banner" />
Discord recently released its new SDK. This plugin will get a huge overhaul and new docs as soon as possible.
<a href="https://discord.com/blog/announcing-discord-social-sdk-to-power-game-comms" target="_blank">Discord's anouncement</a>
---
### This is for the Discord Game SDK NOT the Embedded App SDK
**Discord RPC Plugin for GDScript with an easy-to-use code pattern in Godot Engine 4.1+, with optional Editor Rich Presence! (Compatible with Linux, Windows, & MacOS)**<br><br>
**Discord Social SDK Plugin for GDScript with an easy-to-use code pattern in Godot Engine 4.1+, with optional Editor Rich Presence! (Compatible with Linux, Windows, & MacOS)**<br><br>
<br />
### [My Discord Server](https://discord.gg/EBdaTefpWy)
# [Quick start :rocket: (click here)](https://vaporvee.com/docs/discord-rpc-godot#quick-start)
### [My Discord Server](https://discord.gg/3gqUrtbaur)
# [Quick start :rocket: (click here)](https://docs.vaporvee.com/discord-rpc-godot#quick-start)
<br />
**A small donation with the sponsor button would be nice if you sell your project with this addon but is of course not mandatory!**

View File

@@ -3,19 +3,26 @@ import os
env = SConscript("src/lib/godot-cpp/SConstruct")
env.Append(CPPPATH=["src/","src/nodes/", "src/resources/", "src/lib/discord_social_sdk/include/"])
sources = [Glob("src/*.cpp"), Glob("src/nodes/*.cpp"), Glob("src/resources/*.cpp")]
if env["target"] in ["editor", "template_debug"]:
try:
doc_data = env.GodotCPPDocData("src/gen/doc_data.gen.cpp", source=Glob("doc_classes/*.xml"))
sources.append(doc_data)
except AttributeError:
print("Not including class reference as we're targeting a pre-4.3 baseline.")
if env["platform"] == "macos":
discord_library = "libdiscord_game_sdk.dylib"
discord_library_second = ""
discord_library = "libdiscord_partner_sdk.dylib"
libexportfolder = "/macos/"
elif env["platform"] in ("linuxbsd", "linux"):
discord_library = "libdiscord_game_sdk.so"
discord_library_second = ""
discord_library = "libdiscord_partner_sdk.so"
libexportfolder = "/linux/"
elif env["platform"] == "windows":
discord_library = "discord_game_sdk.dll"
discord_library_second = "discord_game_sdk_x86.dll"
discord_library = "discord_partner_sdk.dll"
libexportfolder = "/windows/"
if env["target"] == "template_debug":
@@ -23,26 +30,15 @@ if env["target"] == "template_debug":
else:
debugsuffix = ""
if env.get("arch") == "arm64":
armsuffix = "_arm64"
else:
armsuffix = ""
env.Append(LIBPATH=["src/lib/discord_game_sdk/bin/"])
sources = Glob("src/lib/discord_game_sdk/cpp/*.cpp")
env.Append(CPPPATH=["src/lib/discord_game_sdk/cpp/"])
env.Append(LIBS=["discord_game_sdk"])
env.Append(CPPPATH=["src/"])
sources += Glob("src/*.cpp")
env.Append(LIBPATH=["src/lib/discord_social_sdk/lib/release/"])
env.Append(LIBS=["discord_partner_sdk"])
env.Append(CPPDEFINES=["HOT_RELOAD_ENABLED"])
library = env.SharedLibrary(
target="project/addons/discord-rpc-gd/bin/"
+ libexportfolder
+ "discord_game_sdk_binding"
+ armsuffix
+ "discord_partner_sdk_binding"
+ debugsuffix,
source=sources,
)
@@ -50,18 +46,7 @@ env.Depends(
library,
Command(
"project/addons/discord-rpc-gd/bin/" + libexportfolder + discord_library,
"src/lib/discord_game_sdk/bin/" + discord_library,
Copy("$TARGET", "$SOURCE"),
),
)
if discord_library_second != "":
env.Depends(
library,
Command(
"project/addons/discord-rpc-gd/bin/"
+ libexportfolder
+ discord_library_second,
"src/lib/discord_game_sdk/bin/" + discord_library_second,
"src/lib/discord_social_sdk/lib/release/" + discord_library,
Copy("$TARGET", "$SOURCE"),
),
)

View File

@@ -31,10 +31,10 @@ elif choice in no:
cur_working_dir = os.path.dirname(os.path.realpath(__file__)) + '/project/addons/discord-rpc-gd/bin/macos/'
os.chdir(cur_working_dir)
os.system(
"lipo -create libdiscord_game_sdk_binding_arm64_debug.dylib libdiscord_game_sdk_binding_debug.dylib -output libdiscord_game_sdk_binding_debug.dylib"
"lipo -create libdiscord_partner_sdk_binding_arm64_debug.dylib libdiscord_partner_sdk_binding_debug.dylib -output libdiscord_partner_sdk_binding_debug.dylib"
)
os.system(
"lipo -create libdiscord_game_sdk_binding_arm64.dylib libdiscord_game_sdk_binding.dylib -output libdiscord_game_sdk_binding.dylib"
"lipo -create libdiscord_partner_sdk_binding_arm64.dylib libdiscord_partner_sdk_binding.dylib -output libdiscord_partner_sdk_binding.dylib"
)
else: # Linux
os.system(

View File

@@ -0,0 +1,73 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="DiscordConnector" inherits="DiscordSocialSDK" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://raw.githubusercontent.com/godotengine/godot/master/doc/class.xsd">
<brief_description>
</brief_description>
<description>
</description>
<tutorials>
</tutorials>
<methods>
<method name="connect_user">
<return type="void" />
<description>
</description>
</method>
<method name="refresh_user_token">
<return type="void" />
<param index="0" name="current_refresh_token" type="String" />
<description>
</description>
</method>
<method name="update_user_token">
<return type="void" />
<param index="0" name="access_token" type="String" />
<description>
</description>
</method>
</methods>
<members>
<member name="app_id" type="int" setter="set_app_id" getter="get_app_id" default="0">
</member>
<member name="auto_connect" type="bool" setter="set_auto_connect" getter="get_auto_connect" default="false">
</member>
<member name="auto_encryption_key" type="String" setter="set_auto_encryption_key" getter="get_auto_encryption_key" default="&quot;&quot;">
</member>
<member name="auto_token_manage" type="bool" setter="set_auto_token_manage" getter="get_auto_token_manage" default="false">
</member>
</members>
<signals>
<signal name="user_connected">
<param index="0" name="access_token" type="String" />
<param index="1" name="refresh_token" type="String" />
<param index="2" name="expires_in" type="int" />
<description>
</description>
</signal>
<signal name="user_connection_failed">
<param index="0" name="error" type="String" />
<description>
</description>
</signal>
<signal name="user_token_refresh_failed">
<param index="0" name="error" type="String" />
<description>
</description>
</signal>
<signal name="user_token_refreshed">
<param index="0" name="access_token" type="String" />
<param index="1" name="refresh_token" type="String" />
<param index="2" name="expires_in" type="int" />
<description>
</description>
</signal>
<signal name="user_update_failed">
<param index="0" name="error" type="String" />
<description>
</description>
</signal>
<signal name="user_updated">
<description>
</description>
</signal>
</signals>
</class>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="DiscordSocialSDK" inherits="Node" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://raw.githubusercontent.com/godotengine/godot/master/doc/class.xsd">
<brief_description>
</brief_description>
<description>
</description>
<tutorials>
</tutorials>
</class>

View File

@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="DiscordUtil" inherits="Object" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://raw.githubusercontent.com/godotengine/godot/master/doc/class.xsd">
<brief_description>
</brief_description>
<description>
</description>
<tutorials>
</tutorials>
<methods>
<method name="debug">
<return type="void" />
<description>
</description>
</method>
<method name="generate_auto_encryption_key">
<return type="String" />
<description>
</description>
</method>
<method name="run_callbacks">
<return type="void" />
<description>
</description>
</method>
<method name="save_tokens">
<return type="void" />
<param index="0" name="access_token" type="String" />
<param index="1" name="refresh_token" type="String" />
<param index="2" name="expires_in" type="int" />
<param index="3" name="auto_encryption_key" type="String" />
<description>
</description>
</method>
</methods>
</class>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="EditorPresence" inherits="DiscordSocialSDK" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://raw.githubusercontent.com/godotengine/godot/master/doc/class.xsd">
<brief_description>
</brief_description>
<description>
</description>
<tutorials>
</tutorials>
</class>

View File

@@ -0,0 +1,3 @@
bin/.gdignore
*.TMP
bin/windows/~*.dll

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

View File

@@ -1,34 +0,0 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://csl0e2px0cwc1"
path="res://.godot/imported/Logo_V2_No_Bg.png-ed667fb599fe1e17ebcfc361ff7c9c93.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/discord-rpc-gd/Logo_V2_No_Bg.png"
dest_files=["res://.godot/imported/Logo_V2_No_Bg.png-ed667fb599fe1e17ebcfc361ff7c9c93.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

View File

@@ -1,6 +1,6 @@
MINIMUM GODOT VERSION: 4.2
PLEASE ACTIVATE THE PLUGIN UNDER Project -> Project Settings... -> Plugins -> DiscordRPC -> Status
PLEASE ACTIVATE THE PLUGIN UNDER Project -> Project Settings... -> Plugins -> DiscordUtil -> Status
IGNORE THE RED ERRORS ON THE FIRST 2 RESTARTS
READ THE TUTORIAL LINKED IN THE WINDOW THAT WILL OPEN ON PLUGIN ENABLE

View File

@@ -1,29 +1,23 @@
[configuration]
entry_symbol = "discordrpcgd_library_init"
entry_symbol = "DiscordUtilgd_library_init"
compatibility_minimum = 4.1
[libraries]
macos.debug = "macos/libdiscord_game_sdk_binding_debug.dylib"
macos.release = "macos/libdiscord_game_sdk_binding.dylib"
windows.debug.x86_64 = "windows/discord_game_sdk_binding_debug.dll"
windows.release.x86_64 = "windows/discord_game_sdk_binding.dll"
linux.debug.x86_64 = "linux/libdiscord_game_sdk_binding_debug.so"
linux.release.x86_64 = "linux/libdiscord_game_sdk_binding.so"
linux.debug.arm64 = "linux/libdiscord_game_sdk_binding_debug.so"
linux.release.arm64 = "linux/libdiscord_game_sdk_binding.so"
linux.debug.rv64 = "linux/libdiscord_game_sdk_binding_debug.so"
linux.release.rv64 = "linux/libdiscord_game_sdk_binding.so"
macos.debug = "macos/libdiscord_partner_sdk_binding_debug.dylib"
macos.release = "macos/libdiscord_partner_sdk_binding.dylib"
windows.debug.x86_64 = "windows/discord_partner_sdk_binding_debug.dll"
windows.release.x86_64 = "windows/discord_partner_sdk_binding.dll"
linux.debug.x86_64 = "linux/libdiscord_partner_sdk_binding_debug.so"
linux.release.x86_64 = "linux/libdiscord_partner_sdk_binding.so"
linux.debug.arm64 = "linux/libdiscord_partner_sdk_binding_debug.so"
linux.release.arm64 = "linux/libdiscord_partner_sdk_binding.so"
linux.debug.rv64 = "linux/libdiscord_partner_sdk_binding_debug.so"
linux.release.rv64 = "linux/libdiscord_partner_sdk_binding.so"
[dependencies]
macos = { "macos/libdiscord_game_sdk.dylib": "" }
windows.debug.x86_64 = { "windows/discord_game_sdk.dll": "" }
windows.release.x86_64 = { "windows/discord_game_sdk.dll": "" }
linux.debug.x86_64 = { "linux/libdiscord_game_sdk.so": "" }
linux.release.x86_64 = { "linux/libdiscord_game_sdk.so": "" }
linux.debug.arm64 = { "linux/libdiscord_game_sdk.so": "" }
linux.release.arm64 = { "linux/libdiscord_game_sdk.so": "" }
linux.debug.rv64 = { "linux/libdiscord_game_sdk.so": "" }
linux.release.rv64 = { "linux/libdiscord_game_sdk.so": "" }
macos = { "macos/libdiscord_partner_sdk.dylib": "" }
windows.x86_64 = { "windows/discord_partner_sdk.dll": "" }
linux = { "linux/libdiscord_partner_sdk.so": "" }

View File

@@ -0,0 +1 @@
uid://jcdwy5o1utpj

View File

@@ -1,8 +1,8 @@
class_name DiscordRPCTutorial
class_name DiscordUtilTutorial
extends Node
## 1. Put the addons/ folder in your Godot project[br]
## 2. Enable the addon in your Project Settings under "Plugins" and "DiscordRPC". [br](if it doesn't show up restart your project and try again)[br]
## 2. Enable the addon in your Project Settings under "Plugins" and "DiscordUtil". [br](if it doesn't show up restart your project and try again)[br]
## 3. Restart your project[br]
## 4. Create an Application under https://discord.com/developers/applications and get the Application ID br]
## 5. (optional) Set images under "Rich Presence" and "Art Assets" and remember the keys[br]
@@ -11,27 +11,27 @@ extends Node
## [codeblock]
## func _ready():
## # Application ID
## DiscordRPC.app_id = 1099618430065324082
## DiscordUtil.app_id = 1099618430065324082
## # this is boolean if everything worked
## print("Discord working: " + str(DiscordRPC.get_is_discord_working()))
## print("Discord working: " + str(DiscordUtil.get_is_discord_working()))
## # Set the first custom text row of the activity here
## DiscordRPC.details = "A demo activity by vaporvee#1231"
## DiscordUtil.details = "A demo activity by vaporvee#1231"
## # Set the second custom text row of the activity here
## DiscordRPC.state = "Checkpoint 23/23"
## DiscordUtil.state = "Checkpoint 23/23"
## # Image key for small image from "Art Assets" from the Discord Developer website
## DiscordRPC.large_image = "game"
## DiscordUtil.large_image = "game"
## # Tooltip text for the large image
## DiscordRPC.large_image_text = "Try it now!"
## DiscordUtil.large_image_text = "Try it now!"
## # Image key for large image from "Art Assets" from the Discord Developer website
## DiscordRPC.small_image = "boss"
## DiscordUtil.small_image = "boss"
## # Tooltip text for the small image
## DiscordRPC.small_image_text = "Fighting the end boss! D:"
## DiscordUtil.small_image_text = "Fighting the end boss! D:"
## # "02:41 elapsed" timestamp for the activity
## DiscordRPC.start_timestamp = int(Time.get_unix_time_from_system())
## DiscordUtil.start_timestamp = int(Time.get_unix_time_from_system())
## # "59:59 remaining" timestamp for the activity
## DiscordRPC.end_timestamp = int(Time.get_unix_time_from_system()) + 3600
## DiscordUtil.end_timestamp = int(Time.get_unix_time_from_system()) + 3600
## # Always refresh after changing the values!
## DiscordRPC.refresh()
## DiscordUtil.refresh()
## [/codeblock]
##
## @tutorial(More information here): https://github.com/vaporvee/discord-rpc-godot/wiki/Quick-start

View File

@@ -0,0 +1 @@
uid://dkv4pruvla8bn

View File

@@ -8,13 +8,13 @@
resource_name = "Debug"
script/source = "extends Node
func _ready():
DiscordRPC.connect(\"activity_join_request\",_on_activity_join_request)
@onready var animation_player: AnimationPlayer = $Panel/TextureRect/AnimationPlayer
func _process(_delta):
if(DiscordRPC.get_is_discord_working()):
func _process(_delta) -> void:
if(false):
$Panel/TextureRect.self_modulate = Color(\"#3eff8d\")
$Panel/TextureRect/AnimationPlayer.play(\"pulsate\")
if !animation_player.is_playing():
animation_player.play(\"pulsate\")
debug_text_update()
else:
$Panel/TextureRect.self_modulate = Color(\"#797979\")
@@ -22,7 +22,7 @@ func _process(_delta):
debug_text_update()
func debug_text_update():
func debug_text_update() -> void:
$Panel/Info.text = \"Application ID : {id}
Details: {details}
State: {state}
@@ -45,35 +45,13 @@ Is party public: {ppublic} (needs to be activated in Discord client settings)
Is instanced: {instanced}
\"
$Panel/Info.text = $Panel/Info.text.replace(\"{ppublic}\",str(DiscordRPC.is_public_party)).replace(\"{instanced}\",str(DiscordRPC.instanced)).replace(\"{ssecret}\",DiscordRPC.spectate_secret).replace(\"{jsecret}\",DiscordRPC.join_secret).replace(\"{msecret}\",DiscordRPC.match_secret).replace(\"{mpartysize}\",str(DiscordRPC.max_party_size)).replace(\"{cpartysize}\",str(DiscordRPC.current_party_size)).replace(\"{partyid}\",DiscordRPC.party_id).replace(\"{id}\",str(DiscordRPC.app_id)).replace(\"{details}\",DiscordRPC.details).replace(\"{state}\",DiscordRPC.state).replace(\"{lkey}\",DiscordRPC.large_image).replace(\"{ltext}\",DiscordRPC.large_image_text).replace(\"{skey}\",DiscordRPC.small_image).replace(\"{stext}\",DiscordRPC.small_image_text).replace(\"{stimestamp}\",str(DiscordRPC.start_timestamp)).replace(\"{etimestamp}\",str(DiscordRPC.end_timestamp))
#$Panel/Info.text = $Panel/Info.text.replace(\"{ppublic}\",str(DiscordUtil.is_public_party)).replace(\"{instanced}\",str(DiscordUtil.instanced)).replace(\"{ssecret}\",DiscordUtil.spectate_secret).replace(\"{jsecret}\",DiscordUtil.join_secret).replace(\"{msecret}\",DiscordUtil.match_secret).replace(\"{mpartysize}\",str(DiscordUtil.max_party_size)).replace(\"{cpartysize}\",str(DiscordUtil.current_party_size)).replace(\"{partyid}\",DiscordUtil.party_id).replace(\"{id}\",str(DiscordUtil.app_id)).replace(\"{details}\",DiscordUtil.details).replace(\"{state}\",DiscordUtil.state).replace(\"{lkey}\",DiscordUtil.large_image).replace(\"{ltext}\",DiscordUtil.large_image_text).replace(\"{skey}\",DiscordUtil.small_image).replace(\"{stext}\",DiscordUtil.small_image_text).replace(\"{stimestamp}\",str(DiscordUtil.start_timestamp)).replace(\"{etimestamp}\",str(DiscordUtil.end_timestamp))
var user_request = {};
var user_request: Dictionary = {};
func _on_activity_join_request(user_requesting):
func _on_activity_join_request(user_requesting: Dictionary) -> void:
print(user_requesting)
user_request = user_requesting
func _on_accept_join_request_pressed():
if(!user_request.is_empty()):
DiscordRPC.accept_join_request(user_request.id)
func _on_invite_with_user_id_text_submitted(new_text):
DiscordRPC.send_invite(int(new_text),true,\"this is a test invite sent from godot\")
func _on_accept_with_user_id_text_submitted(new_text):
DiscordRPC.accept_invite(int(new_text))
func _on_print_current_user_on_console_pressed():
print(DiscordRPC.get_current_user())
func _on_toggle_sdk_toggled(button_pressed):
if(button_pressed):
DiscordRPC.unclear()
else:
DiscordRPC.clear(false)
func _on_print_friends_pressed():
print(DiscordRPC.get_all_relationships())
"
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_8abo6"]
@@ -95,24 +73,25 @@ tracks/0/keys = {
[sub_resource type="Animation" id="Animation_5u02v"]
resource_name = "pulsate"
loop_mode = 1
length = 0.5
loop_mode = 2
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath(".:scale")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/loop_wrap = false
tracks/0/keys = {
"times": PackedFloat32Array(0, 0.5, 1),
"transitions": PackedFloat32Array(1, 1, 1),
"times": PackedFloat32Array(0, 0.5),
"transitions": PackedFloat32Array(1, 1),
"update": 0,
"values": [Vector2(0.5, 0.5), Vector2(0.8, 0.8), Vector2(0.5, 0.5)]
"values": [Vector2(0.5, 0.5), Vector2(0.8, 0.8)]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_a7ofc"]
_data = {
"RESET": SubResource("Animation_mmtmn"),
"pulsate": SubResource("Animation_5u02v")
&"RESET": SubResource("Animation_mmtmn"),
&"pulsate": SubResource("Animation_5u02v")
}
[node name="DebugNodeGroup" type="Node"]
@@ -231,9 +210,9 @@ offset_right = 1144.0
offset_bottom = 665.375
grow_vertical = 2
scale = Vector2(0.05, 0.05)
theme_override_styles/focus = SubResource("StyleBoxEmpty_8abo6")
theme_override_icons/checked = ExtResource("2_q6tao")
theme_override_icons/unchecked = ExtResource("3_5cyem")
theme_override_styles/focus = SubResource("StyleBoxEmpty_8abo6")
button_pressed = true
[node name="TextureRect" type="TextureRect" parent="Panel"]
@@ -256,7 +235,7 @@ texture = ExtResource("3_goflf")
[node name="AnimationPlayer" type="AnimationPlayer" parent="Panel/TextureRect"]
libraries = {
"": SubResource("AnimationLibrary_a7ofc")
&"": SubResource("AnimationLibrary_a7ofc")
}
[connection signal="pressed" from="Panel/PrintCurrentUserOnConsole" to="." method="_on_print_current_user_on_console_pressed"]

View File

@@ -1,6 +1,6 @@
## This is a Debug Node wich will show some usefull info and buttons/input
##
## The DiscordRPC Debug Node will show info about the current values of its variables and some buttons to change them.
## The DiscordUtil Debug Node will show info about the current values of its variables and some buttons to change them.
##
## @tutorial: https://github.com/vaporvee/discord-rpc-godot/wiki
@tool

View File

@@ -0,0 +1 @@
uid://46tue7u6crd6

View File

@@ -1,13 +0,0 @@
## This is a GDscript Node wich gets automatically added as Autoload while installing the addon.
##
## It can run in the background to comunicate with Discord.
## You don't need to use it. If you remove it make sure to run [code]DiscordRPC.run_callbacks()[/code] in a [code]_process[/code] function.
##
## @tutorial: https://github.com/vaporvee/discord-rpc-godot/wiki
extends Node
func _ready() -> void:
pass
func _process(_delta) -> void:
DiscordRPC.run_callbacks()

View File

@@ -1,7 +1,7 @@
[plugin]
name="DiscordRPC"
description="Discord RPC Plugin for GDScript in Godot"
name="Discord Social SDK"
description="Discord Social SDK Plugin for GDScript in Godot"
author="vaporvee"
version="1.3.1"
version="1.3.2"
script="plugin.gd"

View File

@@ -1,42 +1,42 @@
@tool
extends EditorPlugin
const DiscordRPCDebug = preload("res://addons/discord-rpc-gd/nodes/debug.gd")
const DiscordRPCDebug_icon = preload("res://addons/discord-rpc-gd/Debug.svg")
var loaded_DiscordRPCDebug = DiscordRPCDebug.new()
const DiscordSocialSDKDebug: GDScript = preload("res://addons/discord-rpc-gd/nodes/debug.gd")
const DiscordSocialSDKDebug_icon: Texture2D = preload("res://addons/discord-rpc-gd/Debug.svg")
var loaded_DiscordSocialSDKDebug: DiscordSocialSDKDebug = DiscordSocialSDKDebug.new()
var restart_window: ConfirmationDialog = preload("res://addons/discord-rpc-gd/restart_window.tscn").instantiate()
var plugin_cfg: ConfigFile = ConfigFile.new()
const plugin_data_filename = "/plugin_data.cfg"
func _enter_tree() -> void:
add_custom_type("DiscordRPCDebug","Node",DiscordRPCDebug,DiscordRPCDebug_icon)
get_editor_interface().get_editor_settings().settings_changed.connect(_on_editor_settings_changed)
const plugin_data_filename: String = "/plugin_data.cfg"
func _ready() -> void:
await get_tree().create_timer(0.5).timeout
plugin_cfg.load(get_editor_interface().get_editor_paths().get_data_dir() + plugin_data_filename)
if !get_editor_interface().get_editor_settings().has_setting("DiscordRPC/EditorPresence/enabled"):
get_editor_interface().get_editor_settings().set_setting("DiscordRPC/EditorPresence/enabled",plugin_cfg.get_value("Discord","editor_presence",false))
if !get_editor_interface().get_editor_settings().has_setting("DiscordSocialSDK/EditorPresence/enabled"):
get_editor_interface().get_editor_settings().set_setting("DiscordSocialSDK/EditorPresence/enabled",plugin_cfg.get_value("Discord","editor_presence",false))
func _exit_tree():
if get_editor_interface().get_editor_settings().has_setting("DiscordRPC/EditorPresence/enabled"):
get_editor_interface().get_editor_settings().erase("DiscordRPC/EditorPresence/enabled")
func _enter_tree() -> void:
add_custom_type("DiscordSocialSDKDebug","Node",DiscordSocialSDKDebug,DiscordSocialSDKDebug_icon)
get_editor_interface().get_editor_settings().settings_changed.connect(_on_editor_settings_changed)
func _exit_tree() -> void:
if get_editor_interface().get_editor_settings().has_setting("DiscordSocialSDK/EditorPresence/enabled"):
get_editor_interface().get_editor_settings().erase("DiscordSocialSDK/EditorPresence/enabled")
func _enable_plugin() -> void:
add_custom_type("DiscordSocialSDKDebug","Node",DiscordSocialSDKDebug,DiscordSocialSDKDebug_icon)
get_editor_interface().get_editor_settings().settings_changed.connect(_on_editor_settings_changed)
if FileAccess.file_exists(ProjectSettings.globalize_path("res://") + "addons/discord-rpc-gd/bin/.gdignore"):
DirAccess.remove_absolute(ProjectSettings.globalize_path("res://") + "addons/discord-rpc-gd/bin/.gdignore")
add_autoload_singleton("DiscordRPCLoader","res://addons/discord-rpc-gd/nodes/discord_autoload.gd")
restart_window.connect("confirmed", save_no_restart)
restart_window.connect("canceled", save_and_restart)
get_editor_interface().popup_dialog_centered(restart_window)
print("IGNORE RED ERROR MESSAGES BEFORE THE SECOND RESTART!")
func _disable_plugin() -> void:
remove_autoload_singleton("DiscordRPCLoader")
FileAccess.open("res://addons/discord-rpc-gd/bin/.gdignore",FileAccess.WRITE)
remove_custom_type("DiscordRPCDebug")
get_editor_interface().get_editor_settings().erase("DiscordRPC/EditorPresence/enabled")
push_warning("Please restart the editor to fully disable the DiscordRPC plugin")
remove_custom_type("DiscordSocialSDKDebug")
get_editor_interface().get_editor_settings().erase("DiscordSocialSDK/EditorPresence/enabled")
push_warning("Please restart the editor to fully disable the Discord Social SDK plugin")
func save_and_restart() -> void:
get_editor_interface().restart_editor(true)
@@ -46,11 +46,11 @@ func save_no_restart() -> void:
var editor_presence: Node
func _on_editor_settings_changed() -> void:
plugin_cfg.set_value("Discord","editor_presence",get_editor_interface().get_editor_settings().get_setting("DiscordRPC/EditorPresence/enabled"))
plugin_cfg.set_value("Discord","editor_presence",get_editor_interface().get_editor_settings().get_setting("DiscordSocialSDK/EditorPresence/enabled"))
plugin_cfg.save(get_editor_interface().get_editor_paths().get_data_dir() + plugin_data_filename)
if ClassDB.class_exists("EditorPresence") && editor_presence == null:
editor_presence = ClassDB.instantiate("EditorPresence")
if get_editor_interface().get_editor_settings().has_setting("DiscordRPC/EditorPresence/enabled") && get_editor_interface().get_editor_settings().get_setting("DiscordRPC/EditorPresence/enabled"):
if get_editor_interface().get_editor_settings().has_setting("DiscordSocialSDK/EditorPresence/enabled") && get_editor_interface().get_editor_settings().get_setting("DiscordSocialSDK/EditorPresence/enabled"):
add_child(editor_presence)
else:
editor_presence.queue_free()

View File

@@ -0,0 +1 @@
uid://citpv7uf0k1ku

View File

@@ -9,7 +9,7 @@ Button/styles/focus = SubResource("StyleBoxEmpty_1t7mm")
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_5vqdt"]
[sub_resource type="Image" id="Image_v4whe"]
[sub_resource type="Image" id="Image_4rf8i"]
data = {
"data": PackedByteArray(255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 227, 227, 227, 36, 224, 224, 224, 168, 224, 224, 224, 233, 224, 224, 224, 236, 224, 224, 224, 170, 231, 231, 231, 31, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 227, 227, 227, 36, 224, 224, 224, 234, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 239, 230, 230, 230, 30, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 224, 224, 224, 168, 224, 224, 224, 255, 224, 224, 224, 186, 224, 224, 224, 32, 224, 224, 224, 33, 224, 224, 224, 187, 224, 224, 224, 255, 225, 225, 225, 167, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 224, 224, 224, 237, 224, 224, 224, 255, 224, 224, 224, 33, 255, 255, 255, 0, 255, 255, 255, 0, 227, 227, 227, 36, 224, 224, 224, 255, 224, 224, 224, 234, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 224, 224, 224, 237, 224, 224, 224, 255, 224, 224, 224, 33, 255, 255, 255, 0, 255, 255, 255, 0, 229, 229, 229, 38, 224, 224, 224, 255, 224, 224, 224, 229, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 224, 224, 224, 164, 224, 224, 224, 255, 224, 224, 224, 187, 225, 225, 225, 34, 227, 227, 227, 36, 224, 224, 224, 192, 224, 224, 224, 255, 224, 224, 224, 162, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 224, 224, 224, 24, 225, 225, 225, 215, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 229, 224, 224, 224, 32, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 224, 224, 224, 24, 224, 224, 224, 216, 224, 224, 224, 255, 224, 224, 224, 210, 224, 224, 224, 161, 224, 224, 224, 232, 224, 224, 224, 231, 225, 225, 225, 159, 230, 230, 230, 30, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 224, 224, 224, 107, 224, 224, 224, 255, 224, 224, 224, 210, 230, 230, 230, 20, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 224, 224, 224, 105, 230, 230, 230, 20, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 221, 224, 224, 224, 130, 255, 255, 255, 1, 255, 255, 255, 1, 225, 225, 225, 134, 224, 224, 224, 224, 225, 225, 225, 223, 224, 224, 224, 132, 255, 255, 255, 1, 255, 255, 255, 6, 224, 224, 224, 137, 224, 224, 224, 231, 224, 224, 224, 255, 255, 255, 255, 0, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 130, 225, 225, 225, 133, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 129, 224, 224, 224, 137, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 255, 255, 255, 0, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 65, 224, 224, 224, 255, 224, 224, 224, 220, 225, 225, 225, 223, 224, 224, 224, 255, 226, 226, 226, 61, 224, 224, 224, 65, 224, 224, 224, 255, 224, 224, 224, 222, 224, 224, 224, 231, 224, 224, 224, 255, 227, 227, 227, 62, 255, 255, 255, 0, 255, 255, 255, 0, 224, 224, 224, 255, 224, 224, 224, 255, 225, 225, 225, 67, 224, 224, 224, 255, 224, 224, 224, 219, 224, 224, 224, 222, 224, 224, 224, 255, 227, 227, 227, 63, 225, 225, 225, 67, 224, 224, 224, 255, 224, 224, 224, 219, 224, 224, 224, 230, 224, 224, 224, 255, 227, 227, 227, 63, 255, 255, 255, 0, 255, 255, 255, 0, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 225, 225, 225, 127, 224, 224, 224, 129, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 225, 225, 225, 126, 225, 225, 225, 135, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 255, 255, 255, 0, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 221, 225, 225, 225, 127, 255, 255, 255, 0, 255, 255, 255, 1, 224, 224, 224, 128, 224, 224, 224, 220, 224, 224, 224, 219, 225, 225, 225, 127, 255, 255, 255, 0, 255, 255, 255, 5, 225, 225, 225, 134, 224, 224, 224, 229, 224, 224, 224, 255, 255, 255, 255, 0),
"format": "RGBA8",
@@ -19,7 +19,7 @@ data = {
}
[sub_resource type="ImageTexture" id="ImageTexture_gdtpn"]
image = SubResource("Image_v4whe")
image = SubResource("Image_4rf8i")
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_7v0rg"]

View File

@@ -0,0 +1,16 @@
extends DiscordConnector
@onready var discord_activity: DiscordActivity = $DiscordActivity
func _on_authenticated(access_token: String, refresh_token: String, expires_in: int) -> void:
print_debug("Access token: %s \nRefresh Token: %s \nExpires in: %s" % [access_token, refresh_token, expires_in])
func _on_authentication_failed(error: String) -> void:
push_error("Auth failed! Error: " + error)
func _on_connection_error(error: String) -> void:
push_error(error)
func _on_connection_ready() -> void:
print_debug("CONNECTION READY")
discord_activity.update()

View File

@@ -0,0 +1 @@
uid://kmubk5a6i385

View File

@@ -3,9 +3,11 @@
name="Windows Desktop"
platform="Windows Desktop"
runnable=true
advanced_options=false
dedicated_server=false
custom_features=""
export_filter="all_resources"
export_filter="exclude"
export_files=PackedStringArray("res://addons/discord-rpc-gd/bin/discord-rpc-gd.gdextension", "res://addons/discord-rpc-gd/nodes/assets/Checked.svg", "res://addons/discord-rpc-gd/nodes/assets/circle.svg", "res://addons/discord-rpc-gd/nodes/assets/Unchecked.svg", "res://addons/discord-rpc-gd/nodes/debug.gd", "res://addons/discord-rpc-gd/nodes/Debug.tscn", "res://addons/discord-rpc-gd/nodes/discord_autoload.gd", "res://addons/discord-rpc-gd/Debug.svg", "res://addons/discord-rpc-gd/example.gd", "res://addons/discord-rpc-gd/logo.png", "res://addons/discord-rpc-gd/Logo_V2_No_Bg.png", "res://addons/discord-rpc-gd/plugin.gd", "res://addons/discord-rpc-gd/restart_window.tscn")
include_filter=""
exclude_filter=""
export_path="export/windows/discord-rpc-godot-demo.exe"
@@ -13,6 +15,7 @@ encryption_include_filters=""
encryption_exclude_filters=""
encrypt_pck=false
encrypt_directory=false
script_export_mode=2
[preset.0.options]
@@ -20,10 +23,8 @@ custom_template/debug=""
custom_template/release=""
debug/export_console_wrapper=1
binary_format/embed_pck=true
texture_format/bptc=true
texture_format/s3tc=true
texture_format/etc=false
texture_format/etc2=false
texture_format/s3tc_bptc=true
texture_format/etc2_astc=false
binary_format/architecture="x86_64"
codesign/enable=false
codesign/timestamp=true
@@ -39,10 +40,12 @@ application/file_version=""
application/product_version=""
application/company_name=""
application/product_name=""
application/file_description="Discord RPC Godot Test"
application/file_description="Discord Social SDK Godot Test"
application/copyright=""
application/trademarks=""
application/export_angle=0
application/export_d3d12=0
application/d3d12_agility_sdk_multiarch=true
ssh_remote_deploy/enabled=false
ssh_remote_deploy/host="user@host_ip"
ssh_remote_deploy/port="22"
@@ -60,12 +63,17 @@ Unregister-ScheduledTask -TaskName godot_remote_debug -Confirm:$false -ErrorActi
ssh_remote_deploy/cleanup_script="Stop-ScheduledTask -TaskName godot_remote_debug -ErrorAction:SilentlyContinue
Unregister-ScheduledTask -TaskName godot_remote_debug -Confirm:$false -ErrorAction:SilentlyContinue
Remove-Item -Recurse -Force '{temp_dir}'"
texture_format/bptc=true
texture_format/s3tc=true
texture_format/etc=false
texture_format/etc2=false
[preset.1]
name="Linux/X11"
platform="Linux/X11"
platform="Linux"
runnable=true
advanced_options=false
dedicated_server=false
custom_features=""
export_filter="all_resources"
@@ -76,6 +84,7 @@ encryption_include_filters=""
encryption_exclude_filters=""
encrypt_pck=false
encrypt_directory=false
script_export_mode=2
[preset.1.options]
@@ -83,10 +92,8 @@ custom_template/debug=""
custom_template/release=""
debug/export_console_wrapper=1
binary_format/embed_pck=true
texture_format/bptc=true
texture_format/s3tc=true
texture_format/etc=false
texture_format/etc2=false
texture_format/s3tc_bptc=true
texture_format/etc2_astc=false
binary_format/architecture="x86_64"
ssh_remote_deploy/enabled=false
ssh_remote_deploy/host="user@host_ip"
@@ -100,12 +107,17 @@ unzip -o -q \"{temp_dir}/{archive_name}\" -d \"{temp_dir}\"
ssh_remote_deploy/cleanup_script="#!/usr/bin/env bash
kill $(pgrep -x -f \"{temp_dir}/{exe_name} {cmd_args}\")
rm -rf \"{temp_dir}\""
texture_format/bptc=true
texture_format/s3tc=true
texture_format/etc=false
texture_format/etc2=false
[preset.2]
name="macOS"
platform="macOS"
runnable=true
advanced_options=false
dedicated_server=false
custom_features=""
export_filter="all_resources"
@@ -116,6 +128,7 @@ encryption_include_filters=""
encryption_exclude_filters=""
encrypt_pck=false
encrypt_directory=false
script_export_mode=2
[preset.2.options]
@@ -136,6 +149,7 @@ application/copyright_localized={}
application/min_macos_version="10.12"
application/export_angle=0
display/high_res=true
application/additional_plist_content=""
xcode/platform_build="14C18"
xcode/sdk_version="13.1"
xcode/sdk_build="22C55"
@@ -194,6 +208,148 @@ privacy/network_volumes_usage_description=""
privacy/network_volumes_usage_description_localized={}
privacy/removable_volumes_usage_description=""
privacy/removable_volumes_usage_description_localized={}
privacy/tracking_enabled=false
privacy/tracking_domains=PackedStringArray()
privacy/collected_data/name/collected=false
privacy/collected_data/name/linked_to_user=false
privacy/collected_data/name/used_for_tracking=false
privacy/collected_data/name/collection_purposes=0
privacy/collected_data/email_address/collected=false
privacy/collected_data/email_address/linked_to_user=false
privacy/collected_data/email_address/used_for_tracking=false
privacy/collected_data/email_address/collection_purposes=0
privacy/collected_data/phone_number/collected=false
privacy/collected_data/phone_number/linked_to_user=false
privacy/collected_data/phone_number/used_for_tracking=false
privacy/collected_data/phone_number/collection_purposes=0
privacy/collected_data/physical_address/collected=false
privacy/collected_data/physical_address/linked_to_user=false
privacy/collected_data/physical_address/used_for_tracking=false
privacy/collected_data/physical_address/collection_purposes=0
privacy/collected_data/other_contact_info/collected=false
privacy/collected_data/other_contact_info/linked_to_user=false
privacy/collected_data/other_contact_info/used_for_tracking=false
privacy/collected_data/other_contact_info/collection_purposes=0
privacy/collected_data/health/collected=false
privacy/collected_data/health/linked_to_user=false
privacy/collected_data/health/used_for_tracking=false
privacy/collected_data/health/collection_purposes=0
privacy/collected_data/fitness/collected=false
privacy/collected_data/fitness/linked_to_user=false
privacy/collected_data/fitness/used_for_tracking=false
privacy/collected_data/fitness/collection_purposes=0
privacy/collected_data/payment_info/collected=false
privacy/collected_data/payment_info/linked_to_user=false
privacy/collected_data/payment_info/used_for_tracking=false
privacy/collected_data/payment_info/collection_purposes=0
privacy/collected_data/credit_info/collected=false
privacy/collected_data/credit_info/linked_to_user=false
privacy/collected_data/credit_info/used_for_tracking=false
privacy/collected_data/credit_info/collection_purposes=0
privacy/collected_data/other_financial_info/collected=false
privacy/collected_data/other_financial_info/linked_to_user=false
privacy/collected_data/other_financial_info/used_for_tracking=false
privacy/collected_data/other_financial_info/collection_purposes=0
privacy/collected_data/precise_location/collected=false
privacy/collected_data/precise_location/linked_to_user=false
privacy/collected_data/precise_location/used_for_tracking=false
privacy/collected_data/precise_location/collection_purposes=0
privacy/collected_data/coarse_location/collected=false
privacy/collected_data/coarse_location/linked_to_user=false
privacy/collected_data/coarse_location/used_for_tracking=false
privacy/collected_data/coarse_location/collection_purposes=0
privacy/collected_data/sensitive_info/collected=false
privacy/collected_data/sensitive_info/linked_to_user=false
privacy/collected_data/sensitive_info/used_for_tracking=false
privacy/collected_data/sensitive_info/collection_purposes=0
privacy/collected_data/contacts/collected=false
privacy/collected_data/contacts/linked_to_user=false
privacy/collected_data/contacts/used_for_tracking=false
privacy/collected_data/contacts/collection_purposes=0
privacy/collected_data/emails_or_text_messages/collected=false
privacy/collected_data/emails_or_text_messages/linked_to_user=false
privacy/collected_data/emails_or_text_messages/used_for_tracking=false
privacy/collected_data/emails_or_text_messages/collection_purposes=0
privacy/collected_data/photos_or_videos/collected=false
privacy/collected_data/photos_or_videos/linked_to_user=false
privacy/collected_data/photos_or_videos/used_for_tracking=false
privacy/collected_data/photos_or_videos/collection_purposes=0
privacy/collected_data/audio_data/collected=false
privacy/collected_data/audio_data/linked_to_user=false
privacy/collected_data/audio_data/used_for_tracking=false
privacy/collected_data/audio_data/collection_purposes=0
privacy/collected_data/gameplay_content/collected=false
privacy/collected_data/gameplay_content/linked_to_user=false
privacy/collected_data/gameplay_content/used_for_tracking=false
privacy/collected_data/gameplay_content/collection_purposes=0
privacy/collected_data/customer_support/collected=false
privacy/collected_data/customer_support/linked_to_user=false
privacy/collected_data/customer_support/used_for_tracking=false
privacy/collected_data/customer_support/collection_purposes=0
privacy/collected_data/other_user_content/collected=false
privacy/collected_data/other_user_content/linked_to_user=false
privacy/collected_data/other_user_content/used_for_tracking=false
privacy/collected_data/other_user_content/collection_purposes=0
privacy/collected_data/browsing_history/collected=false
privacy/collected_data/browsing_history/linked_to_user=false
privacy/collected_data/browsing_history/used_for_tracking=false
privacy/collected_data/browsing_history/collection_purposes=0
privacy/collected_data/search_hhistory/collected=false
privacy/collected_data/search_hhistory/linked_to_user=false
privacy/collected_data/search_hhistory/used_for_tracking=false
privacy/collected_data/search_hhistory/collection_purposes=0
privacy/collected_data/user_id/collected=false
privacy/collected_data/user_id/linked_to_user=false
privacy/collected_data/user_id/used_for_tracking=false
privacy/collected_data/user_id/collection_purposes=0
privacy/collected_data/device_id/collected=false
privacy/collected_data/device_id/linked_to_user=false
privacy/collected_data/device_id/used_for_tracking=false
privacy/collected_data/device_id/collection_purposes=0
privacy/collected_data/purchase_history/collected=false
privacy/collected_data/purchase_history/linked_to_user=false
privacy/collected_data/purchase_history/used_for_tracking=false
privacy/collected_data/purchase_history/collection_purposes=0
privacy/collected_data/product_interaction/collected=false
privacy/collected_data/product_interaction/linked_to_user=false
privacy/collected_data/product_interaction/used_for_tracking=false
privacy/collected_data/product_interaction/collection_purposes=0
privacy/collected_data/advertising_data/collected=false
privacy/collected_data/advertising_data/linked_to_user=false
privacy/collected_data/advertising_data/used_for_tracking=false
privacy/collected_data/advertising_data/collection_purposes=0
privacy/collected_data/other_usage_data/collected=false
privacy/collected_data/other_usage_data/linked_to_user=false
privacy/collected_data/other_usage_data/used_for_tracking=false
privacy/collected_data/other_usage_data/collection_purposes=0
privacy/collected_data/crash_data/collected=false
privacy/collected_data/crash_data/linked_to_user=false
privacy/collected_data/crash_data/used_for_tracking=false
privacy/collected_data/crash_data/collection_purposes=0
privacy/collected_data/performance_data/collected=false
privacy/collected_data/performance_data/linked_to_user=false
privacy/collected_data/performance_data/used_for_tracking=false
privacy/collected_data/performance_data/collection_purposes=0
privacy/collected_data/other_diagnostic_data/collected=false
privacy/collected_data/other_diagnostic_data/linked_to_user=false
privacy/collected_data/other_diagnostic_data/used_for_tracking=false
privacy/collected_data/other_diagnostic_data/collection_purposes=0
privacy/collected_data/environment_scanning/collected=false
privacy/collected_data/environment_scanning/linked_to_user=false
privacy/collected_data/environment_scanning/used_for_tracking=false
privacy/collected_data/environment_scanning/collection_purposes=0
privacy/collected_data/hands/collected=false
privacy/collected_data/hands/linked_to_user=false
privacy/collected_data/hands/used_for_tracking=false
privacy/collected_data/hands/collection_purposes=0
privacy/collected_data/head/collected=false
privacy/collected_data/head/linked_to_user=false
privacy/collected_data/head/used_for_tracking=false
privacy/collected_data/head/collection_purposes=0
privacy/collected_data/other_data_types/collected=false
privacy/collected_data/other_data_types/linked_to_user=false
privacy/collected_data/other_data_types/used_for_tracking=false
privacy/collected_data/other_data_types/collection_purposes=0
ssh_remote_deploy/enabled=false
ssh_remote_deploy/host="user@host_ip"
ssh_remote_deploy/port="22"

View File

@@ -1,63 +0,0 @@
extends Node
func _ready() -> void:
set_activity()
DiscordRPC.connect("activity_join_request",_on_activity_join_request)
DiscordRPC.connect("activity_join",_on_activity_join)
DiscordRPC.connect("activity_spectate",_on_activity_spectate)
DiscordRPC.connect("relationships_init",_on_relationship_init)
DiscordRPC.connect("updated_relationship", _on_updated_relationship)
func set_activity() -> void:
DiscordRPC.clear(false)
DiscordRPC.app_id = 1099618430065324082
DiscordRPC.details = "A demo activity by vaporvee#1231"
DiscordRPC.state = "Checkpoint 23/23"
DiscordRPC.large_image = "example_game"
DiscordRPC.large_image_text = "Try it now!"
DiscordRPC.small_image = "boss"
DiscordRPC.small_image_text = "Fighting the end boss! D:"
DiscordRPC.end_timestamp = int(Time.get_unix_time_from_system()) + 3600 # +1 hour in unix time
# It is NOT recommended to manage secrets locally! It's meant to be a payload wich the server understands and
# returns the other variables like current_party_size, party_id etc. Most of the values must differ from the others.
var my_secret: String = str(randi_range(0,999999))
DiscordRPC.party_id = "mylobbycanbeeverything_" + my_secret
DiscordRPC.current_party_size = 1
DiscordRPC.max_party_size = 4
DiscordRPC.match_secret = "m_" + my_secret #better use seeds with 1 to 1 range instead of just chars
DiscordRPC.join_secret = "j_" + my_secret
DiscordRPC.spectate_secret = "s_" + my_secret
DiscordRPC.is_public_party = true
DiscordRPC.instanced = true #required for spectate
#DiscordRPC.start_timestamp = int(Time.get_unix_time_from_system())
DiscordRPC.register_command("C:\\Users\\yanni\\Desktop\\demo\\DiscordRPC.exe")
#DiscordRPC.register_steam(1389990)
DiscordRPC.refresh()
var user_request: Dictionary;
func _on_activity_join_request(user_requesting) -> void:
print(user_requesting)
user_request = user_requesting
func _on_activity_join(secret) -> void:
if(DiscordRPC.join_secret != secret):
DiscordRPC.current_party_size = clamp(int(secret) + 1, 0, DiscordRPC.max_party_size)
DiscordRPC.party_id = secret.replace("j_","mylobbycanbeeverything_")
DiscordRPC.match_secret = secret.replace("j_","m_")
DiscordRPC.join_secret = secret
DiscordRPC.spectate_secret = secret.replace("j_","s_")
DiscordRPC.refresh()
func _on_activity_spectate(secret) -> void:
print(secret)
func _on_relationship_init():
print("initialized")
func _on_updated_relationship(relationship):
print(relationship)

View File

@@ -1,11 +1,18 @@
[gd_scene load_steps=4 format=3 uid="uid://dyc3kseph4el7"]
[gd_scene load_steps=5 format=3 uid="uid://dyc3kseph4el7"]
[ext_resource type="Script" path="res://main.gd" id="1_kl8ri"]
[ext_resource type="Texture2D" uid="uid://b3qm246m7pnsx" path="res://assets/Logo_V2.png" id="2_gd222"]
[ext_resource type="Script" path="res://addons/discord-rpc-gd/nodes/debug.gd" id="6_ujijw"]
[ext_resource type="Script" uid="uid://kmubk5a6i385" path="res://discord_connector.gd" id="3_h2yge"]
[ext_resource type="Script" uid="uid://46tue7u6crd6" path="res://addons/discord-rpc-gd/nodes/debug.gd" id="6_ujijw"]
[sub_resource type="RichPresence" id="RichPresence_h2yge"]
details = "Godot -> Discord Social SDK"
state = "Inside a Node"
large_image = "example_game"
large_text = "Example"
small_image = "boss"
small_text = "Fighting the boss D:"
[node name="Node" type="Node"]
script = ExtResource("1_kl8ri")
[node name="ColorRect" type="ColorRect" parent="."]
anchors_preset = 15
@@ -23,7 +30,7 @@ position = Vector2(789, 330.5)
scale = Vector2(0.408203, 0.408203)
texture = ExtResource("2_gd222")
[node name="DiscordRPC Test" type="RichTextLabel" parent="."]
[node name="DiscordUtil Test" type="RichTextLabel" parent="."]
anchors_preset = -1
anchor_left = 0.293
anchor_top = 0.59
@@ -38,7 +45,28 @@ grow_vertical = 2
size_flags_horizontal = 4
size_flags_vertical = 4
bbcode_enabled = true
text = "[center][font s=60]DiscordRPC Test"
text = "[center][font s=60]DiscordUtil Test"
[node name="DiscordRPCDebug" type="Node" parent="."]
[node name="DiscordSocialSDKDebug" type="Node" parent="."]
script = ExtResource("6_ujijw")
[node name="DiscordConnector" type="DiscordConnector" parent="."]
app_id = 1099618430065324082
auto_connect = true
script = ExtResource("3_h2yge")
[node name="DiscordActivity" type="DiscordActivity" parent="DiscordConnector"]
rich_presence = SubResource("RichPresence_h2yge")
root_connector = NodePath("..")
[node name="DiscordLobby" type="DiscordLobby" parent="DiscordConnector"]
root_connector = NodePath("..")
[node name="AnimatedSprite2D" type="AnimatedSprite2D" parent="."]
position = Vector2(789, 330.5)
scale = Vector2(0.408203, 0.408203)
[connection signal="authenticated" from="DiscordConnector" to="DiscordConnector" method="_on_authenticated"]
[connection signal="authentication_failed" from="DiscordConnector" to="DiscordConnector" method="_on_authentication_failed"]
[connection signal="connection_error" from="DiscordConnector" to="DiscordConnector" method="_on_connection_error"]
[connection signal="connection_ready" from="DiscordConnector" to="DiscordConnector" method="_on_connection_ready"]

View File

@@ -0,0 +1,3 @@
[gd_resource type="ActivityResource" format=3 uid="uid://coryo3jlwiadb"]
[resource]

View File

@@ -0,0 +1,4 @@
[gd_resource type="Compositor" format=3 uid="uid://cbg8e12ms0vvc"]
[resource]
compositor_effects = Array[CompositorEffect]([null])

View File

@@ -10,22 +10,28 @@ config_version=5
[application]
config/name="GDExtension DiscordRPC Test Project"
config/name="GDExtension DiscordUtil Test Project"
config/tags=PackedStringArray("vaporvee")
run/main_scene="res://main.tscn"
config/features=PackedStringArray("4.2")
config/features=PackedStringArray("4.4")
boot_splash/bg_color=Color(0.25098, 0.305882, 0.929412, 1)
boot_splash/image="res://assets/discordgodot_cover.png"
boot_splash/fullsize=false
boot_splash/image="res://assets/discordgodot_cover.png"
config/icon="res://assets/Logo_V2.png"
[autoload]
[debug]
DiscordRPCLoader="*res://addons/discord-rpc-gd/nodes/discord_autoload.gd"
gdscript/warnings/untyped_declaration=1
gdscript/warnings/inferred_declaration=1
gdscript/warnings/unsafe_property_access=1
gdscript/warnings/unsafe_method_access=1
gdscript/warnings/unsafe_cast=1
gdscript/warnings/unsafe_call_argument=1
[display]
window/size/resizable=false
display_server/driver.linuxbsd="wayland"
[dotnet]

View File

@@ -1,61 +1,44 @@
import zipfile
from distutils.dir_util import copy_tree
import shutil
import os
import re
import shutil
import sys
import glob
with zipfile.ZipFile("src/lib/discord_game_sdk.zip", "r") as zip_ref:
zip_ref.extractall("src/lib/discord_game_sdk/")
EXPECTED_VERSION = "1.0.7445"
# Patch the SDK to actually build, since it's missing an include
with open("src/lib/discord_game_sdk/cpp/types.h", "r+") as f:
s = f.read()
f.seek(0)
f.write("#include <cstdint>\n" + s)
zip_files = glob.glob("src/lib/DiscordSocialSdk-*.zip")
if not zip_files:
print("Error: No zip file matching 'DiscordSocialSdk-*.zip' found.")
sys.exit(1)
copy_tree("src/lib/discord_game_sdk/lib/", "src/lib/discord_game_sdk/bin/")
os.rename(
"src/lib/discord_game_sdk/bin/aarch64/discord_game_sdk.dylib",
"src/lib/discord_game_sdk/bin/aarch64/discord_game_sdk_aarch64.dylib",
)
os.rename(
"src/lib/discord_game_sdk/bin/x86_64/discord_game_sdk.so",
"src/lib/discord_game_sdk/bin/x86_64/libdiscord_game_sdk.so",
)
os.rename(
"src/lib/discord_game_sdk/bin/x86/discord_game_sdk.dll",
"src/lib/discord_game_sdk/bin/x86/discord_game_sdk_x86.dll",
)
zip_path = zip_files[0] # Use the first matching file
match = re.search(r"DiscordSocialSdk-(\d+\.\d+\.\d+)\.zip", zip_path)
if match:
extracted_version = match.group(1)
if extracted_version != EXPECTED_VERSION:
print(f"Warning: Last tested version {EXPECTED_VERSION}, but found {extracted_version} in the zip file.")
print(f"Extracting {zip_path}...")
os.rename(
"src/lib/discord_game_sdk/bin/x86_64/discord_game_sdk.dll.lib",
"src/lib/discord_game_sdk/bin/x86_64/discord_game_sdk.lib",
)
copy_tree("src/lib/discord_game_sdk/bin/aarch64/", "src/lib/discord_game_sdk/bin/")
copy_tree("src/lib/discord_game_sdk/bin/x86/", "src/lib/discord_game_sdk/bin/")
copy_tree("src/lib/discord_game_sdk/bin/x86_64/", "src/lib/discord_game_sdk/bin/")
# Extract the zip file ignoring the version in the filename
with zipfile.ZipFile(zip_path, "r") as zip_ref:
zip_ref.extractall("src/lib/")
shutil.rmtree("src/lib/discord_game_sdk/c/", ignore_errors=True)
shutil.rmtree("src/lib/discord_game_sdk/csharp/", ignore_errors=True)
shutil.rmtree("src/lib/discord_game_sdk/examples/", ignore_errors=True)
shutil.rmtree("src/lib/discord_game_sdk/lib/", ignore_errors=True)
shutil.rmtree("src/lib/discord_game_sdk/bin/aarch64/", ignore_errors=True)
shutil.rmtree("src/lib/discord_game_sdk/bin/x86/", ignore_errors=True)
shutil.rmtree("src/lib/discord_game_sdk/bin/x86_64/", ignore_errors=True)
os.remove("src/lib/discord_game_sdk/README.md")
release_dll_src = "src/lib/discord_social_sdk/bin/release/discord_partner_sdk.dll"
release_dll_dest = "src/lib/discord_social_sdk/lib/release/"
os.makedirs(release_dll_dest, exist_ok=True)
shutil.copy(release_dll_src, release_dll_dest)
if sys.platform == "darwin":
# Combine the two libraries into one
os.system(
"lipo src/lib/discord_game_sdk/bin/{discord_game_sdk.dylib,discord_game_sdk_aarch64.dylib} -output src/lib/discord_game_sdk/bin/libdiscord_game_sdk.dylib -create"
)
# Change the install name to (library's location)/(its new name)
os.system(
"install_name_tool -id '@loader_path/libdiscord_game_sdk.dylib'\
src/lib/discord_game_sdk/bin/libdiscord_game_sdk.dylib"
)
# Remove the ones it's made of
os.remove("src/lib/discord_game_sdk/bin/discord_game_sdk.dylib")
os.remove("src/lib/discord_game_sdk/bin/discord_game_sdk_aarch64.dylib")
debug_dll_src = "src/lib/discord_social_sdk/bin/debug/discord_partner_sdk.dll"
debug_dll_dest = "src/lib/discord_social_sdk/lib/debug/"
os.makedirs(debug_dll_dest, exist_ok=True)
shutil.copy(debug_dll_src, debug_dll_dest)
bin_folder = "src/lib/discord_social_sdk/bin"
shutil.rmtree(bin_folder, ignore_errors=True)
print(f"Extracted and copied Discord Social SDK version: {extracted_version}")
print("Getting submodules...")
os.system("git submodule update --init --remote")
print("Finished setup.")

18
src/definitions.h Normal file
View File

@@ -0,0 +1,18 @@
#define BIND_METHOD(class_name, method, ...) godot::ClassDB::bind_method(D_METHOD(#method, ##__VA_ARGS__), &class_name::method)
#define BIND_SET_GET(class_name, property_name, variant_type, ...) \
godot::ClassDB::bind_method(D_METHOD("get_" #property_name), &class_name::get_##property_name); \
godot::ClassDB::bind_method(D_METHOD("set_" #property_name, #variant_type), &class_name::set_##property_name); \
godot::ClassDB::add_property(class_name::get_class_static(), PropertyInfo(variant_type, #property_name, ##__VA_ARGS__), "set_" #property_name, "get_" #property_name)
#define BIND_SIGNAL(signal_name, ...) ADD_SIGNAL(MethodInfo(#signal_name, ##__VA_ARGS__))
// getter isn't mandatory for this project
#define SET_GET(class_name, variable, setter, ...) decltype(class_name::variable) class_name::get_##variable() { return variable; } void class_name::set_##variable(decltype(class_name::variable) value) { variable = value; setter; }
#define RESOLVE_TYPE(default_value) \
typename std::conditional<std::is_same<decltype(default_value), const char (&)[1]>::value, godot::String, \
typename std::conditional<std::is_same<decltype(default_value), bool>::value, bool, \
typename std::conditional<std::is_integral<decltype(default_value)>::value, int64_t, \
decltype(default_value)>::type>::type>::type
#define H_SET_GET(property_name, default_value) private: RESOLVE_TYPE(default_value) property_name = default_value; public: RESOLVE_TYPE(default_value) get_##property_name(); void set_##property_name(RESOLVE_TYPE(default_value) value);
#define MAKE_RESOURCE_TYPE_HINT(m_type) vformat("%s/%s:%s", Variant::OBJECT, PROPERTY_HINT_RESOURCE_TYPE, m_type)

View File

@@ -1,430 +0,0 @@
#include "discordgodot.h"
#include "lib/discord_game_sdk/cpp/discord.h"
#include <godot_cpp/core/class_db.hpp>
#include <godot_cpp/variant/utility_functions.hpp>
#define BIND_METHOD(method, ...) godot::ClassDB::bind_method(D_METHOD(#method, ##__VA_ARGS__), &DiscordRPC::method)
#define BIND_SET_GET(property_name, variant_type) \
godot::ClassDB::bind_method(D_METHOD("get_" #property_name), &DiscordRPC::get_##property_name); \
godot::ClassDB::bind_method(D_METHOD("set_" #property_name, #variant_type), &DiscordRPC::set_##property_name); \
godot::ClassDB::add_property(get_class_static(), PropertyInfo(variant_type, #property_name), "set_" #property_name, "get_" #property_name)
#define BIND_SIGNAL(signal_name, ...) godot::ClassDB::add_signal(get_class_static(), MethodInfo(#signal_name, ##__VA_ARGS__))
#define SET_GET(variable, setter, ...) /*getter isn't mandatory for this project*/ \
decltype(DiscordRPC::variable) DiscordRPC::get_##variable() { return variable; } \
void DiscordRPC::set_##variable(decltype(DiscordRPC::variable) value) \
{ \
variable = value; \
setter; \
}
DiscordRPC *DiscordRPC::singleton = nullptr;
discord::Core *core{};
discord::Result result;
discord::Activity activity{};
discord::User user{};
void DiscordRPC::_bind_methods()
{
BIND_SET_GET(app_id, Variant::INT);
BIND_SET_GET(state, Variant::STRING);
BIND_SET_GET(details, Variant::STRING);
BIND_SET_GET(large_image, Variant::STRING);
BIND_SET_GET(large_image_text, Variant::STRING);
BIND_SET_GET(small_image, Variant::STRING);
BIND_SET_GET(small_image_text, Variant::STRING);
BIND_SET_GET(start_timestamp, Variant::INT);
BIND_SET_GET(end_timestamp, Variant::INT);
BIND_SET_GET(party_id, Variant::STRING);
BIND_SET_GET(current_party_size, Variant::INT);
BIND_SET_GET(max_party_size, Variant::INT);
BIND_SET_GET(match_secret, Variant::STRING);
BIND_SET_GET(join_secret, Variant::STRING);
BIND_SET_GET(spectate_secret, Variant::STRING);
BIND_SET_GET(instanced, Variant::BOOL);
BIND_SET_GET(is_public_party, Variant::BOOL);
BIND_SIGNAL(activity_join, PropertyInfo(Variant::STRING, "join_secret"));
BIND_SIGNAL(activity_spectate, PropertyInfo(Variant::STRING, "spectate_secret"));
BIND_SIGNAL(activity_join_request, PropertyInfo(Variant::DICTIONARY, "user_requesting"));
BIND_SIGNAL(updated_relationship, PropertyInfo(Variant::DICTIONARY, "relationship"));
BIND_SIGNAL(overlay_toggle, PropertyInfo(Variant::BOOL, "is_locked"));
BIND_SIGNAL(relationships_init);
BIND_METHOD(debug);
BIND_METHOD(run_callbacks);
BIND_METHOD(refresh);
ClassDB::bind_method(D_METHOD("clear", "reset_values"), &DiscordRPC::clear, DEFVAL(false));
BIND_METHOD(unclear);
BIND_METHOD(register_command, "command");
BIND_METHOD(register_steam, "steam_id");
BIND_METHOD(accept_join_request, "user_id");
BIND_METHOD(send_invite, "user_id", "is_spectate", "message_content");
BIND_METHOD(accept_invite, "user_id");
BIND_METHOD(get_current_user);
BIND_METHOD(get_all_relationships);
BIND_METHOD(get_is_overlay_enabled);
BIND_METHOD(get_is_overlay_locked);
BIND_METHOD(open_invite_overlay, "is_spectate");
BIND_METHOD(open_server_invite_overlay, "invite_code");
BIND_METHOD(open_voice_settings);
BIND_METHOD(get_is_discord_working);
BIND_METHOD(get_result_int);
}
SET_GET(state, activity.SetState(value.utf8().get_data()))
SET_GET(details, activity.SetDetails(value.utf8().get_data()))
SET_GET(large_image, activity.GetAssets().SetLargeImage(value.utf8().get_data()))
SET_GET(large_image_text, activity.GetAssets().SetLargeText(value.utf8().get_data()))
SET_GET(small_image, activity.GetAssets().SetSmallImage(value.utf8().get_data()))
SET_GET(small_image_text, activity.GetAssets().SetSmallText(value.utf8().get_data()))
SET_GET(start_timestamp, activity.GetTimestamps().SetStart(value))
SET_GET(end_timestamp, activity.GetTimestamps().SetEnd(value))
SET_GET(party_id, activity.GetParty().SetId(value.utf8().get_data()))
SET_GET(current_party_size, activity.GetParty().GetSize().SetCurrentSize(value))
SET_GET(max_party_size, activity.GetParty().GetSize().SetMaxSize(value))
SET_GET(match_secret, activity.GetSecrets().SetMatch(value.utf8().get_data()))
SET_GET(join_secret, activity.GetSecrets().SetJoin(value.utf8().get_data()))
SET_GET(spectate_secret, activity.GetSecrets().SetSpectate(value.utf8().get_data()))
SET_GET(instanced, activity.SetInstance(value))
SET_GET(is_public_party, activity.GetParty().SetPrivacy(static_cast<discord::ActivityPartyPrivacy>(value)))
DiscordRPC::DiscordRPC()
{
ERR_FAIL_COND(singleton != nullptr);
singleton = this;
}
DiscordRPC::~DiscordRPC()
{
app_id = 0;
delete core; // couldn't use destructor because it would not compile on linux
core = nullptr;
ERR_FAIL_COND(singleton != this);
singleton = nullptr;
}
DiscordRPC *DiscordRPC::get_singleton()
{
return singleton;
}
void DiscordRPC::run_callbacks()
{
if (result == discord::Result::Ok && app_id > 0)
::core->RunCallbacks();
}
void DiscordRPC::debug()
{
result = discord::Core::Create(1080224638845591692, DiscordCreateFlags_NoRequireDiscord, &core);
activity.SetState("Test from Godot!");
activity.SetDetails("I worked months on this");
activity.GetAssets().SetLargeImage("test1");
activity.GetAssets().SetLargeText("wow test text for large image");
activity.GetAssets().SetSmallImage("godot");
activity.GetAssets().SetSmallText("wow test text for small image");
activity.GetTimestamps().SetStart(1682242800);
if (result == discord::Result::Ok)
{
core->ActivityManager().UpdateActivity(activity, [](discord::Result result) {});
}
else
UtilityFunctions::push_warning("Discord Activity couldn't be updated. It could be that Discord isn't running!");
}
void DiscordRPC::set_app_id(int64_t value)
{
app_id = value;
if (app_id > 0)
{
result = discord::Core::Create(value, DiscordCreateFlags_NoRequireDiscord, &core); // after setting app_ID it initializes everything
if (result == discord::Result::Ok)
{
// initialize currentuser
core->UserManager().OnCurrentUserUpdate.Connect([]()
{discord::User user{};
core->UserManager().GetCurrentUser(&user); });
// signals
core->ActivityManager().OnActivityJoin.Connect([](const char *secret)
{ DiscordRPC::get_singleton()
->emit_signal("activity_join", secret); });
core->ActivityManager().OnActivitySpectate.Connect([](const char *secret)
{ DiscordRPC::get_singleton()
->emit_signal("activity_spectate", secret); });
core->ActivityManager().OnActivityJoinRequest.Connect([this](discord::User const &user)
{ DiscordRPC::get_singleton()
->emit_signal("activity_join_request", user2dict(user)); });
core->OverlayManager().OnToggle.Connect([](bool is_locked)
{ DiscordRPC::get_singleton()
->emit_signal("overlay_toggle", is_locked); });
core->RelationshipManager().OnRefresh.Connect([&]()
{ DiscordRPC::get_singleton()
->emit_signal("relationships_init"); });
core->RelationshipManager().OnRelationshipUpdate.Connect([&](discord::Relationship const &relationship)
{ DiscordRPC::get_singleton()
->emit_signal("updated_relationship", relationship2dict(relationship)); });
}
}
}
int64_t DiscordRPC::get_app_id()
{
if (app_id != 0)
return app_id;
return old_app_id;
}
void DiscordRPC::refresh()
{
if (get_is_discord_working())
{
activity.GetParty().SetPrivacy(discord::ActivityPartyPrivacy::Public);
activity.SetType(discord::ActivityType::Playing);
core->ActivityManager().UpdateActivity(activity, [](discord::Result result) {});
}
else
UtilityFunctions::push_warning("Discord Activity couldn't be updated. It could be that Discord isn't running!");
}
void DiscordRPC::clear(bool reset_values = false)
{
if (get_is_discord_working())
{
if (reset_values)
{
old_app_id = 0;
set_state("");
set_details("");
set_large_image("");
set_large_image_text("");
set_small_image("");
set_small_image_text("");
set_start_timestamp(0);
set_end_timestamp(0);
set_party_id("");
set_current_party_size(0);
set_max_party_size(0);
set_match_secret("");
set_join_secret("");
set_spectate_secret("");
set_instanced(false);
set_is_public_party(false);
set_is_overlay_locked(false);
core->ActivityManager().ClearActivity([](discord::Result result) {});
}
else
old_app_id = app_id;
app_id = 0;
delete core;
core = nullptr;
}
}
void DiscordRPC::unclear()
{
if (old_app_id > 0)
{
set_app_id(old_app_id);
refresh();
old_app_id = 0;
}
else
UtilityFunctions::push_warning("Discord Activity couldn't be uncleared. Maybe it didn't get cleared before?");
}
bool DiscordRPC::get_is_overlay_enabled()
{
bool ie;
if (get_is_discord_working())
core->OverlayManager().IsEnabled(&ie);
return ie;
}
bool DiscordRPC::get_is_overlay_locked()
{
bool il;
if (get_is_discord_working())
core->OverlayManager().IsLocked(&il);
return il;
}
void DiscordRPC::set_is_overlay_locked(bool value)
{
is_overlay_locked = value;
if (get_is_discord_working())
core->OverlayManager().SetLocked(value, {});
}
void DiscordRPC::open_invite_overlay(bool is_spectate)
{
if (get_is_discord_working())
core->OverlayManager().OpenActivityInvite(static_cast<discord::ActivityActionType>(is_spectate + 1), {});
}
void DiscordRPC::open_server_invite_overlay(String invite_code)
{
if (get_is_discord_working())
core->OverlayManager().OpenGuildInvite(invite_code.utf8().get_data(), {});
}
void DiscordRPC::open_voice_settings()
{
if (get_is_discord_working())
core->OverlayManager().OpenVoiceSettings({});
}
void DiscordRPC::accept_join_request(int64_t user_id)
{
if (get_is_discord_working())
core->ActivityManager().SendRequestReply(user_id, static_cast<discord::ActivityJoinRequestReply>(1), {});
}
void DiscordRPC::send_invite(int64_t user_id, bool is_spectate = false, String message_content = "")
{
if (get_is_discord_working())
core->ActivityManager().SendInvite(user_id, static_cast<discord::ActivityActionType>(is_spectate + 1), message_content.utf8().get_data(), {});
}
void DiscordRPC::accept_invite(int64_t user_id)
{
if (get_is_discord_working())
core->ActivityManager().AcceptInvite(user_id, {});
}
void DiscordRPC::register_command(String value)
{
if (get_is_discord_working())
core->ActivityManager().RegisterCommand(value.utf8().get_data());
}
void DiscordRPC::register_steam(int32_t value)
{
if (get_is_discord_working())
core->ActivityManager().RegisterSteam(value);
}
Dictionary DiscordRPC::get_current_user()
{
Dictionary userdict;
if (get_is_discord_working())
{
discord::User user{};
core->UserManager().GetCurrentUser(&user);
return user2dict(user);
}
return userdict;
}
Dictionary DiscordRPC::get_relationship(int64_t user_id)
{
if (get_is_discord_working())
{
discord::Relationship relationship{};
core->RelationshipManager().Get(user_id, &relationship);
return relationship2dict(relationship);
}
Dictionary dict;
return dict;
}
Array DiscordRPC::get_all_relationships()
{
Array all_relationships;
core->RelationshipManager().Filter(
[](discord::Relationship const &relationship) -> bool
{ return true; });
int32_t friendcount{0};
core->RelationshipManager().Count(&friendcount);
for (int i = 0; i < friendcount; i++)
{
discord::Relationship relationship{};
core->RelationshipManager().GetAt(i, &relationship);
all_relationships.append(relationship2dict(relationship));
}
return all_relationships;
}
int DiscordRPC::get_result_int()
{
return static_cast<int>(result);
}
Dictionary DiscordRPC::user2dict(discord::User user)
{
Dictionary userdict;
userdict["avatar"] = user.GetAvatar(); // can be empty when user has no avatar
userdict["is_bot"] = user.GetBot();
userdict["discriminator"] = user.GetDiscriminator();
userdict["id"] = user.GetId();
userdict["username"] = user.GetUsername();
if (String(userdict["avatar"]).is_empty())
userdict["avatar_url"] = String(std::string("https://cdn.discordapp.com/embed/avatars/" + std::to_string((userdict["discriminator"].INT % 5) - 1) + ".png").c_str());
else
userdict["avatar_url"] = String(std::string("https://cdn.discordapp.com/avatars/" + std::to_string(user.GetId()) + "/" + user.GetAvatar() + ".png").c_str());
userdict.make_read_only();
return userdict;
}
Dictionary DiscordRPC::relationship2dict(discord::Relationship relationship)
{
Dictionary dict_relationship;
Dictionary presence;
Dictionary presence_activity;
switch (static_cast<int>(relationship.GetPresence().GetStatus()))
{
case 0:
presence["status"] = "Offline";
break;
case 1:
presence["status"] = "Online";
break;
case 2:
presence["status"] = "Idle";
break;
case 3:
presence["status"] = "DoNotDisturb";
break;
default:
presence["status"] = "NotAvailable";
break;
}
presence_activity["application_id"] = relationship.GetPresence().GetActivity().GetApplicationId();
presence_activity["name"] = relationship.GetPresence().GetActivity().GetName();
presence_activity["state"] = relationship.GetPresence().GetActivity().GetState();
presence_activity["details"] = relationship.GetPresence().GetActivity().GetDetails();
presence_activity["large_image"] = relationship.GetPresence().GetActivity().GetAssets().GetLargeImage();
presence_activity["large_text"] = relationship.GetPresence().GetActivity().GetAssets().GetLargeText();
presence_activity["small_image"] = relationship.GetPresence().GetActivity().GetAssets().GetSmallImage();
presence_activity["small_text"] = relationship.GetPresence().GetActivity().GetAssets().GetSmallText();
presence_activity["timestamps_start"] = relationship.GetPresence().GetActivity().GetTimestamps().GetStart();
presence_activity["timestamps_end"] = relationship.GetPresence().GetActivity().GetTimestamps().GetEnd();
presence_activity["instance"] = relationship.GetPresence().GetActivity().GetInstance();
presence_activity["party_id"] = relationship.GetPresence().GetActivity().GetParty().GetId();
presence_activity["current_party_size"] = relationship.GetPresence().GetActivity().GetParty().GetSize().GetCurrentSize();
presence_activity["max_party_size"] = relationship.GetPresence().GetActivity().GetParty().GetSize().GetMaxSize();
presence_activity["join_secret"] = relationship.GetPresence().GetActivity().GetSecrets().GetJoin();
presence_activity["spectate_secret"] = relationship.GetPresence().GetActivity().GetSecrets().GetSpectate();
presence_activity["match_secret"] = relationship.GetPresence().GetActivity().GetSecrets().GetMatch();
presence["activity"] = presence_activity;
presence.make_read_only();
switch (relationship.GetType())
{
case discord::RelationshipType::None:
dict_relationship["type"] = "None";
break;
case discord::RelationshipType::Friend:
dict_relationship["type"] = "Friend";
break;
case discord::RelationshipType::Blocked:
dict_relationship["type"] = "Blocked";
break;
case discord::RelationshipType::PendingIncoming:
dict_relationship["type"] = "PendingIncoming";
break;
case discord::RelationshipType::PendingOutgoing:
dict_relationship["type"] = "PendingOutgoing";
break;
case discord::RelationshipType::Implicit:
dict_relationship["type"] = "Implicit";
break;
default:
dict_relationship["type"] = "NotAvailable";
break;
}
dict_relationship["user"] = user2dict(relationship.GetUser());
dict_relationship["presence"] = presence;
dict_relationship.make_read_only();
return dict_relationship;
}
bool DiscordRPC::get_is_discord_working()
{
return result == discord::Result::Ok && app_id > 0;
}

View File

@@ -1,79 +0,0 @@
#ifndef DISCORDGODOT_H
#define DISCORDGODOT_H
#include <stdio.h>
#include "lib/discord_game_sdk/cpp/discord.h"
#include <godot_cpp/classes/object.hpp>
#include <godot_cpp/core/class_db.hpp>
#define H_SET_GET(variable_type, property_name) \
variable_type property_name; \
variable_type get_##property_name(); \
void set_##property_name(variable_type value);
using namespace godot;
class DiscordRPC : public Object
{
GDCLASS(DiscordRPC, Object);
static DiscordRPC *singleton;
protected:
static void _bind_methods();
public:
static DiscordRPC *
get_singleton();
DiscordRPC();
~DiscordRPC();
// INTERBNAL
int64_t old_app_id;
Dictionary relationship2dict(discord::Relationship relationship);
Dictionary user2dict(discord::User user);
///
void set_app_id(int64_t value);
int64_t get_app_id();
int64_t app_id = 0; // needs to be directly setted to 0 or it will crash randomly
H_SET_GET(String, state)
H_SET_GET(String, details)
H_SET_GET(String, large_image)
H_SET_GET(String, large_image_text)
H_SET_GET(String, small_image)
H_SET_GET(String, small_image_text)
H_SET_GET(int64_t, start_timestamp)
H_SET_GET(int64_t, end_timestamp)
H_SET_GET(String, party_id)
H_SET_GET(int32_t, current_party_size)
H_SET_GET(int32_t, max_party_size)
H_SET_GET(String, match_secret)
H_SET_GET(String, join_secret)
H_SET_GET(String, spectate_secret)
H_SET_GET(bool, is_public_party)
H_SET_GET(bool, instanced)
H_SET_GET(bool, is_overlay_locked)
void debug();
void run_callbacks();
void refresh();
void clear(bool reset_values);
void unclear();
bool get_is_overlay_enabled();
void open_invite_overlay(bool is_spectate);
void open_server_invite_overlay(String invite_code);
void open_voice_settings();
void accept_join_request(int64_t user_id);
void send_invite(int64_t user_id, bool is_spectate, String message_content);
void accept_invite(int64_t user_id);
void register_command(String value);
void register_steam(int32_t value);
Dictionary get_current_user();
Dictionary get_relationship(int64_t user_id);
Array get_all_relationships();
bool get_is_discord_working();
int get_result_int();
};
#endif

View File

@@ -1,55 +0,0 @@
#include "editor_presence.h"
#include "lib/discord_game_sdk/cpp/discord.h"
#include <godot_cpp/core/class_db.hpp>
#include <godot_cpp/variant/utility_functions.hpp>
#include <godot_cpp/classes/scene_tree.hpp>
EditorPresence *EditorPresence::singleton = nullptr;
void EditorPresence::_bind_methods()
{
}
EditorPresence::EditorPresence()
{
singleton = this;
}
EditorPresence::~EditorPresence()
{
singleton = nullptr;
delete core; // couldn't use destructor because it would not compile on linux
core = nullptr;
}
EditorPresence *EditorPresence::get_singleton()
{
return singleton;
}
void EditorPresence::_ready()
{
result = discord::Core::Create(1108142249990176808, DiscordCreateFlags_NoRequireDiscord, &core);
activity.SetState("Editing a project...");
activity.SetDetails(String(project_settings->get_setting("application/config/name")).utf8());
if (project_settings->has_setting("application/config/name"))
{
activity.GetAssets().SetLargeImage("godot");
}
activity.GetAssets().SetLargeText(String(engine->get_version_info()["string"]).utf8());
activity.GetTimestamps().SetStart(time->get_unix_time_from_system());
if (result == discord::Result::Ok)
core->ActivityManager().UpdateActivity(activity, [](discord::Result result) {});
else
UtilityFunctions::push_warning("EditorPresence couldn't be loaded! Maybe your Discord isn't running?");
}
void EditorPresence::_process(double delta)
{
if (state_string.utf8() != activity.GetState())
{
godot::Node *edited_scene_root = get_tree()->get_edited_scene_root();
activity.SetState(String("Editing: \"" + edited_scene_root->get_scene_file_path() + "\"").replace("res://", "").utf8());
if (result == discord::Result::Ok)
core->ActivityManager().UpdateActivity(activity, [](discord::Result result) {});
}
if (result == discord::Result::Ok)
core->RunCallbacks();
}

View File

@@ -1,44 +0,0 @@
#ifndef EDITOR_PRESENCE_H
#define EDITOR_PRESENCE_H
#include <stdio.h>
#include "lib/discord_game_sdk/cpp/discord.h"
#include <godot_cpp/classes/node.hpp>
#include <godot_cpp/core/class_db.hpp>
#include <godot_cpp/classes/project_settings.hpp>
#include <godot_cpp/classes/engine.hpp>
#include <godot_cpp/classes/time.hpp>
#include <godot_cpp/classes/tree.hpp>
using namespace godot;
class EditorPresence : public Node
{
GDCLASS(EditorPresence, Node);
static EditorPresence *singleton;
protected:
static void _bind_methods();
public:
static EditorPresence *
get_singleton();
godot::Engine *engine = godot::Engine::get_singleton();
godot::ProjectSettings *project_settings = godot::ProjectSettings::get_singleton();
godot::Time *time = godot::Time::get_singleton();
discord::Core *core{};
discord::Result result;
discord::Activity activity{};
String state_string;
EditorPresence();
~EditorPresence();
void _ready() override;
void _process(double delta) override;
};
#endif

696
src/gen/doc_data.gen.cpp Normal file
View File

@@ -0,0 +1,696 @@
/* THIS FILE IS GENERATED DO NOT EDIT */
#include <godot_cpp/godot.hpp>
static const char *_doc_data_hash = "8781033133787346433";
static const int _doc_data_uncompressed_size = 4148;
static const int _doc_data_compressed_size = 684;
static const unsigned char _doc_data_compressed[] = {
120,
218,
237,
87,
193,
114,
218,
48,
16,
61,
39,
95,
225,
209,
161,
183,
96,
146,
92,
58,
20,
146,
67,
211,
94,
154,
166,
157,
161,
153,
233,
205,
35,
75,
139,
81,
99,
75,
174,
36,
7,
248,
251,
174,
44,
139,
98,
195,
0,
45,
208,
118,
166,
185,
192,
90,
171,
221,
247,
118,
181,
43,
175,
135,
183,
243,
34,
143,
158,
65,
27,
161,
228,
136,
92,
246,
250,
36,
2,
201,
20,
23,
50,
27,
145,
199,
47,
239,
47,
94,
147,
232,
246,
230,
124,
200,
114,
106,
76,
36,
105,
1,
35,
114,
39,
12,
83,
154,
191,
85,
82,
2,
179,
74,
147,
72,
200,
41,
104,
97,
205,
82,
55,
86,
76,
208,
124,
124,
247,
129,
68,
8,
32,
205,
96,
110,
196,
136,
76,
173,
45,
7,
113,
60,
155,
205,
122,
179,
235,
158,
210,
89,
124,
213,
239,
95,
198,
95,
63,
222,
143,
217,
20,
10,
122,
33,
164,
177,
84,
50,
64,
43,
35,
6,
82,
61,
32,
158,
41,
41,
3,
175,
191,
87,
140,
218,
154,
168,
243,
100,
208,
149,
166,
179,
94,
38,
236,
180,
74,
43,
3,
154,
41,
105,
65,
218,
30,
83,
69,
156,
41,
174,
240,
33,
19,
18,
188,
28,
23,
212,
88,
208,
49,
87,
44,
174,
163,
233,
205,
13,
39,
55,
231,
103,
195,
84,
11,
152,
36,
28,
12,
211,
162,
116,
254,
221,
98,
188,
113,
181,
187,
169,
243,
108,
43,
76,
7,
6,
110,
106,
101,
235,
169,
0,
59,
85,
220,
137,
65,
110,
178,
201,
124,
26,
19,
23,
128,
163,
131,
122,
13,
182,
210,
50,
178,
139,
18,
245,
207,
74,
112,
18,
197,
94,
211,
198,
59,
91,
99,
128,
11,
222,
249,
58,
142,
134,
137,
6,
51,
173,
113,
18,
171,
158,
64,
238,
68,
43,
169,
166,
5,
30,
46,
135,
249,
136,
96,
101,
52,
132,
43,
173,
49,
203,
73,
112,
232,
125,
53,
246,
99,
171,
177,
116,
142,
193,
183,
42,
57,
181,
112,
56,
93,
202,
24,
24,
115,
52,
150,
65,
108,
14,
181,
72,
177,
119,
26,
242,
78,
14,
160,
101,
153,
56,
102,
30,
78,
72,
75,
34,
3,
22,
203,
111,
68,
240,
63,
9,
234,
172,
89,
203,
86,
214,
56,
76,
104,
149,
91,
23,
65,
128,
118,
142,
55,
96,
96,
121,
37,
77,
245,
4,
164,
84,
169,
188,
3,
213,
218,
213,
2,
108,
105,
150,
176,
19,
44,
88,
216,
7,
26,
239,
9,
189,
168,
83,
148,
60,
193,
162,
155,
218,
53,
14,
221,
237,
107,
84,
186,
27,
150,
140,
94,
125,
175,
148,
125,
227,
127,
247,
33,
86,
31,
117,
82,
80,
73,
51,
216,
145,
152,
246,
214,
53,
74,
109,
245,
246,
20,
5,
177,
46,
12,
35,
50,
233,
27,
63,
200,
161,
170,
93,
57,
55,
73,
7,
78,
14,
44,
220,
150,
225,
37,
233,
116,
250,
222,
150,
87,
193,
18,
230,
165,
64,
211,
68,
200,
86,
233,
238,
223,
38,
62,
214,
237,
97,
187,
3,
158,
80,
145,
239,
8,
31,
180,
118,
175,
150,
223,
109,
216,
173,
76,
252,
185,
134,
60,
253,
75,
100,
254,
183,
154,
104,
110,
249,
191,
124,
4,
158,
69,
192,
255,
21,
111,
65,
196,
86,
31,
250,
177,
2,
133,
3,
134,
170,
149,
193,
233,
231,
80,
245,
160,
56,
188,
12,
82,
199,
75,
242,
163,
21,
249,
106,
126,
63,
165,
223,
234,
119,
224,
75,
134,
183,
143,
170,
28,
210,
42,
59,
229,
140,
154,
129,
4,
237,
238,
131,
77,
3,
193,
6,
220,
227,
77,
155,
186,
146,
9,
163,
121,
158,
82,
246,
100,
78,
25,
162,
161,
207,
224,
111,
97,
115,
186,
129,
246,
207,
190,
3,
90,
54,
215,
100,
255,
25,
241,
176,
241,
251,
176,
171,
224,
29,
23,
88,
242,
159,
49,
42,
168,
187,
248,
229,
19,
118,
223,
155,
247,
7,
100,
41,
93,
61,
};
static godot::internal::DocDataRegistration _doc_data_registration(_doc_data_hash, _doc_data_uncompressed_size, _doc_data_compressed_size, _doc_data_compressed);

Binary file not shown.

View File

@@ -1,99 +0,0 @@
#if !defined(_CRT_SECURE_NO_WARNINGS)
#define _CRT_SECURE_NO_WARNINGS
#endif
#include "achievement_manager.h"
#include "core.h"
#include <cstring>
#include <memory>
namespace discord {
class AchievementEvents final {
public:
static void DISCORD_CALLBACK OnUserAchievementUpdate(void* callbackData,
DiscordUserAchievement* userAchievement)
{
auto* core = reinterpret_cast<Core*>(callbackData);
if (!core) {
return;
}
auto& module = core->AchievementManager();
module.OnUserAchievementUpdate(*reinterpret_cast<UserAchievement const*>(userAchievement));
}
};
IDiscordAchievementEvents AchievementManager::events_{
&AchievementEvents::OnUserAchievementUpdate,
};
void AchievementManager::SetUserAchievement(Snowflake achievementId,
std::uint8_t percentComplete,
std::function<void(Result)> callback)
{
static auto wrapper = [](void* callbackData, EDiscordResult result) -> void {
std::unique_ptr<std::function<void(Result)>> cb(
reinterpret_cast<std::function<void(Result)>*>(callbackData));
if (!cb || !(*cb)) {
return;
}
(*cb)(static_cast<Result>(result));
};
std::unique_ptr<std::function<void(Result)>> cb{};
cb.reset(new std::function<void(Result)>(std::move(callback)));
internal_->set_user_achievement(
internal_, achievementId, percentComplete, cb.release(), wrapper);
}
void AchievementManager::FetchUserAchievements(std::function<void(Result)> callback)
{
static auto wrapper = [](void* callbackData, EDiscordResult result) -> void {
std::unique_ptr<std::function<void(Result)>> cb(
reinterpret_cast<std::function<void(Result)>*>(callbackData));
if (!cb || !(*cb)) {
return;
}
(*cb)(static_cast<Result>(result));
};
std::unique_ptr<std::function<void(Result)>> cb{};
cb.reset(new std::function<void(Result)>(std::move(callback)));
internal_->fetch_user_achievements(internal_, cb.release(), wrapper);
}
void AchievementManager::CountUserAchievements(std::int32_t* count)
{
if (!count) {
return;
}
internal_->count_user_achievements(internal_, reinterpret_cast<int32_t*>(count));
}
Result AchievementManager::GetUserAchievement(Snowflake userAchievementId,
UserAchievement* userAchievement)
{
if (!userAchievement) {
return Result::InternalError;
}
auto result = internal_->get_user_achievement(
internal_, userAchievementId, reinterpret_cast<DiscordUserAchievement*>(userAchievement));
return static_cast<Result>(result);
}
Result AchievementManager::GetUserAchievementAt(std::int32_t index,
UserAchievement* userAchievement)
{
if (!userAchievement) {
return Result::InternalError;
}
auto result = internal_->get_user_achievement_at(
internal_, index, reinterpret_cast<DiscordUserAchievement*>(userAchievement));
return static_cast<Result>(result);
}
} // namespace discord

View File

@@ -1,34 +0,0 @@
#pragma once
#include "types.h"
namespace discord {
class AchievementManager final {
public:
~AchievementManager() = default;
void SetUserAchievement(Snowflake achievementId,
std::uint8_t percentComplete,
std::function<void(Result)> callback);
void FetchUserAchievements(std::function<void(Result)> callback);
void CountUserAchievements(std::int32_t* count);
Result GetUserAchievement(Snowflake userAchievementId, UserAchievement* userAchievement);
Result GetUserAchievementAt(std::int32_t index, UserAchievement* userAchievement);
Event<UserAchievement const&> OnUserAchievementUpdate;
private:
friend class Core;
AchievementManager() = default;
AchievementManager(AchievementManager const& rhs) = delete;
AchievementManager& operator=(AchievementManager const& rhs) = delete;
AchievementManager(AchievementManager&& rhs) = delete;
AchievementManager& operator=(AchievementManager&& rhs) = delete;
IDiscordAchievementManager* internal_;
static IDiscordAchievementEvents events_;
};
} // namespace discord

View File

@@ -1,177 +0,0 @@
#if !defined(_CRT_SECURE_NO_WARNINGS)
#define _CRT_SECURE_NO_WARNINGS
#endif
#include "activity_manager.h"
#include "core.h"
#include <cstring>
#include <memory>
namespace discord {
class ActivityEvents final {
public:
static void DISCORD_CALLBACK OnActivityJoin(void* callbackData, char const* secret)
{
auto* core = reinterpret_cast<Core*>(callbackData);
if (!core) {
return;
}
auto& module = core->ActivityManager();
module.OnActivityJoin(static_cast<const char*>(secret));
}
static void DISCORD_CALLBACK OnActivitySpectate(void* callbackData, char const* secret)
{
auto* core = reinterpret_cast<Core*>(callbackData);
if (!core) {
return;
}
auto& module = core->ActivityManager();
module.OnActivitySpectate(static_cast<const char*>(secret));
}
static void DISCORD_CALLBACK OnActivityJoinRequest(void* callbackData, DiscordUser* user)
{
auto* core = reinterpret_cast<Core*>(callbackData);
if (!core) {
return;
}
auto& module = core->ActivityManager();
module.OnActivityJoinRequest(*reinterpret_cast<User const*>(user));
}
static void DISCORD_CALLBACK OnActivityInvite(void* callbackData,
EDiscordActivityActionType type,
DiscordUser* user,
DiscordActivity* activity)
{
auto* core = reinterpret_cast<Core*>(callbackData);
if (!core) {
return;
}
auto& module = core->ActivityManager();
module.OnActivityInvite(static_cast<ActivityActionType>(type),
*reinterpret_cast<User const*>(user),
*reinterpret_cast<Activity const*>(activity));
}
};
IDiscordActivityEvents ActivityManager::events_{
&ActivityEvents::OnActivityJoin,
&ActivityEvents::OnActivitySpectate,
&ActivityEvents::OnActivityJoinRequest,
&ActivityEvents::OnActivityInvite,
};
Result ActivityManager::RegisterCommand(char const* command)
{
auto result = internal_->register_command(internal_, const_cast<char*>(command));
return static_cast<Result>(result);
}
Result ActivityManager::RegisterSteam(std::uint32_t steamId)
{
auto result = internal_->register_steam(internal_, steamId);
return static_cast<Result>(result);
}
void ActivityManager::UpdateActivity(Activity const& activity, std::function<void(Result)> callback)
{
static auto wrapper = [](void* callbackData, EDiscordResult result) -> void {
std::unique_ptr<std::function<void(Result)>> cb(
reinterpret_cast<std::function<void(Result)>*>(callbackData));
if (!cb || !(*cb)) {
return;
}
(*cb)(static_cast<Result>(result));
};
std::unique_ptr<std::function<void(Result)>> cb{};
cb.reset(new std::function<void(Result)>(std::move(callback)));
internal_->update_activity(internal_,
reinterpret_cast<DiscordActivity*>(const_cast<Activity*>(&activity)),
cb.release(),
wrapper);
}
void ActivityManager::ClearActivity(std::function<void(Result)> callback)
{
static auto wrapper = [](void* callbackData, EDiscordResult result) -> void {
std::unique_ptr<std::function<void(Result)>> cb(
reinterpret_cast<std::function<void(Result)>*>(callbackData));
if (!cb || !(*cb)) {
return;
}
(*cb)(static_cast<Result>(result));
};
std::unique_ptr<std::function<void(Result)>> cb{};
cb.reset(new std::function<void(Result)>(std::move(callback)));
internal_->clear_activity(internal_, cb.release(), wrapper);
}
void ActivityManager::SendRequestReply(UserId userId,
ActivityJoinRequestReply reply,
std::function<void(Result)> callback)
{
static auto wrapper = [](void* callbackData, EDiscordResult result) -> void {
std::unique_ptr<std::function<void(Result)>> cb(
reinterpret_cast<std::function<void(Result)>*>(callbackData));
if (!cb || !(*cb)) {
return;
}
(*cb)(static_cast<Result>(result));
};
std::unique_ptr<std::function<void(Result)>> cb{};
cb.reset(new std::function<void(Result)>(std::move(callback)));
internal_->send_request_reply(internal_,
userId,
static_cast<EDiscordActivityJoinRequestReply>(reply),
cb.release(),
wrapper);
}
void ActivityManager::SendInvite(UserId userId,
ActivityActionType type,
char const* content,
std::function<void(Result)> callback)
{
static auto wrapper = [](void* callbackData, EDiscordResult result) -> void {
std::unique_ptr<std::function<void(Result)>> cb(
reinterpret_cast<std::function<void(Result)>*>(callbackData));
if (!cb || !(*cb)) {
return;
}
(*cb)(static_cast<Result>(result));
};
std::unique_ptr<std::function<void(Result)>> cb{};
cb.reset(new std::function<void(Result)>(std::move(callback)));
internal_->send_invite(internal_,
userId,
static_cast<EDiscordActivityActionType>(type),
const_cast<char*>(content),
cb.release(),
wrapper);
}
void ActivityManager::AcceptInvite(UserId userId, std::function<void(Result)> callback)
{
static auto wrapper = [](void* callbackData, EDiscordResult result) -> void {
std::unique_ptr<std::function<void(Result)>> cb(
reinterpret_cast<std::function<void(Result)>*>(callbackData));
if (!cb || !(*cb)) {
return;
}
(*cb)(static_cast<Result>(result));
};
std::unique_ptr<std::function<void(Result)>> cb{};
cb.reset(new std::function<void(Result)>(std::move(callback)));
internal_->accept_invite(internal_, userId, cb.release(), wrapper);
}
} // namespace discord

View File

@@ -1,42 +0,0 @@
#pragma once
#include "types.h"
namespace discord {
class ActivityManager final {
public:
~ActivityManager() = default;
Result RegisterCommand(char const* command);
Result RegisterSteam(std::uint32_t steamId);
void UpdateActivity(Activity const& activity, std::function<void(Result)> callback);
void ClearActivity(std::function<void(Result)> callback);
void SendRequestReply(UserId userId,
ActivityJoinRequestReply reply,
std::function<void(Result)> callback);
void SendInvite(UserId userId,
ActivityActionType type,
char const* content,
std::function<void(Result)> callback);
void AcceptInvite(UserId userId, std::function<void(Result)> callback);
Event<char const*> OnActivityJoin;
Event<char const*> OnActivitySpectate;
Event<User const&> OnActivityJoinRequest;
Event<ActivityActionType, User const&, Activity const&> OnActivityInvite;
private:
friend class Core;
ActivityManager() = default;
ActivityManager(ActivityManager const& rhs) = delete;
ActivityManager& operator=(ActivityManager const& rhs) = delete;
ActivityManager(ActivityManager&& rhs) = delete;
ActivityManager& operator=(ActivityManager&& rhs) = delete;
IDiscordActivityManager* internal_;
static IDiscordActivityEvents events_;
};
} // namespace discord

View File

@@ -1,78 +0,0 @@
#if !defined(_CRT_SECURE_NO_WARNINGS)
#define _CRT_SECURE_NO_WARNINGS
#endif
#include "application_manager.h"
#include "core.h"
#include <cstring>
#include <memory>
namespace discord {
void ApplicationManager::ValidateOrExit(std::function<void(Result)> callback)
{
static auto wrapper = [](void* callbackData, EDiscordResult result) -> void {
std::unique_ptr<std::function<void(Result)>> cb(
reinterpret_cast<std::function<void(Result)>*>(callbackData));
if (!cb || !(*cb)) {
return;
}
(*cb)(static_cast<Result>(result));
};
std::unique_ptr<std::function<void(Result)>> cb{};
cb.reset(new std::function<void(Result)>(std::move(callback)));
internal_->validate_or_exit(internal_, cb.release(), wrapper);
}
void ApplicationManager::GetCurrentLocale(char locale[128])
{
if (!locale) {
return;
}
internal_->get_current_locale(internal_, reinterpret_cast<DiscordLocale*>(locale));
}
void ApplicationManager::GetCurrentBranch(char branch[4096])
{
if (!branch) {
return;
}
internal_->get_current_branch(internal_, reinterpret_cast<DiscordBranch*>(branch));
}
void ApplicationManager::GetOAuth2Token(std::function<void(Result, OAuth2Token const&)> callback)
{
static auto wrapper =
[](void* callbackData, EDiscordResult result, DiscordOAuth2Token* oauth2Token) -> void {
std::unique_ptr<std::function<void(Result, OAuth2Token const&)>> cb(
reinterpret_cast<std::function<void(Result, OAuth2Token const&)>*>(callbackData));
if (!cb || !(*cb)) {
return;
}
(*cb)(static_cast<Result>(result), *reinterpret_cast<OAuth2Token const*>(oauth2Token));
};
std::unique_ptr<std::function<void(Result, OAuth2Token const&)>> cb{};
cb.reset(new std::function<void(Result, OAuth2Token const&)>(std::move(callback)));
internal_->get_oauth2_token(internal_, cb.release(), wrapper);
}
void ApplicationManager::GetTicket(std::function<void(Result, char const*)> callback)
{
static auto wrapper = [](void* callbackData, EDiscordResult result, char const* data) -> void {
std::unique_ptr<std::function<void(Result, char const*)>> cb(
reinterpret_cast<std::function<void(Result, char const*)>*>(callbackData));
if (!cb || !(*cb)) {
return;
}
(*cb)(static_cast<Result>(result), static_cast<const char*>(data));
};
std::unique_ptr<std::function<void(Result, char const*)>> cb{};
cb.reset(new std::function<void(Result, char const*)>(std::move(callback)));
internal_->get_ticket(internal_, cb.release(), wrapper);
}
} // namespace discord

View File

@@ -1,30 +0,0 @@
#pragma once
#include "types.h"
namespace discord {
class ApplicationManager final {
public:
~ApplicationManager() = default;
void ValidateOrExit(std::function<void(Result)> callback);
void GetCurrentLocale(char locale[128]);
void GetCurrentBranch(char branch[4096]);
void GetOAuth2Token(std::function<void(Result, OAuth2Token const&)> callback);
void GetTicket(std::function<void(Result, char const*)> callback);
private:
friend class Core;
ApplicationManager() = default;
ApplicationManager(ApplicationManager const& rhs) = delete;
ApplicationManager& operator=(ApplicationManager const& rhs) = delete;
ApplicationManager(ApplicationManager&& rhs) = delete;
ApplicationManager& operator=(ApplicationManager&& rhs) = delete;
IDiscordApplicationManager* internal_;
static IDiscordApplicationEvents events_;
};
} // namespace discord

View File

@@ -1,182 +0,0 @@
#if !defined(_CRT_SECURE_NO_WARNINGS)
#define _CRT_SECURE_NO_WARNINGS
#endif
#include "core.h"
#include <cstring>
#include <memory>
namespace discord {
Result Core::Create(ClientId clientId, std::uint64_t flags, Core** instance)
{
if (!instance) {
return Result::InternalError;
}
(*instance) = new Core();
DiscordCreateParams params{};
DiscordCreateParamsSetDefault(&params);
params.client_id = clientId;
params.flags = flags;
params.events = nullptr;
params.event_data = *instance;
params.user_events = &UserManager::events_;
params.activity_events = &ActivityManager::events_;
params.relationship_events = &RelationshipManager::events_;
params.lobby_events = &LobbyManager::events_;
params.network_events = &NetworkManager::events_;
params.overlay_events = &OverlayManager::events_;
params.store_events = &StoreManager::events_;
params.voice_events = &VoiceManager::events_;
params.achievement_events = &AchievementManager::events_;
auto result = DiscordCreate(DISCORD_VERSION, &params, &((*instance)->internal_));
if (result != DiscordResult_Ok || !(*instance)->internal_) {
delete (*instance);
(*instance) = nullptr;
}
return static_cast<Result>(result);
}
Core::~Core()
{
if (internal_) {
internal_->destroy(internal_);
internal_ = nullptr;
}
}
Result Core::RunCallbacks()
{
auto result = internal_->run_callbacks(internal_);
return static_cast<Result>(result);
}
void Core::SetLogHook(LogLevel minLevel, std::function<void(LogLevel, char const*)> hook)
{
setLogHook_.DisconnectAll();
setLogHook_.Connect(std::move(hook));
static auto wrapper =
[](void* callbackData, EDiscordLogLevel level, char const* message) -> void {
auto cb(reinterpret_cast<decltype(setLogHook_)*>(callbackData));
if (!cb) {
return;
}
(*cb)(static_cast<LogLevel>(level), static_cast<const char*>(message));
};
internal_->set_log_hook(
internal_, static_cast<EDiscordLogLevel>(minLevel), &setLogHook_, wrapper);
}
discord::ApplicationManager& Core::ApplicationManager()
{
if (!applicationManager_.internal_) {
applicationManager_.internal_ = internal_->get_application_manager(internal_);
}
return applicationManager_;
}
discord::UserManager& Core::UserManager()
{
if (!userManager_.internal_) {
userManager_.internal_ = internal_->get_user_manager(internal_);
}
return userManager_;
}
discord::ImageManager& Core::ImageManager()
{
if (!imageManager_.internal_) {
imageManager_.internal_ = internal_->get_image_manager(internal_);
}
return imageManager_;
}
discord::ActivityManager& Core::ActivityManager()
{
if (!activityManager_.internal_) {
activityManager_.internal_ = internal_->get_activity_manager(internal_);
}
return activityManager_;
}
discord::RelationshipManager& Core::RelationshipManager()
{
if (!relationshipManager_.internal_) {
relationshipManager_.internal_ = internal_->get_relationship_manager(internal_);
}
return relationshipManager_;
}
discord::LobbyManager& Core::LobbyManager()
{
if (!lobbyManager_.internal_) {
lobbyManager_.internal_ = internal_->get_lobby_manager(internal_);
}
return lobbyManager_;
}
discord::NetworkManager& Core::NetworkManager()
{
if (!networkManager_.internal_) {
networkManager_.internal_ = internal_->get_network_manager(internal_);
}
return networkManager_;
}
discord::OverlayManager& Core::OverlayManager()
{
if (!overlayManager_.internal_) {
overlayManager_.internal_ = internal_->get_overlay_manager(internal_);
}
return overlayManager_;
}
discord::StorageManager& Core::StorageManager()
{
if (!storageManager_.internal_) {
storageManager_.internal_ = internal_->get_storage_manager(internal_);
}
return storageManager_;
}
discord::StoreManager& Core::StoreManager()
{
if (!storeManager_.internal_) {
storeManager_.internal_ = internal_->get_store_manager(internal_);
}
return storeManager_;
}
discord::VoiceManager& Core::VoiceManager()
{
if (!voiceManager_.internal_) {
voiceManager_.internal_ = internal_->get_voice_manager(internal_);
}
return voiceManager_;
}
discord::AchievementManager& Core::AchievementManager()
{
if (!achievementManager_.internal_) {
achievementManager_.internal_ = internal_->get_achievement_manager(internal_);
}
return achievementManager_;
}
} // namespace discord

View File

@@ -1,64 +0,0 @@
#pragma once
#include "types.h"
#include "application_manager.h"
#include "user_manager.h"
#include "image_manager.h"
#include "activity_manager.h"
#include "relationship_manager.h"
#include "lobby_manager.h"
#include "network_manager.h"
#include "overlay_manager.h"
#include "storage_manager.h"
#include "store_manager.h"
#include "voice_manager.h"
#include "achievement_manager.h"
namespace discord {
class Core final {
public:
static Result Create(ClientId clientId, std::uint64_t flags, Core** instance);
~Core();
Result RunCallbacks();
void SetLogHook(LogLevel minLevel, std::function<void(LogLevel, char const*)> hook);
discord::ApplicationManager& ApplicationManager();
discord::UserManager& UserManager();
discord::ImageManager& ImageManager();
discord::ActivityManager& ActivityManager();
discord::RelationshipManager& RelationshipManager();
discord::LobbyManager& LobbyManager();
discord::NetworkManager& NetworkManager();
discord::OverlayManager& OverlayManager();
discord::StorageManager& StorageManager();
discord::StoreManager& StoreManager();
discord::VoiceManager& VoiceManager();
discord::AchievementManager& AchievementManager();
private:
Core() = default;
Core(Core const& rhs) = delete;
Core& operator=(Core const& rhs) = delete;
Core(Core&& rhs) = delete;
Core& operator=(Core&& rhs) = delete;
IDiscordCore* internal_;
Event<LogLevel, char const*> setLogHook_;
discord::ApplicationManager applicationManager_;
discord::UserManager userManager_;
discord::ImageManager imageManager_;
discord::ActivityManager activityManager_;
discord::RelationshipManager relationshipManager_;
discord::LobbyManager lobbyManager_;
discord::NetworkManager networkManager_;
discord::OverlayManager overlayManager_;
discord::StorageManager storageManager_;
discord::StoreManager storeManager_;
discord::VoiceManager voiceManager_;
discord::AchievementManager achievementManager_;
};
} // namespace discord

View File

@@ -1,16 +0,0 @@
#pragma once
#include "types.h"
#include "core.h"
#include "application_manager.h"
#include "user_manager.h"
#include "image_manager.h"
#include "activity_manager.h"
#include "relationship_manager.h"
#include "lobby_manager.h"
#include "network_manager.h"
#include "overlay_manager.h"
#include "storage_manager.h"
#include "store_manager.h"
#include "voice_manager.h"
#include "achievement_manager.h"

View File

@@ -1,59 +0,0 @@
#pragma once
#include <functional>
#include <vector>
namespace discord {
template <typename... Args>
class Event final {
public:
using Token = int;
Event() { slots_.reserve(4); }
Event(Event const&) = default;
Event(Event&&) = default;
~Event() = default;
Event& operator=(Event const&) = default;
Event& operator=(Event&&) = default;
template <typename EventHandler>
Token Connect(EventHandler slot)
{
slots_.emplace_back(Slot{nextToken_, std::move(slot)});
return nextToken_++;
}
void Disconnect(Token token)
{
for (auto& slot : slots_) {
if (slot.token == token) {
slot = slots_.back();
slots_.pop_back();
break;
}
}
}
void DisconnectAll() { slots_ = {}; }
void operator()(Args... args)
{
for (auto const& slot : slots_) {
slot.fn(std::forward<Args>(args)...);
}
}
private:
struct Slot {
Token token;
std::function<void(Args...)> fn;
};
Token nextToken_{};
std::vector<Slot> slots_{};
};
} // namespace discord

File diff suppressed because it is too large Load Diff

View File

@@ -1,57 +0,0 @@
#if !defined(_CRT_SECURE_NO_WARNINGS)
#define _CRT_SECURE_NO_WARNINGS
#endif
#include "image_manager.h"
#include "core.h"
#include <cstring>
#include <memory>
namespace discord {
void ImageManager::Fetch(ImageHandle handle,
bool refresh,
std::function<void(Result, ImageHandle)> callback)
{
static auto wrapper =
[](void* callbackData, EDiscordResult result, DiscordImageHandle handleResult) -> void {
std::unique_ptr<std::function<void(Result, ImageHandle)>> cb(
reinterpret_cast<std::function<void(Result, ImageHandle)>*>(callbackData));
if (!cb || !(*cb)) {
return;
}
(*cb)(static_cast<Result>(result), *reinterpret_cast<ImageHandle const*>(&handleResult));
};
std::unique_ptr<std::function<void(Result, ImageHandle)>> cb{};
cb.reset(new std::function<void(Result, ImageHandle)>(std::move(callback)));
internal_->fetch(internal_,
*reinterpret_cast<DiscordImageHandle const*>(&handle),
(refresh ? 1 : 0),
cb.release(),
wrapper);
}
Result ImageManager::GetDimensions(ImageHandle handle, ImageDimensions* dimensions)
{
if (!dimensions) {
return Result::InternalError;
}
auto result = internal_->get_dimensions(internal_,
*reinterpret_cast<DiscordImageHandle const*>(&handle),
reinterpret_cast<DiscordImageDimensions*>(dimensions));
return static_cast<Result>(result);
}
Result ImageManager::GetData(ImageHandle handle, std::uint8_t* data, std::uint32_t dataLength)
{
auto result = internal_->get_data(internal_,
*reinterpret_cast<DiscordImageHandle const*>(&handle),
reinterpret_cast<uint8_t*>(data),
dataLength);
return static_cast<Result>(result);
}
} // namespace discord

View File

@@ -1,28 +0,0 @@
#pragma once
#include "types.h"
namespace discord {
class ImageManager final {
public:
~ImageManager() = default;
void Fetch(ImageHandle handle, bool refresh, std::function<void(Result, ImageHandle)> callback);
Result GetDimensions(ImageHandle handle, ImageDimensions* dimensions);
Result GetData(ImageHandle handle, std::uint8_t* data, std::uint32_t dataLength);
private:
friend class Core;
ImageManager() = default;
ImageManager(ImageManager const& rhs) = delete;
ImageManager& operator=(ImageManager const& rhs) = delete;
ImageManager(ImageManager&& rhs) = delete;
ImageManager& operator=(ImageManager&& rhs) = delete;
IDiscordImageManager* internal_;
static IDiscordImageEvents events_;
};
} // namespace discord

View File

@@ -1,554 +0,0 @@
#if !defined(_CRT_SECURE_NO_WARNINGS)
#define _CRT_SECURE_NO_WARNINGS
#endif
#include "lobby_manager.h"
#include "core.h"
#include <cstring>
#include <memory>
namespace discord {
class LobbyEvents final {
public:
static void DISCORD_CALLBACK OnLobbyUpdate(void* callbackData, int64_t lobbyId)
{
auto* core = reinterpret_cast<Core*>(callbackData);
if (!core) {
return;
}
auto& module = core->LobbyManager();
module.OnLobbyUpdate(lobbyId);
}
static void DISCORD_CALLBACK OnLobbyDelete(void* callbackData, int64_t lobbyId, uint32_t reason)
{
auto* core = reinterpret_cast<Core*>(callbackData);
if (!core) {
return;
}
auto& module = core->LobbyManager();
module.OnLobbyDelete(lobbyId, reason);
}
static void DISCORD_CALLBACK OnMemberConnect(void* callbackData,
int64_t lobbyId,
int64_t userId)
{
auto* core = reinterpret_cast<Core*>(callbackData);
if (!core) {
return;
}
auto& module = core->LobbyManager();
module.OnMemberConnect(lobbyId, userId);
}
static void DISCORD_CALLBACK OnMemberUpdate(void* callbackData, int64_t lobbyId, int64_t userId)
{
auto* core = reinterpret_cast<Core*>(callbackData);
if (!core) {
return;
}
auto& module = core->LobbyManager();
module.OnMemberUpdate(lobbyId, userId);
}
static void DISCORD_CALLBACK OnMemberDisconnect(void* callbackData,
int64_t lobbyId,
int64_t userId)
{
auto* core = reinterpret_cast<Core*>(callbackData);
if (!core) {
return;
}
auto& module = core->LobbyManager();
module.OnMemberDisconnect(lobbyId, userId);
}
static void DISCORD_CALLBACK OnLobbyMessage(void* callbackData,
int64_t lobbyId,
int64_t userId,
uint8_t* data,
uint32_t dataLength)
{
auto* core = reinterpret_cast<Core*>(callbackData);
if (!core) {
return;
}
auto& module = core->LobbyManager();
module.OnLobbyMessage(lobbyId, userId, data, dataLength);
}
static void DISCORD_CALLBACK OnSpeaking(void* callbackData,
int64_t lobbyId,
int64_t userId,
bool speaking)
{
auto* core = reinterpret_cast<Core*>(callbackData);
if (!core) {
return;
}
auto& module = core->LobbyManager();
module.OnSpeaking(lobbyId, userId, (speaking != 0));
}
static void DISCORD_CALLBACK OnNetworkMessage(void* callbackData,
int64_t lobbyId,
int64_t userId,
uint8_t channelId,
uint8_t* data,
uint32_t dataLength)
{
auto* core = reinterpret_cast<Core*>(callbackData);
if (!core) {
return;
}
auto& module = core->LobbyManager();
module.OnNetworkMessage(lobbyId, userId, channelId, data, dataLength);
}
};
IDiscordLobbyEvents LobbyManager::events_{
&LobbyEvents::OnLobbyUpdate,
&LobbyEvents::OnLobbyDelete,
&LobbyEvents::OnMemberConnect,
&LobbyEvents::OnMemberUpdate,
&LobbyEvents::OnMemberDisconnect,
&LobbyEvents::OnLobbyMessage,
&LobbyEvents::OnSpeaking,
&LobbyEvents::OnNetworkMessage,
};
Result LobbyManager::GetLobbyCreateTransaction(LobbyTransaction* transaction)
{
if (!transaction) {
return Result::InternalError;
}
auto result = internal_->get_lobby_create_transaction(internal_, transaction->Receive());
return static_cast<Result>(result);
}
Result LobbyManager::GetLobbyUpdateTransaction(LobbyId lobbyId, LobbyTransaction* transaction)
{
if (!transaction) {
return Result::InternalError;
}
auto result =
internal_->get_lobby_update_transaction(internal_, lobbyId, transaction->Receive());
return static_cast<Result>(result);
}
Result LobbyManager::GetMemberUpdateTransaction(LobbyId lobbyId,
UserId userId,
LobbyMemberTransaction* transaction)
{
if (!transaction) {
return Result::InternalError;
}
auto result =
internal_->get_member_update_transaction(internal_, lobbyId, userId, transaction->Receive());
return static_cast<Result>(result);
}
void LobbyManager::CreateLobby(LobbyTransaction const& transaction,
std::function<void(Result, Lobby const&)> callback)
{
static auto wrapper =
[](void* callbackData, EDiscordResult result, DiscordLobby* lobby) -> void {
std::unique_ptr<std::function<void(Result, Lobby const&)>> cb(
reinterpret_cast<std::function<void(Result, Lobby const&)>*>(callbackData));
if (!cb || !(*cb)) {
return;
}
(*cb)(static_cast<Result>(result), *reinterpret_cast<Lobby const*>(lobby));
};
std::unique_ptr<std::function<void(Result, Lobby const&)>> cb{};
cb.reset(new std::function<void(Result, Lobby const&)>(std::move(callback)));
internal_->create_lobby(
internal_, const_cast<LobbyTransaction&>(transaction).Internal(), cb.release(), wrapper);
}
void LobbyManager::UpdateLobby(LobbyId lobbyId,
LobbyTransaction const& transaction,
std::function<void(Result)> callback)
{
static auto wrapper = [](void* callbackData, EDiscordResult result) -> void {
std::unique_ptr<std::function<void(Result)>> cb(
reinterpret_cast<std::function<void(Result)>*>(callbackData));
if (!cb || !(*cb)) {
return;
}
(*cb)(static_cast<Result>(result));
};
std::unique_ptr<std::function<void(Result)>> cb{};
cb.reset(new std::function<void(Result)>(std::move(callback)));
internal_->update_lobby(internal_,
lobbyId,
const_cast<LobbyTransaction&>(transaction).Internal(),
cb.release(),
wrapper);
}
void LobbyManager::DeleteLobby(LobbyId lobbyId, std::function<void(Result)> callback)
{
static auto wrapper = [](void* callbackData, EDiscordResult result) -> void {
std::unique_ptr<std::function<void(Result)>> cb(
reinterpret_cast<std::function<void(Result)>*>(callbackData));
if (!cb || !(*cb)) {
return;
}
(*cb)(static_cast<Result>(result));
};
std::unique_ptr<std::function<void(Result)>> cb{};
cb.reset(new std::function<void(Result)>(std::move(callback)));
internal_->delete_lobby(internal_, lobbyId, cb.release(), wrapper);
}
void LobbyManager::ConnectLobby(LobbyId lobbyId,
LobbySecret secret,
std::function<void(Result, Lobby const&)> callback)
{
static auto wrapper =
[](void* callbackData, EDiscordResult result, DiscordLobby* lobby) -> void {
std::unique_ptr<std::function<void(Result, Lobby const&)>> cb(
reinterpret_cast<std::function<void(Result, Lobby const&)>*>(callbackData));
if (!cb || !(*cb)) {
return;
}
(*cb)(static_cast<Result>(result), *reinterpret_cast<Lobby const*>(lobby));
};
std::unique_ptr<std::function<void(Result, Lobby const&)>> cb{};
cb.reset(new std::function<void(Result, Lobby const&)>(std::move(callback)));
internal_->connect_lobby(internal_, lobbyId, const_cast<char*>(secret), cb.release(), wrapper);
}
void LobbyManager::ConnectLobbyWithActivitySecret(
LobbySecret activitySecret,
std::function<void(Result, Lobby const&)> callback)
{
static auto wrapper =
[](void* callbackData, EDiscordResult result, DiscordLobby* lobby) -> void {
std::unique_ptr<std::function<void(Result, Lobby const&)>> cb(
reinterpret_cast<std::function<void(Result, Lobby const&)>*>(callbackData));
if (!cb || !(*cb)) {
return;
}
(*cb)(static_cast<Result>(result), *reinterpret_cast<Lobby const*>(lobby));
};
std::unique_ptr<std::function<void(Result, Lobby const&)>> cb{};
cb.reset(new std::function<void(Result, Lobby const&)>(std::move(callback)));
internal_->connect_lobby_with_activity_secret(
internal_, const_cast<char*>(activitySecret), cb.release(), wrapper);
}
void LobbyManager::DisconnectLobby(LobbyId lobbyId, std::function<void(Result)> callback)
{
static auto wrapper = [](void* callbackData, EDiscordResult result) -> void {
std::unique_ptr<std::function<void(Result)>> cb(
reinterpret_cast<std::function<void(Result)>*>(callbackData));
if (!cb || !(*cb)) {
return;
}
(*cb)(static_cast<Result>(result));
};
std::unique_ptr<std::function<void(Result)>> cb{};
cb.reset(new std::function<void(Result)>(std::move(callback)));
internal_->disconnect_lobby(internal_, lobbyId, cb.release(), wrapper);
}
Result LobbyManager::GetLobby(LobbyId lobbyId, Lobby* lobby)
{
if (!lobby) {
return Result::InternalError;
}
auto result = internal_->get_lobby(internal_, lobbyId, reinterpret_cast<DiscordLobby*>(lobby));
return static_cast<Result>(result);
}
Result LobbyManager::GetLobbyActivitySecret(LobbyId lobbyId, char secret[128])
{
if (!secret) {
return Result::InternalError;
}
auto result = internal_->get_lobby_activity_secret(
internal_, lobbyId, reinterpret_cast<DiscordLobbySecret*>(secret));
return static_cast<Result>(result);
}
Result LobbyManager::GetLobbyMetadataValue(LobbyId lobbyId, MetadataKey key, char value[4096])
{
if (!value) {
return Result::InternalError;
}
auto result = internal_->get_lobby_metadata_value(
internal_, lobbyId, const_cast<char*>(key), reinterpret_cast<DiscordMetadataValue*>(value));
return static_cast<Result>(result);
}
Result LobbyManager::GetLobbyMetadataKey(LobbyId lobbyId, std::int32_t index, char key[256])
{
if (!key) {
return Result::InternalError;
}
auto result = internal_->get_lobby_metadata_key(
internal_, lobbyId, index, reinterpret_cast<DiscordMetadataKey*>(key));
return static_cast<Result>(result);
}
Result LobbyManager::LobbyMetadataCount(LobbyId lobbyId, std::int32_t* count)
{
if (!count) {
return Result::InternalError;
}
auto result =
internal_->lobby_metadata_count(internal_, lobbyId, reinterpret_cast<int32_t*>(count));
return static_cast<Result>(result);
}
Result LobbyManager::MemberCount(LobbyId lobbyId, std::int32_t* count)
{
if (!count) {
return Result::InternalError;
}
auto result = internal_->member_count(internal_, lobbyId, reinterpret_cast<int32_t*>(count));
return static_cast<Result>(result);
}
Result LobbyManager::GetMemberUserId(LobbyId lobbyId, std::int32_t index, UserId* userId)
{
if (!userId) {
return Result::InternalError;
}
auto result =
internal_->get_member_user_id(internal_, lobbyId, index, reinterpret_cast<int64_t*>(userId));
return static_cast<Result>(result);
}
Result LobbyManager::GetMemberUser(LobbyId lobbyId, UserId userId, User* user)
{
if (!user) {
return Result::InternalError;
}
auto result =
internal_->get_member_user(internal_, lobbyId, userId, reinterpret_cast<DiscordUser*>(user));
return static_cast<Result>(result);
}
Result LobbyManager::GetMemberMetadataValue(LobbyId lobbyId,
UserId userId,
MetadataKey key,
char value[4096])
{
if (!value) {
return Result::InternalError;
}
auto result =
internal_->get_member_metadata_value(internal_,
lobbyId,
userId,
const_cast<char*>(key),
reinterpret_cast<DiscordMetadataValue*>(value));
return static_cast<Result>(result);
}
Result LobbyManager::GetMemberMetadataKey(LobbyId lobbyId,
UserId userId,
std::int32_t index,
char key[256])
{
if (!key) {
return Result::InternalError;
}
auto result = internal_->get_member_metadata_key(
internal_, lobbyId, userId, index, reinterpret_cast<DiscordMetadataKey*>(key));
return static_cast<Result>(result);
}
Result LobbyManager::MemberMetadataCount(LobbyId lobbyId, UserId userId, std::int32_t* count)
{
if (!count) {
return Result::InternalError;
}
auto result = internal_->member_metadata_count(
internal_, lobbyId, userId, reinterpret_cast<int32_t*>(count));
return static_cast<Result>(result);
}
void LobbyManager::UpdateMember(LobbyId lobbyId,
UserId userId,
LobbyMemberTransaction const& transaction,
std::function<void(Result)> callback)
{
static auto wrapper = [](void* callbackData, EDiscordResult result) -> void {
std::unique_ptr<std::function<void(Result)>> cb(
reinterpret_cast<std::function<void(Result)>*>(callbackData));
if (!cb || !(*cb)) {
return;
}
(*cb)(static_cast<Result>(result));
};
std::unique_ptr<std::function<void(Result)>> cb{};
cb.reset(new std::function<void(Result)>(std::move(callback)));
internal_->update_member(internal_,
lobbyId,
userId,
const_cast<LobbyMemberTransaction&>(transaction).Internal(),
cb.release(),
wrapper);
}
void LobbyManager::SendLobbyMessage(LobbyId lobbyId,
std::uint8_t* data,
std::uint32_t dataLength,
std::function<void(Result)> callback)
{
static auto wrapper = [](void* callbackData, EDiscordResult result) -> void {
std::unique_ptr<std::function<void(Result)>> cb(
reinterpret_cast<std::function<void(Result)>*>(callbackData));
if (!cb || !(*cb)) {
return;
}
(*cb)(static_cast<Result>(result));
};
std::unique_ptr<std::function<void(Result)>> cb{};
cb.reset(new std::function<void(Result)>(std::move(callback)));
internal_->send_lobby_message(
internal_, lobbyId, reinterpret_cast<uint8_t*>(data), dataLength, cb.release(), wrapper);
}
Result LobbyManager::GetSearchQuery(LobbySearchQuery* query)
{
if (!query) {
return Result::InternalError;
}
auto result = internal_->get_search_query(internal_, query->Receive());
return static_cast<Result>(result);
}
void LobbyManager::Search(LobbySearchQuery const& query, std::function<void(Result)> callback)
{
static auto wrapper = [](void* callbackData, EDiscordResult result) -> void {
std::unique_ptr<std::function<void(Result)>> cb(
reinterpret_cast<std::function<void(Result)>*>(callbackData));
if (!cb || !(*cb)) {
return;
}
(*cb)(static_cast<Result>(result));
};
std::unique_ptr<std::function<void(Result)>> cb{};
cb.reset(new std::function<void(Result)>(std::move(callback)));
internal_->search(
internal_, const_cast<LobbySearchQuery&>(query).Internal(), cb.release(), wrapper);
}
void LobbyManager::LobbyCount(std::int32_t* count)
{
if (!count) {
return;
}
internal_->lobby_count(internal_, reinterpret_cast<int32_t*>(count));
}
Result LobbyManager::GetLobbyId(std::int32_t index, LobbyId* lobbyId)
{
if (!lobbyId) {
return Result::InternalError;
}
auto result = internal_->get_lobby_id(internal_, index, reinterpret_cast<int64_t*>(lobbyId));
return static_cast<Result>(result);
}
void LobbyManager::ConnectVoice(LobbyId lobbyId, std::function<void(Result)> callback)
{
static auto wrapper = [](void* callbackData, EDiscordResult result) -> void {
std::unique_ptr<std::function<void(Result)>> cb(
reinterpret_cast<std::function<void(Result)>*>(callbackData));
if (!cb || !(*cb)) {
return;
}
(*cb)(static_cast<Result>(result));
};
std::unique_ptr<std::function<void(Result)>> cb{};
cb.reset(new std::function<void(Result)>(std::move(callback)));
internal_->connect_voice(internal_, lobbyId, cb.release(), wrapper);
}
void LobbyManager::DisconnectVoice(LobbyId lobbyId, std::function<void(Result)> callback)
{
static auto wrapper = [](void* callbackData, EDiscordResult result) -> void {
std::unique_ptr<std::function<void(Result)>> cb(
reinterpret_cast<std::function<void(Result)>*>(callbackData));
if (!cb || !(*cb)) {
return;
}
(*cb)(static_cast<Result>(result));
};
std::unique_ptr<std::function<void(Result)>> cb{};
cb.reset(new std::function<void(Result)>(std::move(callback)));
internal_->disconnect_voice(internal_, lobbyId, cb.release(), wrapper);
}
Result LobbyManager::ConnectNetwork(LobbyId lobbyId)
{
auto result = internal_->connect_network(internal_, lobbyId);
return static_cast<Result>(result);
}
Result LobbyManager::DisconnectNetwork(LobbyId lobbyId)
{
auto result = internal_->disconnect_network(internal_, lobbyId);
return static_cast<Result>(result);
}
Result LobbyManager::FlushNetwork()
{
auto result = internal_->flush_network(internal_);
return static_cast<Result>(result);
}
Result LobbyManager::OpenNetworkChannel(LobbyId lobbyId, std::uint8_t channelId, bool reliable)
{
auto result =
internal_->open_network_channel(internal_, lobbyId, channelId, (reliable ? 1 : 0));
return static_cast<Result>(result);
}
Result LobbyManager::SendNetworkMessage(LobbyId lobbyId,
UserId userId,
std::uint8_t channelId,
std::uint8_t* data,
std::uint32_t dataLength)
{
auto result = internal_->send_network_message(
internal_, lobbyId, userId, channelId, reinterpret_cast<uint8_t*>(data), dataLength);
return static_cast<Result>(result);
}
} // namespace discord

View File

@@ -1,88 +0,0 @@
#pragma once
#include "types.h"
namespace discord {
class LobbyManager final {
public:
~LobbyManager() = default;
Result GetLobbyCreateTransaction(LobbyTransaction* transaction);
Result GetLobbyUpdateTransaction(LobbyId lobbyId, LobbyTransaction* transaction);
Result GetMemberUpdateTransaction(LobbyId lobbyId,
UserId userId,
LobbyMemberTransaction* transaction);
void CreateLobby(LobbyTransaction const& transaction,
std::function<void(Result, Lobby const&)> callback);
void UpdateLobby(LobbyId lobbyId,
LobbyTransaction const& transaction,
std::function<void(Result)> callback);
void DeleteLobby(LobbyId lobbyId, std::function<void(Result)> callback);
void ConnectLobby(LobbyId lobbyId,
LobbySecret secret,
std::function<void(Result, Lobby const&)> callback);
void ConnectLobbyWithActivitySecret(LobbySecret activitySecret,
std::function<void(Result, Lobby const&)> callback);
void DisconnectLobby(LobbyId lobbyId, std::function<void(Result)> callback);
Result GetLobby(LobbyId lobbyId, Lobby* lobby);
Result GetLobbyActivitySecret(LobbyId lobbyId, char secret[128]);
Result GetLobbyMetadataValue(LobbyId lobbyId, MetadataKey key, char value[4096]);
Result GetLobbyMetadataKey(LobbyId lobbyId, std::int32_t index, char key[256]);
Result LobbyMetadataCount(LobbyId lobbyId, std::int32_t* count);
Result MemberCount(LobbyId lobbyId, std::int32_t* count);
Result GetMemberUserId(LobbyId lobbyId, std::int32_t index, UserId* userId);
Result GetMemberUser(LobbyId lobbyId, UserId userId, User* user);
Result GetMemberMetadataValue(LobbyId lobbyId,
UserId userId,
MetadataKey key,
char value[4096]);
Result GetMemberMetadataKey(LobbyId lobbyId, UserId userId, std::int32_t index, char key[256]);
Result MemberMetadataCount(LobbyId lobbyId, UserId userId, std::int32_t* count);
void UpdateMember(LobbyId lobbyId,
UserId userId,
LobbyMemberTransaction const& transaction,
std::function<void(Result)> callback);
void SendLobbyMessage(LobbyId lobbyId,
std::uint8_t* data,
std::uint32_t dataLength,
std::function<void(Result)> callback);
Result GetSearchQuery(LobbySearchQuery* query);
void Search(LobbySearchQuery const& query, std::function<void(Result)> callback);
void LobbyCount(std::int32_t* count);
Result GetLobbyId(std::int32_t index, LobbyId* lobbyId);
void ConnectVoice(LobbyId lobbyId, std::function<void(Result)> callback);
void DisconnectVoice(LobbyId lobbyId, std::function<void(Result)> callback);
Result ConnectNetwork(LobbyId lobbyId);
Result DisconnectNetwork(LobbyId lobbyId);
Result FlushNetwork();
Result OpenNetworkChannel(LobbyId lobbyId, std::uint8_t channelId, bool reliable);
Result SendNetworkMessage(LobbyId lobbyId,
UserId userId,
std::uint8_t channelId,
std::uint8_t* data,
std::uint32_t dataLength);
Event<std::int64_t> OnLobbyUpdate;
Event<std::int64_t, std::uint32_t> OnLobbyDelete;
Event<std::int64_t, std::int64_t> OnMemberConnect;
Event<std::int64_t, std::int64_t> OnMemberUpdate;
Event<std::int64_t, std::int64_t> OnMemberDisconnect;
Event<std::int64_t, std::int64_t, std::uint8_t*, std::uint32_t> OnLobbyMessage;
Event<std::int64_t, std::int64_t, bool> OnSpeaking;
Event<std::int64_t, std::int64_t, std::uint8_t, std::uint8_t*, std::uint32_t> OnNetworkMessage;
private:
friend class Core;
LobbyManager() = default;
LobbyManager(LobbyManager const& rhs) = delete;
LobbyManager& operator=(LobbyManager const& rhs) = delete;
LobbyManager(LobbyManager&& rhs) = delete;
LobbyManager& operator=(LobbyManager&& rhs) = delete;
IDiscordLobbyManager* internal_;
static IDiscordLobbyEvents events_;
};
} // namespace discord

View File

@@ -1,103 +0,0 @@
#if !defined(_CRT_SECURE_NO_WARNINGS)
#define _CRT_SECURE_NO_WARNINGS
#endif
#include "network_manager.h"
#include "core.h"
#include <cstring>
#include <memory>
namespace discord {
class NetworkEvents final {
public:
static void DISCORD_CALLBACK OnMessage(void* callbackData,
DiscordNetworkPeerId peerId,
DiscordNetworkChannelId channelId,
uint8_t* data,
uint32_t dataLength)
{
auto* core = reinterpret_cast<Core*>(callbackData);
if (!core) {
return;
}
auto& module = core->NetworkManager();
module.OnMessage(peerId, channelId, data, dataLength);
}
static void DISCORD_CALLBACK OnRouteUpdate(void* callbackData, char const* routeData)
{
auto* core = reinterpret_cast<Core*>(callbackData);
if (!core) {
return;
}
auto& module = core->NetworkManager();
module.OnRouteUpdate(static_cast<const char*>(routeData));
}
};
IDiscordNetworkEvents NetworkManager::events_{
&NetworkEvents::OnMessage,
&NetworkEvents::OnRouteUpdate,
};
void NetworkManager::GetPeerId(NetworkPeerId* peerId)
{
if (!peerId) {
return;
}
internal_->get_peer_id(internal_, reinterpret_cast<uint64_t*>(peerId));
}
Result NetworkManager::Flush()
{
auto result = internal_->flush(internal_);
return static_cast<Result>(result);
}
Result NetworkManager::OpenPeer(NetworkPeerId peerId, char const* routeData)
{
auto result = internal_->open_peer(internal_, peerId, const_cast<char*>(routeData));
return static_cast<Result>(result);
}
Result NetworkManager::UpdatePeer(NetworkPeerId peerId, char const* routeData)
{
auto result = internal_->update_peer(internal_, peerId, const_cast<char*>(routeData));
return static_cast<Result>(result);
}
Result NetworkManager::ClosePeer(NetworkPeerId peerId)
{
auto result = internal_->close_peer(internal_, peerId);
return static_cast<Result>(result);
}
Result NetworkManager::OpenChannel(NetworkPeerId peerId, NetworkChannelId channelId, bool reliable)
{
auto result = internal_->open_channel(internal_, peerId, channelId, (reliable ? 1 : 0));
return static_cast<Result>(result);
}
Result NetworkManager::CloseChannel(NetworkPeerId peerId, NetworkChannelId channelId)
{
auto result = internal_->close_channel(internal_, peerId, channelId);
return static_cast<Result>(result);
}
Result NetworkManager::SendMessage(NetworkPeerId peerId,
NetworkChannelId channelId,
std::uint8_t* data,
std::uint32_t dataLength)
{
auto result = internal_->send_message(
internal_, peerId, channelId, reinterpret_cast<uint8_t*>(data), dataLength);
return static_cast<Result>(result);
}
} // namespace discord

View File

@@ -1,63 +0,0 @@
#pragma once
#include "types.h"
namespace discord {
class NetworkManager final {
public:
~NetworkManager() = default;
/**
* Get the local peer ID for this process.
*/
void GetPeerId(NetworkPeerId* peerId);
/**
* Send pending network messages.
*/
Result Flush();
/**
* Open a connection to a remote peer.
*/
Result OpenPeer(NetworkPeerId peerId, char const* routeData);
/**
* Update the route data for a connected peer.
*/
Result UpdatePeer(NetworkPeerId peerId, char const* routeData);
/**
* Close the connection to a remote peer.
*/
Result ClosePeer(NetworkPeerId peerId);
/**
* Open a message channel to a connected peer.
*/
Result OpenChannel(NetworkPeerId peerId, NetworkChannelId channelId, bool reliable);
/**
* Close a message channel to a connected peer.
*/
Result CloseChannel(NetworkPeerId peerId, NetworkChannelId channelId);
/**
* Send a message to a connected peer over an opened message channel.
*/
Result SendMessage(NetworkPeerId peerId,
NetworkChannelId channelId,
std::uint8_t* data,
std::uint32_t dataLength);
Event<NetworkPeerId, NetworkChannelId, std::uint8_t*, std::uint32_t> OnMessage;
Event<char const*> OnRouteUpdate;
private:
friend class Core;
NetworkManager() = default;
NetworkManager(NetworkManager const& rhs) = delete;
NetworkManager& operator=(NetworkManager const& rhs) = delete;
NetworkManager(NetworkManager&& rhs) = delete;
NetworkManager& operator=(NetworkManager&& rhs) = delete;
IDiscordNetworkManager* internal_;
static IDiscordNetworkEvents events_;
};
} // namespace discord

View File

@@ -1,229 +0,0 @@
#if !defined(_CRT_SECURE_NO_WARNINGS)
#define _CRT_SECURE_NO_WARNINGS
#endif
#include "overlay_manager.h"
#include "core.h"
#include <cstring>
#include <memory>
namespace discord {
class OverlayEvents final {
public:
static void DISCORD_CALLBACK OnToggle(void* callbackData, bool locked)
{
auto* core = reinterpret_cast<Core*>(callbackData);
if (!core) {
return;
}
auto& module = core->OverlayManager();
module.OnToggle((locked != 0));
}
};
IDiscordOverlayEvents OverlayManager::events_{
&OverlayEvents::OnToggle,
};
void OverlayManager::IsEnabled(bool* enabled)
{
if (!enabled) {
return;
}
internal_->is_enabled(internal_, reinterpret_cast<bool*>(enabled));
}
void OverlayManager::IsLocked(bool* locked)
{
if (!locked) {
return;
}
internal_->is_locked(internal_, reinterpret_cast<bool*>(locked));
}
void OverlayManager::SetLocked(bool locked, std::function<void(Result)> callback)
{
static auto wrapper = [](void* callbackData, EDiscordResult result) -> void {
std::unique_ptr<std::function<void(Result)>> cb(
reinterpret_cast<std::function<void(Result)>*>(callbackData));
if (!cb || !(*cb)) {
return;
}
(*cb)(static_cast<Result>(result));
};
std::unique_ptr<std::function<void(Result)>> cb{};
cb.reset(new std::function<void(Result)>(std::move(callback)));
internal_->set_locked(internal_, (locked ? 1 : 0), cb.release(), wrapper);
}
void OverlayManager::OpenActivityInvite(ActivityActionType type,
std::function<void(Result)> callback)
{
static auto wrapper = [](void* callbackData, EDiscordResult result) -> void {
std::unique_ptr<std::function<void(Result)>> cb(
reinterpret_cast<std::function<void(Result)>*>(callbackData));
if (!cb || !(*cb)) {
return;
}
(*cb)(static_cast<Result>(result));
};
std::unique_ptr<std::function<void(Result)>> cb{};
cb.reset(new std::function<void(Result)>(std::move(callback)));
internal_->open_activity_invite(
internal_, static_cast<EDiscordActivityActionType>(type), cb.release(), wrapper);
}
void OverlayManager::OpenGuildInvite(char const* code, std::function<void(Result)> callback)
{
static auto wrapper = [](void* callbackData, EDiscordResult result) -> void {
std::unique_ptr<std::function<void(Result)>> cb(
reinterpret_cast<std::function<void(Result)>*>(callbackData));
if (!cb || !(*cb)) {
return;
}
(*cb)(static_cast<Result>(result));
};
std::unique_ptr<std::function<void(Result)>> cb{};
cb.reset(new std::function<void(Result)>(std::move(callback)));
internal_->open_guild_invite(internal_, const_cast<char*>(code), cb.release(), wrapper);
}
void OverlayManager::OpenVoiceSettings(std::function<void(Result)> callback)
{
static auto wrapper = [](void* callbackData, EDiscordResult result) -> void {
std::unique_ptr<std::function<void(Result)>> cb(
reinterpret_cast<std::function<void(Result)>*>(callbackData));
if (!cb || !(*cb)) {
return;
}
(*cb)(static_cast<Result>(result));
};
std::unique_ptr<std::function<void(Result)>> cb{};
cb.reset(new std::function<void(Result)>(std::move(callback)));
internal_->open_voice_settings(internal_, cb.release(), wrapper);
}
Result OverlayManager::InitDrawingDxgi(IDXGISwapChain* swapchain, bool useMessageForwarding)
{
auto result =
internal_->init_drawing_dxgi(internal_, swapchain, (useMessageForwarding ? 1 : 0));
return static_cast<Result>(result);
}
void OverlayManager::OnPresent()
{
internal_->on_present(internal_);
}
void OverlayManager::ForwardMessage(MSG* message)
{
internal_->forward_message(internal_, message);
}
void OverlayManager::KeyEvent(bool down, char const* keyCode, KeyVariant variant)
{
internal_->key_event(internal_,
(down ? 1 : 0),
const_cast<char*>(keyCode),
static_cast<EDiscordKeyVariant>(variant));
}
void OverlayManager::CharEvent(char const* character)
{
internal_->char_event(internal_, const_cast<char*>(character));
}
void OverlayManager::MouseButtonEvent(std::uint8_t down,
std::int32_t clickCount,
MouseButton which,
std::int32_t x,
std::int32_t y)
{
internal_->mouse_button_event(
internal_, down, clickCount, static_cast<EDiscordMouseButton>(which), x, y);
}
void OverlayManager::MouseMotionEvent(std::int32_t x, std::int32_t y)
{
internal_->mouse_motion_event(internal_, x, y);
}
void OverlayManager::ImeCommitText(char const* text)
{
internal_->ime_commit_text(internal_, const_cast<char*>(text));
}
void OverlayManager::ImeSetComposition(char const* text,
ImeUnderline* underlines,
std::uint32_t underlinesLength,
std::int32_t from,
std::int32_t to)
{
internal_->ime_set_composition(internal_,
const_cast<char*>(text),
reinterpret_cast<DiscordImeUnderline*>(underlines),
underlinesLength,
from,
to);
}
void OverlayManager::ImeCancelComposition()
{
internal_->ime_cancel_composition(internal_);
}
void OverlayManager::SetImeCompositionRangeCallback(
std::function<void(std::int32_t, std::int32_t, Rect*, std::uint32_t)>
onImeCompositionRangeChanged)
{
static auto wrapper = [](void* callbackData,
int32_t from,
int32_t to,
DiscordRect* bounds,
uint32_t boundsLength) -> void {
std::unique_ptr<std::function<void(std::int32_t, std::int32_t, Rect*, std::uint32_t)>> cb(
reinterpret_cast<std::function<void(std::int32_t, std::int32_t, Rect*, std::uint32_t)>*>(
callbackData));
if (!cb || !(*cb)) {
return;
}
(*cb)(from, to, reinterpret_cast<Rect*>(bounds), boundsLength);
};
std::unique_ptr<std::function<void(std::int32_t, std::int32_t, Rect*, std::uint32_t)>> cb{};
cb.reset(new std::function<void(std::int32_t, std::int32_t, Rect*, std::uint32_t)>(
std::move(onImeCompositionRangeChanged)));
internal_->set_ime_composition_range_callback(internal_, cb.release(), wrapper);
}
void OverlayManager::SetImeSelectionBoundsCallback(
std::function<void(Rect, Rect, bool)> onImeSelectionBoundsChanged)
{
static auto wrapper =
[](void* callbackData, DiscordRect anchor, DiscordRect focus, bool isAnchorFirst) -> void {
std::unique_ptr<std::function<void(Rect, Rect, bool)>> cb(
reinterpret_cast<std::function<void(Rect, Rect, bool)>*>(callbackData));
if (!cb || !(*cb)) {
return;
}
(*cb)(*reinterpret_cast<Rect const*>(&anchor),
*reinterpret_cast<Rect const*>(&focus),
(isAnchorFirst != 0));
};
std::unique_ptr<std::function<void(Rect, Rect, bool)>> cb{};
cb.reset(new std::function<void(Rect, Rect, bool)>(std::move(onImeSelectionBoundsChanged)));
internal_->set_ime_selection_bounds_callback(internal_, cb.release(), wrapper);
}
bool OverlayManager::IsPointInsideClickZone(std::int32_t x, std::int32_t y)
{
auto result = internal_->is_point_inside_click_zone(internal_, x, y);
return (result != 0);
}
} // namespace discord

View File

@@ -1,57 +0,0 @@
#pragma once
#include "types.h"
namespace discord {
class OverlayManager final {
public:
~OverlayManager() = default;
void IsEnabled(bool* enabled);
void IsLocked(bool* locked);
void SetLocked(bool locked, std::function<void(Result)> callback);
void OpenActivityInvite(ActivityActionType type, std::function<void(Result)> callback);
void OpenGuildInvite(char const* code, std::function<void(Result)> callback);
void OpenVoiceSettings(std::function<void(Result)> callback);
Result InitDrawingDxgi(IDXGISwapChain* swapchain, bool useMessageForwarding);
void OnPresent();
void ForwardMessage(MSG* message);
void KeyEvent(bool down, char const* keyCode, KeyVariant variant);
void CharEvent(char const* character);
void MouseButtonEvent(std::uint8_t down,
std::int32_t clickCount,
MouseButton which,
std::int32_t x,
std::int32_t y);
void MouseMotionEvent(std::int32_t x, std::int32_t y);
void ImeCommitText(char const* text);
void ImeSetComposition(char const* text,
ImeUnderline* underlines,
std::uint32_t underlinesLength,
std::int32_t from,
std::int32_t to);
void ImeCancelComposition();
void SetImeCompositionRangeCallback(
std::function<void(std::int32_t, std::int32_t, Rect*, std::uint32_t)>
onImeCompositionRangeChanged);
void SetImeSelectionBoundsCallback(
std::function<void(Rect, Rect, bool)> onImeSelectionBoundsChanged);
bool IsPointInsideClickZone(std::int32_t x, std::int32_t y);
Event<bool> OnToggle;
private:
friend class Core;
OverlayManager() = default;
OverlayManager(OverlayManager const& rhs) = delete;
OverlayManager& operator=(OverlayManager const& rhs) = delete;
OverlayManager(OverlayManager&& rhs) = delete;
OverlayManager& operator=(OverlayManager&& rhs) = delete;
IDiscordOverlayManager* internal_;
static IDiscordOverlayEvents events_;
};
} // namespace discord

View File

@@ -1,91 +0,0 @@
#if !defined(_CRT_SECURE_NO_WARNINGS)
#define _CRT_SECURE_NO_WARNINGS
#endif
#include "relationship_manager.h"
#include "core.h"
#include <cstring>
#include <memory>
namespace discord {
class RelationshipEvents final {
public:
static void DISCORD_CALLBACK OnRefresh(void* callbackData)
{
auto* core = reinterpret_cast<Core*>(callbackData);
if (!core) {
return;
}
auto& module = core->RelationshipManager();
module.OnRefresh();
}
static void DISCORD_CALLBACK OnRelationshipUpdate(void* callbackData,
DiscordRelationship* relationship)
{
auto* core = reinterpret_cast<Core*>(callbackData);
if (!core) {
return;
}
auto& module = core->RelationshipManager();
module.OnRelationshipUpdate(*reinterpret_cast<Relationship const*>(relationship));
}
};
IDiscordRelationshipEvents RelationshipManager::events_{
&RelationshipEvents::OnRefresh,
&RelationshipEvents::OnRelationshipUpdate,
};
void RelationshipManager::Filter(std::function<bool(Relationship const&)> filter)
{
static auto wrapper = [](void* callbackData, DiscordRelationship* relationship) -> bool {
auto cb(reinterpret_cast<std::function<bool(Relationship const&)>*>(callbackData));
if (!cb || !(*cb)) {
return {};
}
return (*cb)(*reinterpret_cast<Relationship const*>(relationship));
};
std::unique_ptr<std::function<bool(Relationship const&)>> cb{};
cb.reset(new std::function<bool(Relationship const&)>(std::move(filter)));
internal_->filter(internal_, cb.get(), wrapper);
}
Result RelationshipManager::Count(std::int32_t* count)
{
if (!count) {
return Result::InternalError;
}
auto result = internal_->count(internal_, reinterpret_cast<int32_t*>(count));
return static_cast<Result>(result);
}
Result RelationshipManager::Get(UserId userId, Relationship* relationship)
{
if (!relationship) {
return Result::InternalError;
}
auto result =
internal_->get(internal_, userId, reinterpret_cast<DiscordRelationship*>(relationship));
return static_cast<Result>(result);
}
Result RelationshipManager::GetAt(std::uint32_t index, Relationship* relationship)
{
if (!relationship) {
return Result::InternalError;
}
auto result =
internal_->get_at(internal_, index, reinterpret_cast<DiscordRelationship*>(relationship));
return static_cast<Result>(result);
}
} // namespace discord

View File

@@ -1,32 +0,0 @@
#pragma once
#include "types.h"
namespace discord {
class RelationshipManager final {
public:
~RelationshipManager() = default;
void Filter(std::function<bool(Relationship const&)> filter);
Result Count(std::int32_t* count);
Result Get(UserId userId, Relationship* relationship);
Result GetAt(std::uint32_t index, Relationship* relationship);
Event<> OnRefresh;
Event<Relationship const&> OnRelationshipUpdate;
private:
friend class Core;
RelationshipManager() = default;
RelationshipManager(RelationshipManager const& rhs) = delete;
RelationshipManager& operator=(RelationshipManager const& rhs) = delete;
RelationshipManager(RelationshipManager&& rhs) = delete;
RelationshipManager& operator=(RelationshipManager&& rhs) = delete;
IDiscordRelationshipManager* internal_;
static IDiscordRelationshipEvents events_;
};
} // namespace discord

View File

@@ -1,158 +0,0 @@
#if !defined(_CRT_SECURE_NO_WARNINGS)
#define _CRT_SECURE_NO_WARNINGS
#endif
#include "storage_manager.h"
#include "core.h"
#include <cstring>
#include <memory>
namespace discord {
Result StorageManager::Read(char const* name,
std::uint8_t* data,
std::uint32_t dataLength,
std::uint32_t* read)
{
if (!read) {
return Result::InternalError;
}
auto result = internal_->read(internal_,
const_cast<char*>(name),
reinterpret_cast<uint8_t*>(data),
dataLength,
reinterpret_cast<uint32_t*>(read));
return static_cast<Result>(result);
}
void StorageManager::ReadAsync(char const* name,
std::function<void(Result, std::uint8_t*, std::uint32_t)> callback)
{
static auto wrapper =
[](void* callbackData, EDiscordResult result, uint8_t* data, uint32_t dataLength) -> void {
std::unique_ptr<std::function<void(Result, std::uint8_t*, std::uint32_t)>> cb(
reinterpret_cast<std::function<void(Result, std::uint8_t*, std::uint32_t)>*>(
callbackData));
if (!cb || !(*cb)) {
return;
}
(*cb)(static_cast<Result>(result), data, dataLength);
};
std::unique_ptr<std::function<void(Result, std::uint8_t*, std::uint32_t)>> cb{};
cb.reset(new std::function<void(Result, std::uint8_t*, std::uint32_t)>(std::move(callback)));
internal_->read_async(internal_, const_cast<char*>(name), cb.release(), wrapper);
}
void StorageManager::ReadAsyncPartial(
char const* name,
std::uint64_t offset,
std::uint64_t length,
std::function<void(Result, std::uint8_t*, std::uint32_t)> callback)
{
static auto wrapper =
[](void* callbackData, EDiscordResult result, uint8_t* data, uint32_t dataLength) -> void {
std::unique_ptr<std::function<void(Result, std::uint8_t*, std::uint32_t)>> cb(
reinterpret_cast<std::function<void(Result, std::uint8_t*, std::uint32_t)>*>(
callbackData));
if (!cb || !(*cb)) {
return;
}
(*cb)(static_cast<Result>(result), data, dataLength);
};
std::unique_ptr<std::function<void(Result, std::uint8_t*, std::uint32_t)>> cb{};
cb.reset(new std::function<void(Result, std::uint8_t*, std::uint32_t)>(std::move(callback)));
internal_->read_async_partial(
internal_, const_cast<char*>(name), offset, length, cb.release(), wrapper);
}
Result StorageManager::Write(char const* name, std::uint8_t* data, std::uint32_t dataLength)
{
auto result = internal_->write(
internal_, const_cast<char*>(name), reinterpret_cast<uint8_t*>(data), dataLength);
return static_cast<Result>(result);
}
void StorageManager::WriteAsync(char const* name,
std::uint8_t* data,
std::uint32_t dataLength,
std::function<void(Result)> callback)
{
static auto wrapper = [](void* callbackData, EDiscordResult result) -> void {
std::unique_ptr<std::function<void(Result)>> cb(
reinterpret_cast<std::function<void(Result)>*>(callbackData));
if (!cb || !(*cb)) {
return;
}
(*cb)(static_cast<Result>(result));
};
std::unique_ptr<std::function<void(Result)>> cb{};
cb.reset(new std::function<void(Result)>(std::move(callback)));
internal_->write_async(internal_,
const_cast<char*>(name),
reinterpret_cast<uint8_t*>(data),
dataLength,
cb.release(),
wrapper);
}
Result StorageManager::Delete(char const* name)
{
auto result = internal_->delete_(internal_, const_cast<char*>(name));
return static_cast<Result>(result);
}
Result StorageManager::Exists(char const* name, bool* exists)
{
if (!exists) {
return Result::InternalError;
}
auto result =
internal_->exists(internal_, const_cast<char*>(name), reinterpret_cast<bool*>(exists));
return static_cast<Result>(result);
}
void StorageManager::Count(std::int32_t* count)
{
if (!count) {
return;
}
internal_->count(internal_, reinterpret_cast<int32_t*>(count));
}
Result StorageManager::Stat(char const* name, FileStat* stat)
{
if (!stat) {
return Result::InternalError;
}
auto result =
internal_->stat(internal_, const_cast<char*>(name), reinterpret_cast<DiscordFileStat*>(stat));
return static_cast<Result>(result);
}
Result StorageManager::StatAt(std::int32_t index, FileStat* stat)
{
if (!stat) {
return Result::InternalError;
}
auto result = internal_->stat_at(internal_, index, reinterpret_cast<DiscordFileStat*>(stat));
return static_cast<Result>(result);
}
Result StorageManager::GetPath(char path[4096])
{
if (!path) {
return Result::InternalError;
}
auto result = internal_->get_path(internal_, reinterpret_cast<DiscordPath*>(path));
return static_cast<Result>(result);
}
} // namespace discord

View File

@@ -1,46 +0,0 @@
#pragma once
#include "types.h"
namespace discord {
class StorageManager final {
public:
~StorageManager() = default;
Result Read(char const* name,
std::uint8_t* data,
std::uint32_t dataLength,
std::uint32_t* read);
void ReadAsync(char const* name,
std::function<void(Result, std::uint8_t*, std::uint32_t)> callback);
void ReadAsyncPartial(char const* name,
std::uint64_t offset,
std::uint64_t length,
std::function<void(Result, std::uint8_t*, std::uint32_t)> callback);
Result Write(char const* name, std::uint8_t* data, std::uint32_t dataLength);
void WriteAsync(char const* name,
std::uint8_t* data,
std::uint32_t dataLength,
std::function<void(Result)> callback);
Result Delete(char const* name);
Result Exists(char const* name, bool* exists);
void Count(std::int32_t* count);
Result Stat(char const* name, FileStat* stat);
Result StatAt(std::int32_t index, FileStat* stat);
Result GetPath(char path[4096]);
private:
friend class Core;
StorageManager() = default;
StorageManager(StorageManager const& rhs) = delete;
StorageManager& operator=(StorageManager const& rhs) = delete;
StorageManager(StorageManager&& rhs) = delete;
StorageManager& operator=(StorageManager&& rhs) = delete;
IDiscordStorageManager* internal_;
static IDiscordStorageEvents events_;
};
} // namespace discord

View File

@@ -1,162 +0,0 @@
#if !defined(_CRT_SECURE_NO_WARNINGS)
#define _CRT_SECURE_NO_WARNINGS
#endif
#include "store_manager.h"
#include "core.h"
#include <cstring>
#include <memory>
namespace discord {
class StoreEvents final {
public:
static void DISCORD_CALLBACK OnEntitlementCreate(void* callbackData,
DiscordEntitlement* entitlement)
{
auto* core = reinterpret_cast<Core*>(callbackData);
if (!core) {
return;
}
auto& module = core->StoreManager();
module.OnEntitlementCreate(*reinterpret_cast<Entitlement const*>(entitlement));
}
static void DISCORD_CALLBACK OnEntitlementDelete(void* callbackData,
DiscordEntitlement* entitlement)
{
auto* core = reinterpret_cast<Core*>(callbackData);
if (!core) {
return;
}
auto& module = core->StoreManager();
module.OnEntitlementDelete(*reinterpret_cast<Entitlement const*>(entitlement));
}
};
IDiscordStoreEvents StoreManager::events_{
&StoreEvents::OnEntitlementCreate,
&StoreEvents::OnEntitlementDelete,
};
void StoreManager::FetchSkus(std::function<void(Result)> callback)
{
static auto wrapper = [](void* callbackData, EDiscordResult result) -> void {
std::unique_ptr<std::function<void(Result)>> cb(
reinterpret_cast<std::function<void(Result)>*>(callbackData));
if (!cb || !(*cb)) {
return;
}
(*cb)(static_cast<Result>(result));
};
std::unique_ptr<std::function<void(Result)>> cb{};
cb.reset(new std::function<void(Result)>(std::move(callback)));
internal_->fetch_skus(internal_, cb.release(), wrapper);
}
void StoreManager::CountSkus(std::int32_t* count)
{
if (!count) {
return;
}
internal_->count_skus(internal_, reinterpret_cast<int32_t*>(count));
}
Result StoreManager::GetSku(Snowflake skuId, Sku* sku)
{
if (!sku) {
return Result::InternalError;
}
auto result = internal_->get_sku(internal_, skuId, reinterpret_cast<DiscordSku*>(sku));
return static_cast<Result>(result);
}
Result StoreManager::GetSkuAt(std::int32_t index, Sku* sku)
{
if (!sku) {
return Result::InternalError;
}
auto result = internal_->get_sku_at(internal_, index, reinterpret_cast<DiscordSku*>(sku));
return static_cast<Result>(result);
}
void StoreManager::FetchEntitlements(std::function<void(Result)> callback)
{
static auto wrapper = [](void* callbackData, EDiscordResult result) -> void {
std::unique_ptr<std::function<void(Result)>> cb(
reinterpret_cast<std::function<void(Result)>*>(callbackData));
if (!cb || !(*cb)) {
return;
}
(*cb)(static_cast<Result>(result));
};
std::unique_ptr<std::function<void(Result)>> cb{};
cb.reset(new std::function<void(Result)>(std::move(callback)));
internal_->fetch_entitlements(internal_, cb.release(), wrapper);
}
void StoreManager::CountEntitlements(std::int32_t* count)
{
if (!count) {
return;
}
internal_->count_entitlements(internal_, reinterpret_cast<int32_t*>(count));
}
Result StoreManager::GetEntitlement(Snowflake entitlementId, Entitlement* entitlement)
{
if (!entitlement) {
return Result::InternalError;
}
auto result = internal_->get_entitlement(
internal_, entitlementId, reinterpret_cast<DiscordEntitlement*>(entitlement));
return static_cast<Result>(result);
}
Result StoreManager::GetEntitlementAt(std::int32_t index, Entitlement* entitlement)
{
if (!entitlement) {
return Result::InternalError;
}
auto result = internal_->get_entitlement_at(
internal_, index, reinterpret_cast<DiscordEntitlement*>(entitlement));
return static_cast<Result>(result);
}
Result StoreManager::HasSkuEntitlement(Snowflake skuId, bool* hasEntitlement)
{
if (!hasEntitlement) {
return Result::InternalError;
}
auto result =
internal_->has_sku_entitlement(internal_, skuId, reinterpret_cast<bool*>(hasEntitlement));
return static_cast<Result>(result);
}
void StoreManager::StartPurchase(Snowflake skuId, std::function<void(Result)> callback)
{
static auto wrapper = [](void* callbackData, EDiscordResult result) -> void {
std::unique_ptr<std::function<void(Result)>> cb(
reinterpret_cast<std::function<void(Result)>*>(callbackData));
if (!cb || !(*cb)) {
return;
}
(*cb)(static_cast<Result>(result));
};
std::unique_ptr<std::function<void(Result)>> cb{};
cb.reset(new std::function<void(Result)>(std::move(callback)));
internal_->start_purchase(internal_, skuId, cb.release(), wrapper);
}
} // namespace discord

View File

@@ -1,38 +0,0 @@
#pragma once
#include "types.h"
namespace discord {
class StoreManager final {
public:
~StoreManager() = default;
void FetchSkus(std::function<void(Result)> callback);
void CountSkus(std::int32_t* count);
Result GetSku(Snowflake skuId, Sku* sku);
Result GetSkuAt(std::int32_t index, Sku* sku);
void FetchEntitlements(std::function<void(Result)> callback);
void CountEntitlements(std::int32_t* count);
Result GetEntitlement(Snowflake entitlementId, Entitlement* entitlement);
Result GetEntitlementAt(std::int32_t index, Entitlement* entitlement);
Result HasSkuEntitlement(Snowflake skuId, bool* hasEntitlement);
void StartPurchase(Snowflake skuId, std::function<void(Result)> callback);
Event<Entitlement const&> OnEntitlementCreate;
Event<Entitlement const&> OnEntitlementDelete;
private:
friend class Core;
StoreManager() = default;
StoreManager(StoreManager const& rhs) = delete;
StoreManager& operator=(StoreManager const& rhs) = delete;
StoreManager(StoreManager&& rhs) = delete;
StoreManager& operator=(StoreManager&& rhs) = delete;
IDiscordStoreManager* internal_;
static IDiscordStoreEvents events_;
};
} // namespace discord

View File

@@ -1,879 +0,0 @@
#if !defined(_CRT_SECURE_NO_WARNINGS)
#define _CRT_SECURE_NO_WARNINGS
#endif
#include "types.h"
#include <cstring>
#include <memory>
namespace discord {
void User::SetId(UserId id)
{
internal_.id = id;
}
UserId User::GetId() const
{
return internal_.id;
}
void User::SetUsername(char const* username)
{
strncpy(internal_.username, username, 256);
internal_.username[256 - 1] = '\0';
}
char const* User::GetUsername() const
{
return internal_.username;
}
void User::SetDiscriminator(char const* discriminator)
{
strncpy(internal_.discriminator, discriminator, 8);
internal_.discriminator[8 - 1] = '\0';
}
char const* User::GetDiscriminator() const
{
return internal_.discriminator;
}
void User::SetAvatar(char const* avatar)
{
strncpy(internal_.avatar, avatar, 128);
internal_.avatar[128 - 1] = '\0';
}
char const* User::GetAvatar() const
{
return internal_.avatar;
}
void User::SetBot(bool bot)
{
internal_.bot = bot;
}
bool User::GetBot() const
{
return internal_.bot != 0;
}
void OAuth2Token::SetAccessToken(char const* accessToken)
{
strncpy(internal_.access_token, accessToken, 128);
internal_.access_token[128 - 1] = '\0';
}
char const* OAuth2Token::GetAccessToken() const
{
return internal_.access_token;
}
void OAuth2Token::SetScopes(char const* scopes)
{
strncpy(internal_.scopes, scopes, 1024);
internal_.scopes[1024 - 1] = '\0';
}
char const* OAuth2Token::GetScopes() const
{
return internal_.scopes;
}
void OAuth2Token::SetExpires(Timestamp expires)
{
internal_.expires = expires;
}
Timestamp OAuth2Token::GetExpires() const
{
return internal_.expires;
}
void ImageHandle::SetType(ImageType type)
{
internal_.type = static_cast<EDiscordImageType>(type);
}
ImageType ImageHandle::GetType() const
{
return static_cast<ImageType>(internal_.type);
}
void ImageHandle::SetId(std::int64_t id)
{
internal_.id = id;
}
std::int64_t ImageHandle::GetId() const
{
return internal_.id;
}
void ImageHandle::SetSize(std::uint32_t size)
{
internal_.size = size;
}
std::uint32_t ImageHandle::GetSize() const
{
return internal_.size;
}
void ImageDimensions::SetWidth(std::uint32_t width)
{
internal_.width = width;
}
std::uint32_t ImageDimensions::GetWidth() const
{
return internal_.width;
}
void ImageDimensions::SetHeight(std::uint32_t height)
{
internal_.height = height;
}
std::uint32_t ImageDimensions::GetHeight() const
{
return internal_.height;
}
void ActivityTimestamps::SetStart(Timestamp start)
{
internal_.start = start;
}
Timestamp ActivityTimestamps::GetStart() const
{
return internal_.start;
}
void ActivityTimestamps::SetEnd(Timestamp end)
{
internal_.end = end;
}
Timestamp ActivityTimestamps::GetEnd() const
{
return internal_.end;
}
void ActivityAssets::SetLargeImage(char const* largeImage)
{
strncpy(internal_.large_image, largeImage, 128);
internal_.large_image[128 - 1] = '\0';
}
char const* ActivityAssets::GetLargeImage() const
{
return internal_.large_image;
}
void ActivityAssets::SetLargeText(char const* largeText)
{
strncpy(internal_.large_text, largeText, 128);
internal_.large_text[128 - 1] = '\0';
}
char const* ActivityAssets::GetLargeText() const
{
return internal_.large_text;
}
void ActivityAssets::SetSmallImage(char const* smallImage)
{
strncpy(internal_.small_image, smallImage, 128);
internal_.small_image[128 - 1] = '\0';
}
char const* ActivityAssets::GetSmallImage() const
{
return internal_.small_image;
}
void ActivityAssets::SetSmallText(char const* smallText)
{
strncpy(internal_.small_text, smallText, 128);
internal_.small_text[128 - 1] = '\0';
}
char const* ActivityAssets::GetSmallText() const
{
return internal_.small_text;
}
void PartySize::SetCurrentSize(std::int32_t currentSize)
{
internal_.current_size = currentSize;
}
std::int32_t PartySize::GetCurrentSize() const
{
return internal_.current_size;
}
void PartySize::SetMaxSize(std::int32_t maxSize)
{
internal_.max_size = maxSize;
}
std::int32_t PartySize::GetMaxSize() const
{
return internal_.max_size;
}
void ActivityParty::SetId(char const* id)
{
strncpy(internal_.id, id, 128);
internal_.id[128 - 1] = '\0';
}
char const* ActivityParty::GetId() const
{
return internal_.id;
}
PartySize& ActivityParty::GetSize()
{
return reinterpret_cast<PartySize&>(internal_.size);
}
PartySize const& ActivityParty::GetSize() const
{
return reinterpret_cast<PartySize const&>(internal_.size);
}
void ActivityParty::SetPrivacy(ActivityPartyPrivacy privacy)
{
internal_.privacy = static_cast<EDiscordActivityPartyPrivacy>(privacy);
}
ActivityPartyPrivacy ActivityParty::GetPrivacy() const
{
return static_cast<ActivityPartyPrivacy>(internal_.privacy);
}
void ActivitySecrets::SetMatch(char const* match)
{
strncpy(internal_.match, match, 128);
internal_.match[128 - 1] = '\0';
}
char const* ActivitySecrets::GetMatch() const
{
return internal_.match;
}
void ActivitySecrets::SetJoin(char const* join)
{
strncpy(internal_.join, join, 128);
internal_.join[128 - 1] = '\0';
}
char const* ActivitySecrets::GetJoin() const
{
return internal_.join;
}
void ActivitySecrets::SetSpectate(char const* spectate)
{
strncpy(internal_.spectate, spectate, 128);
internal_.spectate[128 - 1] = '\0';
}
char const* ActivitySecrets::GetSpectate() const
{
return internal_.spectate;
}
void Activity::SetType(ActivityType type)
{
internal_.type = static_cast<EDiscordActivityType>(type);
}
ActivityType Activity::GetType() const
{
return static_cast<ActivityType>(internal_.type);
}
void Activity::SetApplicationId(std::int64_t applicationId)
{
internal_.application_id = applicationId;
}
std::int64_t Activity::GetApplicationId() const
{
return internal_.application_id;
}
void Activity::SetName(char const* name)
{
strncpy(internal_.name, name, 128);
internal_.name[128 - 1] = '\0';
}
char const* Activity::GetName() const
{
return internal_.name;
}
void Activity::SetState(char const* state)
{
strncpy(internal_.state, state, 128);
internal_.state[128 - 1] = '\0';
}
char const* Activity::GetState() const
{
return internal_.state;
}
void Activity::SetDetails(char const* details)
{
strncpy(internal_.details, details, 128);
internal_.details[128 - 1] = '\0';
}
char const* Activity::GetDetails() const
{
return internal_.details;
}
ActivityTimestamps& Activity::GetTimestamps()
{
return reinterpret_cast<ActivityTimestamps&>(internal_.timestamps);
}
ActivityTimestamps const& Activity::GetTimestamps() const
{
return reinterpret_cast<ActivityTimestamps const&>(internal_.timestamps);
}
ActivityAssets& Activity::GetAssets()
{
return reinterpret_cast<ActivityAssets&>(internal_.assets);
}
ActivityAssets const& Activity::GetAssets() const
{
return reinterpret_cast<ActivityAssets const&>(internal_.assets);
}
ActivityParty& Activity::GetParty()
{
return reinterpret_cast<ActivityParty&>(internal_.party);
}
ActivityParty const& Activity::GetParty() const
{
return reinterpret_cast<ActivityParty const&>(internal_.party);
}
ActivitySecrets& Activity::GetSecrets()
{
return reinterpret_cast<ActivitySecrets&>(internal_.secrets);
}
ActivitySecrets const& Activity::GetSecrets() const
{
return reinterpret_cast<ActivitySecrets const&>(internal_.secrets);
}
void Activity::SetInstance(bool instance)
{
internal_.instance = instance;
}
bool Activity::GetInstance() const
{
return internal_.instance != 0;
}
void Activity::SetSupportedPlatforms(std::uint32_t supportedPlatforms)
{
internal_.supported_platforms = supportedPlatforms;
}
std::uint32_t Activity::GetSupportedPlatforms() const
{
return internal_.supported_platforms;
}
void Presence::SetStatus(Status status)
{
internal_.status = static_cast<EDiscordStatus>(status);
}
Status Presence::GetStatus() const
{
return static_cast<Status>(internal_.status);
}
Activity& Presence::GetActivity()
{
return reinterpret_cast<Activity&>(internal_.activity);
}
Activity const& Presence::GetActivity() const
{
return reinterpret_cast<Activity const&>(internal_.activity);
}
void Relationship::SetType(RelationshipType type)
{
internal_.type = static_cast<EDiscordRelationshipType>(type);
}
RelationshipType Relationship::GetType() const
{
return static_cast<RelationshipType>(internal_.type);
}
User& Relationship::GetUser()
{
return reinterpret_cast<User&>(internal_.user);
}
User const& Relationship::GetUser() const
{
return reinterpret_cast<User const&>(internal_.user);
}
Presence& Relationship::GetPresence()
{
return reinterpret_cast<Presence&>(internal_.presence);
}
Presence const& Relationship::GetPresence() const
{
return reinterpret_cast<Presence const&>(internal_.presence);
}
void Lobby::SetId(LobbyId id)
{
internal_.id = id;
}
LobbyId Lobby::GetId() const
{
return internal_.id;
}
void Lobby::SetType(LobbyType type)
{
internal_.type = static_cast<EDiscordLobbyType>(type);
}
LobbyType Lobby::GetType() const
{
return static_cast<LobbyType>(internal_.type);
}
void Lobby::SetOwnerId(UserId ownerId)
{
internal_.owner_id = ownerId;
}
UserId Lobby::GetOwnerId() const
{
return internal_.owner_id;
}
void Lobby::SetSecret(LobbySecret secret)
{
strncpy(internal_.secret, secret, 128);
internal_.secret[128 - 1] = '\0';
}
LobbySecret Lobby::GetSecret() const
{
return internal_.secret;
}
void Lobby::SetCapacity(std::uint32_t capacity)
{
internal_.capacity = capacity;
}
std::uint32_t Lobby::GetCapacity() const
{
return internal_.capacity;
}
void Lobby::SetLocked(bool locked)
{
internal_.locked = locked;
}
bool Lobby::GetLocked() const
{
return internal_.locked != 0;
}
void ImeUnderline::SetFrom(std::int32_t from)
{
internal_.from = from;
}
std::int32_t ImeUnderline::GetFrom() const
{
return internal_.from;
}
void ImeUnderline::SetTo(std::int32_t to)
{
internal_.to = to;
}
std::int32_t ImeUnderline::GetTo() const
{
return internal_.to;
}
void ImeUnderline::SetColor(std::uint32_t color)
{
internal_.color = color;
}
std::uint32_t ImeUnderline::GetColor() const
{
return internal_.color;
}
void ImeUnderline::SetBackgroundColor(std::uint32_t backgroundColor)
{
internal_.background_color = backgroundColor;
}
std::uint32_t ImeUnderline::GetBackgroundColor() const
{
return internal_.background_color;
}
void ImeUnderline::SetThick(bool thick)
{
internal_.thick = thick;
}
bool ImeUnderline::GetThick() const
{
return internal_.thick != 0;
}
void Rect::SetLeft(std::int32_t left)
{
internal_.left = left;
}
std::int32_t Rect::GetLeft() const
{
return internal_.left;
}
void Rect::SetTop(std::int32_t top)
{
internal_.top = top;
}
std::int32_t Rect::GetTop() const
{
return internal_.top;
}
void Rect::SetRight(std::int32_t right)
{
internal_.right = right;
}
std::int32_t Rect::GetRight() const
{
return internal_.right;
}
void Rect::SetBottom(std::int32_t bottom)
{
internal_.bottom = bottom;
}
std::int32_t Rect::GetBottom() const
{
return internal_.bottom;
}
void FileStat::SetFilename(char const* filename)
{
strncpy(internal_.filename, filename, 260);
internal_.filename[260 - 1] = '\0';
}
char const* FileStat::GetFilename() const
{
return internal_.filename;
}
void FileStat::SetSize(std::uint64_t size)
{
internal_.size = size;
}
std::uint64_t FileStat::GetSize() const
{
return internal_.size;
}
void FileStat::SetLastModified(std::uint64_t lastModified)
{
internal_.last_modified = lastModified;
}
std::uint64_t FileStat::GetLastModified() const
{
return internal_.last_modified;
}
void Entitlement::SetId(Snowflake id)
{
internal_.id = id;
}
Snowflake Entitlement::GetId() const
{
return internal_.id;
}
void Entitlement::SetType(EntitlementType type)
{
internal_.type = static_cast<EDiscordEntitlementType>(type);
}
EntitlementType Entitlement::GetType() const
{
return static_cast<EntitlementType>(internal_.type);
}
void Entitlement::SetSkuId(Snowflake skuId)
{
internal_.sku_id = skuId;
}
Snowflake Entitlement::GetSkuId() const
{
return internal_.sku_id;
}
void SkuPrice::SetAmount(std::uint32_t amount)
{
internal_.amount = amount;
}
std::uint32_t SkuPrice::GetAmount() const
{
return internal_.amount;
}
void SkuPrice::SetCurrency(char const* currency)
{
strncpy(internal_.currency, currency, 16);
internal_.currency[16 - 1] = '\0';
}
char const* SkuPrice::GetCurrency() const
{
return internal_.currency;
}
void Sku::SetId(Snowflake id)
{
internal_.id = id;
}
Snowflake Sku::GetId() const
{
return internal_.id;
}
void Sku::SetType(SkuType type)
{
internal_.type = static_cast<EDiscordSkuType>(type);
}
SkuType Sku::GetType() const
{
return static_cast<SkuType>(internal_.type);
}
void Sku::SetName(char const* name)
{
strncpy(internal_.name, name, 256);
internal_.name[256 - 1] = '\0';
}
char const* Sku::GetName() const
{
return internal_.name;
}
SkuPrice& Sku::GetPrice()
{
return reinterpret_cast<SkuPrice&>(internal_.price);
}
SkuPrice const& Sku::GetPrice() const
{
return reinterpret_cast<SkuPrice const&>(internal_.price);
}
void InputMode::SetType(InputModeType type)
{
internal_.type = static_cast<EDiscordInputModeType>(type);
}
InputModeType InputMode::GetType() const
{
return static_cast<InputModeType>(internal_.type);
}
void InputMode::SetShortcut(char const* shortcut)
{
strncpy(internal_.shortcut, shortcut, 256);
internal_.shortcut[256 - 1] = '\0';
}
char const* InputMode::GetShortcut() const
{
return internal_.shortcut;
}
void UserAchievement::SetUserId(Snowflake userId)
{
internal_.user_id = userId;
}
Snowflake UserAchievement::GetUserId() const
{
return internal_.user_id;
}
void UserAchievement::SetAchievementId(Snowflake achievementId)
{
internal_.achievement_id = achievementId;
}
Snowflake UserAchievement::GetAchievementId() const
{
return internal_.achievement_id;
}
void UserAchievement::SetPercentComplete(std::uint8_t percentComplete)
{
internal_.percent_complete = percentComplete;
}
std::uint8_t UserAchievement::GetPercentComplete() const
{
return internal_.percent_complete;
}
void UserAchievement::SetUnlockedAt(DateTime unlockedAt)
{
strncpy(internal_.unlocked_at, unlockedAt, 64);
internal_.unlocked_at[64 - 1] = '\0';
}
DateTime UserAchievement::GetUnlockedAt() const
{
return internal_.unlocked_at;
}
Result LobbyTransaction::SetType(LobbyType type)
{
auto result = internal_->set_type(internal_, static_cast<EDiscordLobbyType>(type));
return static_cast<Result>(result);
}
Result LobbyTransaction::SetOwner(UserId ownerId)
{
auto result = internal_->set_owner(internal_, ownerId);
return static_cast<Result>(result);
}
Result LobbyTransaction::SetCapacity(std::uint32_t capacity)
{
auto result = internal_->set_capacity(internal_, capacity);
return static_cast<Result>(result);
}
Result LobbyTransaction::SetMetadata(MetadataKey key, MetadataValue value)
{
auto result =
internal_->set_metadata(internal_, const_cast<char*>(key), const_cast<char*>(value));
return static_cast<Result>(result);
}
Result LobbyTransaction::DeleteMetadata(MetadataKey key)
{
auto result = internal_->delete_metadata(internal_, const_cast<char*>(key));
return static_cast<Result>(result);
}
Result LobbyTransaction::SetLocked(bool locked)
{
auto result = internal_->set_locked(internal_, (locked ? 1 : 0));
return static_cast<Result>(result);
}
Result LobbyMemberTransaction::SetMetadata(MetadataKey key, MetadataValue value)
{
auto result =
internal_->set_metadata(internal_, const_cast<char*>(key), const_cast<char*>(value));
return static_cast<Result>(result);
}
Result LobbyMemberTransaction::DeleteMetadata(MetadataKey key)
{
auto result = internal_->delete_metadata(internal_, const_cast<char*>(key));
return static_cast<Result>(result);
}
Result LobbySearchQuery::Filter(MetadataKey key,
LobbySearchComparison comparison,
LobbySearchCast cast,
MetadataValue value)
{
auto result = internal_->filter(internal_,
const_cast<char*>(key),
static_cast<EDiscordLobbySearchComparison>(comparison),
static_cast<EDiscordLobbySearchCast>(cast),
const_cast<char*>(value));
return static_cast<Result>(result);
}
Result LobbySearchQuery::Sort(MetadataKey key, LobbySearchCast cast, MetadataValue value)
{
auto result = internal_->sort(internal_,
const_cast<char*>(key),
static_cast<EDiscordLobbySearchCast>(cast),
const_cast<char*>(value));
return static_cast<Result>(result);
}
Result LobbySearchQuery::Limit(std::uint32_t limit)
{
auto result = internal_->limit(internal_, limit);
return static_cast<Result>(result);
}
Result LobbySearchQuery::Distance(LobbySearchDistance distance)
{
auto result =
internal_->distance(internal_, static_cast<EDiscordLobbySearchDistance>(distance));
return static_cast<Result>(result);
}
} // namespace discord

View File

@@ -1,568 +0,0 @@
#include <cstdint>
#pragma once
#include "ffi.h"
#include "event.h"
#ifdef _WIN32
#include <Windows.h>
#include <dxgi.h>
#endif
namespace discord {
enum class Result {
Ok = 0,
ServiceUnavailable = 1,
InvalidVersion = 2,
LockFailed = 3,
InternalError = 4,
InvalidPayload = 5,
InvalidCommand = 6,
InvalidPermissions = 7,
NotFetched = 8,
NotFound = 9,
Conflict = 10,
InvalidSecret = 11,
InvalidJoinSecret = 12,
NoEligibleActivity = 13,
InvalidInvite = 14,
NotAuthenticated = 15,
InvalidAccessToken = 16,
ApplicationMismatch = 17,
InvalidDataUrl = 18,
InvalidBase64 = 19,
NotFiltered = 20,
LobbyFull = 21,
InvalidLobbySecret = 22,
InvalidFilename = 23,
InvalidFileSize = 24,
InvalidEntitlement = 25,
NotInstalled = 26,
NotRunning = 27,
InsufficientBuffer = 28,
PurchaseCanceled = 29,
InvalidGuild = 30,
InvalidEvent = 31,
InvalidChannel = 32,
InvalidOrigin = 33,
RateLimited = 34,
OAuth2Error = 35,
SelectChannelTimeout = 36,
GetGuildTimeout = 37,
SelectVoiceForceRequired = 38,
CaptureShortcutAlreadyListening = 39,
UnauthorizedForAchievement = 40,
InvalidGiftCode = 41,
PurchaseError = 42,
TransactionAborted = 43,
DrawingInitFailed = 44,
};
enum class CreateFlags {
Default = 0,
NoRequireDiscord = 1,
};
enum class LogLevel {
Error = 1,
Warn,
Info,
Debug,
};
enum class UserFlag {
Partner = 2,
HypeSquadEvents = 4,
HypeSquadHouse1 = 64,
HypeSquadHouse2 = 128,
HypeSquadHouse3 = 256,
};
enum class PremiumType {
None = 0,
Tier1 = 1,
Tier2 = 2,
};
enum class ImageType {
User,
};
enum class ActivityPartyPrivacy {
Private = 0,
Public = 1,
};
enum class ActivityType {
Playing,
Streaming,
Listening,
Watching,
};
enum class ActivityActionType {
Join = 1,
Spectate,
};
enum class ActivitySupportedPlatformFlags {
Desktop = 1,
Android = 2,
iOS = 4,
};
enum class ActivityJoinRequestReply {
No,
Yes,
Ignore,
};
enum class Status {
Offline = 0,
Online = 1,
Idle = 2,
DoNotDisturb = 3,
};
enum class RelationshipType {
None,
Friend,
Blocked,
PendingIncoming,
PendingOutgoing,
Implicit,
};
enum class LobbyType {
Private = 1,
Public,
};
enum class LobbySearchComparison {
LessThanOrEqual = -2,
LessThan,
Equal,
GreaterThan,
GreaterThanOrEqual,
NotEqual,
};
enum class LobbySearchCast {
String = 1,
Number,
};
enum class LobbySearchDistance {
Local,
Default,
Extended,
Global,
};
enum class KeyVariant {
Normal,
Right,
Left,
};
enum class MouseButton {
Left,
Middle,
Right,
};
enum class EntitlementType {
Purchase = 1,
PremiumSubscription,
DeveloperGift,
TestModePurchase,
FreePurchase,
UserGift,
PremiumPurchase,
};
enum class SkuType {
Application = 1,
DLC,
Consumable,
Bundle,
};
enum class InputModeType {
VoiceActivity = 0,
PushToTalk,
};
using ClientId = std::int64_t;
using Version = std::int32_t;
using Snowflake = std::int64_t;
using Timestamp = std::int64_t;
using UserId = Snowflake;
using Locale = char const*;
using Branch = char const*;
using LobbyId = Snowflake;
using LobbySecret = char const*;
using MetadataKey = char const*;
using MetadataValue = char const*;
using NetworkPeerId = std::uint64_t;
using NetworkChannelId = std::uint8_t;
#ifdef __APPLE__
using IDXGISwapChain = void;
#endif
#ifdef __linux__
using IDXGISwapChain = void;
#endif
#ifdef __APPLE__
using MSG = void;
#endif
#ifdef __linux__
using MSG = void;
#endif
using Path = char const*;
using DateTime = char const*;
class User final {
public:
void SetId(UserId id);
UserId GetId() const;
void SetUsername(char const* username);
char const* GetUsername() const;
void SetDiscriminator(char const* discriminator);
char const* GetDiscriminator() const;
void SetAvatar(char const* avatar);
char const* GetAvatar() const;
void SetBot(bool bot);
bool GetBot() const;
private:
DiscordUser internal_;
};
class OAuth2Token final {
public:
void SetAccessToken(char const* accessToken);
char const* GetAccessToken() const;
void SetScopes(char const* scopes);
char const* GetScopes() const;
void SetExpires(Timestamp expires);
Timestamp GetExpires() const;
private:
DiscordOAuth2Token internal_;
};
class ImageHandle final {
public:
void SetType(ImageType type);
ImageType GetType() const;
void SetId(std::int64_t id);
std::int64_t GetId() const;
void SetSize(std::uint32_t size);
std::uint32_t GetSize() const;
private:
DiscordImageHandle internal_;
};
class ImageDimensions final {
public:
void SetWidth(std::uint32_t width);
std::uint32_t GetWidth() const;
void SetHeight(std::uint32_t height);
std::uint32_t GetHeight() const;
private:
DiscordImageDimensions internal_;
};
class ActivityTimestamps final {
public:
void SetStart(Timestamp start);
Timestamp GetStart() const;
void SetEnd(Timestamp end);
Timestamp GetEnd() const;
private:
DiscordActivityTimestamps internal_;
};
class ActivityAssets final {
public:
void SetLargeImage(char const* largeImage);
char const* GetLargeImage() const;
void SetLargeText(char const* largeText);
char const* GetLargeText() const;
void SetSmallImage(char const* smallImage);
char const* GetSmallImage() const;
void SetSmallText(char const* smallText);
char const* GetSmallText() const;
private:
DiscordActivityAssets internal_;
};
class PartySize final {
public:
void SetCurrentSize(std::int32_t currentSize);
std::int32_t GetCurrentSize() const;
void SetMaxSize(std::int32_t maxSize);
std::int32_t GetMaxSize() const;
private:
DiscordPartySize internal_;
};
class ActivityParty final {
public:
void SetId(char const* id);
char const* GetId() const;
PartySize& GetSize();
PartySize const& GetSize() const;
void SetPrivacy(ActivityPartyPrivacy privacy);
ActivityPartyPrivacy GetPrivacy() const;
private:
DiscordActivityParty internal_;
};
class ActivitySecrets final {
public:
void SetMatch(char const* match);
char const* GetMatch() const;
void SetJoin(char const* join);
char const* GetJoin() const;
void SetSpectate(char const* spectate);
char const* GetSpectate() const;
private:
DiscordActivitySecrets internal_;
};
class Activity final {
public:
void SetType(ActivityType type);
ActivityType GetType() const;
void SetApplicationId(std::int64_t applicationId);
std::int64_t GetApplicationId() const;
void SetName(char const* name);
char const* GetName() const;
void SetState(char const* state);
char const* GetState() const;
void SetDetails(char const* details);
char const* GetDetails() const;
ActivityTimestamps& GetTimestamps();
ActivityTimestamps const& GetTimestamps() const;
ActivityAssets& GetAssets();
ActivityAssets const& GetAssets() const;
ActivityParty& GetParty();
ActivityParty const& GetParty() const;
ActivitySecrets& GetSecrets();
ActivitySecrets const& GetSecrets() const;
void SetInstance(bool instance);
bool GetInstance() const;
void SetSupportedPlatforms(std::uint32_t supportedPlatforms);
std::uint32_t GetSupportedPlatforms() const;
private:
DiscordActivity internal_;
};
class Presence final {
public:
void SetStatus(Status status);
Status GetStatus() const;
Activity& GetActivity();
Activity const& GetActivity() const;
private:
DiscordPresence internal_;
};
class Relationship final {
public:
void SetType(RelationshipType type);
RelationshipType GetType() const;
User& GetUser();
User const& GetUser() const;
Presence& GetPresence();
Presence const& GetPresence() const;
private:
DiscordRelationship internal_;
};
class Lobby final {
public:
void SetId(LobbyId id);
LobbyId GetId() const;
void SetType(LobbyType type);
LobbyType GetType() const;
void SetOwnerId(UserId ownerId);
UserId GetOwnerId() const;
void SetSecret(LobbySecret secret);
LobbySecret GetSecret() const;
void SetCapacity(std::uint32_t capacity);
std::uint32_t GetCapacity() const;
void SetLocked(bool locked);
bool GetLocked() const;
private:
DiscordLobby internal_;
};
class ImeUnderline final {
public:
void SetFrom(std::int32_t from);
std::int32_t GetFrom() const;
void SetTo(std::int32_t to);
std::int32_t GetTo() const;
void SetColor(std::uint32_t color);
std::uint32_t GetColor() const;
void SetBackgroundColor(std::uint32_t backgroundColor);
std::uint32_t GetBackgroundColor() const;
void SetThick(bool thick);
bool GetThick() const;
private:
DiscordImeUnderline internal_;
};
class Rect final {
public:
void SetLeft(std::int32_t left);
std::int32_t GetLeft() const;
void SetTop(std::int32_t top);
std::int32_t GetTop() const;
void SetRight(std::int32_t right);
std::int32_t GetRight() const;
void SetBottom(std::int32_t bottom);
std::int32_t GetBottom() const;
private:
DiscordRect internal_;
};
class FileStat final {
public:
void SetFilename(char const* filename);
char const* GetFilename() const;
void SetSize(std::uint64_t size);
std::uint64_t GetSize() const;
void SetLastModified(std::uint64_t lastModified);
std::uint64_t GetLastModified() const;
private:
DiscordFileStat internal_;
};
class Entitlement final {
public:
void SetId(Snowflake id);
Snowflake GetId() const;
void SetType(EntitlementType type);
EntitlementType GetType() const;
void SetSkuId(Snowflake skuId);
Snowflake GetSkuId() const;
private:
DiscordEntitlement internal_;
};
class SkuPrice final {
public:
void SetAmount(std::uint32_t amount);
std::uint32_t GetAmount() const;
void SetCurrency(char const* currency);
char const* GetCurrency() const;
private:
DiscordSkuPrice internal_;
};
class Sku final {
public:
void SetId(Snowflake id);
Snowflake GetId() const;
void SetType(SkuType type);
SkuType GetType() const;
void SetName(char const* name);
char const* GetName() const;
SkuPrice& GetPrice();
SkuPrice const& GetPrice() const;
private:
DiscordSku internal_;
};
class InputMode final {
public:
void SetType(InputModeType type);
InputModeType GetType() const;
void SetShortcut(char const* shortcut);
char const* GetShortcut() const;
private:
DiscordInputMode internal_;
};
class UserAchievement final {
public:
void SetUserId(Snowflake userId);
Snowflake GetUserId() const;
void SetAchievementId(Snowflake achievementId);
Snowflake GetAchievementId() const;
void SetPercentComplete(std::uint8_t percentComplete);
std::uint8_t GetPercentComplete() const;
void SetUnlockedAt(DateTime unlockedAt);
DateTime GetUnlockedAt() const;
private:
DiscordUserAchievement internal_;
};
class LobbyTransaction final {
public:
Result SetType(LobbyType type);
Result SetOwner(UserId ownerId);
Result SetCapacity(std::uint32_t capacity);
Result SetMetadata(MetadataKey key, MetadataValue value);
Result DeleteMetadata(MetadataKey key);
Result SetLocked(bool locked);
IDiscordLobbyTransaction** Receive() { return &internal_; }
IDiscordLobbyTransaction* Internal() { return internal_; }
private:
IDiscordLobbyTransaction* internal_;
};
class LobbyMemberTransaction final {
public:
Result SetMetadata(MetadataKey key, MetadataValue value);
Result DeleteMetadata(MetadataKey key);
IDiscordLobbyMemberTransaction** Receive() { return &internal_; }
IDiscordLobbyMemberTransaction* Internal() { return internal_; }
private:
IDiscordLobbyMemberTransaction* internal_;
};
class LobbySearchQuery final {
public:
Result Filter(MetadataKey key,
LobbySearchComparison comparison,
LobbySearchCast cast,
MetadataValue value);
Result Sort(MetadataKey key, LobbySearchCast cast, MetadataValue value);
Result Limit(std::uint32_t limit);
Result Distance(LobbySearchDistance distance);
IDiscordLobbySearchQuery** Receive() { return &internal_; }
IDiscordLobbySearchQuery* Internal() { return internal_; }
private:
IDiscordLobbySearchQuery* internal_;
};
} // namespace discord

View File

@@ -1,80 +0,0 @@
#if !defined(_CRT_SECURE_NO_WARNINGS)
#define _CRT_SECURE_NO_WARNINGS
#endif
#include "user_manager.h"
#include "core.h"
#include <cstring>
#include <memory>
namespace discord {
class UserEvents final {
public:
static void DISCORD_CALLBACK OnCurrentUserUpdate(void* callbackData)
{
auto* core = reinterpret_cast<Core*>(callbackData);
if (!core) {
return;
}
auto& module = core->UserManager();
module.OnCurrentUserUpdate();
}
};
IDiscordUserEvents UserManager::events_{
&UserEvents::OnCurrentUserUpdate,
};
Result UserManager::GetCurrentUser(User* currentUser)
{
if (!currentUser) {
return Result::InternalError;
}
auto result =
internal_->get_current_user(internal_, reinterpret_cast<DiscordUser*>(currentUser));
return static_cast<Result>(result);
}
void UserManager::GetUser(UserId userId, std::function<void(Result, User const&)> callback)
{
static auto wrapper = [](void* callbackData, EDiscordResult result, DiscordUser* user) -> void {
std::unique_ptr<std::function<void(Result, User const&)>> cb(
reinterpret_cast<std::function<void(Result, User const&)>*>(callbackData));
if (!cb || !(*cb)) {
return;
}
(*cb)(static_cast<Result>(result), *reinterpret_cast<User const*>(user));
};
std::unique_ptr<std::function<void(Result, User const&)>> cb{};
cb.reset(new std::function<void(Result, User const&)>(std::move(callback)));
internal_->get_user(internal_, userId, cb.release(), wrapper);
}
Result UserManager::GetCurrentUserPremiumType(PremiumType* premiumType)
{
if (!premiumType) {
return Result::InternalError;
}
auto result = internal_->get_current_user_premium_type(
internal_, reinterpret_cast<EDiscordPremiumType*>(premiumType));
return static_cast<Result>(result);
}
Result UserManager::CurrentUserHasFlag(UserFlag flag, bool* hasFlag)
{
if (!hasFlag) {
return Result::InternalError;
}
auto result = internal_->current_user_has_flag(
internal_, static_cast<EDiscordUserFlag>(flag), reinterpret_cast<bool*>(hasFlag));
return static_cast<Result>(result);
}
} // namespace discord

View File

@@ -1,31 +0,0 @@
#pragma once
#include "types.h"
namespace discord {
class UserManager final {
public:
~UserManager() = default;
Result GetCurrentUser(User* currentUser);
void GetUser(UserId userId, std::function<void(Result, User const&)> callback);
Result GetCurrentUserPremiumType(PremiumType* premiumType);
Result CurrentUserHasFlag(UserFlag flag, bool* hasFlag);
Event<> OnCurrentUserUpdate;
private:
friend class Core;
UserManager() = default;
UserManager(UserManager const& rhs) = delete;
UserManager& operator=(UserManager const& rhs) = delete;
UserManager(UserManager&& rhs) = delete;
UserManager& operator=(UserManager&& rhs) = delete;
IDiscordUserManager* internal_;
static IDiscordUserEvents events_;
};
} // namespace discord

View File

@@ -1,124 +0,0 @@
#if !defined(_CRT_SECURE_NO_WARNINGS)
#define _CRT_SECURE_NO_WARNINGS
#endif
#include "voice_manager.h"
#include "core.h"
#include <cstring>
#include <memory>
namespace discord {
class VoiceEvents final {
public:
static void DISCORD_CALLBACK OnSettingsUpdate(void* callbackData)
{
auto* core = reinterpret_cast<Core*>(callbackData);
if (!core) {
return;
}
auto& module = core->VoiceManager();
module.OnSettingsUpdate();
}
};
IDiscordVoiceEvents VoiceManager::events_{
&VoiceEvents::OnSettingsUpdate,
};
Result VoiceManager::GetInputMode(InputMode* inputMode)
{
if (!inputMode) {
return Result::InternalError;
}
auto result =
internal_->get_input_mode(internal_, reinterpret_cast<DiscordInputMode*>(inputMode));
return static_cast<Result>(result);
}
void VoiceManager::SetInputMode(InputMode inputMode, std::function<void(Result)> callback)
{
static auto wrapper = [](void* callbackData, EDiscordResult result) -> void {
std::unique_ptr<std::function<void(Result)>> cb(
reinterpret_cast<std::function<void(Result)>*>(callbackData));
if (!cb || !(*cb)) {
return;
}
(*cb)(static_cast<Result>(result));
};
std::unique_ptr<std::function<void(Result)>> cb{};
cb.reset(new std::function<void(Result)>(std::move(callback)));
internal_->set_input_mode(
internal_, *reinterpret_cast<DiscordInputMode const*>(&inputMode), cb.release(), wrapper);
}
Result VoiceManager::IsSelfMute(bool* mute)
{
if (!mute) {
return Result::InternalError;
}
auto result = internal_->is_self_mute(internal_, reinterpret_cast<bool*>(mute));
return static_cast<Result>(result);
}
Result VoiceManager::SetSelfMute(bool mute)
{
auto result = internal_->set_self_mute(internal_, (mute ? 1 : 0));
return static_cast<Result>(result);
}
Result VoiceManager::IsSelfDeaf(bool* deaf)
{
if (!deaf) {
return Result::InternalError;
}
auto result = internal_->is_self_deaf(internal_, reinterpret_cast<bool*>(deaf));
return static_cast<Result>(result);
}
Result VoiceManager::SetSelfDeaf(bool deaf)
{
auto result = internal_->set_self_deaf(internal_, (deaf ? 1 : 0));
return static_cast<Result>(result);
}
Result VoiceManager::IsLocalMute(Snowflake userId, bool* mute)
{
if (!mute) {
return Result::InternalError;
}
auto result = internal_->is_local_mute(internal_, userId, reinterpret_cast<bool*>(mute));
return static_cast<Result>(result);
}
Result VoiceManager::SetLocalMute(Snowflake userId, bool mute)
{
auto result = internal_->set_local_mute(internal_, userId, (mute ? 1 : 0));
return static_cast<Result>(result);
}
Result VoiceManager::GetLocalVolume(Snowflake userId, std::uint8_t* volume)
{
if (!volume) {
return Result::InternalError;
}
auto result =
internal_->get_local_volume(internal_, userId, reinterpret_cast<uint8_t*>(volume));
return static_cast<Result>(result);
}
Result VoiceManager::SetLocalVolume(Snowflake userId, std::uint8_t volume)
{
auto result = internal_->set_local_volume(internal_, userId, volume);
return static_cast<Result>(result);
}
} // namespace discord

View File

@@ -1,37 +0,0 @@
#pragma once
#include "types.h"
namespace discord {
class VoiceManager final {
public:
~VoiceManager() = default;
Result GetInputMode(InputMode* inputMode);
void SetInputMode(InputMode inputMode, std::function<void(Result)> callback);
Result IsSelfMute(bool* mute);
Result SetSelfMute(bool mute);
Result IsSelfDeaf(bool* deaf);
Result SetSelfDeaf(bool deaf);
Result IsLocalMute(Snowflake userId, bool* mute);
Result SetLocalMute(Snowflake userId, bool mute);
Result GetLocalVolume(Snowflake userId, std::uint8_t* volume);
Result SetLocalVolume(Snowflake userId, std::uint8_t volume);
Event<> OnSettingsUpdate;
private:
friend class Core;
VoiceManager() = default;
VoiceManager(VoiceManager const& rhs) = delete;
VoiceManager& operator=(VoiceManager const& rhs) = delete;
VoiceManager(VoiceManager&& rhs) = delete;
VoiceManager& operator=(VoiceManager&& rhs) = delete;
IDiscordVoiceManager* internal_;
static IDiscordVoiceEvents events_;
};
} // namespace discord

View File

@@ -0,0 +1,70 @@
#include "discord_activity.h"
void DiscordActivity::_bind_methods()
{
BIND_SET_GET(DiscordActivity, rich_presence, Variant::OBJECT, PROPERTY_HINT_RESOURCE_TYPE, "RichPresence");
BIND_SET_GET(DiscordActivity, party_invite, Variant::OBJECT, PROPERTY_HINT_RESOURCE_TYPE, "PartyInvite");
BIND_METHOD(DiscordActivity, update);
}
DiscordActivity::DiscordActivity()
{
}
DiscordActivity::~DiscordActivity()
{
}
Ref<RichPresence> DiscordActivity::get_rich_presence()
{
return rich_presence;
}
void DiscordActivity::set_rich_presence(Ref<RichPresence> value)
{
rich_presence = value;
}
Ref<PartyInvite> DiscordActivity::get_party_invite()
{
return party_invite;
}
void DiscordActivity::set_party_invite(Ref<PartyInvite> value)
{
party_invite = value;
}
void DiscordActivity::update()
{
discordpp::Activity activity;
if (rich_presence.is_valid())
{
activity.SetState(rich_presence->get_state().utf8().get_data());
activity.SetDetails(rich_presence->get_details().utf8().get_data());
discordpp::ActivityAssets assets;
assets.SetSmallImage(String(rich_presence->get_small_image()).utf8().get_data());
assets.SetSmallText(rich_presence->get_small_text().utf8().get_data());
assets.SetLargeImage(String(rich_presence->get_large_image()).utf8().get_data());
assets.SetLargeText(rich_presence->get_large_text().utf8().get_data());
activity.SetAssets(assets);
discordpp::ActivityTimestamps timestamps;
timestamps.SetStart(rich_presence->get_timestamps_start());
timestamps.SetEnd(rich_presence->get_timestamps_end());
activity.SetTimestamps(timestamps);
}
if (party_invite.is_valid())
{
discordpp::ActivityParty party;
party.SetCurrentSize(party_invite->get_current_size());
party.SetMaxSize(party_invite->get_max_size());
party.SetId(party_invite->get_id().utf8().get_data());
party.SetPrivacy(party_invite->get_is_public_party() ? discordpp::ActivityPartyPrivacy::Public : discordpp::ActivityPartyPrivacy::Private);
discordpp::ActivitySecrets secrets;
secrets.SetJoin(party_invite->get_join_secret().utf8().get_data());
activity.SetSecrets(secrets);
activity.SetParty(party);
// TODO: Supported platforms
// activity.SetSupportedPlatforms();
// TODO: Error on invalid values inside getters
}
connector->client->UpdateRichPresence(activity, [](discordpp::ClientResult result) {});
}

View File

@@ -0,0 +1,39 @@
#ifndef DISCORD_ACTIVITY_H
#define DISCORD_ACTIVITY_H
#include "discord_connected.h"
#include "../resources/rich_presence.h"
#include "../resources/party_invite.h"
using namespace godot;
class DiscordActivity : public DiscordConnected
{
GDCLASS(DiscordActivity, DiscordConnected);
protected:
static void _bind_methods();
public:
Ref<RichPresence> rich_presence;
Ref<RichPresence> get_rich_presence();
void set_rich_presence(Ref<RichPresence> value);
Ref<PartyInvite> party_invite;
Ref<PartyInvite> get_party_invite();
void set_party_invite(Ref<PartyInvite> value);
void register_launch_command(String command);
void register_steam(int32_t steam_id);
void accept_join_request(int64_t user_id);
void send_invite(int64_t friend_user_id, bool is_spectate, String message_content);
void accept_invite(int64_t user_id);
void update();
DiscordActivity();
~DiscordActivity();
};
#endif

View File

@@ -0,0 +1,43 @@
#include "discord_connected.h"
void DiscordConnected::_bind_methods()
{
BIND_SET_GET(DiscordConnected, root_connector, Variant::NODE_PATH, godot::PROPERTY_HINT_NODE_PATH_VALID_TYPES, "DiscordConnector");
}
DiscordConnected::DiscordConnected()
{
}
DiscordConnected::~DiscordConnected()
{
}
NodePath DiscordConnected::get_root_connector()
{
return root_connector;
}
void DiscordConnected::set_root_connector(NodePath value)
{
root_connector = value;
}
void DiscordConnected::_enter_tree()
{
if (cast_to<DiscordConnector>(get_parent()))
{
if (root_connector.is_empty())
{
root_connector = cast_to<DiscordConnector>(get_parent())->get_path();
if (!root_connector.is_empty())
{
connector = get_node<DiscordConnector>(root_connector);
}
}
else
{
if (get_node_or_null(root_connector)){
connector = get_node<DiscordConnector>(root_connector);
}
}
}
}

View File

@@ -0,0 +1,31 @@
#ifndef DISCORD_CONNECTED_H
#define DISCORD_CONNECTED_H
#include "discord_social_sdk.h"
#include "discord_connector.h"
using namespace godot;
class DiscordConnected : public DiscordSocialSDK
{
GDCLASS(DiscordConnected, DiscordSocialSDK);
protected:
static void _bind_methods();
private:
NodePath root_connector; // Change to NodePath object
public:
DiscordConnector *connector;
NodePath get_root_connector(); // Adjust return type
void set_root_connector(NodePath value); // Adjust parameter type
DiscordConnected();
~DiscordConnected();
void _enter_tree() override;
};
#endif

View File

@@ -0,0 +1,190 @@
#include "discord_connector.h"
void DiscordConnector::_bind_methods()
{
BIND_SET_GET(DiscordConnector, app_id, Variant::STRING, godot::PROPERTY_HINT_RANGE, "-99999,99999,or_less,or_greater,hide_slider");
ADD_GROUP("Automatic", "auto_");
BIND_SET_GET(DiscordConnector, auto_connect, Variant::BOOL);
BIND_SET_GET(DiscordConnector, auto_token_manage, Variant::BOOL);
BIND_SET_GET(DiscordConnector, auto_encryption_key, Variant::STRING, godot::PROPERTY_HINT_NONE, "", godot::PROPERTY_USAGE_NO_EDITOR);
BIND_METHOD(DiscordConnector, auth);
BIND_METHOD(DiscordConnector, token_connect, "access_token");
BIND_METHOD(DiscordConnector, token_refresh, "current_refresh_token");
BIND_SIGNAL(authenticated, PropertyInfo(Variant::STRING, "access_token"), PropertyInfo(Variant::STRING, "refresh_token"), PropertyInfo(Variant::INT, "expires_in"));
BIND_SIGNAL(authentication_failed, PropertyInfo(Variant::STRING, "error"));
BIND_SIGNAL(connection_ready);
BIND_SIGNAL(connection_error, PropertyInfo(Variant::STRING, "error"));
BIND_SIGNAL(token_refreshed, PropertyInfo(Variant::STRING, "access_token"), PropertyInfo(Variant::STRING, "refresh_token"), PropertyInfo(Variant::INT, "expires_in"));
BIND_SIGNAL(token_refresh_failed, PropertyInfo(Variant::STRING, "error"));
}
DiscordConnector::DiscordConnector()
{
}
DiscordConnector::~DiscordConnector()
{
}
void DiscordConnector::_ready()
{
if (Engine::get_singleton()->is_editor_hint() || editor_process)
return;
client = std::make_shared<discordpp::Client>();
client->SetStatusChangedCallback([this](discordpp::Client::Status status, discordpp::Client::Error error, int32_t errorDetail)
{
if (status == discordpp::Client::Status::Ready)
{
emit_signal("connection_ready");
}
if (error != discordpp::Client::Error::None)
{
emit_signal("connection_error", String(discordpp::Client::ErrorToString(error).c_str()));
} });
if (auto_connect)
{
auth();
}
}
void DiscordConnector::_process(double delta)
{
if (!Engine::get_singleton()->is_editor_hint() && !editor_process && client)
{
discordpp::RunCallbacks();
}
}
void DiscordConnector::set_auto_connect(bool value)
{
auto_connect = value;
}
bool DiscordConnector::get_auto_connect()
{
return auto_connect;
}
void DiscordConnector::set_app_id(int64_t value)
{
app_id = static_cast<int64_t>(value);
}
int64_t DiscordConnector::get_app_id()
{
return static_cast<int64_t>(app_id);
}
void DiscordConnector::set_auto_token_manage(bool value)
{
auto_token_manage = value;
}
bool DiscordConnector::get_auto_token_manage()
{
return auto_token_manage;
}
void DiscordConnector::set_auto_encryption_key(String value)
{
auto_encryption_key = value;
}
String DiscordConnector::get_auto_encryption_key()
{
return auto_encryption_key;
}
void DiscordConnector::auth()
{
if (auto_token_manage)
{
if (auto_encryption_key.is_empty())
{
auto_encryption_key = DiscordUtil::get_singleton()->generate_auto_encryption_key();
}
Ref<godot::ConfigFile> config = DiscordUtil::get_singleton()->get_tokens(auto_encryption_key);
if (config->has_section_key("tokens", "access_token") &&
config->has_section_key("tokens", "refresh_token") &&
config->has_section_key("tokens", "expires_in"))
{
access_token = config->get_value("tokens", "access_token");
refresh_token = config->get_value("tokens", "refresh_token");
expires_in = config->get_value("tokens", "expires_in");
token_connect(access_token);
return;
}
else
{
DiscordUtil::get_singleton()->delete_tokens();
}
}
auto codeVerifier = client->CreateAuthorizationCodeVerifier();
discordpp::AuthorizationArgs args{};
args.SetClientId(app_id);
args.SetScopes(discordpp::Client::GetDefaultPresenceScopes());
args.SetCodeChallenge(codeVerifier.Challenge());
// Begin authentication process // TODO: option to open browser
client->Authorize(args, [this, codeVerifier](auto result, auto code, auto redirectUri)
{
if (!result.Successful()) {
emit_signal("authentication_failed", result.Error().c_str());
return;
} else {
client->GetToken(app_id, code, codeVerifier.Verifier(), redirectUri,
[this](discordpp::ClientResult result,
std::string accessToken,
std::string refreshToken,
discordpp::AuthorizationTokenType tokenType,
int32_t expiresIn,
std::string scope) {
if (result.Successful()) {
if (auto_token_manage)
{
DiscordUtil::get_singleton()->save_tokens(accessToken.c_str(), refreshToken.c_str(), expiresIn, auto_encryption_key);
}
} else {
emit_signal("authenticated", result.Error().c_str());
return;
}
token_connect(accessToken.c_str());
});
} });
}
void DiscordConnector::token_connect(String access_token)
{
client->UpdateToken(discordpp::AuthorizationTokenType::Bearer, access_token.utf8().get_data(), [this](discordpp::ClientResult result)
{
if(result.Successful()) {
client->Connect();
} else {
emit_signal("connection_error", result.Error().c_str());
} });
}
void DiscordConnector::token_refresh(String current_refresh_token)
{
client->RefreshToken(std::stoull(refresh_token.utf8().get_data()), refresh_token.utf8().get_data(), [this, current_refresh_token](discordpp::ClientResult result, std::string accessToken, std::string refreshToken, discordpp::AuthorizationTokenType tokenType, int32_t expiresIn, std::string scopes)
{
if (result.Successful())
{
emit_signal("token_refreshed", accessToken.c_str(), refreshToken.c_str(), expiresIn);
if (auto_token_manage)
{
DiscordUtil::get_singleton()->save_tokens(accessToken.c_str(), refreshToken.c_str(), expiresIn, auto_encryption_key);
token_connect(accessToken.c_str());
}
}
else
{
emit_signal("token_refresh_failed", result.Error().c_str());
} });
}

View File

@@ -0,0 +1,42 @@
#ifndef DISCORD_CONNECTOR_H
#define DISCORD_CONNECTOR_H
#include "discord_social_sdk.h"
#include "../util.h"
using namespace godot;
class DiscordConnector : public DiscordSocialSDK
{
GDCLASS(DiscordConnector, DiscordSocialSDK);
protected:
static void _bind_methods();
public:
bool editor_process = false;
std::shared_ptr<discordpp::Client> client;
H_SET_GET(app_id, 0)
H_SET_GET(auto_encryption_key, "")
H_SET_GET(auto_token_manage, true)
H_SET_GET(auto_connect, false)
String access_token;
String refresh_token;
int64_t expires_in;
void auth();
void token_connect(String access_token);
void token_refresh(String refresh_token);
void refresh_auto_encryption_key();
DiscordConnector();
~DiscordConnector();
void _ready() override;
void _process(double delta) override;
};
#endif

Some files were not shown because too many files have changed in this diff Show More