Merge branch 'discord-rich-presence'
This commit is contained in:
commit
e8809f6de6
@ -47,7 +47,8 @@ SOURCES += main.cpp\
|
|||||||
aotextarea.cpp \
|
aotextarea.cpp \
|
||||||
aolineedit.cpp \
|
aolineedit.cpp \
|
||||||
aotextedit.cpp \
|
aotextedit.cpp \
|
||||||
aoevidencedisplay.cpp
|
aoevidencedisplay.cpp \
|
||||||
|
discord_rich_presence.cpp
|
||||||
|
|
||||||
HEADERS += lobby.h \
|
HEADERS += lobby.h \
|
||||||
aoimage.h \
|
aoimage.h \
|
||||||
@ -76,10 +77,18 @@ HEADERS += lobby.h \
|
|||||||
aotextarea.h \
|
aotextarea.h \
|
||||||
aolineedit.h \
|
aolineedit.h \
|
||||||
aotextedit.h \
|
aotextedit.h \
|
||||||
aoevidencedisplay.h
|
aoevidencedisplay.h \
|
||||||
|
discord_rich_presence.h \
|
||||||
|
discord-rpc.h
|
||||||
|
|
||||||
unix:LIBS += -L$$PWD -lbass
|
# 1. You need to get BASS and put the x86 bass DLL/headers in the project root folder
|
||||||
win32:LIBS += "$$PWD/bass.dll"
|
# AND the compilation output folder. If you want a static link, you'll probably
|
||||||
|
# need the .lib file too. MinGW-GCC is really finicky finding BASS, it seems.
|
||||||
|
# 2. You need to compile the Discord Rich Presence SDK separately and add the lib/headers
|
||||||
|
# in the same way as BASS. Discord RPC uses CMake, which does not play nicely with
|
||||||
|
# QMake, so this step must be manual.
|
||||||
|
unix:LIBS += -L$$PWD -lbass -ldiscord-rpc
|
||||||
|
win32:LIBS += -L$$PWD "$$PWD/bass.dll" -ldiscord-rpc #"$$PWD/discord-rpc.dll"
|
||||||
android:LIBS += -L$$PWD\android\libs\armeabi-v7a\ -lbass
|
android:LIBS += -L$$PWD\android\libs\armeabi-v7a\ -lbass
|
||||||
|
|
||||||
CONFIG += c++11
|
CONFIG += c++11
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
AOApplication::AOApplication(int &argc, char **argv) : QApplication(argc, argv)
|
AOApplication::AOApplication(int &argc, char **argv) : QApplication(argc, argv)
|
||||||
{
|
{
|
||||||
net_manager = new NetworkManager(this);
|
net_manager = new NetworkManager(this);
|
||||||
|
discord = new AttorneyOnline::Discord();
|
||||||
QObject::connect(net_manager, SIGNAL(ms_connect_finished(bool, bool)),
|
QObject::connect(net_manager, SIGNAL(ms_connect_finished(bool, bool)),
|
||||||
SLOT(ms_connect_finished(bool, bool)));
|
SLOT(ms_connect_finished(bool, bool)));
|
||||||
}
|
}
|
||||||
@ -20,6 +21,7 @@ AOApplication::~AOApplication()
|
|||||||
{
|
{
|
||||||
destruct_lobby();
|
destruct_lobby();
|
||||||
destruct_courtroom();
|
destruct_courtroom();
|
||||||
|
delete discord;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AOApplication::construct_lobby()
|
void AOApplication::construct_lobby()
|
||||||
@ -38,6 +40,8 @@ void AOApplication::construct_lobby()
|
|||||||
int y = (screenGeometry.height()-w_lobby->height()) / 2;
|
int y = (screenGeometry.height()-w_lobby->height()) / 2;
|
||||||
w_lobby->move(x, y);
|
w_lobby->move(x, y);
|
||||||
|
|
||||||
|
discord->state_lobby();
|
||||||
|
|
||||||
w_lobby->show();
|
w_lobby->show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include "aopacket.h"
|
#include "aopacket.h"
|
||||||
#include "datatypes.h"
|
#include "datatypes.h"
|
||||||
|
#include "discord_rich_presence.h"
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QVector>
|
#include <QVector>
|
||||||
@ -23,6 +24,7 @@ public:
|
|||||||
NetworkManager *net_manager;
|
NetworkManager *net_manager;
|
||||||
Lobby *w_lobby;
|
Lobby *w_lobby;
|
||||||
Courtroom *w_courtroom;
|
Courtroom *w_courtroom;
|
||||||
|
AttorneyOnline::Discord *discord;
|
||||||
|
|
||||||
bool lobby_constructed = false;
|
bool lobby_constructed = false;
|
||||||
bool courtroom_constructed = false;
|
bool courtroom_constructed = false;
|
||||||
|
@ -151,8 +151,12 @@ void Courtroom::char_clicked(int n_char)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (n_real_char == m_cid)
|
if (n_real_char == m_cid)
|
||||||
|
{
|
||||||
enter_courtroom(m_cid);
|
enter_courtroom(m_cid);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
ao_app->send_server_packet(new AOPacket("CC#" + QString::number(ao_app->s_pv) + "#" + QString::number(n_real_char) + "#" + get_hdid() + "#%"));
|
ao_app->send_server_packet(new AOPacket("CC#" + QString::number(ao_app->s_pv) + "#" + QString::number(n_real_char) + "#" + get_hdid() + "#%"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -660,9 +660,15 @@ void Courtroom::enter_courtroom(int p_cid)
|
|||||||
QString f_char;
|
QString f_char;
|
||||||
|
|
||||||
if (m_cid == -1)
|
if (m_cid == -1)
|
||||||
|
{
|
||||||
|
ao_app->discord->state_spectate();
|
||||||
f_char = "";
|
f_char = "";
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
f_char = ao_app->get_char_name(char_list.at(m_cid).name);
|
f_char = ao_app->get_char_name(char_list.at(m_cid).name);
|
||||||
|
ao_app->discord->state_character(f_char.toStdString());
|
||||||
|
}
|
||||||
|
|
||||||
current_char = f_char;
|
current_char = f_char;
|
||||||
|
|
||||||
|
84
discord-rpc.h
Normal file
84
discord-rpc.h
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
|
||||||
|
#if defined(DISCORD_DYNAMIC_LIB)
|
||||||
|
# if defined(_WIN32)
|
||||||
|
# if defined(DISCORD_BUILDING_SDK)
|
||||||
|
# define DISCORD_EXPORT __declspec(dllexport)
|
||||||
|
# else
|
||||||
|
# define DISCORD_EXPORT __declspec(dllimport)
|
||||||
|
# endif
|
||||||
|
# else
|
||||||
|
# define DISCORD_EXPORT __attribute__((visibility("default")))
|
||||||
|
# endif
|
||||||
|
#else
|
||||||
|
# define DISCORD_EXPORT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct DiscordRichPresence {
|
||||||
|
const char* state; /* max 128 bytes */
|
||||||
|
const char* details; /* max 128 bytes */
|
||||||
|
int64_t startTimestamp;
|
||||||
|
int64_t endTimestamp;
|
||||||
|
const char* largeImageKey; /* max 32 bytes */
|
||||||
|
const char* largeImageText; /* max 128 bytes */
|
||||||
|
const char* smallImageKey; /* max 32 bytes */
|
||||||
|
const char* smallImageText; /* max 128 bytes */
|
||||||
|
const char* partyId; /* max 128 bytes */
|
||||||
|
int partySize;
|
||||||
|
int partyMax;
|
||||||
|
const char* matchSecret; /* max 128 bytes */
|
||||||
|
const char* joinSecret; /* max 128 bytes */
|
||||||
|
const char* spectateSecret; /* max 128 bytes */
|
||||||
|
int8_t instance;
|
||||||
|
} DiscordRichPresence;
|
||||||
|
|
||||||
|
typedef struct DiscordJoinRequest {
|
||||||
|
const char* userId;
|
||||||
|
const char* username;
|
||||||
|
const char* discriminator;
|
||||||
|
const char* avatar;
|
||||||
|
} DiscordJoinRequest;
|
||||||
|
|
||||||
|
typedef struct DiscordEventHandlers {
|
||||||
|
void (*ready)();
|
||||||
|
void (*disconnected)(int errorCode, const char* message);
|
||||||
|
void (*errored)(int errorCode, const char* message);
|
||||||
|
void (*joinGame)(const char* joinSecret);
|
||||||
|
void (*spectateGame)(const char* spectateSecret);
|
||||||
|
void (*joinRequest)(const DiscordJoinRequest* request);
|
||||||
|
} DiscordEventHandlers;
|
||||||
|
|
||||||
|
#define DISCORD_REPLY_NO 0
|
||||||
|
#define DISCORD_REPLY_YES 1
|
||||||
|
#define DISCORD_REPLY_IGNORE 2
|
||||||
|
|
||||||
|
DISCORD_EXPORT void Discord_Initialize(const char* applicationId,
|
||||||
|
DiscordEventHandlers* handlers,
|
||||||
|
int autoRegister,
|
||||||
|
const char* optionalSteamId);
|
||||||
|
DISCORD_EXPORT void Discord_Shutdown(void);
|
||||||
|
|
||||||
|
/* checks for incoming messages, dispatches callbacks */
|
||||||
|
DISCORD_EXPORT void Discord_RunCallbacks(void);
|
||||||
|
|
||||||
|
/* If you disable the lib starting its own io thread, you'll need to call this from your own */
|
||||||
|
#ifdef DISCORD_DISABLE_IO_THREAD
|
||||||
|
DISCORD_EXPORT void Discord_UpdateConnection(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
DISCORD_EXPORT void Discord_UpdatePresence(const DiscordRichPresence* presence);
|
||||||
|
|
||||||
|
DISCORD_EXPORT void Discord_Respond(const char* userid, /* DISCORD_REPLY_ */ int reply);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} /* extern "C" */
|
||||||
|
#endif
|
108
discord_rich_presence.cpp
Normal file
108
discord_rich_presence.cpp
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
#include "discord_rich_presence.h"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
#include <ctime>
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
namespace AttorneyOnline {
|
||||||
|
|
||||||
|
Discord::Discord()
|
||||||
|
{
|
||||||
|
DiscordEventHandlers handlers;
|
||||||
|
std::memset(&handlers, 0, sizeof(handlers));
|
||||||
|
handlers = {};
|
||||||
|
handlers.ready = [] {
|
||||||
|
qInfo() << "Discord RPC ready";
|
||||||
|
};
|
||||||
|
handlers.disconnected = [](int errorCode, const char* message) {
|
||||||
|
qInfo() << "Discord RPC disconnected! " << message;
|
||||||
|
};
|
||||||
|
handlers.errored = [](int errorCode, const char* message) {
|
||||||
|
qWarning() << "Discord RPC errored out! " << message;
|
||||||
|
};
|
||||||
|
qInfo() << "Initializing Discord RPC";
|
||||||
|
Discord_Initialize(APPLICATION_ID, &handlers, 1, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
Discord::~Discord()
|
||||||
|
{
|
||||||
|
Discord_Shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Discord::state_lobby()
|
||||||
|
{
|
||||||
|
DiscordRichPresence presence;
|
||||||
|
std::memset(&presence, 0, sizeof(presence));
|
||||||
|
presence.largeImageKey = "ao2-logo";
|
||||||
|
presence.largeImageText = "Objection!";
|
||||||
|
presence.instance = 1;
|
||||||
|
|
||||||
|
presence.state = "In Lobby";
|
||||||
|
presence.details = "Idle";
|
||||||
|
Discord_UpdatePresence(&presence);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Discord::state_server(std::string name, std::string server_id)
|
||||||
|
{
|
||||||
|
qDebug() << "Discord RPC: Setting server state";
|
||||||
|
|
||||||
|
DiscordRichPresence presence;
|
||||||
|
std::memset(&presence, 0, sizeof(presence));
|
||||||
|
presence.largeImageKey = "ao2-logo";
|
||||||
|
presence.largeImageText = "Objection!";
|
||||||
|
presence.instance = 1;
|
||||||
|
|
||||||
|
auto timestamp = static_cast<int64_t>(std::time(nullptr));
|
||||||
|
|
||||||
|
presence.state = "In a Server";
|
||||||
|
presence.details = name.c_str();
|
||||||
|
presence.matchSecret = server_id.c_str();
|
||||||
|
presence.startTimestamp = this->timestamp;
|
||||||
|
|
||||||
|
this->server_id = server_id;
|
||||||
|
this->server_name = name;
|
||||||
|
this->timestamp = timestamp;
|
||||||
|
Discord_UpdatePresence(&presence);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Discord::state_character(std::string name)
|
||||||
|
{
|
||||||
|
auto name_internal = QString(name.c_str()).toLower().replace(' ', '_').toStdString();
|
||||||
|
auto name_friendly = QString(name.c_str()).replace('_', ' ').toStdString();
|
||||||
|
const std::string playing_as = "Playing as " + name_friendly;
|
||||||
|
qDebug() << "Discord RPC: Setting character state (" << playing_as.c_str() << ")";
|
||||||
|
|
||||||
|
DiscordRichPresence presence;
|
||||||
|
std::memset(&presence, 0, sizeof(presence));
|
||||||
|
presence.largeImageKey = "ao2-logo";
|
||||||
|
presence.largeImageText = "Objection!";
|
||||||
|
presence.instance = 1;
|
||||||
|
presence.details = this->server_name.c_str();
|
||||||
|
presence.matchSecret = this->server_id.c_str();
|
||||||
|
presence.startTimestamp = this->timestamp;
|
||||||
|
|
||||||
|
presence.state = playing_as.c_str();
|
||||||
|
presence.smallImageKey = name_internal.c_str();
|
||||||
|
// presence.smallImageText = name_internal.c_str();
|
||||||
|
Discord_UpdatePresence(&presence);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Discord::state_spectate()
|
||||||
|
{
|
||||||
|
qDebug() << "Discord RPC: Setting specator state";
|
||||||
|
|
||||||
|
DiscordRichPresence presence;
|
||||||
|
std::memset(&presence, 0, sizeof(presence));
|
||||||
|
presence.largeImageKey = "ao2-logo";
|
||||||
|
presence.largeImageText = "Objection!";
|
||||||
|
presence.instance = 1;
|
||||||
|
presence.details = this->server_name.c_str();
|
||||||
|
presence.matchSecret = this->server_id.c_str();
|
||||||
|
presence.startTimestamp = this->timestamp;
|
||||||
|
|
||||||
|
presence.state = "Spectating";
|
||||||
|
Discord_UpdatePresence(&presence);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
26
discord_rich_presence.h
Normal file
26
discord_rich_presence.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#ifndef DISCORD_RICH_PRESENCE_H
|
||||||
|
#define DISCORD_RICH_PRESENCE_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <discord-rpc.h>
|
||||||
|
|
||||||
|
namespace AttorneyOnline {
|
||||||
|
|
||||||
|
class Discord
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
const char* APPLICATION_ID = "399779271737868288";
|
||||||
|
std::string server_name, server_id;
|
||||||
|
int64_t timestamp;
|
||||||
|
public:
|
||||||
|
Discord();
|
||||||
|
~Discord();
|
||||||
|
|
||||||
|
void state_lobby();
|
||||||
|
void state_server(std::string name, std::string server_id);
|
||||||
|
void state_character(std::string name);
|
||||||
|
void state_spectate();
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif // DISCORD_RICH_PRESENCE_H
|
@ -8,6 +8,7 @@
|
|||||||
#include "debug_functions.h"
|
#include "debug_functions.h"
|
||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
#include <QCryptographicHash>
|
||||||
|
|
||||||
void AOApplication::ms_packet_received(AOPacket *p_packet)
|
void AOApplication::ms_packet_received(AOPacket *p_packet)
|
||||||
{
|
{
|
||||||
@ -226,15 +227,24 @@ void AOApplication::server_packet_received(AOPacket *p_packet)
|
|||||||
QString window_title = "Attorney Online 2";
|
QString window_title = "Attorney Online 2";
|
||||||
int selected_server = w_lobby->get_selected_server();
|
int selected_server = w_lobby->get_selected_server();
|
||||||
|
|
||||||
|
QString server_address = "", server_name = "";
|
||||||
if (w_lobby->public_servers_selected)
|
if (w_lobby->public_servers_selected)
|
||||||
{
|
{
|
||||||
if (selected_server >= 0 && selected_server < server_list.size())
|
if (selected_server >= 0 && selected_server < server_list.size()) {
|
||||||
window_title += ": " + server_list.at(selected_server).name;
|
auto info = server_list.at(selected_server);
|
||||||
|
server_name = info.name;
|
||||||
|
server_address = info.ip + info.port;
|
||||||
|
window_title += ": " + server_name;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (selected_server >= 0 && selected_server < favorite_list.size())
|
if (selected_server >= 0 && selected_server < favorite_list.size()) {
|
||||||
window_title += ": " + favorite_list.at(selected_server).name;
|
auto info = favorite_list.at(selected_server);
|
||||||
|
server_name = info.name;
|
||||||
|
server_address = info.ip + info.port;
|
||||||
|
window_title += ": " + server_name;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
w_courtroom->set_window_title(window_title);
|
w_courtroom->set_window_title(window_title);
|
||||||
@ -251,6 +261,10 @@ void AOApplication::server_packet_received(AOPacket *p_packet)
|
|||||||
f_packet = new AOPacket("askchar2#%");
|
f_packet = new AOPacket("askchar2#%");
|
||||||
|
|
||||||
send_server_packet(f_packet);
|
send_server_packet(f_packet);
|
||||||
|
|
||||||
|
QCryptographicHash hash(QCryptographicHash::Algorithm::Sha256);
|
||||||
|
hash.addData(server_address.toUtf8());
|
||||||
|
discord->state_server(server_name.toStdString(), hash.result().toBase64().toStdString());
|
||||||
}
|
}
|
||||||
else if (header == "CI")
|
else if (header == "CI")
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user