Backported IniConfigFolder option

* using C-string instead of std::string.
This commit is contained in:
NovaRain
2023-06-28 08:52:28 +08:00
parent a71c2c901a
commit b2e60ba62e
4 changed files with 67 additions and 8 deletions
+7
View File
@@ -822,6 +822,13 @@ DisableSpecialAreas=0
;To change some engine parameters for the game mechanics, uncomment the next line
;TweaksFile=sfall\Tweaks.ini
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
[Scripts]
;Uncomment the option to specify an additional directory for ini files used by scripts
;The game will search for ini files first relative to this directory and then relative to the root directory if not found
;The path length is limited to 61 characters
;IniConfigFolder=mods\iniConfigs
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
[Debugging]
;Extra sfall configuration settings that can be used by modders
+15
View File
@@ -58,6 +58,8 @@ static char highlightFail2[128];
char ScriptExtender::gTextBuffer[5120]; // used as global temp text buffer for script functions
char ScriptExtender::iniConfigFolder[64];
bool ScriptExtender::OnMapLeave;
static std::vector<long> scriptsIndexList;
@@ -1069,6 +1071,19 @@ void ScriptExtender::init() {
HookCalls(obj_remove_outline_hook, objRemoveOutlineAddr);
}
size_t len = IniReader::GetConfigString("Scripts", "IniConfigFolder", "", iniConfigFolder, 64);
if (len) {
char c = iniConfigFolder[len - 1];
bool pathSeparator = (c == '\\' || c == '/');
if (len > 62 || (len == 62 && !pathSeparator)) {
iniConfigFolder[0] = '\0';
dlogr("Error: IniConfigFolder path is too long.", DL_MAIN);
} else if (!pathSeparator) {
iniConfigFolder[len++] = '\\';
iniConfigFolder[len] = '\0';
}
}
alwaysFindScripts = isDebug && (IniReader::GetIntDefaultConfig("Debugging", "AlwaysFindScripts", 0) != 0);
if (alwaysFindScripts) dlogr("Always searching for global/hook scripts behavior enabled.", DL_SCRIPT);
+1
View File
@@ -39,6 +39,7 @@ public:
static void OnGameReset();
static char iniConfigFolder[64];
static bool OnMapLeave;
static char gTextBuffer[5120];
+43 -7
View File
@@ -38,12 +38,21 @@ void ResetIniCache() {
ConfigArrayCacheDat.clear();
}
static bool IsSpecialIni(const char* str, const char* end) {
const char* pos = strfind(str, &IniReader::instance().getConfigFile()[2]); // TODO test
if (pos && pos < end) return true;
pos = strfind(str, "f2_res.ini");
if (pos && pos < end) return true;
return false;
}
static int ParseIniSetting(const char* iniString, const char* &key, char section[], char file[]) {
key = strstr(iniString, "|");
if (!key) return -1;
DWORD filelen = (DWORD)key - (DWORD)iniString;
if (filelen >= 64) return -1;
if (ScriptExtender::iniConfigFolder[0] == '\0' && filelen >= 64) return -1;
const char* fileEnd = key;
key = strstr(key + 1, "|");
if (!key) return -1;
@@ -53,9 +62,18 @@ static int ParseIniSetting(const char* iniString, const char* &key, char section
file[0] = '.';
file[1] = '\\';
if (ScriptExtender::iniConfigFolder[0] != '\0' && !IsSpecialIni(iniString, fileEnd)) {
size_t len = strlen(ScriptExtender::iniConfigFolder); // limit up to 62 characters
memcpy(&file[2], ScriptExtender::iniConfigFolder, len);
memcpy(&file[2 + len], iniString, filelen); // copy path and file
file[2 + len + filelen] = 0;
if (GetFileAttributesA(file) & FILE_ATTRIBUTE_DIRECTORY) goto defRoot; // also file not found
} else {
defRoot:
memcpy(&file[2], iniString, filelen);
file[2 + filelen] = 0;
}
memcpy(section, &iniString[filelen + 1], seclen);
section[seclen] = 0;
@@ -140,9 +158,28 @@ static std::string GetSanitizedDBPath(const char* pathArg) {
return std::move(path);
}
static std::string GetIniFilePathFromArg(const ScriptValue& arg) {
const char* pathArg = arg.strValue();
std::string fileName(".\\");
if (ScriptExtender::iniConfigFolder[0] == '\0') {
fileName += pathArg;
} else {
fileName += ScriptExtender::iniConfigFolder;
fileName += pathArg;
if (GetFileAttributesA(fileName.c_str()) & FILE_ATTRIBUTE_DIRECTORY) {
const char* str = pathArg;
for (size_t i = 2; ; i++, str++) {
//if (*str == '.') str += (str[1] == '.') ? 3 : 2; // skip '.\' or '..\'
fileName[i] = *str;
if (!*str) break;
}
}
}
return std::move(fileName);
}
void mf_get_ini_sections(OpcodeContext& ctx) {
std::string fileName = std::string(".\\") + ctx.arg(0).strValue();
Config* config = IniReader::instance().getIniConfig(fileName.c_str());
Config* config = IniReader::instance().getIniConfig(GetIniFilePathFromArg(ctx.arg(0)).c_str());
if (config == nullptr) {
ctx.setReturn(CreateTempArray(0, 0));
return;
@@ -169,8 +206,7 @@ void mf_get_ini_section(OpcodeContext& ctx) {
DWORD arrayId = CreateTempArray(-1, 0); // associative
ctx.setReturn(arrayId);
std::string fileName = std::string(".\\") + ctx.arg(0).strValue();
Config* config = IniReader::instance().getIniConfig(fileName.c_str());
Config* config = IniReader::instance().getIniConfig(GetIniFilePathFromArg(ctx.arg(0)).c_str());
if (config == nullptr) return; // ini file not found
const Config::Data& data = config->data();
@@ -184,7 +220,7 @@ void mf_get_ini_config(OpcodeContext& ctx) {
bool isDb = ctx.arg(1).asBool();
std::string filePath(isDb
? GetSanitizedDBPath(ctx.arg(0).strValue())
: std::string(".\\") + ctx.arg(0).strValue());
: GetIniFilePathFromArg(ctx.arg(0)));
if (filePath.size() == 0) {
ctx.printOpcodeError("%s() - invalid config file path: %s", ctx.getMetaruleName(), ctx.arg(0).strValue());