mirror of
https://github.com/coop-deluxe/sm64coopdx.git
synced 2024-11-26 05:55:15 +00:00
More progress on mod table rewrite
This commit is contained in:
parent
0a3d0b2033
commit
0983474429
9 changed files with 248 additions and 45 deletions
|
@ -13,7 +13,7 @@
|
||||||
#include "gfx/gfx_window_manager_api.h"
|
#include "gfx/gfx_window_manager_api.h"
|
||||||
#include "controller/controller_api.h"
|
#include "controller/controller_api.h"
|
||||||
#include "fs/fs.h"
|
#include "fs/fs.h"
|
||||||
#include "pc/mod_list.h"
|
#include "pc/mods/mods.h"
|
||||||
#include "pc/network/ban_list.h"
|
#include "pc/network/ban_list.h"
|
||||||
#include "pc/crash_handler.h"
|
#include "pc/crash_handler.h"
|
||||||
|
|
||||||
|
@ -217,21 +217,27 @@ static const struct ConfigOption options[] = {
|
||||||
// FunctionConfigOption functions
|
// FunctionConfigOption functions
|
||||||
|
|
||||||
static void enable_mod_read(char** tokens, UNUSED int numTokens) {
|
static void enable_mod_read(char** tokens, UNUSED int numTokens) {
|
||||||
for (unsigned int i = 0; i < gModTableLocal.entryCount; i++) {
|
char combined[256] = { 0 };
|
||||||
struct ModListEntry* entry = &gModTableLocal.entries[i];
|
for (int i = 1; i < numTokens; i++) {
|
||||||
if (!strcmp(tokens[1], entry->name)) {
|
if (i != 1) { strncat(combined, " ", 255); }
|
||||||
entry->enabled = true;
|
strncat(combined, tokens[i], 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < gLocalMods.entryCount; i++) {
|
||||||
|
struct Mod* mod = gLocalMods.entries[i];
|
||||||
|
if (!strcmp(combined, mod->relativePath)) {
|
||||||
|
mod->enabled = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void enable_mod_write(FILE* file) {
|
static void enable_mod_write(FILE* file) {
|
||||||
for (unsigned int i = 0; i < gModTableLocal.entryCount; i++) {
|
for (unsigned int i = 0; i < gLocalMods.entryCount; i++) {
|
||||||
struct ModListEntry* entry = &gModTableLocal.entries[i];
|
struct Mod* mod = gLocalMods.entries[i];
|
||||||
if (entry == NULL) { continue; }
|
if (mod == NULL) { continue; }
|
||||||
if (!entry->enabled) { continue; }
|
if (!mod->enabled) { continue; }
|
||||||
fprintf(file, "%s %s\n", "enable-mod:", entry->name);
|
fprintf(file, "%s %s\n", "enable-mod:", mod->relativePath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,8 @@
|
||||||
#include "pc/utils/misc.h"
|
#include "pc/utils/misc.h"
|
||||||
#include "pc/configfile.h"
|
#include "pc/configfile.h"
|
||||||
#include "pc/cheats.h"
|
#include "pc/cheats.h"
|
||||||
#include "pc/mod_list.h"
|
#include "pc/mods/mods.h"
|
||||||
|
#include "pc/mods/mods_utils.h"
|
||||||
|
|
||||||
static struct DjuiFlowLayout* sModLayout = NULL;
|
static struct DjuiFlowLayout* sModLayout = NULL;
|
||||||
static struct DjuiThreePanel* sDescriptionPanel = NULL;
|
static struct DjuiThreePanel* sDescriptionPanel = NULL;
|
||||||
|
@ -43,10 +44,11 @@ static void djui_panel_host_mods_description_create() {
|
||||||
|
|
||||||
static void djui_mod_checkbox_on_hover(struct DjuiBase* base) {
|
static void djui_mod_checkbox_on_hover(struct DjuiBase* base) {
|
||||||
char* description = "";
|
char* description = "";
|
||||||
if (base->tag >= 0 && base->tag < gModTableLocal.entryCount) {
|
if (base->tag >= 0 && base->tag < gLocalMods.entryCount) {
|
||||||
char* d = gModTableLocal.entries[base->tag].description;
|
struct Mod* mod = gLocalMods.entries[base->tag];
|
||||||
|
char* d = mod->description;
|
||||||
if (d != NULL) {
|
if (d != NULL) {
|
||||||
description = gModTableLocal.entries[base->tag].description;
|
description = mod->description;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
djui_text_set_text(sTooltip, description);
|
djui_text_set_text(sTooltip, description);
|
||||||
|
@ -57,15 +59,15 @@ static void djui_mod_checkbox_on_hover_end(UNUSED struct DjuiBase* base) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void djui_mod_checkbox_on_value_change(UNUSED struct DjuiBase* base) {
|
static void djui_mod_checkbox_on_value_change(UNUSED struct DjuiBase* base) {
|
||||||
mod_list_update_selectable();
|
mods_update_selectable();
|
||||||
|
|
||||||
u16 index = 0;
|
u16 index = 0;
|
||||||
struct DjuiBaseChild* node = sModLayout->base.child;
|
struct DjuiBaseChild* node = sModLayout->base.child;
|
||||||
while (node != NULL) {
|
while (node != NULL) {
|
||||||
if (index >= gModTableLocal.entryCount) { break; }
|
if (index >= gLocalMods.entryCount) { break; }
|
||||||
struct ModListEntry* entry = &gModTableLocal.entries[index];
|
struct Mod* mod = gLocalMods.entries[index];
|
||||||
|
|
||||||
djui_base_set_enabled(node->base, entry->selectable);
|
djui_base_set_enabled(node->base, mod->selectable);
|
||||||
|
|
||||||
// iterate
|
// iterate
|
||||||
index++;
|
index++;
|
||||||
|
@ -86,7 +88,7 @@ static void djui_panel_host_mods_destroy(struct DjuiBase* base) {
|
||||||
void djui_panel_host_mods_create(struct DjuiBase* caller) {
|
void djui_panel_host_mods_create(struct DjuiBase* caller) {
|
||||||
f32 bodyHeight = (416) + 64 * 1 + 16 * 1;
|
f32 bodyHeight = (416) + 64 * 1 + 16 * 1;
|
||||||
|
|
||||||
mod_list_update_selectable();
|
mods_update_selectable();
|
||||||
|
|
||||||
struct DjuiBase* defaultBase = NULL;
|
struct DjuiBase* defaultBase = NULL;
|
||||||
struct DjuiThreePanel* panel = djui_panel_menu_create(bodyHeight, "\\#ff0800\\M\\#1be700\\O\\#00b3ff\\D\\#ffef00\\S");
|
struct DjuiThreePanel* panel = djui_panel_menu_create(bodyHeight, "\\#ff0800\\M\\#1be700\\O\\#00b3ff\\D\\#ffef00\\S");
|
||||||
|
@ -95,13 +97,13 @@ void djui_panel_host_mods_create(struct DjuiBase* caller) {
|
||||||
struct DjuiPaginated* paginated = djui_paginated_create(&body->base, 8);
|
struct DjuiPaginated* paginated = djui_paginated_create(&body->base, 8);
|
||||||
sModLayout = paginated->layout;
|
sModLayout = paginated->layout;
|
||||||
struct DjuiBase* layoutBase = &paginated->layout->base;
|
struct DjuiBase* layoutBase = &paginated->layout->base;
|
||||||
for (int i = 0; i < gModTableLocal.entryCount; i++) {
|
for (int i = 0; i < gLocalMods.entryCount; i++) {
|
||||||
struct ModListEntry* entry = &gModTableLocal.entries[i];
|
struct Mod* mod = gLocalMods.entries[i];
|
||||||
struct DjuiCheckbox* checkbox = djui_checkbox_create(layoutBase, entry->displayName ? entry->displayName : entry->name, &entry->enabled);
|
struct DjuiCheckbox* checkbox = djui_checkbox_create(layoutBase, mod->name, &mod->enabled);
|
||||||
checkbox->base.tag = i;
|
checkbox->base.tag = i;
|
||||||
djui_base_set_size_type(&checkbox->base, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE);
|
djui_base_set_size_type(&checkbox->base, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE);
|
||||||
djui_base_set_size(&checkbox->base, 1.0f, 32);
|
djui_base_set_size(&checkbox->base, 1.0f, 32);
|
||||||
djui_base_set_enabled(&checkbox->base, entry->selectable);
|
djui_base_set_enabled(&checkbox->base, mod->selectable);
|
||||||
djui_interactable_hook_hover(&checkbox->base, djui_mod_checkbox_on_hover, djui_mod_checkbox_on_hover_end);
|
djui_interactable_hook_hover(&checkbox->base, djui_mod_checkbox_on_hover, djui_mod_checkbox_on_hover_end);
|
||||||
djui_interactable_hook_value_change(&checkbox->base, djui_mod_checkbox_on_value_change);
|
djui_interactable_hook_value_change(&checkbox->base, djui_mod_checkbox_on_value_change);
|
||||||
if (i == 0) { defaultBase = &checkbox->base; }
|
if (i == 0) { defaultBase = &checkbox->base; }
|
||||||
|
|
|
@ -7,7 +7,10 @@
|
||||||
void mod_clear(struct Mod* mod) {
|
void mod_clear(struct Mod* mod) {
|
||||||
for (int j = 0; j < mod->fileCount; j++) {
|
for (int j = 0; j < mod->fileCount; j++) {
|
||||||
struct ModFile* file = &mod->files[j];
|
struct ModFile* file = &mod->files[j];
|
||||||
file = file;
|
if (file->fp != NULL) {
|
||||||
|
fclose(file->fp);
|
||||||
|
file->fp = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mod->name != NULL) {
|
if (mod->name != NULL) {
|
||||||
|
@ -30,6 +33,8 @@ void mod_clear(struct Mod* mod) {
|
||||||
}
|
}
|
||||||
|
|
||||||
mod->fileCount = 0;
|
mod->fileCount = 0;
|
||||||
|
mod->size = 0;
|
||||||
|
free(mod);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct ModFile* mod_allocate_file(struct Mod* mod, char* relativePath) {
|
static struct ModFile* mod_allocate_file(struct Mod* mod, char* relativePath) {
|
||||||
|
@ -51,6 +56,28 @@ static struct ModFile* mod_allocate_file(struct Mod* mod, char* relativePath) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// figure out full path
|
||||||
|
char fullPath[SYS_MAX_PATH] = { 0 };
|
||||||
|
if (!mod_file_full_path(fullPath, mod, file)) {
|
||||||
|
LOG_ERROR("Failed to concat path: '%s' + '%s'", mod->basePath, relativePath);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// open file
|
||||||
|
FILE* f = fopen(fullPath, "rb");
|
||||||
|
if (f == NULL) {
|
||||||
|
LOG_ERROR("Failed to open '%s'", fullPath);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get size
|
||||||
|
fseek(f, 0, SEEK_END);
|
||||||
|
file->size = ftell(f);
|
||||||
|
mod->size += file->size;
|
||||||
|
|
||||||
|
// close file
|
||||||
|
fclose(f);
|
||||||
|
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,7 +139,7 @@ static bool mod_load_files(struct Mod* mod, char* modName, char* fullPath) {
|
||||||
while ((dir = readdir(d)) != NULL) {
|
while ((dir = readdir(d)) != NULL) {
|
||||||
// sanity check / fill path[]
|
// sanity check / fill path[]
|
||||||
if (!directory_sanity_check(dir, actorsPath, path)) { continue; }
|
if (!directory_sanity_check(dir, actorsPath, path)) { continue; }
|
||||||
if (snprintf(relativePath, SYS_MAX_PATH - 1, "%s/actors/%s", modName, dir->d_name) < 0) {
|
if (snprintf(relativePath, SYS_MAX_PATH - 1, "actors/%s", dir->d_name) < 0) {
|
||||||
LOG_ERROR("Could not concat actor path!");
|
LOG_ERROR("Could not concat actor path!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -229,23 +256,28 @@ bool mod_load(struct Mods* mods, char* basePath, char* modName) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// make sure mod is unique
|
// make sure mod is unique
|
||||||
for (int i = 0; i < mods->modCount; i++) {
|
for (int i = 0; i < mods->entryCount; i++) {
|
||||||
struct Mod* compareMod = &mods->entries[i];
|
struct Mod* compareMod = mods->entries[i];
|
||||||
if (!strcmp(compareMod->relativePath, modName)) {
|
if (!strcmp(compareMod->relativePath, modName)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// allocate mod
|
// allocate mod
|
||||||
u16 modIndex = mods->modCount++;
|
u16 modIndex = mods->entryCount++;
|
||||||
mods->entries = realloc(mods->entries, sizeof(struct Mod) * mods->modCount);
|
mods->entries = realloc(mods->entries, sizeof(struct Mod*) * mods->entryCount);
|
||||||
if (mods->entries == NULL) {
|
if (mods->entries == NULL) {
|
||||||
LOG_ERROR("Failed to allocate entries!");
|
LOG_ERROR("Failed to allocate entries!");
|
||||||
mods_clear(mods);
|
mods_clear(mods);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
struct Mod* mod = &mods->entries[modIndex];
|
mods->entries[modIndex] = calloc(1, sizeof(struct Mod));
|
||||||
memset(mod, 0, sizeof(struct Mod));
|
struct Mod* mod = mods->entries[modIndex];
|
||||||
|
if (mod == NULL) {
|
||||||
|
LOG_ERROR("Failed to allocate mod!");
|
||||||
|
mods_clear(mods);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// set paths
|
// set paths
|
||||||
char* cpyPath = isDirectory ? fullPath : basePath;
|
char* cpyPath = isDirectory ? fullPath : basePath;
|
||||||
|
|
|
@ -9,6 +9,8 @@ struct Mods;
|
||||||
|
|
||||||
struct ModFile {
|
struct ModFile {
|
||||||
char relativePath[SYS_MAX_PATH];
|
char relativePath[SYS_MAX_PATH];
|
||||||
|
size_t size;
|
||||||
|
FILE* fp;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Mod {
|
struct Mod {
|
||||||
|
@ -21,6 +23,8 @@ struct Mod {
|
||||||
u16 fileCount;
|
u16 fileCount;
|
||||||
bool isDirectory;
|
bool isDirectory;
|
||||||
bool enabled;
|
bool enabled;
|
||||||
|
bool selectable;
|
||||||
|
size_t size;
|
||||||
};
|
};
|
||||||
|
|
||||||
void mod_clear(struct Mod* mod);
|
void mod_clear(struct Mod* mod);
|
||||||
|
|
|
@ -5,19 +5,55 @@
|
||||||
|
|
||||||
#define MOD_DIRECTORY "mods"
|
#define MOD_DIRECTORY "mods"
|
||||||
|
|
||||||
static struct Mods gLocalMods = { 0 };
|
struct Mods gLocalMods = { 0 };
|
||||||
|
struct Mods gRemoteMods = { 0 };
|
||||||
|
struct Mods gActiveMods = { 0 };
|
||||||
|
|
||||||
void mods_clear(struct Mods* mods) {
|
void mods_activate(struct Mods* mods) {
|
||||||
for (int i = 0; i < mods->modCount; i ++) {
|
mods_clear(&gActiveMods);
|
||||||
struct Mod* mod = &mods->entries[i];
|
|
||||||
mod_clear(mod);
|
// count enabled
|
||||||
|
u16 enabledCount = 0;
|
||||||
|
for (int i = 0; i < mods->entryCount; i++) {
|
||||||
|
struct Mod* mod = mods->entries[i];
|
||||||
|
if (mod->enabled) { enabledCount++; }
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mods->entries != NULL) {
|
// allocate
|
||||||
free(mods->entries);
|
gActiveMods.entries = calloc(enabledCount, sizeof(struct Mod*));
|
||||||
mods->entries = NULL;
|
if (gActiveMods.entries == NULL) {
|
||||||
|
LOG_ERROR("Failed to allocate active mods table!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy enabled entries
|
||||||
|
for (int i = 0; i < mods->entryCount; i++) {
|
||||||
|
struct Mod* mod = mods->entries[i];
|
||||||
|
if (mod->enabled) {
|
||||||
|
gActiveMods.entries[gActiveMods.entryCount++] = mod;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// open file pointers
|
||||||
|
for (int i = 0; i < gActiveMods.entryCount; i++) {
|
||||||
|
struct Mod* mod = gActiveMods.entries[i];
|
||||||
|
for (int j = 0; j < mod->fileCount; j++) {
|
||||||
|
struct ModFile* file = &mod->files[j];
|
||||||
|
|
||||||
|
char fullPath[SYS_MAX_PATH] = { 0 };
|
||||||
|
if (!mod_file_full_path(fullPath, mod, file)) {
|
||||||
|
LOG_ERROR("Failed to concat path: '%s' + '%s'", mod->basePath, relativePath);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
file->fp = fopen(fullPath, "rb");
|
||||||
|
if (file->fp == NULL) {
|
||||||
|
LOG_ERROR("Failed to open file '%s'", fullPath);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
mods->modCount = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mods_load(struct Mods* mods, char* modsBasePath) {
|
static void mods_load(struct Mods* mods, char* modsBasePath) {
|
||||||
|
@ -78,8 +114,50 @@ void mods_init(void) {
|
||||||
// load mods
|
// load mods
|
||||||
if (hasUserPath) { mods_load(&gLocalMods, userModPath); }
|
if (hasUserPath) { mods_load(&gLocalMods, userModPath); }
|
||||||
mods_load(&gLocalMods, "./" MOD_DIRECTORY);
|
mods_load(&gLocalMods, "./" MOD_DIRECTORY);
|
||||||
|
|
||||||
|
// calculate total size
|
||||||
|
gLocalMods.size = 0;
|
||||||
|
for (int i = 0; i < gLocalMods.entryCount; i++) {
|
||||||
|
struct Mod* mod = gLocalMods.entries[i];
|
||||||
|
gLocalMods.size += mod->size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mods_clear(struct Mods* mods) {
|
||||||
|
if (mods == &gActiveMods) {
|
||||||
|
// don't clear the mods of gActiveMods since they're a copy
|
||||||
|
// just close all file pointers
|
||||||
|
for (int i = 0; i < mods->entryCount; i ++) {
|
||||||
|
struct Mod* mod = mods->entries[i];
|
||||||
|
for (int j = 0; j < mod->fileCount; j++) {
|
||||||
|
struct ModFile* file = &mod->files[j];
|
||||||
|
if (file->fp != NULL) {
|
||||||
|
fclose(file->fp);
|
||||||
|
file->fp = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// clear mods of gLocalMods and gRemoteMods
|
||||||
|
for (int i = 0; i < mods->entryCount; i ++) {
|
||||||
|
struct Mod* mod = mods->entries[i];
|
||||||
|
mod_clear(mod);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// cleanup entries
|
||||||
|
if (mods->entries != NULL) {
|
||||||
|
free(mods->entries);
|
||||||
|
mods->entries = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// cleanup params
|
||||||
|
mods->entryCount = 0;
|
||||||
|
mods->size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mods_shutdown(void) {
|
void mods_shutdown(void) {
|
||||||
|
mods_clear(&gRemoteMods);
|
||||||
|
mods_clear(&gActiveMods);
|
||||||
mods_clear(&gLocalMods);
|
mods_clear(&gLocalMods);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,11 +6,18 @@
|
||||||
#include "src/pc/platform.h"
|
#include "src/pc/platform.h"
|
||||||
#include "mod.h"
|
#include "mod.h"
|
||||||
|
|
||||||
|
#define MAX_MOD_SIZE (2 * 1048576) // 2MB
|
||||||
|
|
||||||
struct Mods {
|
struct Mods {
|
||||||
struct Mod* entries;
|
struct Mod** entries;
|
||||||
u16 modCount;
|
u16 entryCount;
|
||||||
|
size_t size;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern struct Mods gLocalMods;
|
||||||
|
extern struct Mods gRemoteMods;
|
||||||
|
extern struct Mods gActiveMods;
|
||||||
|
|
||||||
void mods_clear(struct Mods* mods);
|
void mods_clear(struct Mods* mods);
|
||||||
void mods_init(void);
|
void mods_init(void);
|
||||||
void mods_shutdown(void);
|
void mods_shutdown(void);
|
||||||
|
|
|
@ -1,8 +1,78 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#include "mods.h"
|
||||||
#include "mods_utils.h"
|
#include "mods_utils.h"
|
||||||
#include "pc/debuglog.h"
|
#include "pc/debuglog.h"
|
||||||
|
|
||||||
|
void mods_size_enforce(void) {
|
||||||
|
for (int i = 0; i < gLocalMods.entryCount; i++) {
|
||||||
|
struct Mod* mod = gLocalMods.entries[i];
|
||||||
|
if (mod->size >= MAX_MOD_SIZE) {
|
||||||
|
mod->enabled = false;
|
||||||
|
mod->selectable = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool mods_incompatible_match(struct Mod* a, struct Mod* b) {
|
||||||
|
if (a->incompatible == NULL || b->incompatible == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (strlen(a->incompatible) == 0 || strlen(b->incompatible) == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* ai = a->incompatible;
|
||||||
|
char* bi = b->incompatible;
|
||||||
|
char* atoken = NULL;
|
||||||
|
char* btoken = NULL;
|
||||||
|
char* arest = NULL;
|
||||||
|
char* brest = NULL;
|
||||||
|
|
||||||
|
for (atoken = strtok_r(ai, " ", &arest); atoken != NULL; atoken = strtok_r(NULL, " ", &arest)) {
|
||||||
|
for (btoken = strtok_r(bi, " ", &brest); btoken != NULL; btoken = strtok_r(NULL, " ", &brest)) {
|
||||||
|
if (!strcmp(atoken, btoken)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mods_update_selectable(void) {
|
||||||
|
// reset selectable value
|
||||||
|
for (int i = 0; i < gLocalMods.entryCount; i++) {
|
||||||
|
struct Mod* mod = gLocalMods.entries[i];
|
||||||
|
mod->selectable = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// figure out which ones to deselect
|
||||||
|
for (int i = 0; i < gLocalMods.entryCount; i++) {
|
||||||
|
struct Mod* mod = gLocalMods.entries[i];
|
||||||
|
if (mod->enabled) { continue; }
|
||||||
|
|
||||||
|
for (int j = 0; j < gLocalMods.entryCount; j++) {
|
||||||
|
if (j == i) { continue; }
|
||||||
|
struct Mod* mod2 = gLocalMods.entries[j];
|
||||||
|
if (!mod2->enabled) { continue; }
|
||||||
|
|
||||||
|
if (mods_incompatible_match(mod, mod2)) {
|
||||||
|
mod->selectable = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mods_size_enforce();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool mod_file_full_path(char* destination, struct Mod* mod, struct ModFile* modFile) {
|
||||||
|
return concat_path(destination, mod->basePath, modFile->relativePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
bool str_ends_with(char* string, char* suffix) {
|
bool str_ends_with(char* string, char* suffix) {
|
||||||
if (string == NULL || suffix == NULL) { return false; }
|
if (string == NULL || suffix == NULL) { return false; }
|
||||||
|
|
||||||
|
@ -14,6 +84,7 @@ bool str_ends_with(char* string, char* suffix) {
|
||||||
return !strcmp(&string[stringLength - suffixLength], suffix);
|
return !strcmp(&string[stringLength - suffixLength], suffix);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
char* extract_lua_field(char* fieldName, char* buffer) {
|
char* extract_lua_field(char* fieldName, char* buffer) {
|
||||||
size_t length = strlen(fieldName);
|
size_t length = strlen(fieldName);
|
||||||
|
@ -25,6 +96,8 @@ char* extract_lua_field(char* fieldName, char* buffer) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
bool path_exists(char* path) {
|
bool path_exists(char* path) {
|
||||||
struct stat sb = { 0 };
|
struct stat sb = { 0 };
|
||||||
return (stat(path, &sb) == 0);
|
return (stat(path, &sb) == 0);
|
||||||
|
|
|
@ -5,6 +5,10 @@
|
||||||
#include <types.h>
|
#include <types.h>
|
||||||
#include "src/pc/platform.h"
|
#include "src/pc/platform.h"
|
||||||
|
|
||||||
|
void mods_size_enforce(void);
|
||||||
|
void mods_update_selectable(void);
|
||||||
|
bool mod_file_full_path(char* destination, struct Mod* mod, struct ModFile* modFile);
|
||||||
|
|
||||||
bool str_ends_with(char* string, char* suffix);
|
bool str_ends_with(char* string, char* suffix);
|
||||||
|
|
||||||
char* extract_lua_field(char* fieldName, char* buffer);
|
char* extract_lua_field(char* fieldName, char* buffer);
|
||||||
|
|
|
@ -49,7 +49,6 @@
|
||||||
#include "pc/network/network_player.h"
|
#include "pc/network/network_player.h"
|
||||||
#include "pc/djui/djui.h"
|
#include "pc/djui/djui.h"
|
||||||
|
|
||||||
#include "pc/mod_list.h"
|
|
||||||
#include "pc/mods/mods.h"
|
#include "pc/mods/mods.h"
|
||||||
|
|
||||||
OSMesg D_80339BEC;
|
OSMesg D_80339BEC;
|
||||||
|
@ -171,7 +170,6 @@ void game_deinit(void) {
|
||||||
gfx_shutdown();
|
gfx_shutdown();
|
||||||
network_shutdown(true);
|
network_shutdown(true);
|
||||||
smlua_shutdown();
|
smlua_shutdown();
|
||||||
mod_list_shutdown();
|
|
||||||
mods_shutdown();
|
mods_shutdown();
|
||||||
inited = false;
|
inited = false;
|
||||||
}
|
}
|
||||||
|
@ -222,7 +220,6 @@ void main_func(void) {
|
||||||
const char *userpath = gCLIOpts.SavePath[0] ? gCLIOpts.SavePath : sys_user_path();
|
const char *userpath = gCLIOpts.SavePath[0] ? gCLIOpts.SavePath : sys_user_path();
|
||||||
fs_init(sys_ropaths, gamedir, userpath);
|
fs_init(sys_ropaths, gamedir, userpath);
|
||||||
|
|
||||||
mod_list_init();
|
|
||||||
mods_init();
|
mods_init();
|
||||||
configfile_load(configfile_name());
|
configfile_load(configfile_name());
|
||||||
if (configPlayerModel >= CT_MAX) { configPlayerModel = 0; }
|
if (configPlayerModel >= CT_MAX) { configPlayerModel = 0; }
|
||||||
|
|
Loading…
Reference in a new issue