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);