Compare commits
3 Commits
discord-so
...
1.3.1-reup
Author | SHA1 | Date | |
---|---|---|---|
|
249fe68abd | ||
|
852e3b09ea | ||
|
0d25a45a57 |
2
.github/ISSUE_TEMPLATE/BUG.yml
vendored
2
.github/ISSUE_TEMPLATE/BUG.yml
vendored
@@ -21,7 +21,7 @@ body:
|
||||
id: version
|
||||
attributes:
|
||||
label: Version
|
||||
description: What version of the Discord Social SDK Godot plugin are you running?
|
||||
description: What version of the Discord RPC Godot plugin are you running?
|
||||
options:
|
||||
- 1.3.1
|
||||
- 1.3.0
|
||||
|
11
.gitignore
vendored
11
.gitignore
vendored
@@ -22,14 +22,7 @@ build/
|
||||
*.a
|
||||
|
||||
#Clean files from setup.py
|
||||
src/lib/discord_social_sdk/*
|
||||
src/lib/godot-cpp/*
|
||||
discordpp.h
|
||||
cdiscord.h
|
||||
*.zip
|
||||
*.so
|
||||
*.dll
|
||||
*.dylib
|
||||
src/lib/discord_game_sdk/
|
||||
|
||||
# release
|
||||
release/
|
||||
@@ -38,5 +31,3 @@ project/export/
|
||||
# venv
|
||||
venv/
|
||||
|
||||
# docs
|
||||
src/gen/
|
2
.gitmodules
vendored
2
.gitmodules
vendored
@@ -1,4 +1,4 @@
|
||||
[submodule "src/lib/godot-cpp"]
|
||||
path = src/lib/godot-cpp
|
||||
url = https://github.com/godotengine/godot-cpp
|
||||
branch = 4.4
|
||||
branch = 4.1
|
||||
|
3
.vscode/c_cpp_properties.json
vendored
3
.vscode/c_cpp_properties.json
vendored
@@ -7,8 +7,7 @@
|
||||
"${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/discord_social_sdk/include"
|
||||
"${workspaceFolder}/src/lib/godot-cpp/gen/include"
|
||||
],
|
||||
"defines": [
|
||||
"_DEBUG",
|
||||
|
73
.vscode/settings.json
vendored
73
.vscode/settings.json
vendored
@@ -4,79 +4,10 @@
|
||||
"${workspaceFolder}/src/lib/godot-cpp/include"
|
||||
],
|
||||
"files.associations": {
|
||||
"*.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"
|
||||
"*.gdextension": "ini"
|
||||
},
|
||||
"[python]": {
|
||||
"editor.defaultFormatter": "ms-python.black-formatter"
|
||||
},
|
||||
"python.formatting.provider": "none",
|
||||
"cmake.ignoreCMakeListsMissing": true
|
||||
"python.formatting.provider": "none"
|
||||
}
|
17
README.md
17
README.md
@@ -1,4 +1,4 @@
|
||||
<img src="/project/assets/discordgodot_banner.png" alt="Project Banner" />
|
||||
<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>
|
||||
@@ -6,11 +6,11 @@ Discord recently released its new SDK. This plugin will get a huge overhaul and
|
||||
---
|
||||
|
||||
### This is for the Discord Game SDK NOT the Embedded App SDK
|
||||
**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 />
|
||||
**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>
|
||||
<br>
|
||||
### [My Discord Server](https://discord.gg/3gqUrtbaur)
|
||||
# [Quick start :rocket: (click here)](https://docs.vaporvee.com/discord-rpc-godot#quick-start)
|
||||
<br />
|
||||
<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!**
|
||||
|
||||
@@ -21,14 +21,15 @@ Discord recently released its new SDK. This plugin will get a huge overhaul and
|
||||
- User information
|
||||
- Relationship Manager (Get friendlist and its updates)
|
||||
- Overlay management
|
||||
- Editor Presence (optional)
|
||||
- Editor Presence (optional) <br>
|
||||
<br>
|
||||
<img width="600px" src="https://raw.githubusercontent.com/vaporvee/discord-sdk-godot/main/project/assets/GodotEditorPresenceBanner.png">
|
||||
<br />
|
||||
<br>
|
||||
|
||||
<br />
|
||||
<br>
|
||||
|
||||
### Credit
|
||||
[@Pukimaa](https://github.com/pukimaa) - Designer<br>
|
||||
<br />
|
||||
<br>
|
||||
|
||||
*This project is not endorsed or affiliated with Discord Inc. or the Godot Foundation.*
|
||||
|
49
SConstruct
49
SConstruct
@@ -3,26 +3,19 @@ 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_partner_sdk.dylib"
|
||||
discord_library = "libdiscord_game_sdk.dylib"
|
||||
discord_library_second = ""
|
||||
libexportfolder = "/macos/"
|
||||
|
||||
elif env["platform"] in ("linuxbsd", "linux"):
|
||||
discord_library = "libdiscord_partner_sdk.so"
|
||||
discord_library = "libdiscord_game_sdk.so"
|
||||
discord_library_second = ""
|
||||
libexportfolder = "/linux/"
|
||||
|
||||
elif env["platform"] == "windows":
|
||||
discord_library = "discord_partner_sdk.dll"
|
||||
discord_library = "discord_game_sdk.dll"
|
||||
discord_library_second = "discord_game_sdk_x86.dll"
|
||||
libexportfolder = "/windows/"
|
||||
|
||||
if env["target"] == "template_debug":
|
||||
@@ -30,15 +23,26 @@ if env["target"] == "template_debug":
|
||||
else:
|
||||
debugsuffix = ""
|
||||
|
||||
env.Append(LIBPATH=["src/lib/discord_social_sdk/lib/release/"])
|
||||
env.Append(LIBS=["discord_partner_sdk"])
|
||||
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(CPPDEFINES=["HOT_RELOAD_ENABLED"])
|
||||
|
||||
library = env.SharedLibrary(
|
||||
target="project/addons/discord-rpc-gd/bin/"
|
||||
+ libexportfolder
|
||||
+ "discord_partner_sdk_binding"
|
||||
+ "discord_game_sdk_binding"
|
||||
+ armsuffix
|
||||
+ debugsuffix,
|
||||
source=sources,
|
||||
)
|
||||
@@ -46,9 +50,20 @@ env.Depends(
|
||||
library,
|
||||
Command(
|
||||
"project/addons/discord-rpc-gd/bin/" + libexportfolder + discord_library,
|
||||
"src/lib/discord_social_sdk/lib/release/" + 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,
|
||||
Copy("$TARGET", "$SOURCE"),
|
||||
),
|
||||
)
|
||||
|
||||
Default(library)
|
||||
|
4
build.py
4
build.py
@@ -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_partner_sdk_binding_arm64_debug.dylib libdiscord_partner_sdk_binding_debug.dylib -output libdiscord_partner_sdk_binding_debug.dylib"
|
||||
"lipo -create libdiscord_game_sdk_binding_arm64_debug.dylib libdiscord_game_sdk_binding_debug.dylib -output libdiscord_game_sdk_binding_debug.dylib"
|
||||
)
|
||||
os.system(
|
||||
"lipo -create libdiscord_partner_sdk_binding_arm64.dylib libdiscord_partner_sdk_binding.dylib -output libdiscord_partner_sdk_binding.dylib"
|
||||
"lipo -create libdiscord_game_sdk_binding_arm64.dylib libdiscord_game_sdk_binding.dylib -output libdiscord_game_sdk_binding.dylib"
|
||||
)
|
||||
else: # Linux
|
||||
os.system(
|
||||
|
@@ -1,73 +0,0 @@
|
||||
<?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="""">
|
||||
</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>
|
@@ -1,9 +0,0 @@
|
||||
<?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>
|
@@ -1,35 +0,0 @@
|
||||
<?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>
|
@@ -1,9 +0,0 @@
|
||||
<?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>
|
BIN
project/addons/discord-rpc-gd/Logo_V2_No_Bg.png
Normal file
BIN
project/addons/discord-rpc-gd/Logo_V2_No_Bg.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.9 KiB |
34
project/addons/discord-rpc-gd/Logo_V2_No_Bg.png.import
Normal file
34
project/addons/discord-rpc-gd/Logo_V2_No_Bg.png.import
Normal file
@@ -0,0 +1,34 @@
|
||||
[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
|
@@ -1,6 +1,6 @@
|
||||
MINIMUM GODOT VERSION: 4.2
|
||||
|
||||
PLEASE ACTIVATE THE PLUGIN UNDER Project -> Project Settings... -> Plugins -> DiscordUtil -> Status
|
||||
PLEASE ACTIVATE THE PLUGIN UNDER Project -> Project Settings... -> Plugins -> DiscordRPC -> Status
|
||||
IGNORE THE RED ERRORS ON THE FIRST 2 RESTARTS
|
||||
READ THE TUTORIAL LINKED IN THE WINDOW THAT WILL OPEN ON PLUGIN ENABLE
|
||||
|
||||
|
@@ -1,23 +1,29 @@
|
||||
[configuration]
|
||||
|
||||
entry_symbol = "DiscordUtilgd_library_init"
|
||||
entry_symbol = "discordrpcgd_library_init"
|
||||
compatibility_minimum = 4.1
|
||||
|
||||
[libraries]
|
||||
|
||||
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"
|
||||
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"
|
||||
|
||||
[dependencies]
|
||||
|
||||
macos = { "macos/libdiscord_partner_sdk.dylib": "" }
|
||||
windows.x86_64 = { "windows/discord_partner_sdk.dll": "" }
|
||||
linux = { "linux/libdiscord_partner_sdk.so": "" }
|
||||
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": "" }
|
||||
|
@@ -1 +0,0 @@
|
||||
uid://jcdwy5o1utpj
|
BIN
project/addons/discord-rpc-gd/bin/linux/libdiscord_game_sdk.so
Normal file
BIN
project/addons/discord-rpc-gd/bin/linux/libdiscord_game_sdk.so
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
project/addons/discord-rpc-gd/bin/windows/discord_game_sdk.dll
Normal file
BIN
project/addons/discord-rpc-gd/bin/windows/discord_game_sdk.dll
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,8 +1,8 @@
|
||||
class_name DiscordUtilTutorial
|
||||
class_name DiscordRPCTutorial
|
||||
extends Node
|
||||
|
||||
## 1. Put the addons/ folder in your Godot project[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]
|
||||
## 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]
|
||||
## 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
|
||||
## DiscordUtil.app_id = 1099618430065324082
|
||||
## DiscordRPC.app_id = 1099618430065324082
|
||||
## # this is boolean if everything worked
|
||||
## print("Discord working: " + str(DiscordUtil.get_is_discord_working()))
|
||||
## print("Discord working: " + str(DiscordRPC.get_is_discord_working()))
|
||||
## # Set the first custom text row of the activity here
|
||||
## DiscordUtil.details = "A demo activity by vaporvee#1231"
|
||||
## DiscordRPC.details = "A demo activity by vaporvee#1231"
|
||||
## # Set the second custom text row of the activity here
|
||||
## DiscordUtil.state = "Checkpoint 23/23"
|
||||
## DiscordRPC.state = "Checkpoint 23/23"
|
||||
## # Image key for small image from "Art Assets" from the Discord Developer website
|
||||
## DiscordUtil.large_image = "game"
|
||||
## DiscordRPC.large_image = "game"
|
||||
## # Tooltip text for the large image
|
||||
## DiscordUtil.large_image_text = "Try it now!"
|
||||
## DiscordRPC.large_image_text = "Try it now!"
|
||||
## # Image key for large image from "Art Assets" from the Discord Developer website
|
||||
## DiscordUtil.small_image = "boss"
|
||||
## DiscordRPC.small_image = "boss"
|
||||
## # Tooltip text for the small image
|
||||
## DiscordUtil.small_image_text = "Fighting the end boss! D:"
|
||||
## DiscordRPC.small_image_text = "Fighting the end boss! D:"
|
||||
## # "02:41 elapsed" timestamp for the activity
|
||||
## DiscordUtil.start_timestamp = int(Time.get_unix_time_from_system())
|
||||
## DiscordRPC.start_timestamp = int(Time.get_unix_time_from_system())
|
||||
## # "59:59 remaining" timestamp for the activity
|
||||
## DiscordUtil.end_timestamp = int(Time.get_unix_time_from_system()) + 3600
|
||||
## DiscordRPC.end_timestamp = int(Time.get_unix_time_from_system()) + 3600
|
||||
## # Always refresh after changing the values!
|
||||
## DiscordUtil.refresh()
|
||||
## DiscordRPC.refresh()
|
||||
## [/codeblock]
|
||||
##
|
||||
## @tutorial(More information here): https://github.com/vaporvee/discord-rpc-godot/wiki/Quick-start
|
||||
|
@@ -1 +0,0 @@
|
||||
uid://dkv4pruvla8bn
|
@@ -10,8 +10,11 @@ script/source = "extends Node
|
||||
|
||||
@onready var animation_player: AnimationPlayer = $Panel/TextureRect/AnimationPlayer
|
||||
|
||||
func _ready():
|
||||
DiscordRPC.connect(\"activity_join_request\",_on_activity_join_request)
|
||||
|
||||
func _process(_delta) -> void:
|
||||
if(false):
|
||||
if(DiscordRPC.get_is_discord_working()):
|
||||
$Panel/TextureRect.self_modulate = Color(\"#3eff8d\")
|
||||
if !animation_player.is_playing():
|
||||
animation_player.play(\"pulsate\")
|
||||
@@ -45,13 +48,35 @@ Is party public: {ppublic} (needs to be activated in Discord client settings)
|
||||
|
||||
Is instanced: {instanced}
|
||||
\"
|
||||
#$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))
|
||||
$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))
|
||||
|
||||
var user_request: Dictionary = {};
|
||||
|
||||
func _on_activity_join_request(user_requesting: Dictionary) -> void:
|
||||
print(user_requesting)
|
||||
user_request = user_requesting
|
||||
|
||||
func _on_accept_join_request_pressed() -> void:
|
||||
if(!user_request.is_empty()):
|
||||
DiscordRPC.accept_join_request(user_request.id)
|
||||
|
||||
func _on_invite_with_user_id_text_submitted(new_text: String) -> void:
|
||||
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: String) -> void:
|
||||
DiscordRPC.accept_invite(int(new_text))
|
||||
|
||||
func _on_print_current_user_on_console_pressed() -> void:
|
||||
print(DiscordRPC.get_current_user())
|
||||
|
||||
func _on_toggle_sdk_toggled(button_pressed: bool) -> void:
|
||||
if(button_pressed):
|
||||
DiscordRPC.unclear()
|
||||
else:
|
||||
DiscordRPC.clear(false)
|
||||
|
||||
func _on_print_friends_pressed() -> void:
|
||||
print(DiscordRPC.get_all_relationships())
|
||||
"
|
||||
|
||||
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_8abo6"]
|
||||
@@ -90,8 +115,8 @@ tracks/0/keys = {
|
||||
|
||||
[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"]
|
||||
@@ -235,7 +260,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"]
|
||||
|
@@ -1,6 +1,6 @@
|
||||
## This is a Debug Node wich will show some usefull info and buttons/input
|
||||
##
|
||||
## The DiscordUtil Debug Node will show info about the current values of its variables and some buttons to change them.
|
||||
## The DiscordRPC 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
|
||||
|
@@ -1 +0,0 @@
|
||||
uid://46tue7u6crd6
|
13
project/addons/discord-rpc-gd/nodes/discord_autoload.gd
Normal file
13
project/addons/discord-rpc-gd/nodes/discord_autoload.gd
Normal file
@@ -0,0 +1,13 @@
|
||||
## 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()
|
@@ -1,7 +1,7 @@
|
||||
[plugin]
|
||||
|
||||
name="Discord Social SDK"
|
||||
description="Discord Social SDK Plugin for GDScript in Godot"
|
||||
name="DiscordRPC"
|
||||
description="Discord RPC Plugin for GDScript in Godot"
|
||||
author="vaporvee"
|
||||
version="1.3.2"
|
||||
script="plugin.gd"
|
||||
|
@@ -1,42 +1,42 @@
|
||||
@tool
|
||||
extends EditorPlugin
|
||||
|
||||
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()
|
||||
const DiscordRPCDebug: GDScript = preload("res://addons/discord-rpc-gd/nodes/debug.gd")
|
||||
const DiscordRPCDebug_icon: Texture2D = preload("res://addons/discord-rpc-gd/Debug.svg")
|
||||
var loaded_DiscordRPCDebug: DiscordRPCDebug = DiscordRPCDebug.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: String = "/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)
|
||||
|
||||
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("DiscordSocialSDK/EditorPresence/enabled"):
|
||||
get_editor_interface().get_editor_settings().set_setting("DiscordSocialSDK/EditorPresence/enabled",plugin_cfg.get_value("Discord","editor_presence",false))
|
||||
|
||||
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)
|
||||
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))
|
||||
|
||||
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")
|
||||
if get_editor_interface().get_editor_settings().has_setting("DiscordRPC/EditorPresence/enabled"):
|
||||
get_editor_interface().get_editor_settings().erase("DiscordRPC/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("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")
|
||||
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")
|
||||
|
||||
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("DiscordSocialSDK/EditorPresence/enabled"))
|
||||
plugin_cfg.set_value("Discord","editor_presence",get_editor_interface().get_editor_settings().get_setting("DiscordRPC/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("DiscordSocialSDK/EditorPresence/enabled") && get_editor_interface().get_editor_settings().get_setting("DiscordSocialSDK/EditorPresence/enabled"):
|
||||
if get_editor_interface().get_editor_settings().has_setting("DiscordRPC/EditorPresence/enabled") && get_editor_interface().get_editor_settings().get_setting("DiscordRPC/EditorPresence/enabled"):
|
||||
add_child(editor_presence)
|
||||
else:
|
||||
editor_presence.queue_free()
|
||||
|
@@ -1 +0,0 @@
|
||||
uid://citpv7uf0k1ku
|
@@ -9,7 +9,7 @@ Button/styles/focus = SubResource("StyleBoxEmpty_1t7mm")
|
||||
|
||||
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_5vqdt"]
|
||||
|
||||
[sub_resource type="Image" id="Image_4rf8i"]
|
||||
[sub_resource type="Image" id="Image_f4u3i"]
|
||||
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_4rf8i")
|
||||
image = SubResource("Image_f4u3i")
|
||||
|
||||
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_7v0rg"]
|
||||
|
||||
|
@@ -1,16 +0,0 @@
|
||||
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()
|
@@ -1 +0,0 @@
|
||||
uid://kmubk5a6i385
|
@@ -40,7 +40,7 @@ application/file_version=""
|
||||
application/product_version=""
|
||||
application/company_name=""
|
||||
application/product_name=""
|
||||
application/file_description="Discord Social SDK Godot Test"
|
||||
application/file_description="Discord RPC Godot Test"
|
||||
application/copyright=""
|
||||
application/trademarks=""
|
||||
application/export_angle=0
|
||||
|
63
project/main.gd
Normal file
63
project/main.gd
Normal file
@@ -0,0 +1,63 @@
|
||||
extends Node
|
||||
|
||||
func _ready() -> void:
|
||||
if GDExtensionManager.is_extension_loaded("res://addons/discord-rpc-gd/bin/discord-rpc-gd.gdextension"):
|
||||
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: Dictionary) -> void:
|
||||
print(user_requesting)
|
||||
user_request = user_requesting
|
||||
|
||||
func _on_activity_join(secret: String) -> 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: String) -> void:
|
||||
print(secret)
|
||||
|
||||
func _on_relationship_init() -> void:
|
||||
print("initialized")
|
||||
|
||||
func _on_updated_relationship(relationship: Dictionary) -> void:
|
||||
print(relationship)
|
@@ -1,18 +1,11 @@
|
||||
[gd_scene load_steps=5 format=3 uid="uid://dyc3kseph4el7"]
|
||||
[gd_scene load_steps=4 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" 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:"
|
||||
[ext_resource type="Script" path="res://addons/discord-rpc-gd/nodes/debug.gd" id="6_ujijw"]
|
||||
|
||||
[node name="Node" type="Node"]
|
||||
script = ExtResource("1_kl8ri")
|
||||
|
||||
[node name="ColorRect" type="ColorRect" parent="."]
|
||||
anchors_preset = 15
|
||||
@@ -30,7 +23,7 @@ position = Vector2(789, 330.5)
|
||||
scale = Vector2(0.408203, 0.408203)
|
||||
texture = ExtResource("2_gd222")
|
||||
|
||||
[node name="DiscordUtil Test" type="RichTextLabel" parent="."]
|
||||
[node name="DiscordRPC Test" type="RichTextLabel" parent="."]
|
||||
anchors_preset = -1
|
||||
anchor_left = 0.293
|
||||
anchor_top = 0.59
|
||||
@@ -45,28 +38,7 @@ grow_vertical = 2
|
||||
size_flags_horizontal = 4
|
||||
size_flags_vertical = 4
|
||||
bbcode_enabled = true
|
||||
text = "[center][font s=60]DiscordUtil Test"
|
||||
text = "[center][font s=60]DiscordRPC Test"
|
||||
|
||||
[node name="DiscordSocialSDKDebug" type="Node" parent="."]
|
||||
[node name="DiscordRPCDebug" 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"]
|
||||
|
@@ -1,3 +0,0 @@
|
||||
[gd_resource type="ActivityResource" format=3 uid="uid://coryo3jlwiadb"]
|
||||
|
||||
[resource]
|
@@ -1,4 +0,0 @@
|
||||
[gd_resource type="Compositor" format=3 uid="uid://cbg8e12ms0vvc"]
|
||||
|
||||
[resource]
|
||||
compositor_effects = Array[CompositorEffect]([null])
|
1
project/plugin_manager.gd
Normal file
1
project/plugin_manager.gd
Normal file
@@ -0,0 +1 @@
|
||||
extends Node
|
@@ -10,15 +10,19 @@ config_version=5
|
||||
|
||||
[application]
|
||||
|
||||
config/name="GDExtension DiscordUtil Test Project"
|
||||
config/name="GDExtension DiscordRPC Test Project"
|
||||
config/tags=PackedStringArray("vaporvee")
|
||||
run/main_scene="res://main.tscn"
|
||||
config/features=PackedStringArray("4.4")
|
||||
config/features=PackedStringArray("4.3")
|
||||
boot_splash/bg_color=Color(0.25098, 0.305882, 0.929412, 1)
|
||||
boot_splash/fullsize=false
|
||||
boot_splash/image="res://assets/discordgodot_cover.png"
|
||||
boot_splash/fullsize=false
|
||||
config/icon="res://assets/Logo_V2.png"
|
||||
|
||||
[autoload]
|
||||
|
||||
PluginManager="*res://plugin_manager.gd"
|
||||
|
||||
[debug]
|
||||
|
||||
gdscript/warnings/untyped_declaration=1
|
||||
@@ -31,16 +35,11 @@ gdscript/warnings/unsafe_call_argument=1
|
||||
[display]
|
||||
|
||||
window/size/resizable=false
|
||||
display_server/driver.linuxbsd="wayland"
|
||||
|
||||
[dotnet]
|
||||
|
||||
project/assembly_name="GDExtension Test Project"
|
||||
|
||||
[editor_plugins]
|
||||
|
||||
enabled=PackedStringArray("res://addons/discord-rpc-gd/plugin.cfg")
|
||||
|
||||
[filesystem]
|
||||
|
||||
import/blender/enabled=false
|
||||
|
83
setup.py
83
setup.py
@@ -1,44 +1,61 @@
|
||||
import zipfile
|
||||
import os
|
||||
import re
|
||||
from distutils.dir_util import copy_tree
|
||||
import shutil
|
||||
import os
|
||||
import sys
|
||||
import glob
|
||||
|
||||
EXPECTED_VERSION = "1.0.7445"
|
||||
with zipfile.ZipFile("src/lib/discord_game_sdk.zip", "r") as zip_ref:
|
||||
zip_ref.extractall("src/lib/discord_game_sdk/")
|
||||
|
||||
zip_files = glob.glob("src/lib/DiscordSocialSdk-*.zip")
|
||||
if not zip_files:
|
||||
print("Error: No zip file matching 'DiscordSocialSdk-*.zip' found.")
|
||||
sys.exit(1)
|
||||
# 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_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}...")
|
||||
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",
|
||||
)
|
||||
|
||||
# Extract the zip file ignoring the version in the filename
|
||||
with zipfile.ZipFile(zip_path, "r") as zip_ref:
|
||||
zip_ref.extractall("src/lib/")
|
||||
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/")
|
||||
|
||||
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)
|
||||
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")
|
||||
|
||||
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)
|
||||
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")
|
||||
|
||||
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.")
|
||||
|
@@ -1,18 +0,0 @@
|
||||
#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)
|
430
src/discordgodot.cpp
Normal file
430
src/discordgodot.cpp
Normal file
@@ -0,0 +1,430 @@
|
||||
#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;
|
||||
}
|
79
src/discordgodot.h
Normal file
79
src/discordgodot.h
Normal file
@@ -0,0 +1,79 @@
|
||||
#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
|
81
src/editor_presence.cpp
Normal file
81
src/editor_presence.cpp
Normal file
@@ -0,0 +1,81 @@
|
||||
#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)
|
||||
{
|
||||
godot::Node *edited_scene_root = get_tree()->get_edited_scene_root();
|
||||
|
||||
if (edited_scene_root != nullptr)
|
||||
{
|
||||
godot::String scene_path = edited_scene_root->get_scene_file_path();
|
||||
|
||||
if (scene_path.is_empty())
|
||||
{
|
||||
state_string = "Editing: (not saved scene)";
|
||||
}
|
||||
else
|
||||
{
|
||||
state_string = "Editing: \"" + scene_path.replace("res://", "") + "\"";
|
||||
}
|
||||
|
||||
if (state_string.utf8() != activity.GetState())
|
||||
{
|
||||
activity.SetState(state_string.utf8());
|
||||
if (result == discord::Result::Ok)
|
||||
core->ActivityManager().UpdateActivity(activity, [](discord::Result result) {});
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
godot::String default_state = "No Scene Loaded";
|
||||
if (default_state.utf8() != activity.GetState())
|
||||
{
|
||||
activity.SetState(default_state.utf8());
|
||||
if (result == discord::Result::Ok)
|
||||
core->ActivityManager().UpdateActivity(activity, [](discord::Result result) {});
|
||||
}
|
||||
}
|
||||
|
||||
if (result == discord::Result::Ok)
|
||||
core->RunCallbacks();
|
||||
}
|
44
src/editor_presence.h
Normal file
44
src/editor_presence.h
Normal file
@@ -0,0 +1,44 @@
|
||||
#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
|
@@ -1,696 +0,0 @@
|
||||
/* 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);
|
||||
|
BIN
src/lib/discord_game_sdk.zip
Normal file
BIN
src/lib/discord_game_sdk.zip
Normal file
Binary file not shown.
Submodule src/lib/godot-cpp updated: 6388e26dd8...4b63d795e4
@@ -1,70 +0,0 @@
|
||||
#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) {});
|
||||
}
|
@@ -1,39 +0,0 @@
|
||||
#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
|
@@ -1,43 +0,0 @@
|
||||
#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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,31 +0,0 @@
|
||||
#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
|
@@ -1,190 +0,0 @@
|
||||
#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());
|
||||
} });
|
||||
}
|
@@ -1,42 +0,0 @@
|
||||
#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
|
@@ -1,16 +0,0 @@
|
||||
#include "discord_linked_channel.h"
|
||||
|
||||
void DiscordLinkedChannel ::_bind_methods()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
DiscordLinkedChannel::DiscordLinkedChannel ()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
DiscordLinkedChannel::~DiscordLinkedChannel()
|
||||
{
|
||||
|
||||
}
|
@@ -1,20 +0,0 @@
|
||||
#ifndef DISCORD_LINKED_CHANNEL_H
|
||||
#define DISCORD_LINKED_CHANNEL_H
|
||||
|
||||
#include "discord_connected.h"
|
||||
|
||||
using namespace godot;
|
||||
|
||||
class DiscordLinkedChannel : public DiscordConnected
|
||||
{
|
||||
GDCLASS(DiscordLinkedChannel, DiscordConnected);
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
DiscordLinkedChannel();
|
||||
~DiscordLinkedChannel();
|
||||
};
|
||||
|
||||
#endif
|
@@ -1,25 +0,0 @@
|
||||
#include "discord_lobby.h"
|
||||
|
||||
void DiscordLobby ::_bind_methods()
|
||||
{
|
||||
BIND_METHOD(DiscordLobby, create_or_join_lobby, "secret");
|
||||
}
|
||||
|
||||
void DiscordLobby::create_or_join_lobby(String secret)
|
||||
{
|
||||
DiscordLobby::connector->client->CreateOrJoinLobby(secret.utf8().get_data(), [this](discordpp::ClientResult result, uint64_t lobbyId)
|
||||
{
|
||||
if(result.Successful()) {
|
||||
std::cout << "Lobby created or joined successfully! Lobby Id: " << lobbyId << std::endl;
|
||||
} else {
|
||||
UtilityFunctions::print("Failed to create or join lobby: " + String(result.Error().c_str()));
|
||||
} });
|
||||
}
|
||||
|
||||
DiscordLobby::DiscordLobby()
|
||||
{
|
||||
}
|
||||
|
||||
DiscordLobby::~DiscordLobby()
|
||||
{
|
||||
}
|
@@ -1,21 +0,0 @@
|
||||
#ifndef DISCORD_LOBBY_H
|
||||
#define DISCORD_LOBBY_H
|
||||
|
||||
#include "discord_connected.h"
|
||||
|
||||
using namespace godot;
|
||||
|
||||
class DiscordLobby : public DiscordConnected
|
||||
{
|
||||
GDCLASS(DiscordLobby, DiscordConnected);
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
void create_or_join_lobby(String secret);
|
||||
DiscordLobby();
|
||||
~DiscordLobby();
|
||||
};
|
||||
|
||||
#endif
|
@@ -1,12 +0,0 @@
|
||||
#include "discord_social_sdk.h"
|
||||
|
||||
|
||||
void DiscordSocialSDK::_bind_methods()
|
||||
{
|
||||
}
|
||||
DiscordSocialSDK::DiscordSocialSDK()
|
||||
{
|
||||
}
|
||||
DiscordSocialSDK::~DiscordSocialSDK()
|
||||
{
|
||||
}
|
@@ -1,33 +0,0 @@
|
||||
#ifndef DISCORD_SOCIAL_SDK_H
|
||||
#define DISCORD_SOCIAL_SDK_H
|
||||
|
||||
#include "discordpp.h"
|
||||
#include "../definitions.h"
|
||||
|
||||
#include <stdio.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>
|
||||
#include <godot_cpp/core/class_db.hpp>
|
||||
#include <godot_cpp/variant/utility_functions.hpp>
|
||||
#include <godot_cpp/classes/scene_tree.hpp>
|
||||
|
||||
using namespace godot;
|
||||
|
||||
class DiscordSocialSDK : public Node
|
||||
{
|
||||
GDCLASS(DiscordSocialSDK, Node);
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
|
||||
DiscordSocialSDK();
|
||||
~DiscordSocialSDK();
|
||||
};
|
||||
|
||||
#endif
|
@@ -1,40 +0,0 @@
|
||||
#include "editor_presence.h"
|
||||
|
||||
void EditorPresence::_bind_methods()
|
||||
{
|
||||
}
|
||||
EditorPresence::EditorPresence()
|
||||
{
|
||||
}
|
||||
EditorPresence::~EditorPresence()
|
||||
{
|
||||
}
|
||||
|
||||
void EditorPresence::_ready()
|
||||
{
|
||||
if (project_settings->has_setting("application/config/name"))
|
||||
{
|
||||
//activity.GetAssets().SetLargeImage("godot");
|
||||
return;
|
||||
}
|
||||
/*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();*/
|
||||
return;
|
||||
}
|
@@ -1,28 +0,0 @@
|
||||
#ifndef EDITOR_PRESENCE_H
|
||||
#define EDITOR_PRESENCE_H
|
||||
|
||||
#include "discord_social_sdk.h"
|
||||
|
||||
using namespace godot;
|
||||
|
||||
class EditorPresence : public DiscordSocialSDK
|
||||
{
|
||||
GDCLASS(EditorPresence, DiscordSocialSDK);
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
godot::Engine *engine = godot::Engine::get_singleton();
|
||||
godot::ProjectSettings *project_settings = godot::ProjectSettings::get_singleton();
|
||||
godot::Time *time = godot::Time::get_singleton();
|
||||
|
||||
String state_string;
|
||||
|
||||
EditorPresence();
|
||||
~EditorPresence();
|
||||
void _ready() override;
|
||||
void _process(double delta) override;
|
||||
};
|
||||
|
||||
#endif
|
@@ -1,45 +1,45 @@
|
||||
#include "register_types.h"
|
||||
|
||||
#include <gdextension_interface.h>
|
||||
#include <godot_cpp/core/class_db.hpp>
|
||||
#include <godot_cpp/core/defs.hpp>
|
||||
#include <godot_cpp/classes/engine.hpp>
|
||||
#include <godot_cpp/godot.hpp>
|
||||
|
||||
#include "discordgodot.h"
|
||||
#include "editor_presence.h"
|
||||
using namespace godot;
|
||||
|
||||
static DiscordUtil *discordutil;
|
||||
static DiscordRPC *discordrpc;
|
||||
|
||||
void initialize_DiscordUtil_module(ModuleInitializationLevel p_level)
|
||||
void initialize_discordrpc_module(ModuleInitializationLevel p_level)
|
||||
{
|
||||
if (p_level == MODULE_INITIALIZATION_LEVEL_SCENE)
|
||||
{
|
||||
ClassDB::register_abstract_class<DiscordSocialSDK>();
|
||||
ClassDB::register_class<DiscordUtil>();
|
||||
discordutil = memnew(DiscordUtil);
|
||||
Engine::get_singleton()->register_singleton("DiscordUtil", DiscordUtil::get_singleton());
|
||||
ClassDB::register_class<DiscordRPC>();
|
||||
discordrpc = memnew(DiscordRPC);
|
||||
Engine::get_singleton()->register_singleton("DiscordRPC", DiscordRPC::get_singleton());
|
||||
ClassDB::register_class<EditorPresence>();
|
||||
ClassDB::register_class<DiscordConnector>();
|
||||
ClassDB::register_abstract_class<DiscordConnected>();
|
||||
ClassDB::register_class<DiscordLobby>();
|
||||
ClassDB::register_class<DiscordLinkedChannel>();
|
||||
ClassDB::register_class<DiscordActivity>();
|
||||
ClassDB::register_class<RichPresence>();
|
||||
ClassDB::register_class<PartyInvite>();
|
||||
}
|
||||
}
|
||||
|
||||
void uninitialize_DiscordUtil_module(ModuleInitializationLevel p_level)
|
||||
void uninitialize_discordrpc_module(ModuleInitializationLevel p_level)
|
||||
{
|
||||
if (p_level == MODULE_INITIALIZATION_LEVEL_SCENE)
|
||||
{
|
||||
Engine::get_singleton()->unregister_singleton("DiscordUtil");
|
||||
memdelete(discordutil);
|
||||
Engine::get_singleton()->unregister_singleton("DiscordRPC");
|
||||
memdelete(discordrpc);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C"
|
||||
{
|
||||
GDExtensionBool GDE_EXPORT DiscordUtilgd_library_init(GDExtensionInterfaceGetProcAddress p_get_proc_address, GDExtensionClassLibraryPtr p_library, GDExtensionInitialization *r_initialization)
|
||||
GDExtensionBool GDE_EXPORT discordrpcgd_library_init(GDExtensionInterfaceGetProcAddress p_get_proc_address, GDExtensionClassLibraryPtr p_library, GDExtensionInitialization *r_initialization)
|
||||
{
|
||||
godot::GDExtensionBinding::InitObject init_obj(p_get_proc_address, p_library, r_initialization);
|
||||
|
||||
init_obj.register_initializer(initialize_DiscordUtil_module);
|
||||
init_obj.register_terminator(uninitialize_DiscordUtil_module);
|
||||
init_obj.register_initializer(initialize_discordrpc_module);
|
||||
init_obj.register_terminator(uninitialize_discordrpc_module);
|
||||
init_obj.set_minimum_library_initialization_level(MODULE_INITIALIZATION_LEVEL_SCENE);
|
||||
|
||||
return init_obj.init();
|
||||
|
@@ -1,26 +1,7 @@
|
||||
#ifndef REGISTER_TYPES_H
|
||||
#define REGISTER_TYPES_H
|
||||
|
||||
#define DISCORDPP_IMPLEMENTATION // this is way too important to forget
|
||||
|
||||
void initialize_DiscordUtil_module();
|
||||
void uninitialize_DiscordUtil_module();
|
||||
|
||||
#include <gdextension_interface.h>
|
||||
#include <godot_cpp/core/class_db.hpp>
|
||||
#include <godot_cpp/core/defs.hpp>
|
||||
#include <godot_cpp/classes/engine.hpp>
|
||||
#include <godot_cpp/godot.hpp>
|
||||
|
||||
#include "util.h"
|
||||
#include "nodes/discord_social_sdk.h"
|
||||
#include "nodes/editor_presence.h"
|
||||
#include "nodes/discord_connector.h"
|
||||
#include "nodes/discord_connected.h"
|
||||
#include "nodes/discord_lobby.h"
|
||||
#include "nodes/discord_linked_channel.h"
|
||||
#include "nodes/discord_activity.h"
|
||||
#include "resources/rich_presence.h"
|
||||
#include "resources/party_invite.h"
|
||||
void initialize_discordrpc_module();
|
||||
void uninitialize_discordrpc_module();
|
||||
|
||||
#endif // REGISTER_TYPES_H
|
@@ -1,76 +0,0 @@
|
||||
#include "party_invite.h"
|
||||
|
||||
void PartyInvite::_bind_methods()
|
||||
{
|
||||
BIND_SET_GET(PartyInvite, id, Variant::STRING);
|
||||
BIND_SET_GET(PartyInvite, current_size, Variant::INT);
|
||||
BIND_SET_GET(PartyInvite, max_size, Variant::INT);
|
||||
BIND_SET_GET(PartyInvite, join_secret, Variant::STRING);
|
||||
BIND_SET_GET(PartyInvite, instanced, Variant::BOOL);
|
||||
BIND_SET_GET(PartyInvite, is_public_party, Variant::BOOL);
|
||||
}
|
||||
|
||||
PartyInvite::PartyInvite()
|
||||
{
|
||||
}
|
||||
|
||||
String PartyInvite::get_id()
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
||||
void PartyInvite::set_id(String value)
|
||||
{
|
||||
id = value;
|
||||
}
|
||||
|
||||
int64_t PartyInvite::get_current_size()
|
||||
{
|
||||
return current_size;
|
||||
}
|
||||
|
||||
void PartyInvite::set_current_size(int64_t value)
|
||||
{
|
||||
current_size = value;
|
||||
}
|
||||
|
||||
int64_t PartyInvite::get_max_size()
|
||||
{
|
||||
return max_size;
|
||||
}
|
||||
|
||||
void PartyInvite::set_max_size(int64_t value)
|
||||
{
|
||||
max_size = value;
|
||||
}
|
||||
|
||||
String PartyInvite::get_join_secret()
|
||||
{
|
||||
return join_secret;
|
||||
}
|
||||
|
||||
void PartyInvite::set_join_secret(String value)
|
||||
{
|
||||
join_secret = value;
|
||||
}
|
||||
|
||||
bool PartyInvite::get_instanced()
|
||||
{
|
||||
return instanced;
|
||||
}
|
||||
|
||||
void PartyInvite::set_instanced(bool value)
|
||||
{
|
||||
instanced = value;
|
||||
}
|
||||
|
||||
bool PartyInvite::get_is_public_party()
|
||||
{
|
||||
return is_public_party;
|
||||
}
|
||||
|
||||
void PartyInvite::set_is_public_party(bool value)
|
||||
{
|
||||
is_public_party = value;
|
||||
}
|
||||
|
@@ -1,29 +0,0 @@
|
||||
#ifndef PARTY_INVITE_H
|
||||
#define PARTY_INVITE_H
|
||||
|
||||
#include <godot_cpp/core/class_db.hpp>
|
||||
#include <godot_cpp/core/defs.hpp>
|
||||
#include <godot_cpp/godot.hpp>
|
||||
#include <godot_cpp/classes/resource.hpp>
|
||||
#include "../util.h"
|
||||
|
||||
using namespace godot;
|
||||
|
||||
class PartyInvite : public Resource {
|
||||
GDCLASS(PartyInvite, Resource);
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
H_SET_GET(id, "")
|
||||
H_SET_GET(current_size, 1)
|
||||
H_SET_GET(max_size, 4)
|
||||
H_SET_GET(join_secret, "")
|
||||
H_SET_GET(instanced, false)
|
||||
H_SET_GET(is_public_party, false)
|
||||
|
||||
PartyInvite();
|
||||
};
|
||||
|
||||
#endif
|
@@ -1,95 +0,0 @@
|
||||
#include "rich_presence.h"
|
||||
|
||||
void RichPresence::_bind_methods()
|
||||
{
|
||||
BIND_SET_GET(RichPresence, details, Variant::STRING);
|
||||
BIND_SET_GET(RichPresence, state, Variant::STRING);
|
||||
ADD_GROUP("Large Image", "large_");
|
||||
BIND_SET_GET(RichPresence, large_image, Variant::STRING);
|
||||
BIND_SET_GET(RichPresence, large_text, Variant::STRING);
|
||||
ADD_GROUP("Small Image", "small_");
|
||||
BIND_SET_GET(RichPresence, small_image, Variant::STRING);
|
||||
BIND_SET_GET(RichPresence, small_text, Variant::STRING);
|
||||
}
|
||||
|
||||
RichPresence::RichPresence() {}
|
||||
|
||||
void RichPresence::set_details(String value)
|
||||
{
|
||||
details = value;
|
||||
}
|
||||
|
||||
String RichPresence::get_details()
|
||||
{
|
||||
return details;
|
||||
}
|
||||
|
||||
void RichPresence::set_state(String value)
|
||||
{
|
||||
state = value;
|
||||
}
|
||||
|
||||
String RichPresence::get_state()
|
||||
{
|
||||
return state;
|
||||
}
|
||||
|
||||
void RichPresence::set_large_image(String value)
|
||||
{
|
||||
large_image = value;
|
||||
}
|
||||
|
||||
String RichPresence::get_large_image()
|
||||
{
|
||||
return large_image;
|
||||
}
|
||||
|
||||
void RichPresence::set_large_text(String value)
|
||||
{
|
||||
large_text = value;
|
||||
}
|
||||
|
||||
String RichPresence::get_large_text()
|
||||
{
|
||||
return large_text;
|
||||
}
|
||||
|
||||
void RichPresence::set_small_image(String value)
|
||||
{
|
||||
small_image = value;
|
||||
}
|
||||
|
||||
String RichPresence::get_small_image()
|
||||
{
|
||||
return small_image;
|
||||
}
|
||||
|
||||
void RichPresence::set_small_text(String value)
|
||||
{
|
||||
small_text = value;
|
||||
}
|
||||
|
||||
String RichPresence::get_small_text()
|
||||
{
|
||||
return small_text;
|
||||
}
|
||||
|
||||
void RichPresence::set_timestamps_start(int64_t value)
|
||||
{
|
||||
timestamps_start = value;
|
||||
}
|
||||
|
||||
int64_t RichPresence::get_timestamps_start()
|
||||
{
|
||||
return timestamps_start;
|
||||
}
|
||||
|
||||
void RichPresence::set_timestamps_end(int64_t value)
|
||||
{
|
||||
timestamps_end = value;
|
||||
}
|
||||
|
||||
int64_t RichPresence::get_timestamps_end()
|
||||
{
|
||||
return timestamps_end;
|
||||
}
|
@@ -1,32 +0,0 @@
|
||||
#ifndef RICH_PRESENCE_H
|
||||
#define RICH_PRESENCE_H
|
||||
|
||||
#include <godot_cpp/core/class_db.hpp>
|
||||
#include <godot_cpp/core/defs.hpp>
|
||||
#include <godot_cpp/godot.hpp>
|
||||
#include <godot_cpp/classes/resource.hpp>
|
||||
#include "../util.h"
|
||||
|
||||
using namespace godot;
|
||||
|
||||
class RichPresence : public Resource
|
||||
{
|
||||
GDCLASS(RichPresence, Resource);
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
H_SET_GET(details, "")
|
||||
H_SET_GET(state, "")
|
||||
H_SET_GET(large_image, "")
|
||||
H_SET_GET(large_text, "")
|
||||
H_SET_GET(small_image, "")
|
||||
H_SET_GET(small_text, "")
|
||||
H_SET_GET(timestamps_start, 0)
|
||||
H_SET_GET(timestamps_end, 0)
|
||||
|
||||
RichPresence();
|
||||
};
|
||||
|
||||
#endif
|
243
src/util.cpp
243
src/util.cpp
@@ -1,243 +0,0 @@
|
||||
#include "util.h"
|
||||
|
||||
DiscordUtil *DiscordUtil::singleton = nullptr;
|
||||
|
||||
void DiscordUtil::_bind_methods()
|
||||
{
|
||||
BIND_METHOD(DiscordUtil, debug);
|
||||
BIND_METHOD(DiscordUtil, run_callbacks);
|
||||
BIND_METHOD(DiscordUtil, save_tokens, "access_token", "refresh_token", "expires_in", "auto_encryption_key");
|
||||
BIND_METHOD(DiscordUtil, generate_auto_encryption_key);
|
||||
}
|
||||
|
||||
DiscordUtil::DiscordUtil()
|
||||
{
|
||||
ERR_FAIL_COND(singleton != nullptr);
|
||||
singleton = this;
|
||||
}
|
||||
|
||||
DiscordUtil::~DiscordUtil()
|
||||
{
|
||||
ERR_FAIL_COND(singleton != this);
|
||||
singleton = nullptr;
|
||||
}
|
||||
|
||||
DiscordUtil *DiscordUtil::get_singleton()
|
||||
{
|
||||
return singleton;
|
||||
}
|
||||
|
||||
void DiscordUtil::run_callbacks()
|
||||
{
|
||||
discordpp::RunCallbacks();
|
||||
}
|
||||
void DiscordUtil::debug()
|
||||
{
|
||||
auto client = std::make_shared<discordpp::Client>();
|
||||
|
||||
client->AddLogCallback([](auto message, auto severity)
|
||||
{ UtilityFunctions::print("[" + String(EnumToString(severity)) + "] " + message.c_str()); }, discordpp::LoggingSeverity::Info);
|
||||
|
||||
client->SetStatusChangedCallback([client](discordpp::Client::Status status, discordpp::Client::Error error, int32_t errorDetail)
|
||||
{
|
||||
UtilityFunctions::print(String("Status changed: ") + discordpp::Client::StatusToString(status).c_str());
|
||||
if (status == discordpp::Client::Status::Ready) {
|
||||
UtilityFunctions::print("Client is ready!\n");
|
||||
UtilityFunctions::print("Friends Count: " + String::num_int64(client->GetRelationships().size()));
|
||||
discordpp::Activity activity;
|
||||
activity.SetType(discordpp::ActivityTypes::Playing);
|
||||
activity.SetState("Debug mode");
|
||||
activity.SetDetails("Godot -> Discord Social SDK");
|
||||
discordpp::ActivityAssets assets;
|
||||
assets.SetSmallImage("boss");
|
||||
assets.SetSmallText("Fighting the boss D:");
|
||||
assets.SetLargeImage("example_game");
|
||||
assets.SetLargeText("Example");
|
||||
activity.SetAssets(assets);
|
||||
|
||||
// Update rich presence
|
||||
client->UpdateRichPresence(activity, [](discordpp::ClientResult result) {
|
||||
if(result.Successful()) {
|
||||
UtilityFunctions::print("Rich Presence updated successfully!");
|
||||
} else {
|
||||
UtilityFunctions::push_error("Rich Presence update failed");
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
} else if (error != discordpp::Client::Error::None) {
|
||||
UtilityFunctions::push_error("Connection Error: " + String(discordpp::Client::ErrorToString(error).c_str()) + " - Details: " + String::num_int64(errorDetail));
|
||||
} });
|
||||
|
||||
// Generate OAuth2 code verifier for authentication
|
||||
UtilityFunctions::print("Trying to authenticate...");
|
||||
UtilityFunctions::print("Generating code verifier...");
|
||||
auto codeVerifier = client->CreateAuthorizationCodeVerifier();
|
||||
|
||||
// Set up authentication arguments
|
||||
discordpp::AuthorizationArgs args{};
|
||||
args.SetClientId(1099618430065324082);
|
||||
args.SetScopes(discordpp::Client::GetDefaultPresenceScopes());
|
||||
args.SetCodeChallenge(codeVerifier.Challenge());
|
||||
|
||||
// Begin authentication process // TODO: option to open browser
|
||||
client->Authorize(args, [client, codeVerifier](auto result, auto code, auto redirectUri)
|
||||
{
|
||||
if (!result.Successful()) {
|
||||
UtilityFunctions::push_error("Authentication Error: " + String(result.Error().c_str()));
|
||||
return;
|
||||
} else {
|
||||
UtilityFunctions::print("Authorization successful! Getting access token...");
|
||||
|
||||
client->GetToken(1099618430065324082, code, codeVerifier.Verifier(), redirectUri,
|
||||
[client](discordpp::ClientResult result,
|
||||
std::string accessToken, // needs to be stored securely
|
||||
std::string refreshToken, // needs to be stored securely
|
||||
discordpp::AuthorizationTokenType tokenType,
|
||||
int32_t expiresIn,
|
||||
std::string scope) {
|
||||
UtilityFunctions::print("Access token received! Establishing connection...");
|
||||
client->UpdateToken(discordpp::AuthorizationTokenType::Bearer, accessToken, [client](discordpp::ClientResult result) {
|
||||
if(result.Successful()) {
|
||||
UtilityFunctions::print("Token updated, connecting to Discord...");
|
||||
client->Connect();
|
||||
} else {
|
||||
UtilityFunctions::push_error("Token update error: " + String(result.Error().c_str()));
|
||||
}
|
||||
});
|
||||
});
|
||||
} });
|
||||
}
|
||||
|
||||
Dictionary DiscordUtil::user2dict(discordpp::UserHandle 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 DiscordUtil::relationship2dict(discordpp::RelationshipHandle 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 discordpp::RelationshipType::None:
|
||||
dict_relationship["type"] = "None";
|
||||
break;
|
||||
case discordpp::RelationshipType::Friend:
|
||||
dict_relationship["type"] = "Friend";
|
||||
break;
|
||||
case discordpp::RelationshipType::Blocked:
|
||||
dict_relationship["type"] = "Blocked";
|
||||
break;
|
||||
case discordpp::RelationshipType::PendingIncoming:
|
||||
dict_relationship["type"] = "PendingIncoming";
|
||||
break;
|
||||
case discordpp::RelationshipType::PendingOutgoing:
|
||||
dict_relationship["type"] = "PendingOutgoing";
|
||||
break;
|
||||
case discordpp::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;
|
||||
}
|
||||
|
||||
String DiscordUtil::generate_auto_encryption_key()
|
||||
{
|
||||
const char *charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!\"$%&/()=?*+#-.,;:_'";
|
||||
String key;
|
||||
for (int i = 0; i < 50; i++)
|
||||
{
|
||||
key += charset[rand() % strlen(charset)];
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
void DiscordUtil::save_tokens(String access_token, String refresh_token, int64_t expires_in, String auto_encryption_key)
|
||||
{
|
||||
Ref<ConfigFile> config;
|
||||
config.instantiate();
|
||||
config->set_value("tokens", "access_token", access_token);
|
||||
config->set_value("tokens", "refresh_token", refresh_token);
|
||||
config->set_value("tokens", "expires_in", expires_in);
|
||||
config->save_encrypted_pass("user://discord_data.binary", auto_encryption_key);
|
||||
}
|
||||
|
||||
void DiscordUtil::delete_tokens()
|
||||
{
|
||||
Ref<ConfigFile> config;
|
||||
config.instantiate();
|
||||
config->save("user://discord_data.binary");
|
||||
}
|
||||
|
||||
Ref<ConfigFile> DiscordUtil::get_tokens(String auto_encryption_key)
|
||||
{
|
||||
Ref<ConfigFile> config;
|
||||
config.instantiate();
|
||||
if (!FileAccess::file_exists("user://discord_data.binary"))
|
||||
{
|
||||
return config;
|
||||
}
|
||||
Error err = config->load_encrypted_pass("user://discord_data.binary", auto_encryption_key);
|
||||
if (err != OK)
|
||||
{
|
||||
config->save("user://discord_data.binary");
|
||||
return config;
|
||||
}
|
||||
return config;
|
||||
}
|
44
src/util.h
44
src/util.h
@@ -1,44 +0,0 @@
|
||||
#ifndef DISCORDGODOT_H
|
||||
#define DISCORDGODOT_H
|
||||
|
||||
#include "definitions.h"
|
||||
#include "discordpp.h"
|
||||
#include <stdio.h>
|
||||
#include <godot_cpp/classes/object.hpp>
|
||||
#include <godot_cpp/core/class_db.hpp>
|
||||
#include <godot_cpp/core/class_db.hpp>
|
||||
#include <godot_cpp/variant/utility_functions.hpp>
|
||||
#include <godot_cpp/classes/config_file.hpp>
|
||||
#include <godot_cpp/classes/file_access.hpp>
|
||||
|
||||
using namespace godot;
|
||||
|
||||
class DiscordUtil : public Object
|
||||
{
|
||||
GDCLASS(DiscordUtil, Object);
|
||||
|
||||
static DiscordUtil *singleton;
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
static DiscordUtil *
|
||||
get_singleton();
|
||||
|
||||
DiscordUtil();
|
||||
~DiscordUtil();
|
||||
|
||||
Dictionary relationship2dict(discordpp::RelationshipHandle relationship);
|
||||
Dictionary user2dict(discordpp::UserHandle user);
|
||||
|
||||
void save_tokens(String access_token, String refresh_token, int64_t expires_in, String auto_encryption_key);
|
||||
String generate_auto_encryption_key();
|
||||
void delete_tokens();
|
||||
Ref<ConfigFile> get_tokens(String auto_encryption_key);
|
||||
|
||||
void debug();
|
||||
void run_callbacks();
|
||||
};
|
||||
|
||||
#endif
|
@@ -1,9 +0,0 @@
|
||||
short_name = "discord-sdk-godot"
|
||||
name = "Discord Social SDK for Godot"
|
||||
major = 2
|
||||
minor = 0
|
||||
patch = 0
|
||||
status = "dev"
|
||||
module_config = ""
|
||||
website = "https://docs.vaporvee.com/"
|
||||
docs = "latest"
|
Reference in New Issue
Block a user