Skip to content

Commit

Permalink
Changed Discord RPC Addon (not working)
Browse files Browse the repository at this point in the history
  • Loading branch information
Killarexe committed Aug 19, 2023
1 parent f7c897e commit ba111a1
Show file tree
Hide file tree
Showing 61 changed files with 1,222 additions and 1,059 deletions.
716 changes: 716 additions & 0 deletions addons/discord-rpc/DiscordRPC.gd

Large diffs are not rendered by default.

145 changes: 145 additions & 0 deletions addons/discord-rpc/DiscordRPCConnection.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
class_name DiscordRPCConnection

signal payload_received(payload: Payload)

const SOCKET_NAME: String = "discord-ipc-%d"

func get_possible_paths() -> Array[String]:
return []

func open(_path: String) -> int:
return ERR_UNAVAILABLE

func read() -> Array:
return [-1, PackedByteArray()]

func write(_bytes: PackedByteArray) -> int:
return ERR_UNAVAILABLE

func is_open() -> bool:
return false

func has_payload() -> bool:
return false

func close() -> void:
pass

func post(request: Payload) -> int:
var error: int = write(request.to_bytes()) if is_open() else ERR_UNCONFIGURED
if error != OK:
push_error("DiscordRPC: Write error: ", error)
return error

func scan() -> Payload:
if not is_open():
push_error("DiscordRPC: Can not recieve payloads while disconnected")
return null

var data: Array = read()
var opcode: int = data[0]
var buffer: PackedByteArray = data[1]

var body: Dictionary = JSON.parse_string(buffer.get_string_from_utf8())

var response: Payload = Payload.new()
response.opcode = opcode
response.nonce = body["nonce"] if body.get("nonce") else ""
response.command = body["cmd"] if body.get("cmd") else ""
response.event = body["evt"] if body.get("evt") else ""
response.data = body["data"] if body.get("data") is Dictionary else body
response.arguments = body["args"] if body.get("args") is Dictionary else {}

return response

func send(request: Payload) -> Payload:
if not is_open():
push_error("DiscordRPC: Can not send payloads while disconnected")
return null

var opcode: int = request.opcode
var nonce: String = request.nonce

if post(request) != OK:
return null

var response: Payload = null
while not response:
var payload: Payload = await payload_received
if opcode == Payload.OpCodes.HANDSHAKE:
response = payload
elif payload.nonce == nonce:
response = payload

if response.is_error():
push_error("DiscordRPC: ", response.get_error_messsage())

return response

func poll() -> void:
if has_payload():
var payload: Payload = scan()
if payload:
payload_received.emit(payload)

class Payload:
enum OpCodes {
HANDSHAKE,
FRAME,
CLOSE,
PING,
PONG
}

var opcode: int = OpCodes.PING
var nonce: String
var command: String
var event: String
var data: Dictionary
var arguments: Dictionary

func _init() -> void:
generate_nonce()

func generate_nonce() -> void:
nonce = Marshalls.raw_to_base64(Crypto.new().generate_random_bytes(12))

func is_event_dispatch() -> bool:
return command == DiscordRPC.Commands.DISPATCH

func is_error() -> bool:
return event == DiscordRPC.Events.ERROR or data.has_all(["code", "message"])

func is_close_request() -> bool:
return opcode == OpCodes.CLOSE

func get_error_code() -> int:
return data["code"] if is_error() else OK

func get_error_messsage() -> String:
return data["message"] if is_error() else ""

func to_dict() -> Dictionary:
return {
nonce = self.nonce,
cmd = self.command,
# warning-ignore:incompatible_ternary
evt = self.event if not event.is_empty() else null,
data = self.data,
args = self.arguments
}

func to_bytes() -> PackedByteArray:
var buffer: PackedByteArray = JSON.stringify(to_dict()).to_utf8_buffer()
var stream: StreamPeerBuffer = StreamPeerBuffer.new()

stream.put_32(opcode)
stream.put_32(buffer.size())
# warning-ignore:return_value_discarded
stream.put_data(buffer)

return stream.data_array

func _to_string() -> String:
return "[Payload:%d:opcode=%d]" % [get_instance_id(), opcode]

92 changes: 92 additions & 0 deletions addons/discord-rpc/DiscordRPCUnix.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
class_name DiscordRPCUnix extends DiscordRPCConnection

# Discord Flatpak sub path
const FLATPAK: String = "/app/com.discordapp.Discord"

# Discord Snap sub path
const SNAP: String = "/snap.discord"

var stream: StreamPeer # StreamPeerUnix

func _init() -> void:
var script: Script = get_script()
if not script.has_meta("LIBUNIXSOCKET"):
var library: GDExtension = GDExtension.new()
var os: String = OS.get_name()
var library_path: String = "./addons/unix-socket"
library_path = library_path.path_join("libunixsocket.%s.%s.%s.%s")
library_path = library_path % [
os.to_lower(),
"debug" if OS.is_debug_build() else "release",
_get_architecture(),
"dylib" if os == "macOS" else "so"
]
var start: int = Time.get_ticks_msec()
if library.open_library(library_path, "unixsocket_library_init") == OK:
start = Time.get_ticks_msec()
var level: int = library.get_minimum_library_initialization_level()
library.initialize_library(level)
script.set_meta("LIBUNIXSOCKET", library)
else:
push_error("Failed loading native library: ", library_path)

func get_possible_paths() -> Array[String]:
var path: String

for env in ["XDG_RUNTIME_DIR", "TMPDIR", "TMP", "TEMP"]:
if OS.has_environment(env):
path = OS.get_environment(env)
break

if path.is_empty():
path = "/tmp/"

path += "{0}".path_join(SOCKET_NAME)

return [path.format([""]), path.format([FLATPAK]), path.format([SNAP])]

func open(path: String) -> int:
if is_open():
return ERR_ALREADY_IN_USE

stream = ClassDB.instantiate("StreamPeerUnix")
return stream.open(path)

func read() -> Array:
if not is_open():
return [-1, PackedByteArray()]

var opcode: int = stream.get_32()
var length: int = stream.get_32()
var buffer: PackedByteArray = stream.get_data(length)[1]

return [opcode, buffer]

func write(bytes: PackedByteArray) -> int:
return stream.put_data(bytes) if is_open() else ERR_UNCONFIGURED

func is_open() -> bool:
return stream and stream.is_open()

func has_payload() -> bool:
return is_open() and stream.get_available_bytes() > 0

func close() -> void:
if is_open():
stream.close()
stream = null

func _to_string() -> String:
return "[DiscordRPCUnix:%d]" % get_instance_id()

static func _get_architecture() -> String:
var arch: String
if OS.get_name() == "macOS":
arch = "universal"
else:
for possible_arch in ["x86_32", "x86_64", "arm32", "arm64"]:
if OS.has_feature(possible_arch):
arch = possible_arch
break
return arch

44 changes: 44 additions & 0 deletions addons/discord-rpc/DiscordRPCWindows.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
class_name DiscordRPCWindows extends DiscordRPCConnection

var file: FileAccess

func get_possible_paths() -> Array[String]:
return ["\\\\?\\pipe\\" + SOCKET_NAME]

func open(path: String) -> int:
if is_open():
return ERR_ALREADY_IN_USE

file = FileAccess.open(path, FileAccess.READ_WRITE)
return FileAccess.get_open_error()

func read() -> Array:
if not is_open():
return [-1, PackedByteArray()]

var opcode: int = file.get_32()
var length: int = file.get_32()
var buffer: PackedByteArray = file.get_buffer(length)

return [opcode, buffer]

func write(bytes: PackedByteArray) -> int:
if is_open():
file.store_buffer(bytes)
return file.get_error()
return ERR_UNCONFIGURED

func is_open() -> bool:
return file and file.is_open()

func has_payload() -> bool:
return is_open() and file.get_length() > 0

func close() -> void:
if is_open():
file.close()
file = null

func _to_string() -> String:
return "[DiscordRPCWindows:%d]" % get_instance_id()

103 changes: 103 additions & 0 deletions addons/discord-rpc/util/RichPresenceBuilder.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
class_name RichPresenceBuilder

var activity: Dictionary = {
timestamps = {},
assets = {},
party = {}
}

## Sets the activity description.
func with_details(details: String) -> RichPresenceBuilder:
activity["details"] = details
return self

## Sets the user's current party status.
func with_state(state: String) -> RichPresenceBuilder:
activity["state"] = state
return self

## Sets the Unix time in milliseconds of when the activity started.
func start_timestamp(timestamp: int) -> RichPresenceBuilder:
activity["timestamps"]["start"] = timestamp
return self

## Sets the Unix time in milliseconds of when the activity ended.
func end_timestamp(timestamp: int) -> RichPresenceBuilder:
activity["timestamps"]["end"] = timestamp
return self

## Sets the large image, can either be an application asset key or a URL.
func with_large_image(image: String) -> RichPresenceBuilder:
activity["assets"]["large_image"] = image
return self

## Sets the large image text.
func with_large_text(text: String) -> RichPresenceBuilder:
activity["assets"]["large_text"] = text
return self

## Sets the small image, can either be an application asset key or a URL.
func with_small_image(image: String) -> RichPresenceBuilder:
activity["assets"]["small_image"] = image
return self

## Sets the large image text.
func with_small_text(text: String) -> RichPresenceBuilder:
activity["assets"]["small_text"] = text
return self

## Sets information for the current party of the player.
## [code]id[/code] is the ID of the party.
## [code]size[/code] is the current party size.
## [code]max_size[/code] is the maxium size of the party.
func with_party(
id: String, size: int = 0, max_size: int = 0
) -> RichPresenceBuilder:
activity["party"]["id"] = id
if max_size > 0:
activity["party"]["size"] = [size, max_size]
return self

## Provides secrets for Rich Presence joining and spectating.
func with_secrets(
join: String = "", spectate: String = "", match: String = ""
) -> RichPresenceBuilder:
var secrets: Dictionary
if activity.has("secrets"):
secrets = activity["secrets"]
else:
activity["secrets"] = secrets

if not join.is_empty():
secrets["join"] = join
if not spectate.is_empty():
secrets["spectate"] = spectate
if not match.is_empty():
secrets["match"] = match

return self

## Adds a custom button (max 2).
func add_button(label: String, url: String) -> RichPresenceBuilder:
var buttons: Array[Dictionary]
if activity.has("buttons"):
buttons.assign(activity["button"])
else:
activity["buttons"] = buttons

if buttons.size() < 2:
buttons.append({label = label, url = url})
else:
push_error("Rich Presence button are limited to 2")

return self

## Whether or not the activity is an instanced game session.
func is_instance(value: bool) -> RichPresenceBuilder:
activity["instance"] = value
return self

## Returns the activity object.
func build() -> Dictionary:
return activity.duplicate(true)

Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
4 changes: 0 additions & 4 deletions addons/discord-sdk-gd/bin/version.txt

This file was deleted.

Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading

0 comments on commit ba111a1

Please sign in to comment.