Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Interface for Game Invites #22

Merged
merged 16 commits into from
Sep 7, 2024
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 23 additions & 16 deletions Cargo.lock
GeckoEidechse marked this conversation as resolved.
Show resolved Hide resolved

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

33 changes: 30 additions & 3 deletions src/discord.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,16 @@
use std::num::NonZeroU32;

use discord_sdk::{
activity::{ActivityBuilder, Assets, PartyPrivacy},
activity::{events::ActivityEvent, ActivityBuilder, Assets, JoinRequestReply, PartyPrivacy},
user::User,
wheel::UserState,
wheel::Wheel,
Discord, DiscordApp, Subscriptions,
};
use rrplug::prelude::*;
use rrplug::{mid::utils::try_cstring, prelude::*};
use tokio::sync::broadcast::Receiver;

use crate::exports::PLUGIN;
use crate::{exports::PLUGIN, invite_handler::JOIN_HANDLER_FUNCTION};

/// the discord app's id, taken from older v1 discord rpc
const APP_ID: i64 = 941428101429231617;
Expand Down Expand Up @@ -42,6 +43,8 @@ pub async fn async_main() {
Err(err) => log::error!("coudln't clear activity because of {:?}", err),
}

let mut events = client.wheel.activity().0;

loop {
let data = activity.lock().clone();

Expand Down Expand Up @@ -84,10 +87,34 @@ pub async fn async_main() {
return;
}

handle_activity_events(&mut events, &client.discord).await;

wait(1000);
}
}

async fn handle_activity_events(
events: &mut Receiver<ActivityEvent>,
discord: &Discord,
) -> Option<()> {
match events.try_recv().ok()? {
ActivityEvent::Join(join) => {
let secret = try_cstring(&join.secret).expect("I like null bytes in my strings cool");
JOIN_HANDLER_FUNCTION.lock()(secret.as_ptr())
}
ActivityEvent::Spectate(_) => log::warn!("spectating cannot be supported!"),
ActivityEvent::JoinRequest(request) => {
log::info!("{} joined the party", request.user.username);
_ = discord
.send_join_request_reply(request.user.id, JoinRequestReply::Yes)
.await;
}
_ => {}
}

None
}

/// discord connection init sourced from https://github.com/EmbarkStudios/discord-sdk/blob/d311db749b7e11cc55cb1a9d7bfd9a95cfe61fd1/examples-shared/src/lib.rs#L16
pub async fn make_client(subs: Subscriptions) -> Result<Client, ()> {
let (wheel, handler) = Wheel::new(Box::new(|err| {
Expand Down
52 changes: 52 additions & 0 deletions src/invite_handler.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
use parking_lot::Mutex;
use std::ffi::{c_char, CStr};

use crate::PLUGIN;

pub static JOIN_HANDLER_FUNCTION: Mutex<JoinHandler> = Mutex::new(default_join_handler);

type JoinHandler = extern "C" fn(*const c_char);

#[repr(C)]
#[must_use]
pub enum IniviteHandlerResult {
Sucess,
Failure,
}

#[repr(C)]
pub(crate) struct InviteHandler;

#[rrplug::as_interface]
impl InviteHandler {
pub fn new() -> Self {
Self
}

pub fn set_join_handler(&self, handler: JoinHandler) {
*JOIN_HANDLER_FUNCTION.lock() = handler;
}

pub fn set_secret(&self, secret: *const c_char) -> IniviteHandlerResult {
if secret.is_null() {
return IniviteHandlerResult::Failure;
}

let Some(secret) = unsafe { CStr::from_ptr(secret) }.to_str().ok() else {
return IniviteHandlerResult::Failure;
};

PLUGIN.wait().activity.lock().secrets.join = Some(secret.to_string());
IniviteHandlerResult::Sucess
}

pub fn clear_secret(&self) {
let secrets = &mut PLUGIN.wait().activity.lock().secrets;

secrets.r#match = None;
secrets.join = None;
secrets.spectate = None;
}
}

extern "C" fn default_join_handler(_secret: *const c_char) {}
5 changes: 5 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,19 @@

use discord_sdk::activity::Secrets;
use parking_lot::Mutex;
use rrplug::interfaces::manager::register_interface;
use rrplug::prelude::*;
use tokio::runtime::Runtime;

use crate::{
discord::async_main,
invite_handler::InviteHandler,
presence::run_presence_updates,
presense_bindings::{GameState, GameStateStruct, UIPresenceStruct},
};

pub(crate) mod discord;
pub(crate) mod invite_handler;
pub(crate) mod presence;
pub(crate) mod presense_bindings;

Expand Down Expand Up @@ -50,6 +53,8 @@ impl Plugin for DiscordRpcPlugin {
fn new(_: bool) -> Self {
register_sq_functions(presence::fetch_presence);

unsafe { register_interface("InviteHandler001", InviteHandler::new()) };

let activity = Mutex::new(ActivityData {
large_image: Some("northstar".to_string()),
state: "Loading...".to_string(),
Expand Down