From 8e899275251cce2e85a0dceeb3293aab54f10935 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Mon, 20 Sep 2021 16:59:40 -0400 Subject: [PATCH] got rpc working --- game/Cargo.toml | 6 ++- game/assets/configs/discord.json | 3 ++ game/src/lib.rs | 45 ++++++++++++++++++- game/src/utilities/datastore.rs | 3 ++ game/src/utilities/discord/config.rs | 13 ++++++ game/src/utilities/discord/mod.rs | 4 ++ .../utilities/{discord.rs => discord/rpc.rs} | 28 +++++++++++- game/src/utilities/mod.rs | 3 +- wrapper/Cargo.toml | 3 +- wrapper/src/main.rs | 5 ++- 10 files changed, 104 insertions(+), 9 deletions(-) create mode 100644 game/assets/configs/discord.json create mode 100644 game/src/utilities/datastore.rs create mode 100644 game/src/utilities/discord/config.rs create mode 100644 game/src/utilities/discord/mod.rs rename game/src/utilities/{discord.rs => discord/rpc.rs} (60%) diff --git a/game/Cargo.toml b/game/Cargo.toml index ad832f4..e5b636f 100644 --- a/game/Cargo.toml +++ b/game/Cargo.toml @@ -8,13 +8,15 @@ edition = "2018" [dependencies] cgmath = "0.18" discord-sdk = "0.1" -tokio = { version = "1.0", features = ["macros", "rt-multi-thread"] } +tokio = { version = "1.0", features = ["macros"] } tracing = { version = "0.1", features = ["log"] } serde = { version = "1.0.126", features = ["derive"] } serde_json = "1.0.64" thiserror = "1.0" chrono = "0.4" +rust-embed = "6.2.0" +raylib = "3.5" [profile.release] lto = true -codegen-units = 1 \ No newline at end of file +codegen-units = 1 diff --git a/game/assets/configs/discord.json b/game/assets/configs/discord.json new file mode 100644 index 0000000..3b98659 --- /dev/null +++ b/game/assets/configs/discord.json @@ -0,0 +1,3 @@ +{ + "app_id": 889531982978117633 +} \ No newline at end of file diff --git a/game/src/lib.rs b/game/src/lib.rs index d99d7b0..ff8d176 100644 --- a/game/src/lib.rs +++ b/game/src/lib.rs @@ -1,7 +1,50 @@ +use discord_sdk::activity::ActivityBuilder; +use tracing::error; +use utilities::{ + datastore::StaticGameData, + discord::{DiscordConfig, DiscordRpcClient}, +}; +use raylib::prelude::*; + #[macro_use] extern crate thiserror; +#[macro_use] +extern crate serde; mod utilities; /// The game entrypoint -pub fn game_begin() {} +pub async fn game_begin() { + // Attempt to connect to a locally running Discord instance for rich presence access + let discord_config = DiscordConfig::load( + StaticGameData::get("configs/discord.json").expect("Failed to load discord.json"), + ) + .expect("Could not load Discord config data"); + let discord_rpc = + match DiscordRpcClient::new(discord_config.app_id, discord_sdk::Subscriptions::ACTIVITY) + .await + { + Ok(client) => Some(client), + Err(err) => { + error!("Could not connect to or find a locally running Discord instance."); + error!("Discord connection error: {:?}", err); + None + } + }; + + if let Some(rpc) = discord_rpc { + rpc.set_rich_presence(ActivityBuilder::default().details("Testing...")).await.unwrap(); + } + + let (mut rl, thread) = raylib::init() + .size(640, 480) + .title("Hello, World") + .build(); + + while !rl.window_should_close() { + let mut d = rl.begin_drawing(&thread); + + d.clear_background(Color::WHITE); + d.draw_text("Hello, world!", 12, 12, 20, Color::BLACK); + } +} diff --git a/game/src/utilities/datastore.rs b/game/src/utilities/datastore.rs new file mode 100644 index 0000000..2c0ce0f --- /dev/null +++ b/game/src/utilities/datastore.rs @@ -0,0 +1,3 @@ +#[derive(rust_embed::RustEmbed)] +#[folder = "assets"] +pub struct StaticGameData; diff --git a/game/src/utilities/discord/config.rs b/game/src/utilities/discord/config.rs new file mode 100644 index 0000000..a2e3526 --- /dev/null +++ b/game/src/utilities/discord/config.rs @@ -0,0 +1,13 @@ +use rust_embed::EmbeddedFile; + +#[derive(Debug, Clone, Deserialize)] +pub struct DiscordConfig { + pub app_id: i64, +} + +impl DiscordConfig { + /// Load from a file + pub fn load(file: EmbeddedFile) -> Result { + serde_json::from_slice(&file.data) + } +} diff --git a/game/src/utilities/discord/mod.rs b/game/src/utilities/discord/mod.rs new file mode 100644 index 0000000..3cab9f3 --- /dev/null +++ b/game/src/utilities/discord/mod.rs @@ -0,0 +1,4 @@ +pub mod rpc; +pub use rpc::DiscordRpcClient; +pub mod config; +pub use config::DiscordConfig; diff --git a/game/src/utilities/discord.rs b/game/src/utilities/discord/rpc.rs similarity index 60% rename from game/src/utilities/discord.rs rename to game/src/utilities/discord/rpc.rs index faeb471..4e7c902 100644 --- a/game/src/utilities/discord.rs +++ b/game/src/utilities/discord/rpc.rs @@ -1,6 +1,11 @@ //! Discord Rich Presence utilities -use discord_sdk::{user::User, wheel::Wheel, Discord, DiscordApp, Subscriptions}; +use discord_sdk::{ + activity::{Activity, ActivityBuilder}, + user::User, + wheel::Wheel, + Discord, DiscordApp, Subscriptions, +}; use tracing::info; #[derive(Debug, Error)] @@ -9,8 +14,11 @@ pub enum DiscordError { SdkError(#[from] discord_sdk::Error), #[error(transparent)] AwaitConnectionError(#[from] tokio::sync::watch::error::RecvError), + #[error("Could not connect")] + ConnectionError, } +/// The client wrapper for Discord RPC pub struct DiscordRpcClient { pub discord: Discord, pub user: User, @@ -18,6 +26,7 @@ pub struct DiscordRpcClient { } impl DiscordRpcClient { + /// Creates a new DiscordRpcClient pub async fn new(app_id: i64, subscriptions: Subscriptions) -> Result { // Create a new wheel let (wheel, handler) = Wheel::new(Box::new(|err| { @@ -40,7 +49,7 @@ impl DiscordRpcClient { // Fetch the final user object let user = match &*user.0.borrow() { discord_sdk::wheel::UserState::Connected(u) => Ok(u.clone()), - discord_sdk::wheel::UserState::Disconnected(err) => Err(err), + discord_sdk::wheel::UserState::Disconnected(_) => Err(DiscordError::ConnectionError), }?; Ok(Self { @@ -49,4 +58,19 @@ impl DiscordRpcClient { wheel, }) } + + /// Clears the user rich presence + pub async fn clear_rich_presence(&self) -> Result, discord_sdk::Error> { + self.discord + .update_activity(ActivityBuilder::default()) + .await + } + + /// Sets the user rich presence + pub async fn set_rich_presence( + &self, + activity: ActivityBuilder, + ) -> Result, discord_sdk::Error> { + self.discord.update_activity(activity).await + } } diff --git a/game/src/utilities/mod.rs b/game/src/utilities/mod.rs index d598d52..937e720 100644 --- a/game/src/utilities/mod.rs +++ b/game/src/utilities/mod.rs @@ -1 +1,2 @@ -pub mod discord; \ No newline at end of file +pub mod discord; +pub mod datastore; \ No newline at end of file diff --git a/wrapper/Cargo.toml b/wrapper/Cargo.toml index 1a7ad6a..6fbc952 100644 --- a/wrapper/Cargo.toml +++ b/wrapper/Cargo.toml @@ -8,4 +8,5 @@ edition = "2018" [dependencies] game = { version = "0.1", path = "../game"} -tracing-subscriber = "0.2" \ No newline at end of file +tracing-subscriber = "0.2" +tokio = { version = "1.0", features = ["macros", "rt-multi-thread"] } \ No newline at end of file diff --git a/wrapper/src/main.rs b/wrapper/src/main.rs index b4a235e..0251307 100644 --- a/wrapper/src/main.rs +++ b/wrapper/src/main.rs @@ -1,9 +1,10 @@ use game::game_begin; -fn main() { +#[tokio::main] +async fn main() { // Enable logging tracing_subscriber::fmt::init(); // Start the game - game_begin(); + game_begin().await; }