From 89e9bcdcec69ef95c076c6ff11a087ad4ae8f794 Mon Sep 17 00:00:00 2001 From: Agent X <44549182+Agent-11@users.noreply.github.com> Date: Mon, 4 Mar 2024 19:25:09 -0500 Subject: [PATCH] Add "-- pausable" field for mods and function so mods can make themselves pausable in singleplayer --- autogen/lua_definitions/functions.lua | 5 +++++ autogen/lua_definitions/structs.lua | 1 + docs/lua/functions-4.md | 18 ++++++++++++++++++ docs/lua/functions.md | 1 + docs/lua/structs.md | 1 + src/engine/behavior_script.c | 5 ++--- src/game/level_update.c | 2 +- src/pc/lua/smlua_cobject_autogen.c | 3 ++- src/pc/lua/smlua_functions_autogen.c | 16 ++++++++++++++++ src/pc/mods/mod.c | 2 ++ src/pc/mods/mod.h | 1 + src/pc/mods/mods.c | 13 +++++++++++++ src/pc/mods/mods.h | 1 + src/pc/network/network.c | 3 +-- src/pc/network/network_utils.c | 6 ++++++ src/pc/network/network_utils.h | 2 ++ src/pc/network/packets/packet_mod_list.c | 2 ++ 17 files changed, 75 insertions(+), 7 deletions(-) diff --git a/autogen/lua_definitions/functions.lua b/autogen/lua_definitions/functions.lua index 1123b1421..55e54df8f 100644 --- a/autogen/lua_definitions/functions.lua +++ b/autogen/lua_definitions/functions.lua @@ -5885,6 +5885,11 @@ function network_player_set_description(np, description, r, g, b, a) -- ... end +--- @return boolean +function network_check_singleplayer_pause() + -- ... +end + --- @param localIndex integer --- @return string function network_get_player_text_color_string(localIndex) diff --git a/autogen/lua_definitions/structs.lua b/autogen/lua_definitions/structs.lua index e34fa3a39..56bc8f44c 100644 --- a/autogen/lua_definitions/structs.lua +++ b/autogen/lua_definitions/structs.lua @@ -1061,6 +1061,7 @@ --- @field public index integer --- @field public isDirectory boolean --- @field public name string +--- @field public pausable boolean --- @field public relativePath string --- @field public renderBehindHud boolean --- @field public selectable boolean diff --git a/docs/lua/functions-4.md b/docs/lua/functions-4.md index 84741cfea..a578d6b12 100644 --- a/docs/lua/functions-4.md +++ b/docs/lua/functions-4.md @@ -354,6 +354,24 @@
+## [network_check_singleplayer_pause](#network_check_singleplayer_pause) + +### Lua Example +`local booleanValue = network_check_singleplayer_pause()` + +### Parameters +- None + +### Returns +- `boolean` + +### C Prototype +`bool network_check_singleplayer_pause(void);` + +[:arrow_up_small:](#) + +
+ ## [network_get_player_text_color_string](#network_get_player_text_color_string) ### Lua Example diff --git a/docs/lua/functions.md b/docs/lua/functions.md index f095b482d..6ca36d5a2 100644 --- a/docs/lua/functions.md +++ b/docs/lua/functions.md @@ -1155,6 +1155,7 @@
- network_utils.h + - [network_check_singleplayer_pause](functions-4.md#network_check_singleplayer_pause) - [network_get_player_text_color_string](functions-4.md#network_get_player_text_color_string) - [network_global_index_from_local](functions-4.md#network_global_index_from_local) - [network_is_moderator](functions-4.md#network_is_moderator) diff --git a/docs/lua/structs.md b/docs/lua/structs.md index 8227c09e6..8228f5960 100644 --- a/docs/lua/structs.md +++ b/docs/lua/structs.md @@ -1435,6 +1435,7 @@ | index | `integer` | read-only | | isDirectory | `boolean` | read-only | | name | `string` | read-only | +| pausable | `boolean` | read-only | | relativePath | `string` | read-only | | renderBehindHud | `boolean` | read-only | | selectable | `boolean` | read-only | diff --git a/src/engine/behavior_script.c b/src/engine/behavior_script.c index 259e51059..76252625a 100644 --- a/src/engine/behavior_script.c +++ b/src/engine/behavior_script.c @@ -1275,7 +1275,6 @@ static BhvCommandProc BehaviorCmdTable[BEHAVIOR_CMD_TABLE_MAX] = { bhv_cmd_load_collision_data_ext, //41 }; -extern s16 gMenuMode; // Execute the behavior script of the current object, process the object flags, and other miscellaneous code for updating objects. void cur_obj_update(void) { if (!gCurrentObject) { return; } @@ -1287,7 +1286,7 @@ void cur_obj_update(void) { } // handle network area timer - if (gCurrentObject->areaTimerType != AREA_TIMER_TYPE_NONE && !(gMenuMode != -1 && network_player_connected_count() == 1 && gActiveMods.entryCount == 0)) { + if (gCurrentObject->areaTimerType != AREA_TIMER_TYPE_NONE && !network_check_singleplayer_pause()) { // make sure the area is valid if (gNetworkPlayerLocal == NULL || !gNetworkPlayerLocal->currAreaSyncValid) { goto cur_obj_update_end; @@ -1437,7 +1436,7 @@ cur_obj_update_begin:; } // update network area timer - if (gCurrentObject->areaTimerType != AREA_TIMER_TYPE_NONE && !(gMenuMode != -1 && network_player_connected_count() == 1 && gActiveMods.entryCount == 0)) { + if (gCurrentObject->areaTimerType != AREA_TIMER_TYPE_NONE && !network_check_singleplayer_pause()) { gCurrentObject->areaTimer++; if (gCurrentObject->areaTimer < gNetworkAreaTimer) { goto cur_obj_update_begin; diff --git a/src/game/level_update.c b/src/game/level_update.c index 7167357a1..fae06e79f 100644 --- a/src/game/level_update.c +++ b/src/game/level_update.c @@ -1669,7 +1669,7 @@ s32 update_level(void) { changeLevel = play_mode_normal(); break; case PLAY_MODE_PAUSED: - if (!(network_player_connected_count() == 1 && gActiveMods.entryCount == 0)) { + if (!network_check_singleplayer_pause()) { changeLevel = play_mode_normal(); } diff --git a/src/pc/lua/smlua_cobject_autogen.c b/src/pc/lua/smlua_cobject_autogen.c index c576ef7e5..bf6d8ed4d 100644 --- a/src/pc/lua/smlua_cobject_autogen.c +++ b/src/pc/lua/smlua_cobject_autogen.c @@ -1177,7 +1177,7 @@ static struct LuaObjectField sMarioStateFields[LUA_MARIO_STATE_FIELD_COUNT] = { { "waterLevel", LVT_S16, offsetof(struct MarioState, waterLevel), false, LOT_NONE }, }; -#define LUA_MOD_FIELD_COUNT 13 +#define LUA_MOD_FIELD_COUNT 14 static struct LuaObjectField sModFields[LUA_MOD_FIELD_COUNT] = { { "basePath", LVT_STRING, offsetof(struct Mod, basePath), true, LOT_NONE }, { "customBehaviorIndex", LVT_U8, offsetof(struct Mod, customBehaviorIndex), true, LOT_NONE }, @@ -1189,6 +1189,7 @@ static struct LuaObjectField sModFields[LUA_MOD_FIELD_COUNT] = { { "index", LVT_S32, offsetof(struct Mod, index), true, LOT_NONE }, { "isDirectory", LVT_BOOL, offsetof(struct Mod, isDirectory), true, LOT_NONE }, { "name", LVT_STRING_P, offsetof(struct Mod, name), true, LOT_NONE }, + { "pausable", LVT_BOOL, offsetof(struct Mod, pausable), true, LOT_NONE }, { "relativePath", LVT_STRING, offsetof(struct Mod, relativePath), true, LOT_NONE }, { "renderBehindHud", LVT_BOOL, offsetof(struct Mod, renderBehindHud), true, LOT_NONE }, { "selectable", LVT_BOOL, offsetof(struct Mod, selectable), true, LOT_NONE }, diff --git a/src/pc/lua/smlua_functions_autogen.c b/src/pc/lua/smlua_functions_autogen.c index c8807bf0b..2f4b2becc 100644 --- a/src/pc/lua/smlua_functions_autogen.c +++ b/src/pc/lua/smlua_functions_autogen.c @@ -20003,6 +20003,21 @@ int smlua_func_network_player_set_description(lua_State* L) { // network_utils.h // ///////////////////// +int smlua_func_network_check_singleplayer_pause(UNUSED lua_State* L) { + if (L == NULL) { return 0; } + + int top = lua_gettop(L); + if (top != 0) { + LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "network_check_singleplayer_pause", 0, top); + return 0; + } + + + lua_pushboolean(L, network_check_singleplayer_pause()); + + return 1; +} + int smlua_func_network_get_player_text_color_string(lua_State* L) { if (L == NULL) { return 0; } @@ -32586,6 +32601,7 @@ void smlua_bind_functions_autogen(void) { smlua_bind_function(L, "network_player_set_description", smlua_func_network_player_set_description); // network_utils.h + smlua_bind_function(L, "network_check_singleplayer_pause", smlua_func_network_check_singleplayer_pause); smlua_bind_function(L, "network_get_player_text_color_string", smlua_func_network_get_player_text_color_string); smlua_bind_function(L, "network_global_index_from_local", smlua_func_network_global_index_from_local); smlua_bind_function(L, "network_is_moderator", smlua_func_network_is_moderator); diff --git a/src/pc/mods/mod.c b/src/pc/mods/mod.c index 0a6cc7c2c..62d72f572 100644 --- a/src/pc/mods/mod.c +++ b/src/pc/mods/mod.c @@ -434,6 +434,8 @@ static void mod_extract_fields(struct Mod* mod) { } } else if (!mod->deluxe && (extracted = extract_lua_field("-- deluxe:", buffer))) { mod->deluxe = !strcmp(extracted, "true"); + } else if (!mod->pausable && (extracted = extract_lua_field("-- pausable:", buffer))) { + mod->pausable = !strcmp(extracted, "true"); } } diff --git a/src/pc/mods/mod.h b/src/pc/mods/mod.h index bec06b480..927fdff90 100644 --- a/src/pc/mods/mod.h +++ b/src/pc/mods/mod.h @@ -35,6 +35,7 @@ struct Mod { bool selectable; bool renderBehindHud; bool deluxe; + bool pausable; size_t size; u8 customBehaviorIndex; }; diff --git a/src/pc/mods/mods.c b/src/pc/mods/mods.c index ebd4c24f1..44575c4cb 100644 --- a/src/pc/mods/mods.c +++ b/src/pc/mods/mods.c @@ -61,6 +61,19 @@ u16 mods_get_character_select_count(void) { return enabled; } +bool mods_get_all_pausable(void) { + bool pausable = true; + + for (u16 i = 0; i < gActiveMods.entryCount; i++) { + if (!gActiveMods.entries[i]->pausable) { + pausable = false; + break; + } + } + + return pausable; +} + static void mods_local_store_enabled(void) { assert(sLocalEnabledPaths == NULL); struct LocalEnabledPath* prev = NULL; diff --git a/src/pc/mods/mods.h b/src/pc/mods/mods.h index 04ed71d19..75b08770b 100644 --- a/src/pc/mods/mods.h +++ b/src/pc/mods/mods.h @@ -25,6 +25,7 @@ extern char gRemoteModsBasePath[]; void mods_get_main_mod_name(char* destination, u32 maxSize); u16 mods_get_enabled_count(void); u16 mods_get_character_select_count(void); +bool mods_get_all_pausable(void); bool mods_generate_remote_base_path(void); void mods_activate(struct Mods* mods); void mods_clear(struct Mods* mods); diff --git a/src/pc/network/network.c b/src/pc/network/network.c index d5c748ae5..4f7d83b16 100644 --- a/src/pc/network/network.c +++ b/src/pc/network/network.c @@ -502,7 +502,6 @@ static void network_rehost_update(void) { djui_panel_do_host(true); } -extern s16 gMenuMode; static void network_update_area_timer(void) { bool brokenClock = false; #ifdef DEVELOPMENT @@ -523,7 +522,7 @@ static void network_update_area_timer(void) { //brokenClock = (skipClockCount > 0); #endif if (!brokenClock) { - if (gMenuMode != -1 && network_player_connected_count() == 1 && gActiveMods.entryCount == 0) { + if (network_check_singleplayer_pause()) { gNetworkAreaTimerClock++; } // update network area timer diff --git a/src/pc/network/network_utils.c b/src/pc/network/network_utils.c index 09abb4162..d25169212 100644 --- a/src/pc/network/network_utils.c +++ b/src/pc/network/network_utils.c @@ -1,6 +1,7 @@ #include #include "network_utils.h" #include "game/mario_misc.h" +#include "pc/mods/mods.h" u8 network_global_index_from_local(u8 localIndex) { if (gNetworkType == NT_SERVER) { return localIndex; } @@ -49,3 +50,8 @@ const char* network_get_player_text_color_string(u8 localIndex) { snprintf(sColorString, 10, "\\#%02x%02x%02x\\", rgb[0], rgb[1], rgb[2]); return sColorString; } + +extern s16 gMenuMode; +bool network_check_singleplayer_pause(void) { + return gMenuMode != -1 && network_player_connected_count() == 1 && mods_get_all_pausable(); +} diff --git a/src/pc/network/network_utils.h b/src/pc/network/network_utils.h index 767308490..3fb05e3c7 100644 --- a/src/pc/network/network_utils.h +++ b/src/pc/network/network_utils.h @@ -13,4 +13,6 @@ bool network_is_moderator(void); u8* network_get_player_text_color(u8 localIndex); const char* network_get_player_text_color_string(u8 localIndex); +bool network_check_singleplayer_pause(void); + #endif \ No newline at end of file diff --git a/src/pc/network/packets/packet_mod_list.c b/src/pc/network/packets/packet_mod_list.c index 0c022a479..0315e6dce 100644 --- a/src/pc/network/packets/packet_mod_list.c +++ b/src/pc/network/packets/packet_mod_list.c @@ -86,6 +86,7 @@ void network_send_mod_list(void) { packet_write(&p, &mod->isDirectory, sizeof(u8)); if (!configCoopCompatibility) { packet_write(&p, &mod->deluxe, sizeof(u8)); + packet_write(&p, &mod->pausable, sizeof(u8)); } packet_write(&p, &mod->fileCount, sizeof(u16)); network_send_to(0, &p); @@ -227,6 +228,7 @@ void network_receive_mod_list_entry(struct Packet* p) { packet_read(p, &mod->isDirectory, sizeof(u8)); if (!configCoopCompatibility) { packet_read(p, &mod->deluxe, sizeof(u8)); + packet_read(p, &mod->pausable, sizeof(u8)); } normalize_path(mod->relativePath); LOG_INFO(" '%s': %llu", mod->name, (u64)mod->size);