working discord presence

This commit is contained in:
Songtronix 2019-06-04 22:12:32 +02:00 committed by Songtronix
parent 60500d9235
commit 1e40bd09ba
2 changed files with 158 additions and 6 deletions

104
voxygen/src/discord.rs Normal file
View File

@ -0,0 +1,104 @@
use discord_game_sdk::{Activity, Discord};
use std::ffi::CString;
use std::sync::mpsc::Sender;
use std::sync::{mpsc, Mutex, MutexGuard};
use std::thread;
use std::thread::JoinHandle;
use crate::DEFAULT_PUBLIC_SERVER;
use chrono::Utc;
const DISCORD_APPLICATION_ID: i64 = 583662036194689035;
/// Represents an update of the game which should be reflected in Discord
pub enum DiscordUpdate {
Details(String),
State(String),
SmallImg(String),
SmallImgDesc(String),
LargeImg(String),
LargeImgDesc(String),
Shutdown,
}
pub struct DiscordState {
pub tx: Sender<DiscordUpdate>,
pub thread: Option<JoinHandle<()>>,
}
pub fn run() -> Mutex<DiscordState> {
let (tx, rx) = mpsc::channel();
Mutex::new(DiscordState {
tx,
thread: Some(thread::spawn(move || {
let mut discord =
Discord::new(DISCORD_APPLICATION_ID).expect("failed to initiate discord_game_sdk");
//Set initial Status
let mut current_activity = Activity::empty();
current_activity.with_details(CString::new("Menu").expect("failed to create CString"));
current_activity.with_state(CString::new("Idling").expect("failed to create CString"));
current_activity.with_small_image_key(
CString::new("veloren_logo_squareicon_2000").expect("failed to create CString"),
);
current_activity.with_small_image_tooltip(
CString::new("Veloren").expect("failed to create CString"),
);
current_activity
.with_large_image_key(CString::new("bg_main").expect("failed to create CString"));
current_activity.with_large_image_tooltip(
CString::new("veloren.net").expect("failed to create CString"),
);
current_activity.with_start_time(Utc::now());
discord.update_activity(&current_activity, |_, _| {});
'outer: loop {
discord.empty_event_receivers();
discord.run_callbacks();
let msg = rx.try_recv();
match msg {
Ok(update) => {
match update {
DiscordUpdate::Details(x) => current_activity
.with_details(CString::new(x).expect("failed to create CString")),
DiscordUpdate::State(x) => current_activity
.with_state(CString::new(x).expect("failed to create CString")),
DiscordUpdate::SmallImg(x) => current_activity.with_small_image_key(
CString::new(x).expect("failed to create CString"),
),
DiscordUpdate::SmallImgDesc(x) => current_activity
.with_small_image_tooltip(
CString::new(x).expect("failed to create CString"),
),
DiscordUpdate::LargeImg(x) => current_activity.with_large_image_key(
CString::new(x).expect("failed to create CString"),
),
DiscordUpdate::LargeImgDesc(x) => current_activity
.with_large_image_tooltip(
CString::new(x).expect("failed to create CString"),
),
DiscordUpdate::Shutdown => break 'outer,
};
discord.update_activity(&current_activity, |_, _| {});
}
Err(_) => {}
}
}
})),
})
}
/* Some helpers */
pub fn send_menu(disc: &mut MutexGuard<DiscordState>) {
disc.tx.send(DiscordUpdate::Details("Menu".into()));
disc.tx.send(DiscordUpdate::State("Idling".into()));
disc.tx.send(DiscordUpdate::LargeImg("bg_main".into()));
}
pub fn send_singleplayer(disc: &mut MutexGuard<DiscordState>) {
disc.tx.send(DiscordUpdate::Details("Singleplayer".into()));
disc.tx.send(DiscordUpdate::State("Playing...".into()));
}

View File

@ -1,6 +1,10 @@
#![feature(drain_filter)]
#![recursion_limit = "2048"]
#[cfg(feature = "discord")]
#[macro_use]
extern crate lazy_static;
#[macro_use]
pub mod ui;
pub mod anim;
@ -17,16 +21,21 @@ pub mod settings;
pub mod singleplayer;
pub mod window;
#[cfg(feature = "discord")]
pub mod discord;
// Reexports
pub use crate::error::Error;
use crate::{
audio::{base::Genre, AudioFrontend},
menu::main::MainMenuState,
settings::Settings,
window::Window,
use crate::{audio::AudioFrontend, menu::main::MainMenuState, settings::Settings, window::Window};
use log::{self, debug, error, info, warn};
#[cfg(feature = "discord")]
use std::sync::{
mpsc::Sender,
Mutex,
};
use log::{debug, error, info, warn};
use simplelog::{CombinedLogger, Config, TermLogger, WriteLogger};
use std::{fs::File, mem, panic, str::FromStr};
@ -80,6 +89,14 @@ pub trait PlayState {
fn name(&self) -> &'static str;
}
#[cfg(feature = "discord")]
lazy_static! {
//Set up discord rich presence
static ref discord_instance: Mutex<discord::DiscordState> = {
discord::run()
};
}
fn main() {
// Set up the global state.
let settings = Settings::load();
@ -109,6 +126,17 @@ fn main() {
),
])
.unwrap();
// Initialize discord. (lazy_static intialise lazily...)
#[cfg(feature = "discord")]
{
match discord_instance.lock() {
Ok(disc) => {
//great
}
Err(e) => {}
}
}
// Set up panic handler to relay swish panic messages to the user
let settings_clone = global_state.settings.clone();
@ -238,6 +266,26 @@ fn main() {
}
}
}
//Properly shutdown discord thread
#[cfg(feature = "discord")]
{
match discord_instance.lock() {
Ok(mut disc) => {
disc.tx.send(discord::DiscordUpdate::Shutdown);
match disc.thread.take() {
Some(th) => {
th.join();
}
None => {
error!("couldn't gracefully shutdown discord thread");
}
}
}
Err(e) => error!("couldn't gracefully shutdown discord thread: {}", e),
}
}
// Save settings to add new fields or create the file if it is not already there
if let Err(err) = global_state.settings.save_to_file() {
warn!("Failed to save settings: {:?}", err);