mirror of
https://github.com/mkxp-z/mkxp-z.git
synced 2025-04-21 21:52:04 +02:00
Add ability to change configuration from Ruby
- `System.config` has become `CONFIG.to_hash` - `CONFIG[]` can be used to look up settings - `CONFIG[]=` can be used to add/change settings - When reading settings, user settings are preferred over defaults - Changes are immediately stored in the user settings file
This commit is contained in:
parent
45f870b86c
commit
0131abd4dd
4 changed files with 100 additions and 28 deletions
|
@ -135,6 +135,10 @@ RB_METHOD(mkxpAddPath);
|
||||||
RB_METHOD(mkxpRemovePath);
|
RB_METHOD(mkxpRemovePath);
|
||||||
RB_METHOD(mkxpLaunch);
|
RB_METHOD(mkxpLaunch);
|
||||||
|
|
||||||
|
RB_METHOD(mkxpGetJSONSetting);
|
||||||
|
RB_METHOD(mkxpSetJSONSetting);
|
||||||
|
RB_METHOD(mkxpGetAllJSONSettings);
|
||||||
|
|
||||||
RB_METHOD(mkxpSetDefaultFontFamily);
|
RB_METHOD(mkxpSetDefaultFontFamily);
|
||||||
|
|
||||||
RB_METHOD(mriRgssMain);
|
RB_METHOD(mriRgssMain);
|
||||||
|
@ -145,6 +149,7 @@ RB_METHOD(mkxpStringToUTF8);
|
||||||
RB_METHOD(mkxpStringToUTF8Bang);
|
RB_METHOD(mkxpStringToUTF8Bang);
|
||||||
|
|
||||||
VALUE json2rb(json5pp::value const &v);
|
VALUE json2rb(json5pp::value const &v);
|
||||||
|
json5pp::value rb2json(VALUE v);
|
||||||
|
|
||||||
static void mriBindingInit() {
|
static void mriBindingInit() {
|
||||||
tableBindingInit();
|
tableBindingInit();
|
||||||
|
@ -245,6 +250,11 @@ static void mriBindingInit() {
|
||||||
_rb_define_method(rb_cString, "to_utf8", mkxpStringToUTF8);
|
_rb_define_method(rb_cString, "to_utf8", mkxpStringToUTF8);
|
||||||
_rb_define_method(rb_cString, "to_utf8!", mkxpStringToUTF8Bang);
|
_rb_define_method(rb_cString, "to_utf8!", mkxpStringToUTF8Bang);
|
||||||
|
|
||||||
|
VALUE cmod = rb_define_module("CONFIG");
|
||||||
|
_rb_define_module_function(cmod, "[]", mkxpGetJSONSetting);
|
||||||
|
_rb_define_module_function(cmod, "[]=", mkxpSetJSONSetting);
|
||||||
|
_rb_define_module_function(cmod, "to_hash", mkxpGetAllJSONSettings);
|
||||||
|
|
||||||
/* Load global constants */
|
/* Load global constants */
|
||||||
rb_gv_set("MKXP", Qtrue);
|
rb_gv_set("MKXP", Qtrue);
|
||||||
|
|
||||||
|
@ -260,10 +270,6 @@ static void mriBindingInit() {
|
||||||
rb_str_freeze(vers);
|
rb_str_freeze(vers);
|
||||||
rb_define_const(mod, "VERSION", vers);
|
rb_define_const(mod, "VERSION", vers);
|
||||||
|
|
||||||
VALUE cfg = json2rb(shState->config().raw);
|
|
||||||
rb_hash_freeze(cfg);
|
|
||||||
rb_define_const(mod, "CONFIG", cfg);
|
|
||||||
|
|
||||||
// Set $stdout and its ilk accordingly on Windows
|
// Set $stdout and its ilk accordingly on Windows
|
||||||
// I regret teaching you that word
|
// I regret teaching you that word
|
||||||
#ifdef __WIN32__
|
#ifdef __WIN32__
|
||||||
|
@ -359,7 +365,7 @@ RB_METHOD(mkxpDesensitize) {
|
||||||
SafeStringValue(filename);
|
SafeStringValue(filename);
|
||||||
|
|
||||||
return rb_utf8_str_new_cstr(
|
return rb_utf8_str_new_cstr(
|
||||||
shState->fileSystem().desensitize(RSTRING_PTR(filename)));
|
shState->fileSystem().desensitize(RSTRING_PTR(filename)));
|
||||||
}
|
}
|
||||||
|
|
||||||
RB_METHOD(mkxpPuts) {
|
RB_METHOD(mkxpPuts) {
|
||||||
|
@ -381,7 +387,7 @@ RB_METHOD(mkxpPlatform) {
|
||||||
|
|
||||||
if (mkxp_sys::isRosetta())
|
if (mkxp_sys::isRosetta())
|
||||||
platform += " (Rosetta)";
|
platform += " (Rosetta)";
|
||||||
|
|
||||||
#elif MKXPZ_PLATFORM == MKXPZ_PLATFORM_WINDOWS
|
#elif MKXPZ_PLATFORM == MKXPZ_PLATFORM_WINDOWS
|
||||||
std::string platform("Windows");
|
std::string platform("Windows");
|
||||||
|
|
||||||
|
@ -456,8 +462,8 @@ RB_METHOD(mkxpUserLanguage) {
|
||||||
RB_METHOD(mkxpUserName) {
|
RB_METHOD(mkxpUserName) {
|
||||||
RB_UNUSED_PARAM;
|
RB_UNUSED_PARAM;
|
||||||
|
|
||||||
// Using the Windows API isn't working with usernames that involve Unicode
|
// Using the Windows API isn't working with usernames that involve Unicode
|
||||||
// characters for some dumb reason
|
// characters for some dumb reason
|
||||||
#ifdef __WIN32__
|
#ifdef __WIN32__
|
||||||
VALUE env = rb_const_get(rb_mKernel, rb_intern("ENV"));
|
VALUE env = rb_const_get(rb_mKernel, rb_intern("ENV"));
|
||||||
return rb_funcall(env, rb_intern("[]"), 1, rb_str_new_cstr("USERNAME"));
|
return rb_funcall(env, rb_intern("[]"), 1, rb_str_new_cstr("USERNAME"));
|
||||||
|
@ -652,6 +658,70 @@ RB_METHOD(mkxpLaunch) {
|
||||||
return RUBY_Qnil;
|
return RUBY_Qnil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
json5pp::value userSettings;
|
||||||
|
|
||||||
|
void loadUserSettings() {
|
||||||
|
if (!userSettings.is_null())
|
||||||
|
return;
|
||||||
|
|
||||||
|
VALUE cpath = rb_utf8_str_new_cstr(shState->config().userConfPath.c_str());
|
||||||
|
|
||||||
|
if (rb_funcall(rb_cFile, rb_intern("exists?"), 1, cpath) == Qtrue) {
|
||||||
|
VALUE f = rb_funcall(rb_cFile, rb_intern("open"), 2, cpath, rb_str_new("r", 1));
|
||||||
|
VALUE data = rb_funcall(f, rb_intern("read"), 0);
|
||||||
|
rb_funcall(f, rb_intern("close"), 0);
|
||||||
|
userSettings = rb2json(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!userSettings.is_object())
|
||||||
|
userSettings = json5pp::object({});
|
||||||
|
}
|
||||||
|
|
||||||
|
void saveUserSettings() {
|
||||||
|
VALUE cpath = rb_utf8_str_new_cstr(shState->config().userConfPath.c_str());
|
||||||
|
VALUE f = rb_funcall(rb_cFile, rb_intern("open"), 2, cpath, rb_str_new("w", 1));
|
||||||
|
rb_funcall(f, rb_intern("write"), 1, rb_utf8_str_new_cstr(userSettings.stringify5(json5pp::rule::space_indent<>()).c_str()));
|
||||||
|
rb_funcall(f, rb_intern("close"), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
RB_METHOD(mkxpGetJSONSetting) {
|
||||||
|
RB_UNUSED_PARAM;
|
||||||
|
|
||||||
|
VALUE sname;
|
||||||
|
rb_scan_args(argc, argv, "1", &sname);
|
||||||
|
SafeStringValue(sname);
|
||||||
|
|
||||||
|
loadUserSettings();
|
||||||
|
auto &s = userSettings.as_object();
|
||||||
|
|
||||||
|
if (s[RSTRING_PTR(sname)].is_null()) {
|
||||||
|
return json2rb(shState->config().raw.as_object()[RSTRING_PTR(sname)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return json2rb(s[RSTRING_PTR(sname)]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
RB_METHOD(mkxpSetJSONSetting) {
|
||||||
|
RB_UNUSED_PARAM;
|
||||||
|
|
||||||
|
VALUE sname, svalue;
|
||||||
|
rb_scan_args(argc, argv, "2", &sname, &svalue);
|
||||||
|
SafeStringValue(sname);
|
||||||
|
|
||||||
|
loadUserSettings();
|
||||||
|
userSettings.as_object()[RSTRING_PTR(sname)] = rb2json(svalue);
|
||||||
|
|
||||||
|
saveUserSettings();
|
||||||
|
return Qnil;
|
||||||
|
}
|
||||||
|
|
||||||
|
RB_METHOD(mkxpGetAllJSONSettings) {
|
||||||
|
RB_UNUSED_PARAM;
|
||||||
|
|
||||||
|
return json2rb(shState->config().raw);
|
||||||
|
}
|
||||||
|
|
||||||
static VALUE rgssMainCb(VALUE block) {
|
static VALUE rgssMainCb(VALUE block) {
|
||||||
rb_funcall2(block, rb_intern("call"), 0, 0);
|
rb_funcall2(block, rb_intern("call"), 0, 0);
|
||||||
return Qnil;
|
return Qnil;
|
||||||
|
@ -877,7 +947,7 @@ static void runRMXPScripts(BacktraceData &btData) {
|
||||||
/* Execute preloaded scripts */
|
/* Execute preloaded scripts */
|
||||||
for (std::vector<std::string>::const_iterator i = conf.preloadScripts.begin();
|
for (std::vector<std::string>::const_iterator i = conf.preloadScripts.begin();
|
||||||
i != conf.preloadScripts.end(); ++i)
|
i != conf.preloadScripts.end(); ++i)
|
||||||
runCustomScript(*i);
|
runCustomScript(*i);
|
||||||
|
|
||||||
VALUE exc = rb_gv_get("$!");
|
VALUE exc = rb_gv_get("$!");
|
||||||
if (exc != Qnil)
|
if (exc != Qnil)
|
||||||
|
@ -912,21 +982,21 @@ static void runRMXPScripts(BacktraceData &btData) {
|
||||||
|
|
||||||
// Adding a 'not' symbol means it WON'T run on that
|
// Adding a 'not' symbol means it WON'T run on that
|
||||||
// platform (i.e. |!W| won't run on Windows)
|
// platform (i.e. |!W| won't run on Windows)
|
||||||
/*
|
/*
|
||||||
if (scriptName[0] == '|') {
|
if (scriptName[0] == '|') {
|
||||||
int len = strlen(scriptName);
|
int len = strlen(scriptName);
|
||||||
if (len > 2) {
|
if (len > 2) {
|
||||||
if (scriptName[1] == '!' && len > 3 &&
|
if (scriptName[1] == '!' && len > 3 &&
|
||||||
scriptName[3] == scriptName[0]) {
|
scriptName[3] == scriptName[0]) {
|
||||||
if (toupper(scriptName[2]) == platform[0])
|
if (toupper(scriptName[2]) == platform[0])
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (scriptName[2] == scriptName[0] &&
|
if (scriptName[2] == scriptName[0] &&
|
||||||
toupper(scriptName[1]) != platform[0])
|
toupper(scriptName[1]) != platform[0])
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int state;
|
int state;
|
||||||
|
|
||||||
|
@ -958,9 +1028,9 @@ static void showExc(VALUE exc, const BacktraceData &btData) {
|
||||||
#endif
|
#endif
|
||||||
/* omit "useless" last entry (from ruby:1:in `eval') */
|
/* omit "useless" last entry (from ruby:1:in `eval') */
|
||||||
for (long i = 1, btlen = RARRAY_LEN(bt) - 1; i < btlen; ++i)
|
for (long i = 1, btlen = RARRAY_LEN(bt) - 1; i < btlen; ++i)
|
||||||
rb_str_catf(ds, "\n\tfrom %" PRIsVALUE,
|
rb_str_catf(ds, "\n\tfrom %" PRIsVALUE,
|
||||||
#if RAPI_MAJOR >= 2
|
#if RAPI_MAJOR >= 2
|
||||||
rb_ary_entry(bt, i));
|
rb_ary_entry(bt, i));
|
||||||
#else
|
#else
|
||||||
RSTRING_PTR(rb_ary_entry(bt, i)));
|
RSTRING_PTR(rb_ary_entry(bt, i)));
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -311,7 +311,7 @@ RB_METHOD(httpJsonStringify) {
|
||||||
rb_scan_args(argc, argv, "1", &obj);
|
rb_scan_args(argc, argv, "1", &obj);
|
||||||
|
|
||||||
json5pp::value v = rb2json(obj);
|
json5pp::value v = rb2json(obj);
|
||||||
return rb_utf8_str_new_cstr(v.stringify().c_str());
|
return rb_utf8_str_new_cstr(v.stringify5(json5pp::rule::space_indent<>()).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void httpBindingInit() {
|
void httpBindingInit() {
|
||||||
|
|
|
@ -239,7 +239,7 @@ try { exp } catch (...) {}
|
||||||
readGameINI();
|
readGameINI();
|
||||||
|
|
||||||
// Now check for an extra mkxp.conf in the user's save directory and merge anything else from that
|
// Now check for an extra mkxp.conf in the user's save directory and merge anything else from that
|
||||||
std::string userConfPath = customDataPath + "/" CONF_FILE;
|
userConfPath = customDataPath + "/" CONF_FILE;
|
||||||
json::value userConf = readConfFile(userConfPath.c_str());
|
json::value userConf = readConfFile(userConfPath.c_str());
|
||||||
copyObject(optsJ, userConf);
|
copyObject(optsJ, userConf);
|
||||||
|
|
||||||
|
|
|
@ -136,6 +136,8 @@ struct Config {
|
||||||
std::string r;
|
std::string r;
|
||||||
} kbActionNames;
|
} kbActionNames;
|
||||||
|
|
||||||
|
std::string userConfPath;
|
||||||
|
|
||||||
/* Internal */
|
/* Internal */
|
||||||
std::string customDataPath;
|
std::string customDataPath;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue