aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoroldmud0 <oldmud0@users.noreply.github.com>2018-01-08 13:40:29 -0600
committeroldmud0 <oldmud0@users.noreply.github.com>2018-01-08 13:40:29 -0600
commite8809f6de6acc04f93ed9c5f406f3ad5f0bb021f (patch)
treed85865e121a6c7d312e14373797ae6f0c76932ca
parent0504d2b5d71aa8f3d5d0ebecf4eba4e0efeb701f (diff)
parent8a91dea6ce2fa88cdc720759f17d3ac4cf05070b (diff)
Merge branch 'discord-rich-presence'
-rw-r--r--Attorney_Online_remake.pro17
-rw-r--r--aoapplication.cpp4
-rw-r--r--aoapplication.h2
-rw-r--r--charselect.cpp4
-rw-r--r--courtroom.cpp6
-rw-r--r--discord-rpc.h84
-rw-r--r--discord_rich_presence.cpp108
-rw-r--r--discord_rich_presence.h26
-rw-r--r--packet_distribution.cpp22
9 files changed, 265 insertions, 8 deletions
diff --git a/Attorney_Online_remake.pro b/Attorney_Online_remake.pro
index 40b2028a..b19c6ecf 100644
--- a/Attorney_Online_remake.pro
+++ b/Attorney_Online_remake.pro
@@ -47,7 +47,8 @@ SOURCES += main.cpp\
aotextarea.cpp \
aolineedit.cpp \
aotextedit.cpp \
- aoevidencedisplay.cpp
+ aoevidencedisplay.cpp \
+ discord_rich_presence.cpp
HEADERS += lobby.h \
aoimage.h \
@@ -76,10 +77,18 @@ HEADERS += lobby.h \
aotextarea.h \
aolineedit.h \
aotextedit.h \
- aoevidencedisplay.h
+ aoevidencedisplay.h \
+ discord_rich_presence.h \
+ discord-rpc.h
-unix:LIBS += -L$$PWD -lbass
-win32:LIBS += "$$PWD/bass.dll"
+# 1. You need to get BASS and put the x86 bass DLL/headers in the project root folder
+# 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
CONFIG += c++11
diff --git a/aoapplication.cpp b/aoapplication.cpp
index 43629022..e170c990 100644
--- a/aoapplication.cpp
+++ b/aoapplication.cpp
@@ -12,6 +12,7 @@
AOApplication::AOApplication(int &argc, char **argv) : QApplication(argc, argv)
{
net_manager = new NetworkManager(this);
+ discord = new AttorneyOnline::Discord();
QObject::connect(net_manager, SIGNAL(ms_connect_finished(bool, bool)),
SLOT(ms_connect_finished(bool, bool)));
}
@@ -20,6 +21,7 @@ AOApplication::~AOApplication()
{
destruct_lobby();
destruct_courtroom();
+ delete discord;
}
void AOApplication::construct_lobby()
@@ -38,6 +40,8 @@ void AOApplication::construct_lobby()
int y = (screenGeometry.height()-w_lobby->height()) / 2;
w_lobby->move(x, y);
+ discord->state_lobby();
+
w_lobby->show();
}
diff --git a/aoapplication.h b/aoapplication.h
index 592c030d..9762549b 100644
--- a/aoapplication.h
+++ b/aoapplication.h
@@ -3,6 +3,7 @@
#include "aopacket.h"
#include "datatypes.h"
+#include "discord_rich_presence.h"
#include <QApplication>
#include <QVector>
@@ -23,6 +24,7 @@ public:
NetworkManager *net_manager;
Lobby *w_lobby;
Courtroom *w_courtroom;
+ AttorneyOnline::Discord *discord;
bool lobby_constructed = false;
bool courtroom_constructed = false;
diff --git a/charselect.cpp b/charselect.cpp
index 1f76e0b2..4e4bccbf 100644
--- a/charselect.cpp
+++ b/charselect.cpp
@@ -151,8 +151,12 @@ void Courtroom::char_clicked(int n_char)
}
if (n_real_char == m_cid)
+ {
enter_courtroom(m_cid);
+ }
else
+ {
ao_app->send_server_packet(new AOPacket("CC#" + QString::number(ao_app->s_pv) + "#" + QString::number(n_real_char) + "#" + get_hdid() + "#%"));
+ }
}
diff --git a/courtroom.cpp b/courtroom.cpp
index a8b96eb5..14d3cbb3 100644
--- a/courtroom.cpp
+++ b/courtroom.cpp
@@ -660,9 +660,15 @@ void Courtroom::enter_courtroom(int p_cid)
QString f_char;
if (m_cid == -1)
+ {
+ ao_app->discord->state_spectate();
f_char = "";
+ }
else
+ {
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;
diff --git a/discord-rpc.h b/discord-rpc.h
new file mode 100644
index 00000000..8c117acd
--- /dev/null
+++ b/discord-rpc.h
@@ -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
diff --git a/discord_rich_presence.cpp b/discord_rich_presence.cpp
new file mode 100644
index 00000000..bcc0d2af
--- /dev/null
+++ b/discord_rich_presence.cpp
@@ -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);
+}
+
+}
diff --git a/discord_rich_presence.h b/discord_rich_presence.h
new file mode 100644
index 00000000..3c9f2bda
--- /dev/null
+++ b/discord_rich_presence.h
@@ -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
diff --git a/packet_distribution.cpp b/packet_distribution.cpp
index 4d746546..3908ffa1 100644
--- a/packet_distribution.cpp
+++ b/packet_distribution.cpp
@@ -8,6 +8,7 @@
#include "debug_functions.h"
#include <QDebug>
+#include <QCryptographicHash>
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";
int selected_server = w_lobby->get_selected_server();
+ QString server_address = "", server_name = "";
if (w_lobby->public_servers_selected)
{
- if (selected_server >= 0 && selected_server < server_list.size())
- window_title += ": " + server_list.at(selected_server).name;
+ if (selected_server >= 0 && selected_server < server_list.size()) {
+ auto info = server_list.at(selected_server);
+ server_name = info.name;
+ server_address = info.ip + info.port;
+ window_title += ": " + server_name;
+ }
}
else
{
- if (selected_server >= 0 && selected_server < favorite_list.size())
- window_title += ": " + favorite_list.at(selected_server).name;
+ if (selected_server >= 0 && selected_server < favorite_list.size()) {
+ 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);
@@ -251,6 +261,10 @@ void AOApplication::server_packet_received(AOPacket *p_packet)
f_packet = new AOPacket("askchar2#%");
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")
{