diff --git a/macos/macpack.sh b/macos/macpack.sh index f271281c..42d5f912 100755 --- a/macos/macpack.sh +++ b/macos/macpack.sh @@ -1,3 +1,6 @@ #!/bin/bash -macpack ${MESON_INSTALL_PREFIX}/Contents/MacOS/mkxp-z +EXE=${MESON_INSTALL_PREFIX}/Contents/MacOS/mkxp-z +install_name_tool -add_rpath "@executable_path/../libs" $EXE + +macpack -v $EXE diff --git a/macos/meson.build b/macos/meson.build index 626154cc..95b0d617 100644 --- a/macos/meson.build +++ b/macos/meson.build @@ -1,3 +1,4 @@ install_data('icon.icns', install_dir: 'Contents/Resources') install_data('Info.plist', install_dir: 'Contents') + meson.add_install_script('macpack.sh') diff --git a/meson.build b/meson.build index 5cdbb329..b081371e 100644 --- a/meson.build +++ b/meson.build @@ -9,6 +9,29 @@ xxd = find_program('xxd', native: true) host_system = host_machine.system() compiler = meson.get_compiler('cpp') +# ==================== +# Ext libs +# ==================== +ext_dependencies = [] + +# DISCORD + +discord = false +discord_libpath = get_option('discord_sdk_path') +if discord_libpath != '' + discordlib = compiler.find_library('discord_game_sdk', required: false, dirs: '@0@/lib/@1@'.format(discord_libpath, host_machine.cpu_family())) + + if discordlib.found() == true + add_project_arguments(['-I@0@/c'.format(discord_libpath), '-DHAVE_DISCORDSDK'], language: 'cpp') + ext_dependencies += discordlib + discord = true + endif +endif + +# ==================== +# Main source +# ==================== + if get_option('workdir_current') add_project_arguments('-DWORKDIR_CURRENT', language: 'cpp') endif @@ -33,6 +56,7 @@ include_dirs = [include_directories('src', 'binding')] all_sources += files('cwalk/src/cwalk.c') include_dirs += include_directories('cwalk/include') + linker_args = [] if host_system == 'windows' @@ -51,7 +75,7 @@ endif executable(meson.project_name(), sources: all_sources, - dependencies: [main_dependencies, binding_dependencies], + dependencies: [main_dependencies, binding_dependencies, ext_dependencies], include_directories: include_dirs, gui_app: (get_option('console') == false), install: (host_system == 'darwin') diff --git a/meson_options.txt b/meson_options.txt index b1d57e76..be9fb909 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -8,4 +8,6 @@ option('cjk_fallback_font', type: 'boolean', value: false, description: 'Use Wen option('use_fakeapi', type: 'boolean', value: false, description: 'Attempt to repair Win32API calls that do not work with MKXP') option('default_framerate', type: 'boolean', value: false, description: 'Disable syncToRefreshrate and fixedFramerate configuration options') option('no_preload_scripts', type: 'boolean', value: false, description: 'Disable the preloadScript configuration option') -option('workdir_current', type: 'boolean', value: false, description: 'Keep current directory on startup') \ No newline at end of file +option('workdir_current', type: 'boolean', value: false, description: 'Keep current directory on startup') + +option('discord_sdk_path', type: 'string', value: '', description: 'Path to Discord GameSDK') \ No newline at end of file diff --git a/src/config.cpp b/src/config.cpp index 60cd0d76..c5f27212 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -35,6 +35,11 @@ #include "sdl-util.h" #include "iniconfig.h" +#ifdef HAVE_DISCORDSDK +#include +#include "discordstate.h" +#endif + #ifdef INI_ENCODING extern "C" { #include @@ -216,6 +221,9 @@ void Config::read(int argc, char *argv[]) po::options_description podesc; podesc.add_options() PO_DESC_ALL +#ifdef HAVE_DISCORDSDK + PO_DESC(discordClientId, DiscordClientId, DEFAULT_CLIENT_ID) +#endif ("preloadScript", po::value()->composing()) ("RTP", po::value()->composing()) ("fontSub", po::value()->composing()) @@ -256,6 +264,10 @@ void Config::read(int argc, char *argv[]) #define PO_DESC(key, type, def) GUARD_ALL( key = vm[#key].as< type >(); ) PO_DESC_ALL; + +#ifdef HAVE_DISCORDSDK + PO_DESC(discordClientId, DiscordClientId, DEFAULT_CLIENT_ID) +#endif GUARD_ALL( preloadScripts = setFromVec(vm["preloadScript"].as()); ); diff --git a/src/config.h b/src/config.h index e3802504..f7f57144 100644 --- a/src/config.h +++ b/src/config.h @@ -26,6 +26,10 @@ #include #include +#ifdef HAVE_DISCORDSDK +#include +#endif + struct Config { int rgssVersion; @@ -79,6 +83,10 @@ struct Config } SE; bool useScriptNames; + +#ifdef HAVE_DISCORDSDK + DiscordClientId discordClientId; +#endif std::string customScript; std::set preloadScripts; diff --git a/src/discordstate.cpp b/src/discordstate.cpp new file mode 100644 index 00000000..d3e2364c --- /dev/null +++ b/src/discordstate.cpp @@ -0,0 +1,180 @@ +#include +#include "sharedstate.h" +#include "eventthread.h" +#include "discordstate.h" +#include "exception.h" +#include "debugwriter.h" +#include "bitmap.h" + +struct Application { + struct IDiscordCore* core; + struct IDiscordUserManager* users; + struct IDiscordAchievementManager* achievements; + struct IDiscordActivityManager* activities; + struct IDiscordRelationshipManager* relationships; + struct IDiscordApplicationManager* application; + struct IDiscordLobbyManager* lobbies; + DiscordUserId user_id; +}; + +struct DiscordStatePrivate +{ + DiscordClientId clientId; + + IDiscordCore *core; + + Application app; + IDiscordActivityEvents activityEvents; + IDiscordUserEvents userEvents; + + DiscordUser currentUser; + + bool discordInstalled; + bool connected; + bool userPresent; + + DiscordStatePrivate() + : discordInstalled(false), + connected(false), + userPresent(false) + {}; + + ~DiscordStatePrivate() + { + if (core) core->destroy(core); + } +}; + +void onCurrentUserUpdateCb(void *event_data) +{ + DiscordStatePrivate *p = (DiscordStatePrivate*)event_data; + p->app.users->get_current_user(p->app.users, &p->currentUser); + p->userPresent = true; +} + +void onActivityJoinCb(void *event_data, const char *secret) +{ + +} + +void onActivitySpectateCb(void *event_data, const char *secret) +{ + +} + +void onActivityJoinRequestCb(void *event_data, struct DiscordUser *user) +{ + +} + +void onActivityInviteRequestCb(void *event_data, enum EDiscordActivityActionType type, struct DiscordUser *user, struct DiscordActivity *activity) +{ + +} + +void discordLogHook(void *hook_data, enum EDiscordLogLevel level, const char *message) +{ + Debug() << "DISCORD:" << message; +} + +int discordTryConnect(DiscordStatePrivate *p) +{ + DiscordCreateParams params{}; + DiscordCreateParamsSetDefault(¶ms); + + params.client_id = p->clientId; + params.flags = DiscordCreateFlags_NoRequireDiscord; + params.event_data = (void*)p; + + p->activityEvents.on_activity_join = onActivityJoinCb; + p->activityEvents.on_activity_spectate = onActivitySpectateCb; + p->activityEvents.on_activity_join_request = onActivityJoinRequestCb; + p->activityEvents.on_activity_invite = onActivityInviteRequestCb; + params.activity_events = &p->activityEvents; + + + p->userEvents.on_current_user_update = onCurrentUserUpdateCb; + params.user_events = &p->userEvents; + + int rc = DiscordCreate(DISCORD_VERSION, ¶ms, &p->core); + + if (rc != DiscordResult_NotInstalled) + p->discordInstalled = true; + + if (rc != DiscordResult_Ok) + return rc; + + p->core->set_log_hook(p->core, DiscordLogLevel_Debug, (void*)p, discordLogHook); + + p->app.activities = p->core->get_activity_manager(p->core); + p->app.users = p->core->get_user_manager(p->core); + + p->connected = true; + + return rc; +} + +DiscordState::DiscordState(DiscordClientId clientId, int *result) +{ + p = new DiscordStatePrivate(); + p->clientId = clientId; + int rc = discordTryConnect(p); + if (result) *result = rc; +} + +DiscordState::~DiscordState() +{ + delete p; +} + +int DiscordState::update() +{ + if (!p->discordInstalled) return DiscordResult_NotInstalled; + + if (p->connected) + { + int rc = p->core->run_callbacks(p->core); + if (rc == DiscordResult_NotRunning) + { + p->connected = false; + memset(&p->currentUser, 0, sizeof(DiscordUser)); + p->userPresent = false; + return rc; + } + return rc; + } + + return discordTryConnect(p); +} + +bool DiscordState::isConnected() +{ + return p->connected; +} + +std::string DiscordState::userName() +{ + std::string ret; ret.clear(); + if (p->userPresent) ret = p->currentUser.username; + return ret; +} + +std::string DiscordState::userDiscrim() +{ + std::string ret; ret.clear(); + if (p->userPresent) ret = p->currentUser.discriminator; + return ret; +} + +DiscordUserId DiscordState::userId() +{ + return (p->userPresent) ? p->currentUser.id : 0; +} + +// NYI +Bitmap *userAvatar() +{ + Bitmap *ret = new Bitmap(256, 256); + + return ret; +} diff --git a/src/discordstate.h b/src/discordstate.h new file mode 100644 index 00000000..109e8fe0 --- /dev/null +++ b/src/discordstate.h @@ -0,0 +1,28 @@ +#pragma once + +#include +#include + +#include "bitmap.h" + +#define DEFAULT_CLIENT_ID 618672572183347211 + +struct DiscordStatePrivate; + +class DiscordState +{ +public: + DiscordState(DiscordClientId clientId, int *result); + ~DiscordState(); + + int update(); + bool isConnected(); + + std::string userName(); + std::string userDiscrim(); + DiscordUserId userId(); + Bitmap *userAvatar(); + +private: + DiscordStatePrivate *p; +}; diff --git a/src/graphics.cpp b/src/graphics.cpp index 2169aff9..6b86a695 100644 --- a/src/graphics.cpp +++ b/src/graphics.cpp @@ -31,6 +31,7 @@ #include "scene.h" #include "quad.h" #include "eventthread.h" +#include "discordstate.h" #include "texpool.h" #include "filesystem.h" #include "bitmap.h" @@ -687,6 +688,10 @@ void Graphics::update() } } +#ifdef HAVE_DISCORDSDK + if (p->frameCount % 10 == 0) shState->discord().update(); +#endif + p->checkResize(); p->redrawScreen(); } diff --git a/src/meson.build b/src/meson.build index a9c6e2cf..8fb60e0b 100644 --- a/src/meson.build +++ b/src/meson.build @@ -153,3 +153,7 @@ main = [main_source, main_headers] if get_option('use_fakeapi') == true main += files('fake-api.cpp', 'fake-api.h') endif + +if discord == true + main += files('discordstate.cpp', 'discordstate.h') +endif diff --git a/src/sharedstate.cpp b/src/sharedstate.cpp index 0778da99..3be59bad 100644 --- a/src/sharedstate.cpp +++ b/src/sharedstate.cpp @@ -37,6 +37,7 @@ #include "binding.h" #include "exception.h" #include "sharedmidistate.h" +#include "discordstate.h" #include #include @@ -85,6 +86,10 @@ struct SharedStatePrivate SharedFontState fontState; Font *defaultFont; + +#ifdef HAVE_DISCORDSDK + DiscordState discord; +#endif TEX::ID globalTex; int globalTexW, globalTexH; @@ -106,6 +111,9 @@ struct SharedStatePrivate rtData(*threadData), config(threadData->config), midiState(threadData->config), +#ifdef HAVE_DISCORDSDK + discord(threadData->config.discordClientId, 0), +#endif graphics(threadData), input(*threadData), audio(*threadData), @@ -234,6 +242,7 @@ GSATT(TexPool&, texPool) GSATT(Quad&, gpQuad) GSATT(SharedFontState&, fontState) GSATT(SharedMidiState&, midiState) +GSATT(DiscordState&, discord) void SharedState::setBindingData(void *data) { diff --git a/src/sharedstate.h b/src/sharedstate.h index d2d6f290..8a1905b5 100644 --- a/src/sharedstate.h +++ b/src/sharedstate.h @@ -46,6 +46,9 @@ class GLState; class TexPool; class Font; class SharedFontState; +#ifdef HAVE_DISCORDSDK +class DiscordState; +#endif struct GlobalIBO; struct Config; struct Vec2i; @@ -79,7 +82,9 @@ struct SharedState SharedFontState &fontState() const; Font &defaultFont() const; - +#ifdef HAVE_DISCORDSDK + DiscordState &discord() const; +#endif SharedMidiState &midiState() const; sigc::signal prepareDraw;