/* display the option dialog */ void display_options(nh_bool change_birth_opt) { struct nh_menuitem *items; int icount, size; struct nh_option_desc *nhoptions = nh_get_options(GAME_OPTIONS); struct nh_option_desc *birthoptions = NULL; int n; size = 10; items = malloc(sizeof(struct nh_menuitem) * size); do { icount = 0; if (!change_birth_opt) { birthoptions = nh_get_options(ACTIVE_BIRTH_OPTIONS); /* add general game options */ add_menu_txt(items, size, icount, "游戏设置:", MI_HEADING); menu_add_options(&items, &size, &icount, GAME_OPTS, nhoptions, FALSE); /* add or display birth options */ add_menu_txt(items, size, icount, "本次游戏人物设置:", MI_HEADING); menu_add_options(&items, &size, &icount, ACT_BIRTH_OPTS, birthoptions, TRUE); } else { birthoptions = nh_get_options(CURRENT_BIRTH_OPTIONS); /* add or display birth options */ add_menu_txt(items, size, icount, "创建人物设置:", MI_HEADING); menu_add_options(&items, &size, &icount, CUR_BIRTH_OPTS, birthoptions, FALSE); add_menu_txt(items, size, icount, "游戏设置:", MI_HEADING); menu_add_options(&items, &size, &icount, GAME_OPTS, nhoptions, FALSE); } /* add UI specific options */ add_menu_txt(items, size, icount, "界面设置:", MI_HEADING); menu_add_options(&items, &size, &icount, UI_OPTS, curses_options, FALSE); n = curses_display_menu_core(items, icount, "选择哪个设置?", PICK_ONE, NULL, 0, 0, -1, -1, get_option_value, FALSE); } while (n > 0); free(items); write_config(); }
struct nh_option_desc * curses_get_nh_opts(void) { if (game_is_running) return nh_get_options(); else return nh_options; }
void write_config(void) { FILE *fp; fnchar filename[BUFSZ]; fnchar uiconfname[BUFSZ]; get_config_name(filename, FALSE); get_config_name(uiconfname, TRUE); fp = open_config_file(filename); if (fp && should_write_config()) { write_config_options(fp, nh_get_options(GAME_OPTIONS)); write_config_options(fp, nh_get_options(CURRENT_BIRTH_OPTIONS)); fclose(fp); } fp = open_config_file(uiconfname); if (fp) { write_config_options(fp, curses_options); fclose(fp); } }
void print_options(void) { struct nh_menuitem *items; int i, icount, size; char buf[BUFSZ]; struct nh_option_desc *options; icount = 0; size = 10; items = malloc(sizeof(struct nh_menuitem) * size); add_menu_txt(items, size, icount, "创建人物设置:", MI_HEADING); options = nh_get_options(CURRENT_BIRTH_OPTIONS); for (i = 0; options[i].name; i++) { snprintf(buf, BUFSZ, "%s\t%s", options[i].name, options[i].helptxt); add_menu_txt(items, size, icount, buf, MI_TEXT); } add_menu_txt(items, size, icount, "", MI_TEXT); add_menu_txt(items, size, icount, "游戏设置:", MI_HEADING); options = nh_get_options(GAME_OPTIONS); for (i = 0; options[i].name; i++) { snprintf(buf, BUFSZ, "%s\t%s", options[i].name, options[i].helptxt); add_menu_txt(items, size, icount, buf, MI_TEXT); } add_menu_txt(items, size, icount, "", MI_TEXT); /* add UI specific options */ add_menu_txt(items, size, icount, "界面设置:", MI_HEADING); for (i = 0; curses_options[i].name; i++) { snprintf(buf, BUFSZ, "%s\t%s", curses_options[i].name, curses_options[i].helptxt); add_menu_txt(items, size, icount, buf, MI_TEXT); } curses_display_menu(items, icount, "可用选项:", PICK_NONE, NULL); free(items); }
static void ccmd_get_options(json_t * params) { int list, i; const struct nh_option_desc *options; json_t *jmsg, *jarr; if (json_unpack(params, "{si*}", "list", &list) == -1) exit_client("Bad parameters for get_options"); jarr = json_array(); options = nh_get_options(list); for (i = 0; options[i].name; i++) json_array_append_new(jarr, json_option(&options[i])); jmsg = json_pack("{so}", "options", jarr); client_msg("get_options", jmsg); }
nh_bool read_nh_config(void) { fnchar filename[BUFSZ]; struct nh_option_desc *opts = nh_get_options(); if (!opts) return FALSE; nhlib_free_optlist(nh_options); nh_options = opts; get_config_name(filename, FALSE); read_config_file(filename); return TRUE; }
struct nh_option_desc * nhnet_get_options(enum nh_option_list list) { struct nh_option_desc *olist; json_t *jmsg, *jarr, *jobj; int count, i; if (!nhnet_active()) return nh_get_options(list); if (list >= 0 && list < OPTION_LIST_COUNT && option_lists[list]) return option_lists[list]; if (!api_entry()) { olist = xmalloc(sizeof (struct nh_option_desc)); memset(olist, 0, sizeof (struct nh_option_desc)); return olist; } jmsg = send_receive_msg("get_options", json_pack("{si}", "list", list)); if (json_unpack(jmsg, "{so!}", "options", &jarr) == -1 || !json_is_array(jarr)) { print_error("Incorrect return object in nhnet_get_options"); olist = xmalloc(sizeof (struct nh_option_desc)); memset(olist, 0, sizeof (struct nh_option_desc)); } else { count = json_array_size(jarr); option_lists[list] = olist = malloc(sizeof (struct nh_option_desc) * (count + 1)); memset(olist, 0, sizeof (struct nh_option_desc) * (count + 1)); for (i = 0; i < count; i++) { jobj = json_array_get(jarr, i); read_json_option(jobj, &olist[i]); } } json_decref(jmsg); api_exit(); return olist; }
static void ccmd_set_option(json_t * params) { const char *optname, *optstr, *pattern; json_t *jmsg, *joval, *jopt; int isstr, i, ret; const struct nh_option_desc *gameopt, *birthopt, *option; union nh_optvalue value; struct nh_autopickup_rules ar = { NULL, 0 }; struct nh_autopickup_rule *r; if (json_unpack (params, "{ss,so,si*}", "name", &optname, "value", &joval, "isstr", &isstr) == -1) exit_client("Bad parameters for set_option"); /* find the option_desc for the options that should be set; the option type is required in order to decode the option value. */ gameopt = nh_get_options(GAME_OPTIONS); birthopt = nh_get_options(gameid ? ACTIVE_BIRTH_OPTIONS : CURRENT_BIRTH_OPTIONS); option = find_option(optname, gameopt, birthopt); if (!option) { jmsg = json_pack("{si,so}", "return", FALSE, "option", json_object()); client_msg("set_option", jmsg); return; } /* decode the option value depending on the option type */ if (isstr || option->type == OPTTYPE_STRING) { if (!json_is_string(joval)) exit_client("could not decode option string"); value.s = (char *)json_string_value(joval); } else if (option->type == OPTTYPE_INT || option->type == OPTTYPE_ENUM || option->type == OPTTYPE_BOOL) { if (!json_is_integer(joval)) exit_client("could not decode option value"); value.i = json_integer_value(joval); } else if (option->type == OPTTYPE_AUTOPICKUP_RULES) { if (!json_is_array(joval)) exit_client("could not decode option"); ar.num_rules = json_array_size(joval); ar.rules = malloc(sizeof (struct nh_autopickup_rule) * ar.num_rules); if (ar.num_rules) { value.ar = &ar; for (i = 0; i < ar.num_rules; i++) { r = &ar.rules[i]; if (json_unpack (json_array_get(joval, i), "{ss,si,si,si}", "pattern", &pattern, "oclass", &r->oclass, "buc", &r->buc, "action", &r->action) == -1) exit_client("Error unpacking autopickup rule"); strncpy(r->pattern, pattern, sizeof (r->pattern) - 1); } } else value.ar = NULL; } ret = nh_set_option(optname, value, isstr); if (option->type == OPTTYPE_AUTOPICKUP_RULES) free(ar.rules); gameopt = nh_get_options(GAME_OPTIONS); birthopt = nh_get_options(gameid ? ACTIVE_BIRTH_OPTIONS : CURRENT_BIRTH_OPTIONS); option = find_option(optname, gameopt, birthopt); jopt = json_option(option); optstr = nh_get_option_string(option); if (ret == TRUE) db_set_option(user_info.uid, optname, option->type, optstr); /* return the altered option struct and the string representation to the client. The intent is to save some network round trips and make a separate get_option_string message unneccessary */ jmsg = json_pack("{si,so}", "return", ret, "option", jopt); client_msg("set_option", jmsg); }
/* get a new value of the appropriate type for the given option */ static nh_bool get_option_value(struct win_menu *mdat, int idx) { char buf[BUFSZ], query[BUFSZ]; union nh_optvalue value; struct nh_option_desc *option, *optlist; int listid = mdat->items[idx].id >> 10; int id = mdat->items[idx].id & 0x1ff; char strbuf[BUFSZ]; int prev_optstyle = settings.optstyle; switch (listid) { case ACT_BIRTH_OPTS: optlist = nh_get_options(ACTIVE_BIRTH_OPTIONS); break; case CUR_BIRTH_OPTS: optlist = nh_get_options(CURRENT_BIRTH_OPTIONS); break; case GAME_OPTS: optlist = nh_get_options(GAME_OPTIONS); break; case UI_OPTS: optlist = curses_options; break; default: return FALSE; } option = &optlist[id]; value.s = strbuf; switch ((int)option->type) { case OPTTYPE_BOOL: select_boolean_value(&value, option); break; case OPTTYPE_INT: sprintf(query, "New value for %s (number from %d to %d)", option->name, option->i.min, option->i.max); sprintf(buf, "%d", value.i); curses_getline(query, buf); if (buf[0] == '\033') return FALSE; sscanf(buf, "%d", &value.i); break; case OPTTYPE_ENUM: select_enum_value(&value, option); break; case OPTTYPE_STRING: sprintf(query, "New value for %s (text)", option->name); curses_getline(query, value.s); if (value.s[0] == '\033') return FALSE; break; case OPTTYPE_AUTOPICKUP_RULES: show_autopickup_menu(option); return FALSE; case OPTTYPE_MSGTYPE: show_msgtype_menu(option); return FALSE; case OPTTYPE_KEYMAP: show_keymap_menu(FALSE); return FALSE; default: return FALSE; } if (!nh_set_option(option->name, value, FALSE)) { sprintf(strbuf, "new value for %s rejected", option->name); curses_msgwin(strbuf); } else print_option_string(option, mdat->items[idx].caption); /* special case: directly redo option menu appearance */ if (settings.optstyle != prev_optstyle) return TRUE; return FALSE; }