Add Discord Game SDK networking system
Allows players to host without forwarding their ports or using a program like Hamachi.
This commit is contained in:
parent
fc9d7022b5
commit
3e1b193ea8
|
@ -78,6 +78,7 @@ sm64config.txt
|
|||
!/sound/**/*custom*/**/*.aiff
|
||||
!/assets/**/*custom*.bin
|
||||
!/assets/**/*custom*/**/*.bin
|
||||
!/lib/discordsdk/*.*
|
||||
|
||||
# visual studio
|
||||
build-windows-visual-studio/.vs
|
||||
|
|
37
Makefile
37
Makefile
|
@ -54,8 +54,9 @@ DISCORDRPC ?= 0
|
|||
DOCKERBUILD ?= 0
|
||||
|
||||
# Force various options due since coop assumes they are set this way
|
||||
NODRAWINGDISTANCE = 1
|
||||
TEXTSAVES = 0
|
||||
NODRAWINGDISTANCE := 1
|
||||
TEXTSAVES := 0
|
||||
DISCORDRPC := 0
|
||||
|
||||
# Various workarounds for weird toolchains
|
||||
|
||||
|
@ -292,7 +293,8 @@ LEVEL_DIRS := $(patsubst levels/%,%,$(dir $(wildcard levels/*/header.h)))
|
|||
# Directories containing source files
|
||||
|
||||
# Hi, I'm a PC
|
||||
SRC_DIRS := src src/engine src/game src/audio src/menu src/buffers actors levels bin data assets src/pc src/pc/gfx src/pc/audio src/pc/controller src/pc/fs src/pc/fs/packtypes src/pc/network src/pc/network/packets src/pc/network/socket
|
||||
SRC_DIRS := src src/engine src/game src/audio src/menu src/buffers actors levels bin data assets src/pc src/pc/gfx src/pc/audio src/pc/controller src/pc/fs src/pc/fs/packtypes
|
||||
SRC_DIRS += src/pc/network src/pc/network/packets src/pc/network/socket src/pc/network/discord
|
||||
ASM_DIRS :=
|
||||
|
||||
ifeq ($(DISCORDRPC),1)
|
||||
|
@ -427,6 +429,16 @@ ifeq ($(DISCORDRPC),1)
|
|||
endif
|
||||
endif
|
||||
|
||||
DISCORD_SDK_LIBS :=
|
||||
ifeq ($(WINDOWS_BUILD),1)
|
||||
DISCORD_SDK_LIBS := lib/discordsdk/discord_game_sdk.dll
|
||||
else ifeq ($(OSX_BUILD),1)
|
||||
# needs testing
|
||||
DISCORD_SDK_LIBS := lib/discordsdk/discord_game_sdk.dylib
|
||||
else
|
||||
DISCORD_SDK_LIBS := lib/discordsdk/discord_game_sdk.so
|
||||
endif
|
||||
|
||||
# Automatic dependency files
|
||||
DEP_FILES := $(O_FILES:.o=.d) $(ULTRA_O_FILES:.o=.d) $(GODDARD_O_FILES:.o=.d) $(BUILD_DIR)/$(LD_SCRIPT).d
|
||||
|
||||
|
@ -659,7 +671,7 @@ ifeq ($(TARGET_WEB),1)
|
|||
LDFLAGS := -lm -lGL -lSDL2 -no-pie -s TOTAL_MEMORY=20MB -g4 --source-map-base http://localhost:8080/ -s "EXTRA_EXPORTED_RUNTIME_METHODS=['callMain']"
|
||||
|
||||
else ifeq ($(WINDOWS_BUILD),1)
|
||||
LDFLAGS := $(BITS) -march=$(TARGET_ARCH) -Llib -L"ws2_32" -lwsock32 -lpthread $(BACKEND_LDFLAGS) -static
|
||||
LDFLAGS := $(BITS) -march=$(TARGET_ARCH) -Llib -lpthread $(BACKEND_LDFLAGS) -static
|
||||
ifeq ($(CROSS),)
|
||||
LDFLAGS += -no-pie
|
||||
endif
|
||||
|
@ -679,7 +691,17 @@ else
|
|||
LDFLAGS += -ldl -Wl,-rpath .
|
||||
endif
|
||||
|
||||
endif # End of LDFLAGS
|
||||
endif
|
||||
|
||||
# coop specific libraries
|
||||
|
||||
ifeq ($(WINDOWS_BUILD),1)
|
||||
LDFLAGS += -L"ws2_32" -lwsock32
|
||||
endif
|
||||
|
||||
LDFLAGS += -Wl,-Bdynamic -ldiscord_game_sdk
|
||||
|
||||
# End of LDFLAGS
|
||||
|
||||
# Prevent a crash with -sopt
|
||||
export LANG := C
|
||||
|
@ -768,6 +790,9 @@ load: $(ROM)
|
|||
$(BUILD_DIR)/$(RPC_LIBS):
|
||||
@$(CP) -f $(RPC_LIBS) $(BUILD_DIR)
|
||||
|
||||
$(BUILD_DIR)/$(DISCORD_SDK_LIBS):
|
||||
@$(CP) -f $(DISCORD_SDK_LIBS) $(BUILD_DIR)
|
||||
|
||||
libultra: $(BUILD_DIR)/libultra.a
|
||||
|
||||
$(BUILD_DIR)/asm/boot.o: $(IPL3_RAW_FILES)
|
||||
|
@ -1022,7 +1047,7 @@ $(BUILD_DIR)/%.o: %.s
|
|||
|
||||
|
||||
|
||||
$(EXE): $(O_FILES) $(MIO0_FILES:.mio0=.o) $(SOUND_OBJ_FILES) $(ULTRA_O_FILES) $(GODDARD_O_FILES) $(BUILD_DIR)/$(RPC_LIBS)
|
||||
$(EXE): $(O_FILES) $(MIO0_FILES:.mio0=.o) $(SOUND_OBJ_FILES) $(ULTRA_O_FILES) $(GODDARD_O_FILES) $(BUILD_DIR)/$(RPC_LIBS) $(BUILD_DIR)/$(DISCORD_SDK_LIBS)
|
||||
$(LD) -L $(BUILD_DIR) -o $@ $(O_FILES) $(SOUND_OBJ_FILES) $(ULTRA_O_FILES) $(GODDARD_O_FILES) $(LDFLAGS)
|
||||
|
||||
.PHONY: all clean distclean default diff test load libultra res
|
||||
|
|
|
@ -3949,6 +3949,11 @@
|
|||
<ClCompile Include="..\src\pc\gfx\gfx_sdl2.c" />
|
||||
<ClCompile Include="..\src\pc\ini.c" />
|
||||
<ClCompile Include="..\src\pc\mixer.c" />
|
||||
<ClCompile Include="..\src\pc\network\discord\activity.c" />
|
||||
<ClCompile Include="..\src\pc\network\discord\discord.c" />
|
||||
<ClCompile Include="..\src\pc\network\discord\lobby.c" />
|
||||
<ClCompile Include="..\src\pc\network\discord\discord_network.c" />
|
||||
<ClCompile Include="..\src\pc\network\discord\user.c" />
|
||||
<ClCompile Include="..\src\pc\network\network.c" />
|
||||
<ClCompile Include="..\src\pc\network\packets\packet_collect_coin.c" />
|
||||
<ClCompile Include="..\src\pc\network\packets\packet_collect_item.c" />
|
||||
|
@ -4308,6 +4313,12 @@
|
|||
<ClInclude Include="..\include\behavior_table.h" />
|
||||
<ClInclude Include="..\src\pc\controller\controller_keyboard_debug.h" />
|
||||
<ClInclude Include="..\src\pc\debuglog.h" />
|
||||
<ClInclude Include="..\src\pc\network\discord\activity.h" />
|
||||
<ClInclude Include="..\src\pc\network\discord\discord.h" />
|
||||
<ClInclude Include="..\src\pc\network\discord\discord_game_sdk.h" />
|
||||
<ClInclude Include="..\src\pc\network\discord\lobby.h" />
|
||||
<ClInclude Include="..\src\pc\network\discord\discord_network.h" />
|
||||
<ClInclude Include="..\src\pc\network\discord\user.h" />
|
||||
<ClInclude Include="..\src\pc\network\network.h" />
|
||||
<ClInclude Include="..\src\pc\network\socket\socket.h" />
|
||||
<ClInclude Include="..\src\pc\network\socket\socket_linux.h" />
|
||||
|
|
|
@ -3427,6 +3427,12 @@
|
|||
<Filter Include="Header Files\src\pc\network\socket">
|
||||
<UniqueIdentifier>{b1b4937e-775c-4a0c-92f5-48b010783e4d}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Source Files\src\pc\network\discord">
|
||||
<UniqueIdentifier>{6d48a98e-e5ac-4409-a834-f2756dabfa4a}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Header Files\src\pc\network\discord">
|
||||
<UniqueIdentifier>{7fd7fed2-3f22-4bbf-a118-8ff54107c341}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\actors\amp\anims\anim_0800401C.inc.c">
|
||||
|
@ -15015,6 +15021,21 @@
|
|||
<ClCompile Include="..\src\pc\controller\controller_keyboard_debug.c">
|
||||
<Filter>Source Files\src\pc\controller</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\pc\network\discord\activity.c">
|
||||
<Filter>Source Files\src\pc\network\discord</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\pc\network\discord\discord.c">
|
||||
<Filter>Source Files\src\pc\network\discord</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\pc\network\discord\lobby.c">
|
||||
<Filter>Source Files\src\pc\network\discord</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\pc\network\discord\user.c">
|
||||
<Filter>Source Files\src\pc\network\discord</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\pc\network\discord\discord_network.c">
|
||||
<Filter>Source Files\src\pc\network\discord</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\actors\common0.h">
|
||||
|
@ -15937,5 +15958,23 @@
|
|||
<ClInclude Include="..\src\pc\controller\controller_keyboard_debug.h">
|
||||
<Filter>Source Files\src\pc\controller</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\src\pc\network\discord\activity.h">
|
||||
<Filter>Header Files\src\pc\network\discord</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\src\pc\network\discord\discord.h">
|
||||
<Filter>Header Files\src\pc\network\discord</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\src\pc\network\discord\discord_game_sdk.h">
|
||||
<Filter>Header Files\src\pc\network\discord</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\src\pc\network\discord\lobby.h">
|
||||
<Filter>Header Files\src\pc\network\discord</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\src\pc\network\discord\user.h">
|
||||
<Filter>Header Files\src\pc\network\discord</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\src\pc\network\discord\discord_network.h">
|
||||
<Filter>Header Files\src\pc\network\discord</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -11,10 +11,16 @@ if [ ! -f "$FILE" ]; then
|
|||
FILE=./build/us_pc/sm64.us.f3dex2e
|
||||
fi
|
||||
|
||||
$FILE --server 27015 --configfile sm64config_server.txt &
|
||||
#$FILE --discord 2 --configfile sm64config_server.txt &
|
||||
#$FILE --discord 1 --configfile sm64config_client.txt &
|
||||
#exit
|
||||
|
||||
#$FILE --server 27015 --configfile sm64config_server.txt &
|
||||
#$FILE --client 127.0.0.1 27015 --configfile sm64config_client.txt &
|
||||
#exit
|
||||
|
||||
$FILE --server 27015 --configfile sm64config_server.txt &
|
||||
|
||||
# debug if cgdb exists
|
||||
if ! [ -x "$(command -v cgdb)" ]; then
|
||||
$FILE --client 127.0.0.1 27015 --configfile sm64config_client.txt &
|
||||
|
|
|
@ -42,6 +42,8 @@
|
|||
*/
|
||||
|
||||
static u8 joinVersionMismatch = FALSE;
|
||||
static char joinMenuCustomText[64] = { 0 };
|
||||
static u8 forceOpenJoinMenu = 0;
|
||||
|
||||
#ifdef VERSION_US
|
||||
// The current sound mode is automatically centered on US due to
|
||||
|
@ -385,6 +387,9 @@ void exit_join_to_network_menu(void) {
|
|||
// Begin exit
|
||||
if (sMainMenuButtons[MENU_BUTTON_JOIN]->oMenuButtonState == MENU_BUTTON_STATE_FULLSCREEN
|
||||
&& sCursorClickingTimer == 2) {
|
||||
// clear custom text
|
||||
joinMenuCustomText[0] = '\0';
|
||||
|
||||
play_sound(SOUND_MENU_CAMERA_ZOOM_OUT, gDefaultSoundArgs);
|
||||
sMainMenuButtons[MENU_BUTTON_JOIN]->oMenuButtonState = MENU_BUTTON_STATE_SHRINKING;
|
||||
network_shutdown();
|
||||
|
@ -468,8 +473,37 @@ void render_network_mode_menu_buttons(struct Object* soundModeButton) {
|
|||
sMainMenuButtons[MENU_BUTTON_JOIN]->oFaceAngleRoll = 0;
|
||||
}
|
||||
|
||||
void open_join_menu(char* customText) {
|
||||
if (sMainMenuButtons[MENU_BUTTON_JOIN] == NULL) {
|
||||
forceOpenJoinMenu = (forceOpenJoinMenu == 0) ? 1 : forceOpenJoinMenu;
|
||||
} else if (sMainMenuButtons[MENU_BUTTON_JOIN]->oMenuButtonState != MENU_BUTTON_STATE_FULLSCREEN) {
|
||||
forceOpenJoinMenu = 0;
|
||||
play_sound(SOUND_MENU_CAMERA_ZOOM_IN, gDefaultSoundArgs);
|
||||
sMainMenuButtons[MENU_BUTTON_JOIN]->oMenuButtonState = MENU_BUTTON_STATE_GROWING;
|
||||
sSelectedButtonID = MENU_BUTTON_JOIN;
|
||||
sCurrentMenuLevel = MENU_LAYER_SUBMENU;
|
||||
} else {
|
||||
forceOpenJoinMenu = 0;
|
||||
}
|
||||
|
||||
if (customText == joinMenuCustomText) { return; }
|
||||
|
||||
if (customText != NULL) {
|
||||
strncpy(joinMenuCustomText, customText, 63);
|
||||
} else if (*gTextInput == '\0') {
|
||||
joinMenuCustomText[0] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
void check_network_mode_menu_clicked_buttons(struct Object* networkModeButton) {
|
||||
if (networkModeButton->oMenuButtonState == MENU_BUTTON_STATE_FULLSCREEN) {
|
||||
|
||||
if (forceOpenJoinMenu && forceOpenJoinMenu++ > 3) {
|
||||
forceOpenJoinMenu = 0;
|
||||
open_join_menu(joinMenuCustomText);
|
||||
return;
|
||||
}
|
||||
|
||||
s32 buttonID;
|
||||
// Configure sound mode menu button group
|
||||
for (buttonID = MENU_BUTTON_NETWORK_MIN; buttonID < MENU_BUTTON_NETWORK_MAX; buttonID++) {
|
||||
|
@ -486,9 +520,7 @@ void check_network_mode_menu_clicked_buttons(struct Object* networkModeButton) {
|
|||
}
|
||||
}
|
||||
else if (buttonID == MENU_BUTTON_JOIN) {
|
||||
play_sound(SOUND_MENU_CAMERA_ZOOM_IN, gDefaultSoundArgs);
|
||||
sMainMenuButtons[buttonID]->oMenuButtonState = MENU_BUTTON_STATE_GROWING;
|
||||
sSelectedButtonID = buttonID;
|
||||
open_join_menu(NULL);
|
||||
|
||||
// start input
|
||||
keyboard_start_text_input(TIM_IP, keyboard_exit_join_to_network_menu, join_server_as_client);
|
||||
|
@ -565,16 +597,21 @@ void print_join_mode_menu_strings(void) {
|
|||
gDPSetEnvColor(gDisplayListHead++, 255, 255, 255, sTextBaseAlpha);
|
||||
|
||||
// Print level name
|
||||
print_generic_ascii_string(JOIN_LEVEL_NAME_X, 191 - (12 * 0), "Type or paste the host's IP.");
|
||||
print_generic_ascii_string(JOIN_LEVEL_NAME_X, 191 - (12 * 2), gTextInput);
|
||||
if (joinMenuCustomText[0] != '\0') {
|
||||
print_generic_ascii_string(JOIN_LEVEL_NAME_X, 191 - (14 * 3), joinMenuCustomText);
|
||||
} else {
|
||||
print_generic_ascii_string(JOIN_LEVEL_NAME_X, 191 - (14 * 0), "Accept a Discord invite.");
|
||||
print_generic_ascii_string(JOIN_LEVEL_NAME_X, 191 - (14 * 1), "Alternatively, type or paste the host's IP.");
|
||||
print_generic_ascii_string(JOIN_LEVEL_NAME_X, 191 - (14 * 3), gTextInput);
|
||||
}
|
||||
|
||||
// Print status
|
||||
if (joinVersionMismatch) {
|
||||
print_generic_ascii_string(JOIN_LEVEL_NAME_X, 191 - (12 * 14), "Error - versions don't match. Both should rebuild!");
|
||||
print_generic_ascii_string(JOIN_LEVEL_NAME_X, 191 - (13 * 14), "Error - versions don't match. Both should rebuild!");
|
||||
} else if (gNetworkType == NT_CLIENT) {
|
||||
print_generic_ascii_string(JOIN_LEVEL_NAME_X, 191 - (12 * 14), "Connecting...");
|
||||
print_generic_ascii_string(JOIN_LEVEL_NAME_X, 191 - (13 * 14), "Connecting...");
|
||||
} else if (strlen(gTextInput) > 0) {
|
||||
print_generic_ascii_string(JOIN_LEVEL_NAME_X, 191 - (12 * 14), "Press (ENTER) to join.");
|
||||
print_generic_ascii_string(JOIN_LEVEL_NAME_X, 191 - (13 * 14), "Press (ENTER) to directly connect.");
|
||||
}
|
||||
|
||||
gSPDisplayList(gDisplayListHead++, dl_menu_ia8_text_end);
|
||||
|
@ -1619,6 +1656,7 @@ void check_main_menu_clicked_buttons(void) {
|
|||
button->oMenuButtonTimer = 0;
|
||||
|
||||
sSelectedButtonID = MENU_BUTTON_NETWORK_MODE;
|
||||
|
||||
networkInit = TRUE;
|
||||
}
|
||||
|
||||
|
|
|
@ -145,5 +145,6 @@ s32 lvl_init_menu_values_and_cursor_pos(UNUSED s32 arg, UNUSED s32 unused);
|
|||
s32 lvl_update_obj_and_load_file_selected(UNUSED s32 arg, UNUSED s32 unused);
|
||||
void joined_server_as_client(s16 fileIndex);
|
||||
void joined_server_version_mismatch(void);
|
||||
void open_join_menu(char* customText);
|
||||
|
||||
#endif // FILE_SELECT_H
|
||||
|
|
|
@ -79,6 +79,9 @@ void parse_cli_opts(int argc, char* argv[]) {
|
|||
else if (strcmp(argv[i], "--savepath") == 0 && (i + 1) < argc)
|
||||
arg_string("--savepath", argv[++i], gCLIOpts.SavePath, SYS_MAX_PATH);
|
||||
|
||||
else if (strcmp(argv[i], "--discord") == 0 && (i + 1) < argc)
|
||||
arg_uint("--discord", argv[++i], &gCLIOpts.Discord);
|
||||
|
||||
// Print help
|
||||
else if (strcmp(argv[i], "--help") == 0) {
|
||||
print_help();
|
||||
|
|
|
@ -22,6 +22,7 @@ struct PCCLIOptions {
|
|||
char ConfigFile[SYS_MAX_PATH];
|
||||
char SavePath[SYS_MAX_PATH];
|
||||
char GameDir[SYS_MAX_PATH];
|
||||
unsigned int Discord;
|
||||
};
|
||||
|
||||
extern struct PCCLIOptions gCLIOpts;
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
#include "activity.h"
|
||||
#include "lobby.h"
|
||||
#include "discord_network.h"
|
||||
#include "pc/debuglog.h"
|
||||
#include "menu/file_select.h"
|
||||
|
||||
#define HASH_LENGTH 8
|
||||
struct DiscordActivity gCurActivity = { 0 };
|
||||
|
||||
static void on_activity_update_callback(UNUSED void* data, enum EDiscordResult result) {
|
||||
LOG_INFO("> on_activity_update_callback returned %d", result);
|
||||
DISCORD_REQUIRE(result);
|
||||
}
|
||||
|
||||
static void on_activity_join_callback(UNUSED void* data, enum EDiscordResult result, struct DiscordLobby* lobby) {
|
||||
LOG_INFO("> on_activity_join_callback returned %d, lobby %lld", result, lobby->id);
|
||||
DISCORD_REQUIRE(result);
|
||||
network_init(NT_CLIENT);
|
||||
|
||||
gCurActivity.type = DiscordActivityType_Playing;
|
||||
snprintf(gCurActivity.party.id, 128, "%lld", lobby->id);
|
||||
gCurActivity.party.size.current_size = 2;
|
||||
gCurActivity.party.size.max_size = lobby->capacity;
|
||||
|
||||
gCurLobbyId = lobby->id;
|
||||
|
||||
discord_network_init(lobby->id);
|
||||
discord_activity_update(false);
|
||||
|
||||
network_on_joined();
|
||||
}
|
||||
|
||||
static void on_activity_join(UNUSED void* data, const char* secret) {
|
||||
LOG_INFO("> on_activity_join, secret: %s", secret);
|
||||
open_join_menu("Joining Discord invite...");
|
||||
app.lobbies->connect_lobby_with_activity_secret(app.lobbies, (char*)secret, NULL, on_activity_join_callback);
|
||||
}
|
||||
|
||||
static void on_activity_join_request_callback(UNUSED void* data, enum EDiscordResult result) {
|
||||
LOG_INFO("> on_activity_join_request_callback returned %d", (int)result);
|
||||
}
|
||||
|
||||
static void on_activity_join_request(UNUSED void* data, struct DiscordUser* user) {
|
||||
LOG_INFO("> on_activity_join_request from %lld", user->id);
|
||||
//app.activities->send_request_reply(app.activities, user->id, DiscordActivityJoinRequestReply_Yes, NULL, on_activity_join_request_callback);
|
||||
}
|
||||
|
||||
void discord_activity_update(bool hosting) {
|
||||
gCurActivity.type = DiscordActivityType_Playing;
|
||||
if (gCurActivity.party.size.current_size > 1) {
|
||||
strcpy(gCurActivity.state, "Playing!");
|
||||
} else if (hosting) {
|
||||
strcpy(gCurActivity.state, "Waiting for player...");
|
||||
} else {
|
||||
strcpy(gCurActivity.state, "In-game.");
|
||||
gCurActivity.party.size.current_size = 1;
|
||||
gCurActivity.party.size.max_size = 1;
|
||||
}
|
||||
|
||||
char hash[HASH_LENGTH] = GIT_HASH;
|
||||
strcpy(gCurActivity.details, "version ");
|
||||
strncat(gCurActivity.details, GIT_HASH, 127);
|
||||
|
||||
app.activities->update_activity(app.activities, &gCurActivity, NULL, on_activity_update_callback);
|
||||
LOG_INFO("set activity");
|
||||
}
|
||||
|
||||
struct IDiscordActivityEvents* discord_activity_initialize(void) {
|
||||
static struct IDiscordActivityEvents events = { 0 };
|
||||
events.on_activity_join = on_activity_join;
|
||||
events.on_activity_join_request = on_activity_join_request;
|
||||
return &events;
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
#ifndef DISCORD_ACTIVITY_H
|
||||
#define DISCORD_ACTIVITY_H
|
||||
#include "discord.h"
|
||||
|
||||
extern struct DiscordActivity gCurActivity;
|
||||
|
||||
void discord_activity_update(bool hosting);
|
||||
struct IDiscordActivityEvents* discord_activity_initialize(void);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,120 @@
|
|||
#include "discord.h"
|
||||
#include "user.h"
|
||||
#include "activity.h"
|
||||
#include "lobby.h"
|
||||
#include "discord_network.h"
|
||||
#include "pc/debuglog.h"
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#define MAX_LAUNCH_CMD (MAX_PATH + 12)
|
||||
|
||||
static int64_t applicationId = 752700005210390568;
|
||||
struct DiscordApplication app = { 0 };
|
||||
bool gDiscordInitialized = false;
|
||||
|
||||
static void set_instance_env_variable(void) {
|
||||
// set local instance id
|
||||
char environmentVariables[64] = { 0 };
|
||||
int instance = (gCLIOpts.Discord == 0) ? 0 : (gCLIOpts.Discord - 1);
|
||||
sprintf(environmentVariables, "DISCORD_INSTANCE_ID=%d", instance);
|
||||
putenv(environmentVariables);
|
||||
LOG_INFO("set environment variables: %s", environmentVariables);
|
||||
}
|
||||
|
||||
static void get_oauth2_token_callback(UNUSED void* data, enum EDiscordResult result, struct DiscordOAuth2Token* token) {
|
||||
LOG_INFO("> get_oauth2_token_callback returned %d", result);
|
||||
if (result != DiscordResult_Ok) { return; }
|
||||
LOG_INFO("OAuth2 token: %s", token->access_token);
|
||||
}
|
||||
|
||||
static void register_launch_command(void) {
|
||||
char cmd[MAX_LAUNCH_CMD];
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
HMODULE hModule = GetModuleHandle(NULL);
|
||||
if (hModule == NULL) {
|
||||
LOG_ERROR("unable to retrieve absolute path!");
|
||||
return;
|
||||
}
|
||||
GetModuleFileName(hModule, cmd, sizeof(cmd));
|
||||
#else
|
||||
int rc = readlink("/proc/self/exe", cmd, sizeof(MAX_LAUNCH_CMD) - 1);
|
||||
if (rc) {
|
||||
LOG_ERROR("unable to retrieve absolute path! rc = %d", rc);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
strncat(cmd, " --discord 1", MAX_LAUNCH_CMD - 1);
|
||||
DISCORD_REQUIRE(app.activities->register_command(app.activities, cmd));
|
||||
LOG_INFO("cmd: %s", cmd);
|
||||
}
|
||||
|
||||
static void ns_discord_update(void) {
|
||||
if (!gDiscordInitialized) { return; }
|
||||
DISCORD_REQUIRE(app.core->run_callbacks(app.core));
|
||||
discord_network_flush();
|
||||
}
|
||||
|
||||
static bool ns_discord_initialize(enum NetworkType networkType) {
|
||||
#ifdef DEBUG
|
||||
set_instance_env_variable();
|
||||
#endif
|
||||
if (!gDiscordInitialized) {
|
||||
// set up discord params
|
||||
struct DiscordCreateParams params;
|
||||
DiscordCreateParamsSetDefault(¶ms);
|
||||
params.client_id = applicationId;
|
||||
params.flags = DiscordCreateFlags_NoRequireDiscord;
|
||||
params.event_data = &app;
|
||||
params.user_events = discord_user_initialize();
|
||||
params.activity_events = discord_activity_initialize();
|
||||
params.lobby_events = discord_lobby_initialize();
|
||||
|
||||
int rc = DiscordCreate(DISCORD_VERSION, ¶ms, &app.core);
|
||||
if (rc) {
|
||||
LOG_ERROR("DiscordCreate failed: %d", rc);
|
||||
return false;
|
||||
}
|
||||
|
||||
// set up manager pointers
|
||||
app.users = app.core->get_user_manager(app.core);
|
||||
app.achievements = app.core->get_achievement_manager(app.core);
|
||||
app.activities = app.core->get_activity_manager(app.core);
|
||||
app.application = app.core->get_application_manager(app.core);
|
||||
app.lobbies = app.core->get_lobby_manager(app.core);
|
||||
|
||||
// register launch params
|
||||
register_launch_command();
|
||||
|
||||
// get oath2 token
|
||||
app.application->get_oauth2_token(app.application, NULL, get_oauth2_token_callback);
|
||||
|
||||
// set activity
|
||||
discord_activity_update(false);
|
||||
}
|
||||
|
||||
// create lobby
|
||||
if (networkType == NT_SERVER) { discord_lobby_create(); }
|
||||
|
||||
gDiscordInitialized = true;
|
||||
LOG_INFO("initialized");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void ns_discord_shutdown(void) {
|
||||
if (!gDiscordInitialized) { return; }
|
||||
discord_lobby_leave();
|
||||
LOG_INFO("shutdown");
|
||||
}
|
||||
|
||||
struct NetworkSystem gNetworkSystemDiscord = {
|
||||
.initialize = ns_discord_initialize,
|
||||
.update = ns_discord_update,
|
||||
.send = ns_discord_network_send,
|
||||
.shutdown = ns_discord_shutdown,
|
||||
};
|
|
@ -0,0 +1,35 @@
|
|||
#ifndef DISCORD_H
|
||||
#define DISCORD_H
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#pragma pack(push, 8)
|
||||
#include "discord_game_sdk.h"
|
||||
#pragma pack(pop)
|
||||
#ifdef _WIN32
|
||||
#include <Windows.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#endif
|
||||
#include "../network.h"
|
||||
|
||||
#define DISCORD_REQUIRE(x) assert(x == DiscordResult_Ok)
|
||||
|
||||
extern struct NetworkSystem gNetworkSystemDiscord;
|
||||
extern bool gDiscordInitialized;
|
||||
|
||||
struct DiscordApplication {
|
||||
struct IDiscordCore* core;
|
||||
struct IDiscordUserManager* users;
|
||||
struct IDiscordAchievementManager* achievements;
|
||||
struct IDiscordActivityManager* activities;
|
||||
struct IDiscordRelationshipManager* relationships;
|
||||
struct IDiscordApplicationManager* application;
|
||||
struct IDiscordLobbyManager* lobbies;
|
||||
DiscordUserId userId;
|
||||
};
|
||||
|
||||
extern struct DiscordApplication app;
|
||||
|
||||
#endif
|
|
@ -0,0 +1,646 @@
|
|||
#ifndef _DISCORD_GAME_SDK_H_
|
||||
#define _DISCORD_GAME_SDK_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#ifndef __cplusplus
|
||||
#include <stdbool.h>
|
||||
#endif
|
||||
|
||||
#define DISCORD_VERSION 2
|
||||
#define DISCORD_APPLICATION_MANAGER_VERSION 1
|
||||
#define DISCORD_USER_MANAGER_VERSION 1
|
||||
#define DISCORD_IMAGE_MANAGER_VERSION 1
|
||||
#define DISCORD_ACTIVITY_MANAGER_VERSION 1
|
||||
#define DISCORD_RELATIONSHIP_MANAGER_VERSION 1
|
||||
#define DISCORD_LOBBY_MANAGER_VERSION 1
|
||||
#define DISCORD_NETWORK_MANAGER_VERSION 1
|
||||
#define DISCORD_OVERLAY_MANAGER_VERSION 1
|
||||
#define DISCORD_STORAGE_MANAGER_VERSION 1
|
||||
#define DISCORD_STORE_MANAGER_VERSION 1
|
||||
#define DISCORD_VOICE_MANAGER_VERSION 1
|
||||
#define DISCORD_ACHIEVEMENT_MANAGER_VERSION 1
|
||||
|
||||
enum EDiscordResult {
|
||||
DiscordResult_Ok = 0,
|
||||
DiscordResult_ServiceUnavailable = 1,
|
||||
DiscordResult_InvalidVersion = 2,
|
||||
DiscordResult_LockFailed = 3,
|
||||
DiscordResult_InternalError = 4,
|
||||
DiscordResult_InvalidPayload = 5,
|
||||
DiscordResult_InvalidCommand = 6,
|
||||
DiscordResult_InvalidPermissions = 7,
|
||||
DiscordResult_NotFetched = 8,
|
||||
DiscordResult_NotFound = 9,
|
||||
DiscordResult_Conflict = 10,
|
||||
DiscordResult_InvalidSecret = 11,
|
||||
DiscordResult_InvalidJoinSecret = 12,
|
||||
DiscordResult_NoEligibleActivity = 13,
|
||||
DiscordResult_InvalidInvite = 14,
|
||||
DiscordResult_NotAuthenticated = 15,
|
||||
DiscordResult_InvalidAccessToken = 16,
|
||||
DiscordResult_ApplicationMismatch = 17,
|
||||
DiscordResult_InvalidDataUrl = 18,
|
||||
DiscordResult_InvalidBase64 = 19,
|
||||
DiscordResult_NotFiltered = 20,
|
||||
DiscordResult_LobbyFull = 21,
|
||||
DiscordResult_InvalidLobbySecret = 22,
|
||||
DiscordResult_InvalidFilename = 23,
|
||||
DiscordResult_InvalidFileSize = 24,
|
||||
DiscordResult_InvalidEntitlement = 25,
|
||||
DiscordResult_NotInstalled = 26,
|
||||
DiscordResult_NotRunning = 27,
|
||||
DiscordResult_InsufficientBuffer = 28,
|
||||
DiscordResult_PurchaseCanceled = 29,
|
||||
DiscordResult_InvalidGuild = 30,
|
||||
DiscordResult_InvalidEvent = 31,
|
||||
DiscordResult_InvalidChannel = 32,
|
||||
DiscordResult_InvalidOrigin = 33,
|
||||
DiscordResult_RateLimited = 34,
|
||||
DiscordResult_OAuth2Error = 35,
|
||||
DiscordResult_SelectChannelTimeout = 36,
|
||||
DiscordResult_GetGuildTimeout = 37,
|
||||
DiscordResult_SelectVoiceForceRequired = 38,
|
||||
DiscordResult_CaptureShortcutAlreadyListening = 39,
|
||||
DiscordResult_UnauthorizedForAchievement = 40,
|
||||
DiscordResult_InvalidGiftCode = 41,
|
||||
DiscordResult_PurchaseError = 42,
|
||||
DiscordResult_TransactionAborted = 43,
|
||||
};
|
||||
|
||||
enum EDiscordCreateFlags {
|
||||
DiscordCreateFlags_Default = 0,
|
||||
DiscordCreateFlags_NoRequireDiscord = 1,
|
||||
};
|
||||
|
||||
enum EDiscordLogLevel {
|
||||
DiscordLogLevel_Error = 1,
|
||||
DiscordLogLevel_Warn,
|
||||
DiscordLogLevel_Info,
|
||||
DiscordLogLevel_Debug,
|
||||
};
|
||||
|
||||
enum EDiscordUserFlag {
|
||||
DiscordUserFlag_Partner = 2,
|
||||
DiscordUserFlag_HypeSquadEvents = 4,
|
||||
DiscordUserFlag_HypeSquadHouse1 = 64,
|
||||
DiscordUserFlag_HypeSquadHouse2 = 128,
|
||||
DiscordUserFlag_HypeSquadHouse3 = 256,
|
||||
};
|
||||
|
||||
enum EDiscordPremiumType {
|
||||
DiscordPremiumType_None = 0,
|
||||
DiscordPremiumType_Tier1 = 1,
|
||||
DiscordPremiumType_Tier2 = 2,
|
||||
};
|
||||
|
||||
enum EDiscordImageType {
|
||||
DiscordImageType_User,
|
||||
};
|
||||
|
||||
enum EDiscordActivityType {
|
||||
DiscordActivityType_Playing,
|
||||
DiscordActivityType_Streaming,
|
||||
DiscordActivityType_Listening,
|
||||
DiscordActivityType_Watching,
|
||||
};
|
||||
|
||||
enum EDiscordActivityActionType {
|
||||
DiscordActivityActionType_Join = 1,
|
||||
DiscordActivityActionType_Spectate,
|
||||
};
|
||||
|
||||
enum EDiscordActivityJoinRequestReply {
|
||||
DiscordActivityJoinRequestReply_No,
|
||||
DiscordActivityJoinRequestReply_Yes,
|
||||
DiscordActivityJoinRequestReply_Ignore,
|
||||
};
|
||||
|
||||
enum EDiscordStatus {
|
||||
DiscordStatus_Offline = 0,
|
||||
DiscordStatus_Online = 1,
|
||||
DiscordStatus_Idle = 2,
|
||||
DiscordStatus_DoNotDisturb = 3,
|
||||
};
|
||||
|
||||
enum EDiscordRelationshipType {
|
||||
DiscordRelationshipType_None,
|
||||
DiscordRelationshipType_Friend,
|
||||
DiscordRelationshipType_Blocked,
|
||||
DiscordRelationshipType_PendingIncoming,
|
||||
DiscordRelationshipType_PendingOutgoing,
|
||||
DiscordRelationshipType_Implicit,
|
||||
};
|
||||
|
||||
enum EDiscordLobbyType {
|
||||
DiscordLobbyType_Private = 1,
|
||||
DiscordLobbyType_Public,
|
||||
};
|
||||
|
||||
enum EDiscordLobbySearchComparison {
|
||||
DiscordLobbySearchComparison_LessThanOrEqual = -2,
|
||||
DiscordLobbySearchComparison_LessThan,
|
||||
DiscordLobbySearchComparison_Equal,
|
||||
DiscordLobbySearchComparison_GreaterThan,
|
||||
DiscordLobbySearchComparison_GreaterThanOrEqual,
|
||||
DiscordLobbySearchComparison_NotEqual,
|
||||
};
|
||||
|
||||
enum EDiscordLobbySearchCast {
|
||||
DiscordLobbySearchCast_String = 1,
|
||||
DiscordLobbySearchCast_Number,
|
||||
};
|
||||
|
||||
enum EDiscordLobbySearchDistance {
|
||||
DiscordLobbySearchDistance_Local,
|
||||
DiscordLobbySearchDistance_Default,
|
||||
DiscordLobbySearchDistance_Extended,
|
||||
DiscordLobbySearchDistance_Global,
|
||||
};
|
||||
|
||||
enum EDiscordEntitlementType {
|
||||
DiscordEntitlementType_Purchase = 1,
|
||||
DiscordEntitlementType_PremiumSubscription,
|
||||
DiscordEntitlementType_DeveloperGift,
|
||||
DiscordEntitlementType_TestModePurchase,
|
||||
DiscordEntitlementType_FreePurchase,
|
||||
DiscordEntitlementType_UserGift,
|
||||
DiscordEntitlementType_PremiumPurchase,
|
||||
};
|
||||
|
||||
enum EDiscordSkuType {
|
||||
DiscordSkuType_Application = 1,
|
||||
DiscordSkuType_DLC,
|
||||
DiscordSkuType_Consumable,
|
||||
DiscordSkuType_Bundle,
|
||||
};
|
||||
|
||||
enum EDiscordInputModeType {
|
||||
DiscordInputModeType_VoiceActivity = 0,
|
||||
DiscordInputModeType_PushToTalk,
|
||||
};
|
||||
|
||||
typedef int64_t DiscordClientId;
|
||||
typedef int32_t DiscordVersion;
|
||||
typedef int64_t DiscordSnowflake;
|
||||
typedef int64_t DiscordTimestamp;
|
||||
typedef DiscordSnowflake DiscordUserId;
|
||||
typedef char DiscordLocale[128];
|
||||
typedef char DiscordBranch[4096];
|
||||
typedef DiscordSnowflake DiscordLobbyId;
|
||||
typedef char DiscordLobbySecret[128];
|
||||
typedef char DiscordMetadataKey[256];
|
||||
typedef char DiscordMetadataValue[4096];
|
||||
typedef uint64_t DiscordNetworkPeerId;
|
||||
typedef uint8_t DiscordNetworkChannelId;
|
||||
typedef char DiscordPath[4096];
|
||||
typedef char DiscordDateTime[64];
|
||||
|
||||
struct DiscordUser {
|
||||
DiscordUserId id;
|
||||
char username[256];
|
||||
char discriminator[8];
|
||||
char avatar[128];
|
||||
bool bot;
|
||||
};
|
||||
|
||||
struct DiscordOAuth2Token {
|
||||
char access_token[128];
|
||||
char scopes[1024];
|
||||
DiscordTimestamp expires;
|
||||
};
|
||||
|
||||
struct DiscordImageHandle {
|
||||
enum EDiscordImageType type;
|
||||
int64_t id;
|
||||
uint32_t size;
|
||||
};
|
||||
|
||||
struct DiscordImageDimensions {
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
};
|
||||
|
||||
struct DiscordActivityTimestamps {
|
||||
DiscordTimestamp start;
|
||||
DiscordTimestamp end;
|
||||
};
|
||||
|
||||
struct DiscordActivityAssets {
|
||||
char large_image[128];
|
||||
char large_text[128];
|
||||
char small_image[128];
|
||||
char small_text[128];
|
||||
};
|
||||
|
||||
struct DiscordPartySize {
|
||||
int32_t current_size;
|
||||
int32_t max_size;
|
||||
};
|
||||
|
||||
struct DiscordActivityParty {
|
||||
char id[128];
|
||||
struct DiscordPartySize size;
|
||||
};
|
||||
|
||||
struct DiscordActivitySecrets {
|
||||
char match[128];
|
||||
char join[128];
|
||||
char spectate[128];
|
||||
};
|
||||
|
||||
struct DiscordActivity {
|
||||
enum EDiscordActivityType type;
|
||||
int64_t application_id;
|
||||
char name[128];
|
||||
char state[128];
|
||||
char details[128];
|
||||
struct DiscordActivityTimestamps timestamps;
|
||||
struct DiscordActivityAssets assets;
|
||||
struct DiscordActivityParty party;
|
||||
struct DiscordActivitySecrets secrets;
|
||||
bool instance;
|
||||
};
|
||||
|
||||
struct DiscordPresence {
|
||||
enum EDiscordStatus status;
|
||||
struct DiscordActivity activity;
|
||||
};
|
||||
|
||||
struct DiscordRelationship {
|
||||
enum EDiscordRelationshipType type;
|
||||
struct DiscordUser user;
|
||||
struct DiscordPresence presence;
|
||||
};
|
||||
|
||||
struct DiscordLobby {
|
||||
DiscordLobbyId id;
|
||||
enum EDiscordLobbyType type;
|
||||
DiscordUserId owner_id;
|
||||
DiscordLobbySecret secret;
|
||||
uint32_t capacity;
|
||||
bool locked;
|
||||
};
|
||||
|
||||
struct DiscordFileStat {
|
||||
char filename[260];
|
||||
uint64_t size;
|
||||
uint64_t last_modified;
|
||||
};
|
||||
|
||||
struct DiscordEntitlement {
|
||||
DiscordSnowflake id;
|
||||
enum EDiscordEntitlementType type;
|
||||
DiscordSnowflake sku_id;
|
||||
};
|
||||
|
||||
struct DiscordSkuPrice {
|
||||
uint32_t amount;
|
||||
char currency[16];
|
||||
};
|
||||
|
||||
struct DiscordSku {
|
||||
DiscordSnowflake id;
|
||||
enum EDiscordSkuType type;
|
||||
char name[256];
|
||||
struct DiscordSkuPrice price;
|
||||
};
|
||||
|
||||
struct DiscordInputMode {
|
||||
enum EDiscordInputModeType type;
|
||||
char shortcut[256];
|
||||
};
|
||||
|
||||
struct DiscordUserAchievement {
|
||||
DiscordSnowflake user_id;
|
||||
DiscordSnowflake achievement_id;
|
||||
uint8_t percent_complete;
|
||||
DiscordDateTime unlocked_at;
|
||||
};
|
||||
|
||||
struct IDiscordLobbyTransaction {
|
||||
enum EDiscordResult (*set_type)(struct IDiscordLobbyTransaction* lobby_transaction, enum EDiscordLobbyType type);
|
||||
enum EDiscordResult (*set_owner)(struct IDiscordLobbyTransaction* lobby_transaction, DiscordUserId owner_id);
|
||||
enum EDiscordResult (*set_capacity)(struct IDiscordLobbyTransaction* lobby_transaction, uint32_t capacity);
|
||||
enum EDiscordResult (*set_metadata)(struct IDiscordLobbyTransaction* lobby_transaction, DiscordMetadataKey key, DiscordMetadataValue value);
|
||||
enum EDiscordResult (*delete_metadata)(struct IDiscordLobbyTransaction* lobby_transaction, DiscordMetadataKey key);
|
||||
enum EDiscordResult (*set_locked)(struct IDiscordLobbyTransaction* lobby_transaction, bool locked);
|
||||
};
|
||||
|
||||
struct IDiscordLobbyMemberTransaction {
|
||||
enum EDiscordResult (*set_metadata)(struct IDiscordLobbyMemberTransaction* lobby_member_transaction, DiscordMetadataKey key, DiscordMetadataValue value);
|
||||
enum EDiscordResult (*delete_metadata)(struct IDiscordLobbyMemberTransaction* lobby_member_transaction, DiscordMetadataKey key);
|
||||
};
|
||||
|
||||
struct IDiscordLobbySearchQuery {
|
||||
enum EDiscordResult (*filter)(struct IDiscordLobbySearchQuery* lobby_search_query, DiscordMetadataKey key, enum EDiscordLobbySearchComparison comparison, enum EDiscordLobbySearchCast cast, DiscordMetadataValue value);
|
||||
enum EDiscordResult (*sort)(struct IDiscordLobbySearchQuery* lobby_search_query, DiscordMetadataKey key, enum EDiscordLobbySearchCast cast, DiscordMetadataValue value);
|
||||
enum EDiscordResult (*limit)(struct IDiscordLobbySearchQuery* lobby_search_query, uint32_t limit);
|
||||
enum EDiscordResult (*distance)(struct IDiscordLobbySearchQuery* lobby_search_query, enum EDiscordLobbySearchDistance distance);
|
||||
};
|
||||
|
||||
typedef void* IDiscordApplicationEvents;
|
||||
|
||||
struct IDiscordApplicationManager {
|
||||
void (*validate_or_exit)(struct IDiscordApplicationManager* manager, void* callback_data, void (*callback)(void* callback_data, enum EDiscordResult result));
|
||||
void (*get_current_locale)(struct IDiscordApplicationManager* manager, DiscordLocale* locale);
|
||||
void (*get_current_branch)(struct IDiscordApplicationManager* manager, DiscordBranch* branch);
|
||||
void (*get_oauth2_token)(struct IDiscordApplicationManager* manager, void* callback_data, void (*callback)(void* callback_data, enum EDiscordResult result, struct DiscordOAuth2Token* oauth2_token));
|
||||
void (*get_ticket)(struct IDiscordApplicationManager* manager, void* callback_data, void (*callback)(void* callback_data, enum EDiscordResult result, const char* data));
|
||||
};
|
||||
|
||||
struct IDiscordUserEvents {
|
||||
void (*on_current_user_update)(void* event_data);
|
||||
};
|
||||
|
||||
struct IDiscordUserManager {
|
||||
enum EDiscordResult (*get_current_user)(struct IDiscordUserManager* manager, struct DiscordUser* current_user);
|
||||
void (*get_user)(struct IDiscordUserManager* manager, DiscordUserId user_id, void* callback_data, void (*callback)(void* callback_data, enum EDiscordResult result, struct DiscordUser* user));
|
||||
enum EDiscordResult (*get_current_user_premium_type)(struct IDiscordUserManager* manager, enum EDiscordPremiumType* premium_type);
|
||||
enum EDiscordResult (*current_user_has_flag)(struct IDiscordUserManager* manager, enum EDiscordUserFlag flag, bool* has_flag);
|
||||
};
|
||||
|
||||
typedef void* IDiscordImageEvents;
|
||||
|
||||
struct IDiscordImageManager {
|
||||
void (*fetch)(struct IDiscordImageManager* manager, struct DiscordImageHandle handle, bool refresh, void* callback_data, void (*callback)(void* callback_data, enum EDiscordResult result, struct DiscordImageHandle handle_result));
|
||||
enum EDiscordResult (*get_dimensions)(struct IDiscordImageManager* manager, struct DiscordImageHandle handle, struct DiscordImageDimensions* dimensions);
|
||||
enum EDiscordResult (*get_data)(struct IDiscordImageManager* manager, struct DiscordImageHandle handle, uint8_t* data, uint32_t data_length);
|
||||
};
|
||||
|
||||
struct IDiscordActivityEvents {
|
||||
void (*on_activity_join)(void* event_data, const char* secret);
|
||||
void (*on_activity_spectate)(void* event_data, const char* secret);
|
||||
void (*on_activity_join_request)(void* event_data, struct DiscordUser* user);
|
||||
void (*on_activity_invite)(void* event_data, enum EDiscordActivityActionType type, struct DiscordUser* user, struct DiscordActivity* activity);
|
||||
};
|
||||
|
||||
struct IDiscordActivityManager {
|
||||
enum EDiscordResult (*register_command)(struct IDiscordActivityManager* manager, const char* command);
|
||||
enum EDiscordResult (*register_steam)(struct IDiscordActivityManager* manager, uint32_t steam_id);
|
||||
void (*update_activity)(struct IDiscordActivityManager* manager, struct DiscordActivity* activity, void* callback_data, void (*callback)(void* callback_data, enum EDiscordResult result));
|
||||
void (*clear_activity)(struct IDiscordActivityManager* manager, void* callback_data, void (*callback)(void* callback_data, enum EDiscordResult result));
|
||||
void (*send_request_reply)(struct IDiscordActivityManager* manager, DiscordUserId user_id, enum EDiscordActivityJoinRequestReply reply, void* callback_data, void (*callback)(void* callback_data, enum EDiscordResult result));
|
||||
void (*send_invite)(struct IDiscordActivityManager* manager, DiscordUserId user_id, enum EDiscordActivityActionType type, const char* content, void* callback_data, void (*callback)(void* callback_data, enum EDiscordResult result));
|
||||
void (*accept_invite)(struct IDiscordActivityManager* manager, DiscordUserId user_id, void* callback_data, void (*callback)(void* callback_data, enum EDiscordResult result));
|
||||
};
|
||||
|
||||
struct IDiscordRelationshipEvents {
|
||||
void (*on_refresh)(void* event_data);
|
||||
void (*on_relationship_update)(void* event_data, struct DiscordRelationship* relationship);
|
||||
};
|
||||
|
||||
struct IDiscordRelationshipManager {
|
||||
void (*filter)(struct IDiscordRelationshipManager* manager, void* filter_data, bool (*filter)(void* filter_data, struct DiscordRelationship* relationship));
|
||||
enum EDiscordResult (*count)(struct IDiscordRelationshipManager* manager, int32_t* count);
|
||||
enum EDiscordResult (*get)(struct IDiscordRelationshipManager* manager, DiscordUserId user_id, struct DiscordRelationship* relationship);
|
||||
enum EDiscordResult (*get_at)(struct IDiscordRelationshipManager* manager, uint32_t index, struct DiscordRelationship* relationship);
|
||||
};
|
||||
|
||||
struct IDiscordLobbyEvents {
|
||||
void (*on_lobby_update)(void* event_data, int64_t lobby_id);
|
||||
void (*on_lobby_delete)(void* event_data, int64_t lobby_id, uint32_t reason);
|
||||
void (*on_member_connect)(void* event_data, int64_t lobby_id, int64_t user_id);
|
||||
void (*on_member_update)(void* event_data, int64_t lobby_id, int64_t user_id);
|
||||
void (*on_member_disconnect)(void* event_data, int64_t lobby_id, int64_t user_id);
|
||||
void (*on_lobby_message)(void* event_data, int64_t lobby_id, int64_t user_id, uint8_t* data, uint32_t data_length);
|
||||
void (*on_speaking)(void* event_data, int64_t lobby_id, int64_t user_id, bool speaking);
|
||||
void (*on_network_message)(void* event_data, int64_t lobby_id, int64_t user_id, uint8_t channel_id, uint8_t* data, uint32_t data_length);
|
||||
};
|
||||
|
||||
struct IDiscordLobbyManager {
|
||||
enum EDiscordResult (*get_lobby_create_transaction)(struct IDiscordLobbyManager* manager, struct IDiscordLobbyTransaction** transaction);
|
||||
enum EDiscordResult (*get_lobby_update_transaction)(struct IDiscordLobbyManager* manager, DiscordLobbyId lobby_id, struct IDiscordLobbyTransaction** transaction);
|
||||
enum EDiscordResult (*get_member_update_transaction)(struct IDiscordLobbyManager* manager, DiscordLobbyId lobby_id, DiscordUserId user_id, struct IDiscordLobbyMemberTransaction** transaction);
|
||||
void (*create_lobby)(struct IDiscordLobbyManager* manager, struct IDiscordLobbyTransaction* transaction, void* callback_data, void (*callback)(void* callback_data, enum EDiscordResult result, struct DiscordLobby* lobby));
|
||||
void (*update_lobby)(struct IDiscordLobbyManager* manager, DiscordLobbyId lobby_id, struct IDiscordLobbyTransaction* transaction, void* callback_data, void (*callback)(void* callback_data, enum EDiscordResult result));
|
||||
void (*delete_lobby)(struct IDiscordLobbyManager* manager, DiscordLobbyId lobby_id, void* callback_data, void (*callback)(void* callback_data, enum EDiscordResult result));
|
||||
void (*connect_lobby)(struct IDiscordLobbyManager* manager, DiscordLobbyId lobby_id, DiscordLobbySecret secret, void* callback_data, void (*callback)(void* callback_data, enum EDiscordResult result, struct DiscordLobby* lobby));
|
||||
void (*connect_lobby_with_activity_secret)(struct IDiscordLobbyManager* manager, DiscordLobbySecret activity_secret, void* callback_data, void (*callback)(void* callback_data, enum EDiscordResult result, struct DiscordLobby* lobby));
|
||||
void (*disconnect_lobby)(struct IDiscordLobbyManager* manager, DiscordLobbyId lobby_id, void* callback_data, void (*callback)(void* callback_data, enum EDiscordResult result));
|
||||
enum EDiscordResult (*get_lobby)(struct IDiscordLobbyManager* manager, DiscordLobbyId lobby_id, struct DiscordLobby* lobby);
|
||||
enum EDiscordResult (*get_lobby_activity_secret)(struct IDiscordLobbyManager* manager, DiscordLobbyId lobby_id, DiscordLobbySecret* secret);
|
||||
enum EDiscordResult (*get_lobby_metadata_value)(struct IDiscordLobbyManager* manager, DiscordLobbyId lobby_id, DiscordMetadataKey key, DiscordMetadataValue* value);
|
||||
enum EDiscordResult (*get_lobby_metadata_key)(struct IDiscordLobbyManager* manager, DiscordLobbyId lobby_id, int32_t index, DiscordMetadataKey* key);
|
||||
enum EDiscordResult (*lobby_metadata_count)(struct IDiscordLobbyManager* manager, DiscordLobbyId lobby_id, int32_t* count);
|
||||
enum EDiscordResult (*member_count)(struct IDiscordLobbyManager* manager, DiscordLobbyId lobby_id, int32_t* count);
|
||||
enum EDiscordResult (*get_member_user_id)(struct IDiscordLobbyManager* manager, DiscordLobbyId lobby_id, int32_t index, DiscordUserId* user_id);
|
||||
enum EDiscordResult (*get_member_user)(struct IDiscordLobbyManager* manager, DiscordLobbyId lobby_id, DiscordUserId user_id, struct DiscordUser* user);
|
||||
enum EDiscordResult (*get_member_metadata_value)(struct IDiscordLobbyManager* manager, DiscordLobbyId lobby_id, DiscordUserId user_id, DiscordMetadataKey key, DiscordMetadataValue* value);
|
||||
enum EDiscordResult (*get_member_metadata_key)(struct IDiscordLobbyManager* manager, DiscordLobbyId lobby_id, DiscordUserId user_id, int32_t index, DiscordMetadataKey* key);
|
||||
enum EDiscordResult (*member_metadata_count)(struct IDiscordLobbyManager* manager, DiscordLobbyId lobby_id, DiscordUserId user_id, int32_t* count);
|
||||
void (*update_member)(struct IDiscordLobbyManager* manager, DiscordLobbyId lobby_id, DiscordUserId user_id, struct IDiscordLobbyMemberTransaction* transaction, void* callback_data, void (*callback)(void* callback_data, enum EDiscordResult result));
|
||||
void (*send_lobby_message)(struct IDiscordLobbyManager* manager, DiscordLobbyId lobby_id, uint8_t* data, uint32_t data_length, void* callback_data, void (*callback)(void* callback_data, enum EDiscordResult result));
|
||||
enum EDiscordResult (*get_search_query)(struct IDiscordLobbyManager* manager, struct IDiscordLobbySearchQuery** query);
|
||||
void (*search)(struct IDiscordLobbyManager* manager, struct IDiscordLobbySearchQuery* query, void* callback_data, void (*callback)(void* callback_data, enum EDiscordResult result));
|
||||
void (*lobby_count)(struct IDiscordLobbyManager* manager, int32_t* count);
|
||||
enum EDiscordResult (*get_lobby_id)(struct IDiscordLobbyManager* manager, int32_t index, DiscordLobbyId* lobby_id);
|
||||
void (*connect_voice)(struct IDiscordLobbyManager* manager, DiscordLobbyId lobby_id, void* callback_data, void (*callback)(void* callback_data, enum EDiscordResult result));
|
||||
void (*disconnect_voice)(struct IDiscordLobbyManager* manager, DiscordLobbyId lobby_id, void* callback_data, void (*callback)(void* callback_data, enum EDiscordResult result));
|
||||
enum EDiscordResult (*connect_network)(struct IDiscordLobbyManager* manager, DiscordLobbyId lobby_id);
|
||||
enum EDiscordResult (*disconnect_network)(struct IDiscordLobbyManager* manager, DiscordLobbyId lobby_id);
|
||||
enum EDiscordResult (*flush_network)(struct IDiscordLobbyManager* manager);
|
||||
enum EDiscordResult (*open_network_channel)(struct IDiscordLobbyManager* manager, DiscordLobbyId lobby_id, uint8_t channel_id, bool reliable);
|
||||
enum EDiscordResult (*send_network_message)(struct IDiscordLobbyManager* manager, DiscordLobbyId lobby_id, DiscordUserId user_id, uint8_t channel_id, uint8_t* data, uint32_t data_length);
|
||||
};
|
||||
|
||||
struct IDiscordNetworkEvents {
|
||||
void (*on_message)(void* event_data, DiscordNetworkPeerId peer_id, DiscordNetworkChannelId channel_id, uint8_t* data, uint32_t data_length);
|
||||
void (*on_route_update)(void* event_data, const char* route_data);
|
||||
};
|
||||
|
||||
struct IDiscordNetworkManager {
|
||||
/**
|
||||
* Get the local peer ID for this process.
|
||||
*/
|
||||
void (*get_peer_id)(struct IDiscordNetworkManager* manager, DiscordNetworkPeerId* peer_id);
|
||||
/**
|
||||
* Send pending network messages.
|
||||
*/
|
||||
enum EDiscordResult (*flush)(struct IDiscordNetworkManager* manager);
|
||||
/**
|
||||
* Open a connection to a remote peer.
|
||||
*/
|
||||
enum EDiscordResult (*open_peer)(struct IDiscordNetworkManager* manager, DiscordNetworkPeerId peer_id, const char* route_data);
|
||||
/**
|
||||
* Update the route data for a connected peer.
|
||||
*/
|
||||
enum EDiscordResult (*update_peer)(struct IDiscordNetworkManager* manager, DiscordNetworkPeerId peer_id, const char* route_data);
|
||||
/**
|
||||
* Close the connection to a remote peer.
|
||||
*/
|
||||
enum EDiscordResult (*close_peer)(struct IDiscordNetworkManager* manager, DiscordNetworkPeerId peer_id);
|
||||
/**
|
||||
* Open a message channel to a connected peer.
|
||||
*/
|
||||
enum EDiscordResult (*open_channel)(struct IDiscordNetworkManager* manager, DiscordNetworkPeerId peer_id, DiscordNetworkChannelId channel_id, bool reliable);
|
||||
/**
|
||||
* Close a message channel to a connected peer.
|
||||
*/
|
||||
enum EDiscordResult (*close_channel)(struct IDiscordNetworkManager* manager, DiscordNetworkPeerId peer_id, DiscordNetworkChannelId channel_id);
|
||||
/**
|
||||
* Send a message to a connected peer over an opened message channel.
|
||||
*/
|
||||
enum EDiscordResult (*send_message)(struct IDiscordNetworkManager* manager, DiscordNetworkPeerId peer_id, DiscordNetworkChannelId channel_id, uint8_t* data, uint32_t data_length);
|
||||
};
|
||||
|
||||
struct IDiscordOverlayEvents {
|
||||
void (*on_toggle)(void* event_data, bool locked);
|
||||
};
|
||||
|
||||
struct IDiscordOverlayManager {
|
||||
void (*is_enabled)(struct IDiscordOverlayManager* manager, bool* enabled);
|
||||
void (*is_locked)(struct IDiscordOverlayManager* manager, bool* locked);
|
||||
void (*set_locked)(struct IDiscordOverlayManager* manager, bool locked, void* callback_data, void (*callback)(void* callback_data, enum EDiscordResult result));
|
||||
void (*open_activity_invite)(struct IDiscordOverlayManager* manager, enum EDiscordActivityActionType type, void* callback_data, void (*callback)(void* callback_data, enum EDiscordResult result));
|
||||
void (*open_guild_invite)(struct IDiscordOverlayManager* manager, const char* code, void* callback_data, void (*callback)(void* callback_data, enum EDiscordResult result));
|
||||
void (*open_voice_settings)(struct IDiscordOverlayManager* manager, void* callback_data, void (*callback)(void* callback_data, enum EDiscordResult result));
|
||||
};
|
||||
|
||||
typedef void* IDiscordStorageEvents;
|
||||
|
||||
struct IDiscordStorageManager {
|
||||
enum EDiscordResult (*read)(struct IDiscordStorageManager* manager, const char* name, uint8_t* data, uint32_t data_length, uint32_t* read);
|
||||
void (*read_async)(struct IDiscordStorageManager* manager, const char* name, void* callback_data, void (*callback)(void* callback_data, enum EDiscordResult result, uint8_t* data, uint32_t data_length));
|
||||
void (*read_async_partial)(struct IDiscordStorageManager* manager, const char* name, uint64_t offset, uint64_t length, void* callback_data, void (*callback)(void* callback_data, enum EDiscordResult result, uint8_t* data, uint32_t data_length));
|
||||
enum EDiscordResult (*write)(struct IDiscordStorageManager* manager, const char* name, uint8_t* data, uint32_t data_length);
|
||||
void (*write_async)(struct IDiscordStorageManager* manager, const char* name, uint8_t* data, uint32_t data_length, void* callback_data, void (*callback)(void* callback_data, enum EDiscordResult result));
|
||||
enum EDiscordResult (*delete_)(struct IDiscordStorageManager* manager, const char* name);
|
||||
enum EDiscordResult (*exists)(struct IDiscordStorageManager* manager, const char* name, bool* exists);
|
||||
void (*count)(struct IDiscordStorageManager* manager, int32_t* count);
|
||||
enum EDiscordResult (*stat)(struct IDiscordStorageManager* manager, const char* name, struct DiscordFileStat* stat);
|
||||
enum EDiscordResult (*stat_at)(struct IDiscordStorageManager* manager, int32_t index, struct DiscordFileStat* stat);
|
||||
enum EDiscordResult (*get_path)(struct IDiscordStorageManager* manager, DiscordPath* path);
|
||||
};
|
||||
|
||||
struct IDiscordStoreEvents {
|
||||
void (*on_entitlement_create)(void* event_data, struct DiscordEntitlement* entitlement);
|
||||
void (*on_entitlement_delete)(void* event_data, struct DiscordEntitlement* entitlement);
|
||||
};
|
||||
|
||||
struct IDiscordStoreManager {
|
||||
void (*fetch_skus)(struct IDiscordStoreManager* manager, void* callback_data, void (*callback)(void* callback_data, enum EDiscordResult result));
|
||||
void (*count_skus)(struct IDiscordStoreManager* manager, int32_t* count);
|
||||
enum EDiscordResult (*get_sku)(struct IDiscordStoreManager* manager, DiscordSnowflake sku_id, struct DiscordSku* sku);
|
||||
enum EDiscordResult (*get_sku_at)(struct IDiscordStoreManager* manager, int32_t index, struct DiscordSku* sku);
|
||||
void (*fetch_entitlements)(struct IDiscordStoreManager* manager, void* callback_data, void (*callback)(void* callback_data, enum EDiscordResult result));
|
||||
void (*count_entitlements)(struct IDiscordStoreManager* manager, int32_t* count);
|
||||
enum EDiscordResult (*get_entitlement)(struct IDiscordStoreManager* manager, DiscordSnowflake entitlement_id, struct DiscordEntitlement* entitlement);
|
||||
enum EDiscordResult (*get_entitlement_at)(struct IDiscordStoreManager* manager, int32_t index, struct DiscordEntitlement* entitlement);
|
||||
enum EDiscordResult (*has_sku_entitlement)(struct IDiscordStoreManager* manager, DiscordSnowflake sku_id, bool* has_entitlement);
|
||||
void (*start_purchase)(struct IDiscordStoreManager* manager, DiscordSnowflake sku_id, void* callback_data, void (*callback)(void* callback_data, enum EDiscordResult result));
|
||||
};
|
||||
|
||||
struct IDiscordVoiceEvents {
|
||||
void (*on_settings_update)(void* event_data);
|
||||
};
|
||||
|
||||
struct IDiscordVoiceManager {
|
||||
enum EDiscordResult (*get_input_mode)(struct IDiscordVoiceManager* manager, struct DiscordInputMode* input_mode);
|
||||
void (*set_input_mode)(struct IDiscordVoiceManager* manager, struct DiscordInputMode input_mode, void* callback_data, void (*callback)(void* callback_data, enum EDiscordResult result));
|
||||
enum EDiscordResult (*is_self_mute)(struct IDiscordVoiceManager* manager, bool* mute);
|
||||
enum EDiscordResult (*set_self_mute)(struct IDiscordVoiceManager* manager, bool mute);
|
||||
enum EDiscordResult (*is_self_deaf)(struct IDiscordVoiceManager* manager, bool* deaf);
|
||||
enum EDiscordResult (*set_self_deaf)(struct IDiscordVoiceManager* manager, bool deaf);
|
||||
enum EDiscordResult (*is_local_mute)(struct IDiscordVoiceManager* manager, DiscordSnowflake user_id, bool* mute);
|
||||
enum EDiscordResult (*set_local_mute)(struct IDiscordVoiceManager* manager, DiscordSnowflake user_id, bool mute);
|
||||
enum EDiscordResult (*get_local_volume)(struct IDiscordVoiceManager* manager, DiscordSnowflake user_id, uint8_t* volume);
|
||||
enum EDiscordResult (*set_local_volume)(struct IDiscordVoiceManager* manager, DiscordSnowflake user_id, uint8_t volume);
|
||||
};
|
||||
|
||||
struct IDiscordAchievementEvents {
|
||||
void (*on_user_achievement_update)(void* event_data, struct DiscordUserAchievement* user_achievement);
|
||||
};
|
||||
|
||||
struct IDiscordAchievementManager {
|
||||
void (*set_user_achievement)(struct IDiscordAchievementManager* manager, DiscordSnowflake achievement_id, uint8_t percent_complete, void* callback_data, void (*callback)(void* callback_data, enum EDiscordResult result));
|
||||
void (*fetch_user_achievements)(struct IDiscordAchievementManager* manager, void* callback_data, void (*callback)(void* callback_data, enum EDiscordResult result));
|
||||
void (*count_user_achievements)(struct IDiscordAchievementManager* manager, int32_t* count);
|
||||
enum EDiscordResult (*get_user_achievement)(struct IDiscordAchievementManager* manager, DiscordSnowflake user_achievement_id, struct DiscordUserAchievement* user_achievement);
|
||||
enum EDiscordResult (*get_user_achievement_at)(struct IDiscordAchievementManager* manager, int32_t index, struct DiscordUserAchievement* user_achievement);
|
||||
};
|
||||
|
||||
typedef void* IDiscordCoreEvents;
|
||||
|
||||
struct IDiscordCore {
|
||||
void (*destroy)(struct IDiscordCore* core);
|
||||
enum EDiscordResult (*run_callbacks)(struct IDiscordCore* core);
|
||||
void (*set_log_hook)(struct IDiscordCore* core, enum EDiscordLogLevel min_level, void* hook_data, void (*hook)(void* hook_data, enum EDiscordLogLevel level, const char* message));
|
||||
struct IDiscordApplicationManager* (*get_application_manager)(struct IDiscordCore* core);
|
||||
struct IDiscordUserManager* (*get_user_manager)(struct IDiscordCore* core);
|
||||
struct IDiscordImageManager* (*get_image_manager)(struct IDiscordCore* core);
|
||||
struct IDiscordActivityManager* (*get_activity_manager)(struct IDiscordCore* core);
|
||||
struct IDiscordRelationshipManager* (*get_relationship_manager)(struct IDiscordCore* core);
|
||||
struct IDiscordLobbyManager* (*get_lobby_manager)(struct IDiscordCore* core);
|
||||
struct IDiscordNetworkManager* (*get_network_manager)(struct IDiscordCore* core);
|
||||
struct IDiscordOverlayManager* (*get_overlay_manager)(struct IDiscordCore* core);
|
||||
struct IDiscordStorageManager* (*get_storage_manager)(struct IDiscordCore* core);
|
||||
struct IDiscordStoreManager* (*get_store_manager)(struct IDiscordCore* core);
|
||||
struct IDiscordVoiceManager* (*get_voice_manager)(struct IDiscordCore* core);
|
||||
struct IDiscordAchievementManager* (*get_achievement_manager)(struct IDiscordCore* core);
|
||||
};
|
||||
|
||||
struct DiscordCreateParams {
|
||||
DiscordClientId client_id;
|
||||
uint64_t flags;
|
||||
IDiscordCoreEvents* events;
|
||||
void* event_data;
|
||||
IDiscordApplicationEvents* application_events;
|
||||
DiscordVersion application_version;
|
||||
struct IDiscordUserEvents* user_events;
|
||||
DiscordVersion user_version;
|
||||
IDiscordImageEvents* image_events;
|
||||
DiscordVersion image_version;
|
||||
struct IDiscordActivityEvents* activity_events;
|
||||
DiscordVersion activity_version;
|
||||
struct IDiscordRelationshipEvents* relationship_events;
|
||||
DiscordVersion relationship_version;
|
||||
struct IDiscordLobbyEvents* lobby_events;
|
||||
DiscordVersion lobby_version;
|
||||
struct IDiscordNetworkEvents* network_events;
|
||||
DiscordVersion network_version;
|
||||
struct IDiscordOverlayEvents* overlay_events;
|
||||
DiscordVersion overlay_version;
|
||||
IDiscordStorageEvents* storage_events;
|
||||
DiscordVersion storage_version;
|
||||
struct IDiscordStoreEvents* store_events;
|
||||
DiscordVersion store_version;
|
||||
struct IDiscordVoiceEvents* voice_events;
|
||||
DiscordVersion voice_version;
|
||||
struct IDiscordAchievementEvents* achievement_events;
|
||||
DiscordVersion achievement_version;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
inline
|
||||
#else
|
||||
static
|
||||
#endif
|
||||
void DiscordCreateParamsSetDefault(struct DiscordCreateParams* params)
|
||||
{
|
||||
memset(params, 0, sizeof(struct DiscordCreateParams));
|
||||
params->application_version = DISCORD_APPLICATION_MANAGER_VERSION;
|
||||
params->user_version = DISCORD_USER_MANAGER_VERSION;
|
||||
params->image_version = DISCORD_IMAGE_MANAGER_VERSION;
|
||||
params->activity_version = DISCORD_ACTIVITY_MANAGER_VERSION;
|
||||
params->relationship_version = DISCORD_RELATIONSHIP_MANAGER_VERSION;
|
||||
params->lobby_version = DISCORD_LOBBY_MANAGER_VERSION;
|
||||
params->network_version = DISCORD_NETWORK_MANAGER_VERSION;
|
||||
params->overlay_version = DISCORD_OVERLAY_MANAGER_VERSION;
|
||||
params->storage_version = DISCORD_STORAGE_MANAGER_VERSION;
|
||||
params->store_version = DISCORD_STORE_MANAGER_VERSION;
|
||||
params->voice_version = DISCORD_VOICE_MANAGER_VERSION;
|
||||
params->achievement_version = DISCORD_ACHIEVEMENT_MANAGER_VERSION;
|
||||
}
|
||||
|
||||
enum EDiscordResult DiscordCreate(DiscordVersion version, struct DiscordCreateParams* params, struct IDiscordCore** result);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,39 @@
|
|||
#include "discord_network.h"
|
||||
#include "lobby.h"
|
||||
#include "pc/debuglog.h"
|
||||
|
||||
int ns_discord_network_send(u8* data, u16 dataLength) {
|
||||
if (!gDiscordInitialized) { return 1; }
|
||||
if (gCurLobbyId == 0) { return 2; }
|
||||
int32_t memberCount = 0;
|
||||
DISCORD_REQUIRE(app.lobbies->member_count(app.lobbies, gCurLobbyId, &memberCount));
|
||||
if (memberCount <= 1) { return 3; }
|
||||
|
||||
for (int i = 0; i < memberCount; i++) {
|
||||
DiscordUserId userId;
|
||||
DISCORD_REQUIRE(app.lobbies->get_member_user_id(app.lobbies, gCurLobbyId, i, &userId));
|
||||
if (userId == app.userId) { continue; }
|
||||
DISCORD_REQUIRE(app.lobbies->send_network_message(app.lobbies, gCurLobbyId, userId, 0, data, dataLength));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void discord_network_on_message(UNUSED void* eventData, int64_t lobbyId, int64_t userId, uint8_t channelId, uint8_t* data, uint32_t dataLength) {
|
||||
network_receive((u8*)data, (u16)dataLength);
|
||||
}
|
||||
|
||||
void discord_network_flush(void) {
|
||||
app.lobbies->flush_network(app.lobbies);
|
||||
}
|
||||
|
||||
void discord_network_init(int64_t lobbyId) {
|
||||
DISCORD_REQUIRE(app.lobbies->connect_network(app.lobbies, lobbyId));
|
||||
DISCORD_REQUIRE(app.lobbies->open_network_channel(app.lobbies, lobbyId, 0, false));
|
||||
}
|
||||
|
||||
void discord_network_shutdown(void) {
|
||||
app.lobbies->flush_network(app.lobbies);
|
||||
if (gCurLobbyId == 0) { return; }
|
||||
app.lobbies->disconnect_network(app.lobbies, gCurLobbyId);
|
||||
LOG_INFO("shutdown network, lobby = %lld", gCurLobbyId);
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
#ifndef DISCORD_NETWORK_H
|
||||
#define DISCORD_NETWORK_H
|
||||
#include "discord.h"
|
||||
|
||||
int ns_discord_network_send(u8* data, u16 dataLength);
|
||||
void discord_network_on_message(UNUSED void* eventData, int64_t lobbyId, int64_t userId, uint8_t channelId, uint8_t* data, uint32_t dataLength);
|
||||
void discord_network_flush(void);
|
||||
void discord_network_init(int64_t lobbyId);
|
||||
void discord_network_shutdown(void);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,93 @@
|
|||
#include "lobby.h"
|
||||
#include "activity.h"
|
||||
#include "discord_network.h"
|
||||
#include "pc/debuglog.h"
|
||||
|
||||
static bool isHosting = false;
|
||||
DiscordLobbyId gCurLobbyId = 0;
|
||||
|
||||
static void on_lobby_create_callback(UNUSED void* data, enum EDiscordResult result, struct DiscordLobby* lobby) {
|
||||
LOG_INFO("> on_lobby_update returned %d\n", (int)result);
|
||||
LOG_INFO("Lobby id: %lld\n", lobby->id);
|
||||
LOG_INFO("Lobby type: %u\n", lobby->type);
|
||||
LOG_INFO("Lobby owner id: %lld\n", lobby->owner_id);
|
||||
LOG_INFO("Lobby secret: %s\n", lobby->secret);
|
||||
LOG_INFO("Lobby capacity: %u\n", lobby->capacity);
|
||||
LOG_INFO("Lobby locked: %d\n", lobby->locked);
|
||||
|
||||
gCurActivity.type = DiscordActivityType_Playing;
|
||||
snprintf(gCurActivity.party.id, 128, "%lld", lobby->id);
|
||||
gCurActivity.party.size.current_size = 1;
|
||||
gCurActivity.party.size.max_size = 2;
|
||||
|
||||
char secretJoin[128] = "";
|
||||
snprintf(secretJoin, 128, "%lld:%s", lobby->id, lobby->secret);
|
||||
strcpy(gCurActivity.secrets.join, secretJoin);
|
||||
|
||||
isHosting = true;
|
||||
gCurLobbyId = lobby->id;
|
||||
|
||||
discord_network_init(lobby->id);
|
||||
discord_activity_update(true);
|
||||
}
|
||||
|
||||
static void on_lobby_update(UNUSED void* data, int64_t lobbyId) {
|
||||
LOG_INFO("> on_lobby_update id: %lld", lobbyId);
|
||||
}
|
||||
|
||||
static void on_member_connect(UNUSED void* data, int64_t lobbyId, int64_t userId) {
|
||||
LOG_INFO("> on_member_connect lobby: %lld, user: %lld", lobbyId, userId);
|
||||
gCurActivity.party.size.current_size++;
|
||||
discord_activity_update(true);
|
||||
}
|
||||
|
||||
static void on_member_update(UNUSED void* data, int64_t lobbyId, int64_t userId) {
|
||||
LOG_INFO("> on_member_update lobby: %lld, user: %lld", lobbyId, userId);
|
||||
}
|
||||
|
||||
static void on_member_disconnect(UNUSED void* data, int64_t lobbyId, int64_t userId) {
|
||||
LOG_INFO("> on_member_disconnect lobby: %lld, user: %lld", lobbyId, userId);
|
||||
gCurActivity.party.size.current_size--;
|
||||
discord_activity_update(isHosting);
|
||||
}
|
||||
|
||||
void discord_lobby_create(void) {
|
||||
struct IDiscordLobbyTransaction* txn = { 0 };
|
||||
|
||||
DISCORD_REQUIRE(app.lobbies->get_lobby_create_transaction(app.lobbies, &txn));
|
||||
txn->set_capacity(txn, 2);
|
||||
txn->set_type(txn, DiscordLobbyType_Public);
|
||||
//txn->set_metadata(txn, "a", "123");
|
||||
|
||||
app.lobbies->create_lobby(app.lobbies, txn, NULL, on_lobby_create_callback);
|
||||
}
|
||||
|
||||
static void on_lobby_leave_callback(UNUSED void* data, enum EDiscordResult result) {
|
||||
LOG_INFO("> on_lobby_leave returned %d", result);
|
||||
}
|
||||
|
||||
void discord_lobby_leave(void) {
|
||||
if (gCurLobbyId == 0) { return; }
|
||||
|
||||
discord_network_shutdown();
|
||||
if (isHosting) {
|
||||
app.lobbies->delete_lobby(app.lobbies, gCurLobbyId, NULL, on_lobby_leave_callback);
|
||||
} else {
|
||||
app.lobbies->disconnect_lobby(app.lobbies, gCurLobbyId, NULL, on_lobby_leave_callback);
|
||||
}
|
||||
|
||||
LOG_INFO("left lobby %lld", gCurLobbyId);
|
||||
|
||||
isHosting = false;
|
||||
gCurLobbyId = 0;
|
||||
}
|
||||
|
||||
struct IDiscordLobbyEvents* discord_lobby_initialize(void) {
|
||||
static struct IDiscordLobbyEvents events = { 0 };
|
||||
events.on_lobby_update = on_lobby_update;
|
||||
events.on_member_connect = on_member_connect;
|
||||
events.on_member_update = on_member_update;
|
||||
events.on_member_disconnect = on_member_disconnect;
|
||||
events.on_network_message = discord_network_on_message;
|
||||
return &events;
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
#ifndef DISCORD_LOBBY_H
|
||||
#define DISCORD_LOBBY_H
|
||||
#include "discord.h"
|
||||
|
||||
extern DiscordLobbyId gCurLobbyId;
|
||||
|
||||
void discord_lobby_create(void);
|
||||
void discord_lobby_leave(void);
|
||||
struct IDiscordLobbyEvents* discord_lobby_initialize(void);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,15 @@
|
|||
#include "user.h"
|
||||
#include "pc/debuglog.h"
|
||||
|
||||
static void on_current_user_update(UNUSED void* data) {
|
||||
LOG_INFO("> on_current_user_update");
|
||||
struct DiscordUser user;
|
||||
app.users->get_current_user(app.users, &user);
|
||||
app.userId = user.id;
|
||||
}
|
||||
|
||||
struct IDiscordUserEvents* discord_user_initialize(void) {
|
||||
static struct IDiscordUserEvents events = { 0 };
|
||||
events.on_current_user_update = on_current_user_update;
|
||||
return &events;
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
#ifndef DISCORD_USER_H
|
||||
#define DISCORD_USER_H
|
||||
#include "discord.h"
|
||||
|
||||
struct IDiscordUserEvents* discord_user_initialize(void);
|
||||
|
||||
#endif
|
|
@ -3,6 +3,7 @@
|
|||
#include "object_fields.h"
|
||||
#include "object_constants.h"
|
||||
#include "socket/socket.h"
|
||||
#include "discord/discord.h"
|
||||
#include "pc/configfile.h"
|
||||
#include "pc/debuglog.h"
|
||||
|
||||
|
@ -10,7 +11,7 @@
|
|||
extern s16 sCurrPlayMode;
|
||||
|
||||
enum NetworkType gNetworkType = NT_NONE;
|
||||
struct NetworkSystem* gNetworkSystem = &gNetworkSystemSocket;
|
||||
struct NetworkSystem* gNetworkSystem = &gNetworkSystemDiscord;
|
||||
|
||||
#define LOADING_LEVEL_THRESHOLD 10
|
||||
u8 networkLoadingLevel = 0;
|
||||
|
@ -21,6 +22,15 @@ struct ServerSettings gServerSettings = {
|
|||
.playerKnockbackStrength = 25,
|
||||
};
|
||||
|
||||
|
||||
void network_set_system(enum NetworkSystemType nsType) {
|
||||
switch (nsType) {
|
||||
case NS_SOCKET: gNetworkSystem = &gNetworkSystemSocket; break;
|
||||
case NS_DISCORD: gNetworkSystem = &gNetworkSystemDiscord; break;
|
||||
default: LOG_ERROR("Unknown network system: %d", nsType);
|
||||
}
|
||||
}
|
||||
|
||||
bool network_init(enum NetworkType inNetworkType) {
|
||||
// sanity check network system
|
||||
if (gNetworkSystem == NULL) {
|
||||
|
@ -28,6 +38,11 @@ bool network_init(enum NetworkType inNetworkType) {
|
|||
return false;
|
||||
}
|
||||
|
||||
// set server settings
|
||||
gServerSettings.playerInteractions = configPlayerInteraction;
|
||||
gServerSettings.playerKnockbackStrength = configPlayerKnockbackStrength;
|
||||
gServerSettings.stayInLevelAfterStar = configStayInLevelAfterStar;
|
||||
|
||||
// initialize the network system
|
||||
int rc = gNetworkSystem->initialize(inNetworkType);
|
||||
if (!rc) {
|
||||
|
@ -38,26 +53,15 @@ bool network_init(enum NetworkType inNetworkType) {
|
|||
// set network type
|
||||
gNetworkType = inNetworkType;
|
||||
|
||||
// set server settings
|
||||
if (gNetworkType == NT_SERVER) {
|
||||
gServerSettings.playerInteractions = configPlayerInteraction;
|
||||
gServerSettings.playerKnockbackStrength = configPlayerKnockbackStrength;
|
||||
gServerSettings.stayInLevelAfterStar = configStayInLevelAfterStar;
|
||||
}
|
||||
|
||||
// exit early if we're not really initializing the network
|
||||
if (gNetworkType == NT_NONE) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// send connection request
|
||||
if (gNetworkType == NT_CLIENT) {
|
||||
network_send_save_file_request();
|
||||
}
|
||||
LOG_INFO("initialized");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void network_on_joined(void) {
|
||||
network_send_save_file_request();
|
||||
}
|
||||
|
||||
void network_on_init_level(void) {
|
||||
// reset loading timer
|
||||
networkLoadingLevel = 0;
|
||||
|
@ -131,7 +135,6 @@ void network_receive(u8* data, u16 dataLength) {
|
|||
}
|
||||
|
||||
void network_update(void) {
|
||||
if (gNetworkType == NT_NONE) { return; }
|
||||
|
||||
// check for level loaded event
|
||||
if (!gNetworkLevelLoaded) {
|
||||
|
@ -141,10 +144,12 @@ void network_update(void) {
|
|||
}
|
||||
}
|
||||
|
||||
// figure out which update loop to run
|
||||
if (sCurrPlayMode == PLAY_MODE_NORMAL || sCurrPlayMode == PLAY_MODE_PAUSED) {
|
||||
network_update_player();
|
||||
network_update_objects();
|
||||
// send out update packets
|
||||
if (gNetworkType != NT_NONE) {
|
||||
if (sCurrPlayMode == PLAY_MODE_NORMAL || sCurrPlayMode == PLAY_MODE_PAUSED) {
|
||||
network_update_player();
|
||||
network_update_objects();
|
||||
}
|
||||
}
|
||||
|
||||
// receive packets
|
||||
|
@ -153,13 +158,16 @@ void network_update(void) {
|
|||
}
|
||||
|
||||
// update reliable packets
|
||||
network_update_reliable();
|
||||
if (gNetworkType != NT_NONE) {
|
||||
network_update_reliable();
|
||||
}
|
||||
}
|
||||
|
||||
void network_shutdown(void) {
|
||||
if (gNetworkType == NT_NONE) { return; }
|
||||
gNetworkType = NT_NONE;
|
||||
|
||||
if (gNetworkSystem == NULL) { LOG_ERROR("no network system attached"); return; }
|
||||
gNetworkSystem->shutdown();
|
||||
|
||||
gNetworkType = NT_NONE;
|
||||
}
|
||||
|
|
|
@ -16,7 +16,14 @@ extern struct MarioState gMarioStates[];
|
|||
#define MAX_SYNC_OBJECTS 256 // note: increasing this requires code to be rewritten
|
||||
#define MAX_SYNC_OBJECT_FIELDS 64
|
||||
#define PACKET_LENGTH 1024
|
||||
#define NETWORKTYPESTR (gNetworkType == NT_CLIENT ? "Client" : "Server")
|
||||
#define NETWORKTYPESTR (gNetworkType == NT_CLIENT \
|
||||
? "Client" \
|
||||
: (gNetworkType == NT_SERVER ? "Server" : " None ")) \
|
||||
|
||||
enum NetworkSystemType {
|
||||
NS_SOCKET,
|
||||
NS_DISCORD,
|
||||
};
|
||||
|
||||
struct NetworkSystem {
|
||||
bool (*initialize)(enum NetworkType);
|
||||
|
@ -92,11 +99,13 @@ extern struct SyncObject gSyncObjects[];
|
|||
extern struct ServerSettings gServerSettings;
|
||||
|
||||
// network.c
|
||||
void network_set_system(enum NetworkSystemType nsType);
|
||||
bool network_init(enum NetworkType inNetworkType);
|
||||
void network_on_init_level(void);
|
||||
void network_on_loaded_level(void);
|
||||
void network_send(struct Packet* p);
|
||||
void network_receive(u8* data, u16 dataLength);
|
||||
void network_on_joined(void);
|
||||
void network_update(void);
|
||||
void network_shutdown(void);
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include "socket.h"
|
||||
#include "pc/configfile.h"
|
||||
#include "pc/debuglog.h"
|
||||
#include "menu/file_select.h"
|
||||
|
||||
static SOCKET curSocket = INVALID_SOCKET;
|
||||
struct sockaddr_in txAddr = { 0 };
|
||||
|
@ -70,6 +71,16 @@ static bool ns_socket_initialize(enum NetworkType networkType) {
|
|||
LOG_INFO("connecting to %s %u", configJoinIp, port);
|
||||
}
|
||||
|
||||
// kick off first packet
|
||||
if (networkType == NT_CLIENT) {
|
||||
char joinText[128] = { 0 };
|
||||
snprintf(joinText, 63, "%s %d", configJoinIp, configJoinPort);
|
||||
open_join_menu(joinText);
|
||||
|
||||
gNetworkType = NT_CLIENT;
|
||||
network_on_joined();
|
||||
}
|
||||
|
||||
LOG_INFO("initialized");
|
||||
|
||||
// success
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include "socket.h"
|
||||
|
||||
#define SOCKET_LAST_ERROR WSAGetLastError()
|
||||
#define SOCKET_EWOULDBLOCK WSAEWOULDBLOCK
|
||||
|
|
|
@ -262,12 +262,16 @@ void main_func(void) {
|
|||
}
|
||||
|
||||
if (gCLIOpts.Network == NT_CLIENT) {
|
||||
network_set_system(NS_SOCKET);
|
||||
strncpy(configJoinIp, gCLIOpts.JoinIp, IP_MAX_LEN);
|
||||
configJoinPort = gCLIOpts.NetworkPort;
|
||||
network_init(NT_CLIENT);
|
||||
} else if (gCLIOpts.Network == NT_SERVER) {
|
||||
network_set_system(NS_SOCKET);
|
||||
configHostPort = gCLIOpts.NetworkPort;
|
||||
network_init(NT_SERVER);
|
||||
} else {
|
||||
network_init(NT_NONE);
|
||||
}
|
||||
|
||||
audio_init();
|
||||
|
|
Loading…
Reference in New Issue