diff --git a/autogen/lua_definitions/constants.lua b/autogen/lua_definitions/constants.lua index 18c43586..d57a61c2 100644 --- a/autogen/lua_definitions/constants.lua +++ b/autogen/lua_definitions/constants.lua @@ -4747,7 +4747,7 @@ PLAYER_INTERACTIONS_PVP = 2 MAX_RX_SEQ_IDS = 64 --- @type integer -NETWORK_PLAYER_PING_TIMEOUT = 1 +NETWORK_PLAYER_PING_TIMEOUT = 3 --- @type integer NETWORK_PLAYER_TIMEOUT = 10 diff --git a/lib/coopnet/include/libcoopnet.h b/lib/coopnet/include/libcoopnet.h index 09e0e9b3..47ceddb8 100644 --- a/lib/coopnet/include/libcoopnet.h +++ b/lib/coopnet/include/libcoopnet.h @@ -30,7 +30,7 @@ typedef struct { void (*OnLobbyCreated)(uint64_t aLobbyId, const char* aGame, const char* aVersion, const char* aHostName, const char* aMode, uint16_t aMaxConnections); void (*OnLobbyJoined)(uint64_t aLobbyId, uint64_t aUserId, uint64_t aOwnerId, uint64_t aDestId); void (*OnLobbyLeft)(uint64_t aLobbyId, uint64_t aUserId); - void (*OnLobbyListGot)(uint64_t aLobbyId, uint64_t aOwnerId, uint16_t aConnections, uint16_t aMaxConnections, const char* aGame, const char* aVersion, const char* aHostName, const char* aMode); + void (*OnLobbyListGot)(uint64_t aLobbyId, uint64_t aOwnerId, uint16_t aConnections, uint16_t aMaxConnections, const char* aGame, const char* aVersion, const char* aHostName, const char* aMode, const char* aDescription); void (*OnLobbyListFinish)(void); void (*OnReceive)(uint64_t aFromUserId, const uint8_t* aData, uint64_t aSize); void (*OnError)(enum MPacketErrorNumber aErrorNumber); @@ -49,8 +49,8 @@ bool coopnet_is_connected(void); CoopNetRc coopnet_begin(const char* aHost, uint32_t aPort); CoopNetRc coopnet_shutdown(void); CoopNetRc coopnet_update(void); -CoopNetRc coopnet_lobby_create(const char* aGame, const char* aVersion, const char* aHostName, const char* aMode, uint16_t aMaxConnections, const char* aPassword); -CoopNetRc coopnet_lobby_update(uint64_t aLobbyId, const char* aGame, const char* aVersion, const char* aHostName, const char* aMode); +CoopNetRc coopnet_lobby_create(const char* aGame, const char* aVersion, const char* aHostName, const char* aMode, uint16_t aMaxConnections, const char* aPassword, const char* aDescription); +CoopNetRc coopnet_lobby_update(uint64_t aLobbyId, const char* aGame, const char* aVersion, const char* aHostName, const char* aMode, const char* aDescription); CoopNetRc coopnet_lobby_join(uint64_t aLobbyId, const char* aPassword); CoopNetRc coopnet_lobby_leave(uint64_t aLobbyId); CoopNetRc coopnet_lobby_list_get(const char* aGame, const char* aPassword); diff --git a/lib/coopnet/linux/libcoopnet.a b/lib/coopnet/linux/libcoopnet.a index e9139df6..38041dcd 100644 Binary files a/lib/coopnet/linux/libcoopnet.a and b/lib/coopnet/linux/libcoopnet.a differ diff --git a/src/pc/discord/discord_activity.c b/src/pc/discord/discord_activity.c index 78d04594..c5a5e3d3 100644 --- a/src/pc/discord/discord_activity.c +++ b/src/pc/discord/discord_activity.c @@ -85,7 +85,6 @@ static void discord_populate_details(char* buffer, int bufferLength) { buffer += 3; bufferLength -= 3; - // concat mod strings str_seperator_concat(buffer, bufferLength, strings, gActiveMods.entryCount, ", "); } diff --git a/src/pc/djui/djui_lobby_entry.c b/src/pc/djui/djui_lobby_entry.c index b2d480a5..7aea75e9 100644 --- a/src/pc/djui/djui_lobby_entry.c +++ b/src/pc/djui/djui_lobby_entry.c @@ -32,13 +32,16 @@ static void djui_lobby_entry_update_style(struct DjuiBase* base) { static void djui_lobby_entry_destroy(struct DjuiBase* base) { struct DjuiLobbyEntry* lobbyEntry = (struct DjuiLobbyEntry*)base; + if (lobbyEntry->description) { free((char*)lobbyEntry->description); } free(lobbyEntry); } -struct DjuiLobbyEntry* djui_lobby_entry_create(struct DjuiBase* parent, char* host, char* mode, char* players, void (*on_click)(struct DjuiBase*)) { +struct DjuiLobbyEntry* djui_lobby_entry_create(struct DjuiBase* parent, char* host, char* mode, char* players, char* description, void (*on_click)(struct DjuiBase*), void (*on_hover)(struct DjuiBase*), void (*on_hover_end)(struct DjuiBase*)) { struct DjuiLobbyEntry* lobbyEntry = calloc(1, sizeof(struct DjuiLobbyEntry)); struct DjuiBase* base = &lobbyEntry->base; + lobbyEntry->description = strdup(description); + djui_base_init(parent, base, djui_rect_render, djui_lobby_entry_destroy); djui_base_set_size_type(&lobbyEntry->base, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE); djui_base_set_size(&lobbyEntry->base, 1.0f, 32); @@ -48,6 +51,7 @@ struct DjuiLobbyEntry* djui_lobby_entry_create(struct DjuiBase* parent, char* ho djui_base_set_border_width_type(&lobbyEntry->base, DJUI_SVT_ABSOLUTE); djui_interactable_create(base, djui_lobby_entry_update_style); djui_interactable_hook_click(base, on_click); + djui_interactable_hook_hover(base, on_hover, on_hover_end); u8 numColumns = 3; f32 x = 0; diff --git a/src/pc/djui/djui_lobby_entry.h b/src/pc/djui/djui_lobby_entry.h index e96fca23..02c946e2 100644 --- a/src/pc/djui/djui_lobby_entry.h +++ b/src/pc/djui/djui_lobby_entry.h @@ -3,6 +3,7 @@ struct DjuiLobbyEntry { struct DjuiBase base; + const char* description; }; -struct DjuiLobbyEntry* djui_lobby_entry_create(struct DjuiBase* parent, char* host, char* mode, char* players, void (*on_click)(struct DjuiBase*)); +struct DjuiLobbyEntry* djui_lobby_entry_create(struct DjuiBase* parent, char* host, char* mode, char* players, char* description, void (*on_click)(struct DjuiBase*), void (*on_hover)(struct DjuiBase*), void (*on_hover_end)(struct DjuiBase*)); diff --git a/src/pc/djui/djui_panel_join_lobbies.c b/src/pc/djui/djui_panel_join_lobbies.c index 09cd43ed..43c458f3 100644 --- a/src/pc/djui/djui_panel_join_lobbies.c +++ b/src/pc/djui/djui_panel_join_lobbies.c @@ -14,10 +14,54 @@ #ifdef COOPNET +#define DJUI_DESC_PANEL_WIDTH (410.0f + (16 * 2.0f)) + static struct DjuiFlowLayout* sLobbyLayout = NULL; static struct DjuiButton* sRefreshButton = NULL; +static struct DjuiThreePanel* sDescriptionPanel = NULL; +static struct DjuiText* sTooltip = NULL; static char* sPassword = NULL; +static void djui_panel_join_lobby_description_create() { + f32 bodyHeight = 600; + + struct DjuiThreePanel* panel = djui_three_panel_create(&gDjuiRoot->base, 64, bodyHeight, 0); + + djui_base_set_alignment(&panel->base, DJUI_HALIGN_RIGHT, DJUI_VALIGN_CENTER); + djui_base_set_size_type(&panel->base, DJUI_SVT_ABSOLUTE, DJUI_SVT_RELATIVE); + djui_base_set_size(&panel->base, DJUI_DESC_PANEL_WIDTH, 1.0f); + djui_base_set_color(&panel->base, 0, 0, 0, 240); + djui_base_set_border_color(&panel->base, 0, 0, 0, 200); + djui_base_set_border_width(&panel->base, 8); + djui_base_set_padding(&panel->base, 16, 16, 16, 16); + { + struct DjuiFlowLayout* body = djui_flow_layout_create(&panel->base); + djui_base_set_alignment(&body->base, DJUI_HALIGN_CENTER, DJUI_VALIGN_CENTER); + djui_base_set_size_type(&body->base, DJUI_SVT_RELATIVE, DJUI_SVT_RELATIVE); + djui_base_set_size(&body->base, 1.0f, 1.0f); + djui_base_set_color(&body->base, 0, 0, 0, 0); + djui_flow_layout_set_margin(body, 16); + djui_flow_layout_set_flow_direction(body, DJUI_FLOW_DIR_DOWN); + + struct DjuiText* description = djui_text_create(&panel->base, ""); + djui_base_set_size_type(&description->base, DJUI_SVT_RELATIVE, DJUI_SVT_RELATIVE); + djui_base_set_size(&description->base, 1.0f, 1.0f); + djui_base_set_color(&description->base, 222, 222, 222, 255); + djui_text_set_alignment(description, DJUI_HALIGN_LEFT, DJUI_VALIGN_CENTER); + sTooltip = description; + } + sDescriptionPanel = panel; +} + +static void djui_lobby_on_hover(struct DjuiBase* base) { + struct DjuiLobbyEntry* entry = (struct DjuiLobbyEntry*)base; + djui_text_set_text(sTooltip, entry->description); +} + +static void djui_lobby_on_hover_end(UNUSED struct DjuiBase* base) { + djui_text_set_text(sTooltip, ""); +} + void djui_panel_join_lobby(struct DjuiBase* caller) { gCoopNetDesiredLobby = (uint64_t)caller->tag; snprintf(gCoopNetPassword, 64, "%s", sPassword); @@ -27,7 +71,7 @@ void djui_panel_join_lobby(struct DjuiBase* caller) { djui_panel_join_message_create(caller); } -void djui_panel_join_query(uint64_t aLobbyId, UNUSED uint64_t aOwnerId, uint16_t aConnections, uint16_t aMaxConnections, UNUSED const char* aGame, UNUSED const char* aVersion, const char* aHostName, const char* aMode) { +void djui_panel_join_query(uint64_t aLobbyId, UNUSED uint64_t aOwnerId, uint16_t aConnections, uint16_t aMaxConnections, UNUSED const char* aGame, const char* aVersion, const char* aHostName, const char* aMode, const char* aDescription) { if (!sLobbyLayout) { return; } char playerText[64] = ""; @@ -44,7 +88,7 @@ void djui_panel_join_query(uint64_t aLobbyId, UNUSED uint64_t aOwnerId, uint16_t } struct DjuiBase* layoutBase = &sLobbyLayout->base; - struct DjuiLobbyEntry* entry = djui_lobby_entry_create(layoutBase, (char*)aHostName, (char*)mode, playerText, djui_panel_join_lobby); + struct DjuiLobbyEntry* entry = djui_lobby_entry_create(layoutBase, (char*)aHostName, (char*)mode, playerText, (char*)aDescription, djui_panel_join_lobby, djui_lobby_on_hover, djui_lobby_on_hover_end); entry->base.tag = (s64)aLobbyId; } @@ -66,6 +110,11 @@ void djui_panel_join_lobbies_on_destroy(UNUSED struct DjuiBase* caller) { sPassword = NULL; sRefreshButton = NULL; sLobbyLayout = NULL; + + if (sDescriptionPanel != NULL) { + djui_base_destroy(&sDescriptionPanel->base); + sDescriptionPanel = NULL; + } } void djui_panel_join_lobbies_refresh(UNUSED struct DjuiBase* caller) { @@ -79,7 +128,8 @@ void djui_panel_join_lobbies_create(struct DjuiBase* caller, const char* passwor if (sPassword) { free(sPassword); sPassword = NULL; } sPassword = strdup(password); bool private = (strlen(password) > 0); - bool querying = ns_coopnet_query(djui_panel_join_query, djui_panel_join_query_finish, password); + + djui_panel_join_lobby_description_create(); struct DjuiBase* defaultBase = NULL; struct DjuiThreePanel* panel = djui_panel_menu_create(private ? DLANG(LOBBIES, PRIVATE_LOBBIES) : DLANG(LOBBIES, PUBLIC_LOBBIES)); @@ -89,17 +139,7 @@ void djui_panel_join_lobbies_create(struct DjuiBase* caller, const char* passwor sLobbyLayout = paginated->layout; djui_flow_layout_set_margin(sLobbyLayout, 4); - #if 0 - struct DjuiBase* layoutBase = &sLobbyLayout->base; - for (int i = 0; i < 1; i++) { - djui_lobby_entry_create(layoutBase, "MysterD", "Super Mario 64", "15/16", NULL); - djui_lobby_entry_create(layoutBase, "djoslin0", "Star Road", "1/16", NULL); - djui_lobby_entry_create(layoutBase, "abcdefghijklmnopqrs", "Snowstorm Avalanche", "16/16", NULL); - djui_lobby_entry_create(layoutBase, "Prince Frizzy", "Hide and Seek", "4/16", NULL); - djui_lobby_entry_create(layoutBase, "Sunk", "Super Mario 74 (+EE)", "5/8", NULL); - } - djui_paginated_calculate_height(paginated); - #endif + bool querying = ns_coopnet_query(djui_panel_join_query, djui_panel_join_query_finish, password); if (!querying) { struct DjuiText* text = djui_text_create(&sLobbyLayout->base, DLANG(NOTIF, COOPNET_CONNECTION_FAILED)); djui_base_set_size_type(&text->base, DJUI_SVT_RELATIVE, DJUI_SVT_RELATIVE); diff --git a/src/pc/lua/smlua_constants_autogen.c b/src/pc/lua/smlua_constants_autogen.c index 7343f989..0f1b414b 100644 --- a/src/pc/lua/smlua_constants_autogen.c +++ b/src/pc/lua/smlua_constants_autogen.c @@ -1768,7 +1768,7 @@ char gSmluaConstants[] = "" "UNKNOWN_GLOBAL_INDEX = (-1)\n" "UNKNOWN_NETWORK_INDEX = (-1)\n" "NETWORK_PLAYER_TIMEOUT = 10\n" -"NETWORK_PLAYER_PING_TIMEOUT = 1\n" +"NETWORK_PLAYER_PING_TIMEOUT = 3\n" "MAX_RX_SEQ_IDS = 64\n" "USE_REAL_PALETTE_VAR = 0xFF\n" "NPT_UNKNOWN = 0\n" diff --git a/src/pc/network/coopnet/coopnet.c b/src/pc/network/coopnet/coopnet.c index 92c3f2fd..cd4aafea 100644 --- a/src/pc/network/coopnet/coopnet.c +++ b/src/pc/network/coopnet/coopnet.c @@ -6,6 +6,7 @@ #include "pc/djui/djui_language.h" #include "pc/djui/djui_popup.h" #include "pc/mods/mods.h" +#include "pc/utils/misc.h" #include "pc/debuglog.h" #ifdef DISCORD_SDK #include "pc/discord/discord.h" @@ -17,6 +18,7 @@ uint64_t gCoopNetDesiredLobby = 0; char gCoopNetPassword[64] = ""; +char sCoopNetDescription[256] = ""; static uint64_t sLocalLobbyId = 0; static uint64_t sLocalLobbyOwnerId = 0; @@ -139,6 +141,33 @@ bool ns_coopnet_is_connected(void) { return coopnet_is_connected(); } +static void coopnet_populate_description(void) { + char* buffer = sCoopNetDescription; + int bufferLength = 256; + // get version + char* version = get_version(); + int versionLength = strlen(version); + snprintf(buffer, bufferLength, "%s", version); + buffer += versionLength; + bufferLength -= versionLength; + + // get mod strings + if (gActiveMods.entryCount <= 0) { return; } + char* strings[gActiveMods.entryCount]; + for (int i = 0; i < gActiveMods.entryCount; i++) { + strings[i] = gActiveMods.entries[i]->name; + } + + // add seperator + char* sep = "\n\nMods:\n"; + snprintf(buffer, bufferLength, "%s", sep); + buffer += strlen(sep); + bufferLength -= strlen(sep); + + // concat mod strings + str_seperator_concat(buffer, bufferLength, strings, gActiveMods.entryCount, "\n"); +} + void ns_coopnet_update(void) { if (!coopnet_is_connected()) { return; } @@ -149,11 +178,13 @@ void ns_coopnet_update(void) { mods_get_main_mod_name(mode, 64); if (sReconnecting) { LOG_INFO("Update lobby"); - coopnet_lobby_update(sLocalLobbyId, CN_GAME_STR, get_version(), configPlayerName, mode); + coopnet_populate_description(); + coopnet_lobby_update(sLocalLobbyId, CN_GAME_STR, get_version(), configPlayerName, mode, sCoopNetDescription); } else { LOG_INFO("Create lobby"); snprintf(gCoopNetPassword, 64, "%s", configPassword); - coopnet_lobby_create(CN_GAME_STR, get_version(), configPlayerName, mode, (uint16_t)configAmountofPlayers, gCoopNetPassword); + coopnet_populate_description(); + coopnet_lobby_create(CN_GAME_STR, get_version(), configPlayerName, mode, (uint16_t)configAmountofPlayers, gCoopNetPassword, sCoopNetDescription); } } else if (sNetworkType == NT_CLIENT) { LOG_INFO("Join lobby"); diff --git a/src/pc/network/coopnet/coopnet.h b/src/pc/network/coopnet/coopnet.h index 49987e34..ec094c7d 100644 --- a/src/pc/network/coopnet/coopnet.h +++ b/src/pc/network/coopnet/coopnet.h @@ -2,7 +2,7 @@ #define COOPNET_H #ifdef COOPNET -typedef void (*QueryCallbackPtr)(uint64_t aLobbyId, uint64_t aOwnerId, uint16_t aConnections, uint16_t aMaxConnections, const char* aGame, const char* aVersion, const char* aHostName, const char* aMode); +typedef void (*QueryCallbackPtr)(uint64_t aLobbyId, uint64_t aOwnerId, uint16_t aConnections, uint16_t aMaxConnections, const char* aGame, const char* aVersion, const char* aHostName, const char* aMode, const char* aDescription); typedef void (*QueryFinishCallbackPtr)(void); extern struct NetworkSystem gNetworkSystemCoopNet;