From d34eed7ad0bc8ccda464f0bc1f384f753062692d Mon Sep 17 00:00:00 2001 From: PeachyPeach <72323920+PeachyPeachSM64@users.noreply.github.com> Date: Mon, 4 Apr 2022 22:43:29 +0200 Subject: [PATCH] Set loading order of mods files to alphabetical; Fixed a bug with downloaded mod folders (#54) Mods as a directory of files depend on loading order for them to work properly. Currently, the loading order is basically undefined behavior and unpredictable. The function mod_set_loading_order is here to specify this order. By default (and for now), the order will be alphabetical and will follow the ascii table values, meaning digits come before capital letters and lowercase letters. Fixed a bug with mods as directories of files when they are downloaded. The bug was the following: If two selected mods have files with the same relative filename, they overwrite each other when downloaded, causing file corruption and making the client game crash when loaded. To fix it, the mod's directory name is appended to every .lua filename, so each file has a unique filename when downloaded. --- src/pc/mods/mod.c | 23 +++++++++++++++++++++++ src/pc/network/packets/packet_mod_list.c | 5 +++++ 2 files changed, 28 insertions(+) diff --git a/src/pc/mods/mod.c b/src/pc/mods/mod.c index 7cf485bd..a1753924 100644 --- a/src/pc/mods/mod.c +++ b/src/pc/mods/mod.c @@ -231,6 +231,26 @@ static bool mod_load_files(struct Mod* mod, char* modName, char* fullPath) { return true; } +static void mod_set_loading_order(struct Mod* mod) { + if (mod->fileCount <= 1) { + return; + } + + // TODO: add a way to specify the loading order of a mod's files? + + // By default, this is the alphabetical order on relative path + for (s32 i = 1; i < mod->fileCount; ++i) { + struct ModFile file = mod->files[i]; + for (s32 j = 0; j < i; ++j) { + if (strcmp(file.relativePath, mod->files[j].relativePath) < 0) { + memmove(mod->files + j + 1, mod->files + j, sizeof(struct ModFile) * (i - j)); + memcpy(mod->files + j, &file, sizeof(struct ModFile)); + break; + } + } + } +} + static void mod_extract_fields(struct Mod* mod) { // get full path char path[SYS_MAX_PATH] = { 0 }; @@ -372,6 +392,9 @@ bool mod_load(struct Mods* mods, char* basePath, char* modName) { return false; } + // set loading order + mod_set_loading_order(mod); + // extract fields mod_extract_fields(mod); diff --git a/src/pc/network/packets/packet_mod_list.c b/src/pc/network/packets/packet_mod_list.c index ce529279..cd62bccd 100644 --- a/src/pc/network/packets/packet_mod_list.c +++ b/src/pc/network/packets/packet_mod_list.c @@ -170,6 +170,11 @@ void network_receive_mod_list(struct Packet* p) { packet_read(p, &relativePathLength, sizeof(u16)); packet_read(p, file->relativePath, relativePathLength * sizeof(u8)); packet_read(p, &file->size, sizeof(u64)); + if (mod->isDirectory && !strstr(file->relativePath, "actors")) { + char tmp[SYS_MAX_PATH]; + snprintf(tmp, SYS_MAX_PATH, "%s-%s", mod->relativePath, file->relativePath); + memcpy(file->relativePath, tmp, strlen(tmp) + 1); + } normalize_path(file->relativePath); LOG_INFO(" '%s': %llu", file->relativePath, (u64)file->size); }