summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHaru <haru@dotalux.com>2014-11-09 02:07:09 +0100
committerHaru <haru@dotalux.com>2015-01-18 21:35:36 +0100
commitce08d6238d902590dbfb650f889a8ab8887356bf (patch)
tree218266957f961e71a51a307b432b02ed9647243a
parent0285ddf7cee2f6569a513fe6118c43f99fd71279 (diff)
downloadhercules-ce08d6238d902590dbfb650f889a8ab8887356bf.tar.gz
hercules-ce08d6238d902590dbfb650f889a8ab8887356bf.tar.bz2
hercules-ce08d6238d902590dbfb650f889a8ab8887356bf.tar.xz
hercules-ce08d6238d902590dbfb650f889a8ab8887356bf.zip
Command line arguments handling overhaul
- login_server, char_server, map_server as well as the tools (mapcache) now have a common command line arguments handling mechanism. - All of them now accept `--help` (`-h`), `--version` (`-v`) and `--load-plugin`. - login_server now accepts `--login-config` and `--lan-config` instead of relying on positional arguments to override those files. The old syntax will no longer work, please update your custom startup scripts. - char_server now accepts `--char-config`, `--inter-config`, `--lan-config` instead of relying on positional arguments. The old syntax will no longer work, please update your custom startup scripts. - mapcache now accepts `--grf-list`, `--map-list`, `--map-cache`, `--rebuild` in place of, respectively, `-grf`, `-list`, `-cache`, `-rebuild`. - A new macro `CMDLINEARG()` is provided, to help defining new command line argument handlers (i.e. in plugins). the `addArg()` call is still required, but its syntax has changed. The `help` argument is now of type `const char *` rather than a function pointer, and it is supposed to contain the message to show in the `--help` screen. Pass `NULL` if no help message is desired. Signed-off-by: Haru <haru@dotalux.com>
-rw-r--r--src/char/char.c90
-rw-r--r--src/char/char.h5
-rw-r--r--src/char/inter.h2
-rw-r--r--src/common/HPM.c104
-rw-r--r--src/common/HPM.h20
-rw-r--r--src/common/HPMi.h4
-rw-r--r--src/common/core.c207
-rw-r--r--src/common/core.h44
-rw-r--r--src/common/malloc.c36
-rw-r--r--src/common/malloc.h7
-rw-r--r--src/login/login.c68
-rw-r--r--src/login/login.h5
-rw-r--r--src/map/atcommand.c2
-rw-r--r--src/map/map.c363
-rw-r--r--src/map/map.h13
-rw-r--r--src/plugins/db2sql.c6
-rw-r--r--src/tool/mapcache.c102
17 files changed, 735 insertions, 343 deletions
diff --git a/src/char/char.c b/src/char/char.c
index f29bf8cff..1301f2cc4 100644
--- a/src/char/char.c
+++ b/src/char/char.c
@@ -50,10 +50,6 @@
#endif
// private declarations
-#define CHAR_CONF_NAME "conf/char-server.conf"
-#define LAN_CONF_NAME "conf/subnet.conf"
-#define SQL_CONF_NAME "conf/inter-server.conf"
-
char char_db[256] = "char";
char scdata_db[256] = "sc_data";
char cart_db[256] = "cart_inventory";
@@ -5707,6 +5703,11 @@ int do_final(void) {
if( chr->server[i].map )
aFree(chr->server[i].map);
+ aFree(chr->CHAR_CONF_NAME);
+ aFree(chr->LAN_CONF_NAME);
+ aFree(chr->SQL_CONF_NAME);
+ aFree(chr->INTER_CONF_NAME);
+
HPM->event(HPET_POST_FINAL);
ShowStatus("Finished.\n");
@@ -5763,45 +5764,80 @@ void char_hp_symbols(void) {
HPM->share(inter->sql_handle, "sql_handle");
}
+/**
+ * --char-config handler
+ *
+ * Overrides the default char configuration file.
+ * @see cmdline->exec
+ */
+static CMDLINEARG(charconfig)
+{
+ aFree(chr->CHAR_CONF_NAME);
+ chr->CHAR_CONF_NAME = aStrdup(params);
+ return true;
+}
+/**
+ * --inter-config handler
+ *
+ * Overrides the default inter-server configuration file.
+ * @see cmdline->exec
+ */
+static CMDLINEARG(interconfig)
+{
+ aFree(chr->INTER_CONF_NAME);
+ chr->INTER_CONF_NAME = aStrdup(params);
+ return true;
+}
+/**
+ * --lan-config handler
+ *
+ * Overrides the default subnet configuration file.
+ * @see cmdline->exec
+ */
+static CMDLINEARG(lanconfig)
+{
+ aFree(chr->LAN_CONF_NAME);
+ chr->LAN_CONF_NAME = aStrdup(params);
+ return true;
+}
+/**
+ * Initializes the command line arguments handlers.
+ */
+void cmdline_args_init_local(void)
+{
+ CMDLINEARG_DEF2(char-config, charconfig, "Alternative char-server configuration.", CMDLINE_OPT_PARAM);
+ CMDLINEARG_DEF2(inter-config, interconfig, "Alternative inter-server configuration.", CMDLINE_OPT_PARAM);
+ CMDLINEARG_DEF2(lan-config, lanconfig, "Alternative subnet configuration.", CMDLINE_OPT_PARAM);
+}
+
int do_init(int argc, char **argv) {
int i;
memset(&skillid2idx, 0, sizeof(skillid2idx));
char_load_defaults();
+ chr->CHAR_CONF_NAME = aStrdup("conf/char-server.conf");
+ chr->LAN_CONF_NAME = aStrdup("conf/subnet.conf");
+ chr->SQL_CONF_NAME = aStrdup("conf/inter-server.conf");
+ chr->INTER_CONF_NAME = aStrdup("conf/inter-server.conf");
+
for(i = 0; i < MAX_MAP_SERVERS; i++ )
chr->server[i].map = NULL;
HPM_char_do_init();
HPM->symbol_defaults_sub = char_hp_symbols;
-#if 0
- /* TODO: Move to common code */
- for( i = 1; i < argc; i++ ) {
- const char* arg = argv[i];
- if( strcmp(arg, "--load-plugin") == 0 ) {
- if( map->arg_next_value(arg, i, argc, true) ) {
- RECREATE(load_extras, char *, ++load_extras_count);
- load_extras[load_extras_count-1] = argv[++i];
- }
- }
- }
- HPM->config_read((const char * const *)load_extras, load_extras_count);
- if (load_extras) {
- aFree(load_extras);
- load_extras = NULL;
- load_extras_count = 0;
- }
-#endif
- HPM->config_read(NULL, 0);
+ cmdline->exec(argc, argv, CMDLINE_OPT_PREINIT);
+ HPM->config_read();
HPM->event(HPET_PRE_INIT);
//Read map indexes
mapindex->init();
start_point.map = mapindex->name2id("new_zone01");
- chr->config_read((argc < 2) ? CHAR_CONF_NAME : argv[1]);
- chr->lan_config_read((argc > 3) ? argv[3] : LAN_CONF_NAME);
- chr->sql_config_read(SQL_CONF_NAME);
+ cmdline->exec(argc, argv, CMDLINE_OPT_NORMAL);
+ chr->config_read(chr->CHAR_CONF_NAME);
+ chr->lan_config_read(chr->LAN_CONF_NAME);
+ chr->sql_config_read(chr->SQL_CONF_NAME);
if (strcmp(chr->userid, "s1")==0 && strcmp(chr->passwd, "p1")==0) {
ShowWarning("Using the default user/password s1/p1 is NOT RECOMMENDED.\n");
@@ -5809,7 +5845,7 @@ int do_init(int argc, char **argv) {
ShowNotice("And then change the user/password to use in conf/char-server.conf (or conf/import/char_conf.txt)\n");
}
- inter->init_sql((argc > 2) ? argv[2] : inter_cfgName); // inter server configuration
+ inter->init_sql(chr->INTER_CONF_NAME); // inter server configuration
auth_db = idb_alloc(DB_OPT_RELEASE_DATA);
chr->online_char_db = idb_alloc(DB_OPT_RELEASE_DATA);
diff --git a/src/char/char.h b/src/char/char.h
index 4b68dc43c..e27aa0b44 100644
--- a/src/char/char.h
+++ b/src/char/char.h
@@ -144,6 +144,11 @@ struct char_interface {
int server_type;
int new_display;
+ char *CHAR_CONF_NAME;
+ char *LAN_CONF_NAME;
+ char *SQL_CONF_NAME;
+ char *INTER_CONF_NAME;
+
int (*waiting_disconnect) (int tid, int64 tick, int id, intptr_t data);
int (*delete_char_sql) (int char_id);
DBData (*create_online_char_data) (DBKey key, va_list args);
diff --git a/src/char/inter.h b/src/char/inter.h
index 7f5b5fc22..a58d3b3a9 100644
--- a/src/char/inter.h
+++ b/src/char/inter.h
@@ -11,8 +11,6 @@
struct accreg;
-#define inter_cfgName "conf/inter-server.conf"
-
#ifdef HERCULES_CORE
extern unsigned int party_share_level;
diff --git a/src/common/HPM.c b/src/common/HPM.c
index 6d9a2cb6b..10208cdad 100644
--- a/src/common/HPM.c
+++ b/src/common/HPM.c
@@ -293,7 +293,20 @@ void hplugin_unload(struct hplugin* plugin) {
}
}
-void hplugins_config_read(const char * const *extra_plugins, int extra_plugins_count) {
+/**
+ * Adds a plugin requested from the command line to the auto-load list.
+ */
+CMDLINEARG(loadplugin)
+{
+ RECREATE(HPM->cmdline_plugins, char *, ++HPM->cmdline_plugins_count);
+ HPM->cmdline_plugins[HPM->cmdline_plugins_count-1] = aStrdup(params);
+ return true;
+}
+
+/**
+ * Reads the plugin configuration and loads the plugins as necessary.
+ */
+void hplugins_config_read(void) {
config_t plugins_conf;
config_setting_t *plist = NULL;
const char *config_filename = "conf/plugins.conf"; // FIXME hardcoded name
@@ -313,9 +326,9 @@ void hplugins_config_read(const char * const *extra_plugins, int extra_plugins_c
HPM->symbol_defaults_sub();
plist = libconfig->lookup(&plugins_conf, "plugins_list");
- for (i = 0; i < extra_plugins_count; i++) {
+ for (i = 0; i < HPM->cmdline_plugins_count; i++) {
config_setting_t *entry = libconfig->setting_add(plist, NULL, CONFIG_TYPE_STRING);
- config_setting_set_string(entry, extra_plugins[i]);
+ config_setting_set_string(entry, HPM->cmdline_plugins[i]);
}
if (plist != NULL) {
@@ -562,6 +575,9 @@ unsigned char hplugins_parse_packets(int fd, enum HPluginPacketHookingPoints poi
char *hplugins_id2name (unsigned int pid) {
unsigned int i;
+ if (pid == HPM_PID_CORE)
+ return "core";
+
for( i = 0; i < HPM->plugin_count; i++ ) {
if( HPM->plugins[i]->idx == pid )
return HPM->plugins[i]->info->name;
@@ -624,50 +640,32 @@ void HPM_HookStop (const char *func, unsigned int pID) {
bool HPM_HookStopped (void) {
return HPM->force_return;
}
-/* command-line args */
-bool hpm_parse_arg(const char *arg, int *index, char *argv[], bool param) {
- struct HPMArgData *data;
-
- if( (data = strdb_get(HPM->arg_db,arg)) ) {
- data->func((data->has_param && param)?argv[(*index)+1]:NULL);
- if( data->has_param && param ) *index += 1;
- return true;
- }
-
- return false;
-}
-void hpm_arg_help(void) {
- DBIterator *iter = db_iterator(HPM->arg_db);
- struct HPMArgData *data = NULL;
-
- for( data = dbi_first(iter); dbi_exists(iter); data = dbi_next(iter) ) {
- if( data->help != NULL )
- data->help();
- else
- ShowInfo(" %s (%s)\t\t<no description provided>\n",data->name,HPM->pid2name(data->pluginID));
- }
-
- dbi_destroy(iter);
-}
-bool hpm_add_arg(unsigned int pluginID, char *name, bool has_param, void (*func) (char *param),void (*help) (void)) {
- struct HPMArgData *data = NULL;
+/**
+ * Adds a plugin-defined command-line argument.
+ *
+ * @param pluginID the current plugin's ID.
+ * @param name the command line argument's name, including the leading '--'.
+ * @param has_param whether the command line argument expects to be followed by a value.
+ * @param func the triggered function.
+ * @param help the help string to be displayed by '--help', if any.
+ * @return the success status.
+ */
+bool hpm_add_arg(unsigned int pluginID, char *name, bool has_param, CmdlineExecFunc func, const char *help) {
+ int i;
- if( strdb_exists(HPM->arg_db, name) ) {
- ShowError("HPM:add_arg:%s duplicate! (from %s)\n",name,HPM->pid2name(pluginID));
+ if (!name || strlen(name) < 3 || name[0] != '-' || name[1] != '-') {
+ ShowError("HPM:add_arg:%s invalid argument name: arguments must begin with '--' (from %s)\n", name, HPM->pid2name(pluginID));
return false;
}
- CREATE(data, struct HPMArgData, 1);
+ ARR_FIND(0, cmdline->args_data_count, i, strcmp(cmdline->args_data[i].name, name) == 0);
- data->pluginID = pluginID;
- data->name = aStrdup(name);
- data->func = func;
- data->help = help;
- data->has_param = has_param;
+ if (i < cmdline->args_data_count) {
+ ShowError("HPM:add_arg:%s duplicate! (from %s)\n",name,HPM->pid2name(pluginID));
+ return false;
+ }
- strdb_put(HPM->arg_db, data->name, data);
-
- return true;
+ return cmdline->arg_add(pluginID, name, '\0', func, help, has_param ? CMDLINE_OPT_PARAM : CMDLINE_OPT_NORMAL);
}
bool hplugins_addconf(unsigned int pluginID, enum HPluginConfType type, char *name, void (*func) (const char *val)) {
struct HPConfListenStorage *conf;
@@ -833,8 +831,6 @@ void hpm_init(void) {
HPM->packetsc[i] = 0;
}
- HPM->arg_db = strdb_alloc(DB_OPT_RELEASE_DATA, 0);
-
HPM->symbol_defaults();
#ifdef CONSOLE_INPUT
@@ -855,13 +851,6 @@ void hpm_memdown(void) {
free(HPM->fnames);
}
}
-int hpm_arg_db_clear_sub(DBKey key, DBData *data, va_list args) {
- struct HPMArgData *a = DB->data2ptr(data);
-
- aFree(a->name);
-
- return 0;
-}
void hpm_final(void) {
unsigned int i;
@@ -892,8 +881,13 @@ void hpm_final(void) {
if( HPM->confsc[i] )
aFree(HPM->confs[i]);
}
-
- HPM->arg_db->destroy(HPM->arg_db,HPM->arg_db_clear_sub);
+ if (HPM->cmdline_plugins) {
+ for (i = 0; i < HPM->cmdline_plugins_count; i++)
+ aFree(HPM->cmdline_plugins[i]);
+ aFree(HPM->cmdline_plugins);
+ HPM->cmdline_plugins = NULL;
+ HPM->cmdline_plugins_count = 0;
+ }
/* HPM->fnames is cleared after the memory manager goes down */
iMalloc->post_shutdown = hpm_memdown;
@@ -919,7 +913,8 @@ void hpm_defaults(void) {
HPM->confs[i] = NULL;
HPM->confsc[i] = 0;
}
- HPM->arg_db = NULL;
+ HPM->cmdline_plugins = NULL;
+ HPM->cmdline_plugins_count = 0;
/* */
HPM->init = hpm_init;
HPM->final = hpm_final;
@@ -940,9 +935,6 @@ void hpm_defaults(void) {
HPM->parse_packets = hplugins_parse_packets;
HPM->load_sub = NULL;
HPM->addhook_sub = NULL;
- HPM->arg_db_clear_sub = hpm_arg_db_clear_sub;
- HPM->parse_arg = hpm_parse_arg;
- HPM->arg_help = hpm_arg_help;
HPM->grabHPData = hplugins_grabHPData;
HPM->grabHPDataSub = NULL;
HPM->parseConf = hplugins_parse_conf;
diff --git a/src/common/HPM.h b/src/common/HPM.h
index 973bc6cca..e99b0f2ae 100644
--- a/src/common/HPM.h
+++ b/src/common/HPM.h
@@ -82,14 +82,6 @@ struct HPMFileNameCache {
char *name;
};
-struct HPMArgData {
- unsigned int pluginID;
- char *name;/* e.g. "--my-arg","-v","--whatever" */
- void (*help) (void);/* to display when --help is used */
- void (*func) (char *param);/* NULL when no param is available */
- bool has_param;/* because of the weird "--arg<space>param" instead of the "--arg=param" */
-};
-
struct HPDataOperationStorage {
void **HPDataSRCPtr;
unsigned int *hdatac;
@@ -123,8 +115,9 @@ struct HPM_interface {
/* config listen */
struct HPConfListenStorage *confs[HPCT_MAX];
unsigned int confsc[HPCT_MAX];
- /* --command-line */
- DBMap *arg_db;
+ /** Plugins requested through the command line */
+ char **cmdline_plugins;
+ int cmdline_plugins_count;
/* funcs */
void (*init) (void);
void (*final) (void);
@@ -137,16 +130,13 @@ struct HPM_interface {
void *(*import_symbol) (char *name, unsigned int pID);
void (*share) (void *, char *);
void (*symbol_defaults) (void);
- void (*config_read) (const char * const *extra_plugins, int extra_plugins_count);
+ void (*config_read) (void);
bool (*populate) (struct hplugin *plugin,const char *filename);
void (*symbol_defaults_sub) (void);//TODO drop
char *(*pid2name) (unsigned int pid);
unsigned char (*parse_packets) (int fd, enum HPluginPacketHookingPoints point);
void (*load_sub) (struct hplugin *plugin);
bool (*addhook_sub) (enum HPluginHookType type, const char *target, void *hook, unsigned int pID);
- bool (*parse_arg) (const char *arg, int* index, char *argv[], bool param);
- void (*arg_help) (void);
- int (*arg_db_clear_sub) (DBKey key, DBData *data, va_list args);
void (*grabHPData) (struct HPDataOperationStorage *ret, enum HPluginDataTypes type, void *ptr);
/* for server-specific HPData e.g. map_session_data */
bool (*grabHPDataSub) (struct HPDataOperationStorage *ret, enum HPluginDataTypes type, void *ptr);
@@ -158,6 +148,8 @@ struct HPM_interface {
void (*datacheck_final) (void);
};
+CMDLINEARG(loadplugin);
+
struct HPM_interface *HPM;
void hpm_defaults(void);
diff --git a/src/common/HPMi.h b/src/common/HPMi.h
index 47f4e6b8b..d4b2e323c 100644
--- a/src/common/HPMi.h
+++ b/src/common/HPMi.h
@@ -104,7 +104,7 @@ enum HPluginConfType {
#define hookStop() (HPMi->HookStop(__func__,HPMi->pid))
#define hookStopped() (HPMi->HookStopped())
-#define addArg(name,param,func,help) (HPMi->addArg(HPMi->pid,(name),(param),(func),(help)))
+#define addArg(name, param,func,help) (HPMi->addArg(HPMi->pid,(name),(param),(cmdline_arg_ ## func),(help)))
/* HPData handy redirects */
/* session[] */
#define addToSession(ptr,data,index,autofree) (HPMi->addToHPData(HPDT_SESSION,HPMi->pid,(ptr),(data),(index),(autofree)))
@@ -214,7 +214,7 @@ HPExport struct HPMi_interface {
void (*HookStop) (const char *func, unsigned int pID);
bool (*HookStopped) (void);
/* program --arg/-a */
- bool (*addArg) (unsigned int pluginID, char *name, bool has_param,void (*func) (char *param),void (*help) (void));
+ bool (*addArg) (unsigned int pluginID, char *name, bool has_param, CmdlineExecFunc func, const char *help);
/* battle-config recv param */
bool (*addConf) (unsigned int pluginID, enum HPluginConfType type, char *name, void (*func) (const char *val));
/* pc group permission */
diff --git a/src/common/core.c b/src/common/core.c
index e1bb9ed0b..6ad971c86 100644
--- a/src/common/core.c
+++ b/src/common/core.c
@@ -178,6 +178,7 @@ void core_defaults(void) {
console_defaults();
strlib_defaults();
malloc_defaults();
+ cmdline_defaults();
#ifndef MINICORE
libconfig_defaults();
sql_defaults();
@@ -186,6 +187,196 @@ void core_defaults(void) {
socket_defaults();
#endif
}
+/**
+ * Returns the source (core or plugin name) for the given command-line argument
+ */
+const char *cmdline_arg_source(struct CmdlineArgData *arg) {
+#ifdef MINICORE
+ return "core";
+#else // !MINICORE
+ return HPM->pid2name(arg->pluginID);
+#endif // MINICORE
+}
+/**
+ * Defines a command line argument.
+ *
+ * @param pluginID the source plugin ID (use HPM_PID_CORE if loading from the core).
+ * @param name the command line argument name, including the leading '--'.
+ * @param shortname an optional short form (single-character, it will be prefixed with '-'). Use '\0' to skip.
+ * @param func the triggered function.
+ * @param help the help string to be displayed by '--help', if any.
+ * @param options options associated to the command-line argument. @see enum cmdline_options.
+ * @return the success status.
+ */
+bool cmdline_arg_add(unsigned int pluginID, const char *name, char shortname, CmdlineExecFunc func, const char *help, unsigned int options) {
+ struct CmdlineArgData *data = NULL;
+
+ RECREATE(cmdline->args_data, struct CmdlineArgData, ++cmdline->args_data_count);
+ data = &cmdline->args_data[cmdline->args_data_count-1];
+ data->pluginID = pluginID;
+ data->name = aStrdup(name);
+ data->shortname = shortname;
+ data->func = func;
+ data->help = aStrdup(help);
+ data->options = options;
+
+ return true;
+}
+/**
+ * Help screen to be displayed by '--help'.
+ */
+static CMDLINEARG(help)
+{
+ int i;
+ ShowInfo("Usage: %s [options]\n", SERVER_NAME);
+ ShowInfo("\n");
+ ShowInfo("Options:\n");
+
+ for (i = 0; i < cmdline->args_data_count; i++) {
+ struct CmdlineArgData *data = &cmdline->args_data[i];
+ char altname[16], paramnames[256];
+ if (data->shortname) {
+ snprintf(altname, sizeof(altname), " [-%c]", data->shortname);
+ } else {
+ *altname = '\0';
+ }
+ snprintf(paramnames, sizeof(paramnames), "%s%s%s", data->name, altname, data->options&CMDLINE_OPT_PARAM ? " <name>" : "");
+ ShowInfo(" %-30s %s [%s]\n", paramnames, data->help ? data->help : "<no description provided>", cmdline->arg_source(data));
+ }
+ return false;
+}
+/**
+ * Info screen to be displayed by '--version'.
+ */
+static CMDLINEARG(version)
+{
+ ShowInfo(CL_GREEN"Website/Forum:"CL_RESET"\thttp://hercules.ws/\n");
+ ShowInfo(CL_GREEN"IRC Channel:"CL_RESET"\tirc://irc.rizon.net/#Hercules\n");
+ ShowInfo("Open "CL_WHITE"readme.txt"CL_RESET" for more information.\n");
+ return false;
+}
+/**
+ * Checks if there is a value available for the current argument
+ *
+ * @param name the current argument's name.
+ * @param current_arg the current argument's position.
+ * @param argc the program's argc.
+ * @return true if a value for the current argument is available on the command line.
+ */
+bool cmdline_arg_next_value(const char *name, int current_arg, int argc)
+{
+ if (current_arg >= argc-1) {
+ ShowError("Missing value for option '%s'.\n", name);
+ return false;
+ }
+
+ return true;
+}
+/**
+ * Executes the command line arguments handlers.
+ *
+ * @param argc the program's argc
+ * @param argv the program's argv
+ * @param options Execution options. Allowed values:
+ * - CMDLINE_OPT_SILENT: Scans the argv for a command line argument that
+ * requires the server's silent mode, and triggers it. Invalid command line
+ * arguments don't cause it to abort. No command handlers are executed.
+ * - CMDLINE_OPT_PREINIT: Scans the argv for command line arguments with the
+ * CMDLINE_OPT_PREINIT flag set and executes their handlers. Invalid command
+ * line arguments don't cause it to abort. Handler's failure causes the
+ * program to abort.
+ * - CMDLINE_OPT_NORMAL: Scans the argv for normal command line arguments,
+ * skipping the pre-init ones, and executes their handlers. Invalid command
+ * line arguments or handler's failure cause the program to abort.
+ * @return the amount of command line handlers successfully executed.
+ */
+int cmdline_exec(int argc, char **argv, unsigned int options)
+{
+ int count = 0, i, j;
+ for (i = 1; i < argc; i++) {
+ struct CmdlineArgData *data = NULL;
+ const char *arg = argv[i];
+ if (arg[0] != '-') { // All arguments must begin with '-'
+ ShowError("Invalid option '%s'.\n", argv[i]);
+ exit(EXIT_FAILURE);
+ }
+ if (arg[1] != '-' && strlen(arg) == 2) {
+ ARR_FIND(0, cmdline->args_data_count, j, cmdline->args_data[j].shortname == arg[1]);
+ } else {
+ ARR_FIND(0, cmdline->args_data_count, j, strcmpi(cmdline->args_data[j].name, arg) == 0);
+ }
+ if (j == cmdline->args_data_count) {
+ if (options&(CMDLINE_OPT_SILENT|CMDLINE_OPT_PREINIT))
+ continue;
+ ShowError("Unknown option '%s'.\n", arg);
+ exit(EXIT_FAILURE);
+ }
+ data = &cmdline->args_data[j];
+ if (data->options&CMDLINE_OPT_PARAM) {
+ if (!cmdline->arg_next_value(arg, i, argc))
+ exit(EXIT_FAILURE);
+ i++;
+ }
+ if (options&CMDLINE_OPT_SILENT) {
+ if (data->options&CMDLINE_OPT_SILENT) {
+ msg_silent = 0x7; // silence information and status messages
+ break;
+ }
+ } else if ((data->options&CMDLINE_OPT_PREINIT) == (options&CMDLINE_OPT_PREINIT)) {
+ const char *param = NULL;
+ if (data->options&CMDLINE_OPT_PARAM) {
+ param = argv[i]; // Already incremented above
+ }
+ if (!data->func(arg, param))
+ exit(EXIT_SUCCESS);
+ count++;
+ }
+ }
+ return count;
+}
+/**
+ * Defines the global command-line arguments.
+ */
+void cmdline_init(void)
+{
+#ifdef MINICORE
+ // Minicore has no HPM. This value isn't used, but the arg_add function requires it, so we're (re)defining it here
+#define HPM_PID_CORE ((unsigned int)-1)
+#endif
+ CMDLINEARG_DEF(help, 'h', "Displays this help screen", CMDLINE_OPT_NORMAL);
+ CMDLINEARG_DEF(version, 'v', "Displays the server's version.", CMDLINE_OPT_NORMAL);
+#ifndef MINICORE
+ CMDLINEARG_DEF2(load-plugin, loadplugin, "Loads an additional plugin (can be repeated).", CMDLINE_OPT_PARAM|CMDLINE_OPT_PREINIT);
+#endif // !MINICORE
+ cmdline_args_init_local();
+}
+void cmdline_final(void)
+{
+ int i;
+ for (i = 0; i < cmdline->args_data_count; i++) {
+ aFree(cmdline->args_data[i].name);
+ aFree(cmdline->args_data[i].help);
+ }
+ if (cmdline->args_data)
+ aFree(cmdline->args_data);
+}
+
+struct cmdline_interface cmdline_s;
+
+void cmdline_defaults(void)
+{
+ cmdline = &cmdline_s;
+
+ cmdline->args_data = NULL;
+ cmdline->args_data_count = 0;
+
+ cmdline->init = cmdline_init;
+ cmdline->final = cmdline_final;
+ cmdline->arg_add = cmdline_arg_add;
+ cmdline->exec = cmdline_exec;
+ cmdline->arg_next_value = cmdline_arg_next_value;
+ cmdline->arg_source = cmdline_arg_source;
+}
/*======================================
* CORE : MAINROUTINE
*--------------------------------------*/
@@ -203,17 +394,14 @@ int main (int argc, char **argv) {
}
core_defaults();
- {
- int i;
- for(i = 0; i < argc; i++) {
- if( strcmp(argv[i], "--script-check") == 0 ) {
- msg_silent = 0x7; // silence information and status messages
- }
- }
- }
-
iMalloc->init();// needed for Show* in display_title() [FlavioJS]
+ cmdline->init();
+
+ cmdline->exec(argc, argv, CMDLINE_OPT_SILENT);
+
+ iMalloc->init_messages(); // Initialization messages (after buying us some time to suppress them if needed)
+
sysinfo->init();
if (!(msg_silent&0x1))
@@ -269,6 +457,7 @@ int main (int argc, char **argv) {
rathread_final();
ers_final();
#endif
+ cmdline->final();
//sysinfo->final(); Called by iMalloc->final()
iMalloc->final();
diff --git a/src/common/core.h b/src/common/core.h
index 025f636e9..827d345ba 100644
--- a/src/common/core.h
+++ b/src/common/core.h
@@ -5,6 +5,7 @@
#ifndef COMMON_CORE_H
#define COMMON_CORE_H
+#include "../common/cbasetypes.h"
#include "../common/db.h"
#include "../common/mmo.h"
@@ -39,6 +40,7 @@ extern char *SERVER_NAME;
enum server_types SERVER_TYPE;
+extern void cmdline_args_init_local(void);
extern int do_init(int,char**);
extern void set_server_type(void);
extern void do_abort(void);
@@ -49,4 +51,46 @@ extern int do_final(void);
extern void (*shutdown_callback)(void);
#endif // HERCULES_CORE
+/// Options for command line argument handlers.
+enum cmdline_options {
+ CMDLINE_OPT_NORMAL = 0x0, ///< No special options.
+ CMDLINE_OPT_PARAM = 0x1, ///< An additional value parameter is expected.
+ CMDLINE_OPT_SILENT = 0x2, ///< If this command-line argument is passed, the server won't print any messages.
+ CMDLINE_OPT_PREINIT = 0x4, ///< This command-line argument is executed before initializing the HPM.
+};
+typedef bool (*CmdlineExecFunc)(const char *name, const char *params);
+struct CmdlineArgData {
+ unsigned int pluginID; ///< Plugin ID (HPM_PID_CORE if used by the core)
+ unsigned int options; ///< Command line argument options (@see enum cmdline_options)
+ char *name; ///< Command-line argument (i.e. "--my-arg", "--version", "--whatever")
+ char shortname; ///< Short form (i.e. "-v") - only store the 'v' part.
+ CmdlineExecFunc func; ///< Function to call
+ char *help; ///< Help message
+};
+
+struct cmdline_interface {
+ struct CmdlineArgData *args_data;
+ int args_data_count;
+
+ void (*init) (void);
+ void (*final) (void);
+ bool (*arg_add) (unsigned int pluginID, const char *name, char shortname, CmdlineExecFunc func, const char *help, unsigned int options);
+ int (*exec) (int argc, char **argv, unsigned int options);
+ bool (*arg_next_value) (const char *name, int current_arg, int argc);
+ const char *(*arg_source) (struct CmdlineArgData *arg);
+};
+
+struct cmdline_interface *cmdline;
+
+#define CMDLINEARG(x) bool cmdline_arg_ ## x (const char *name, const char *params)
+#ifdef HERCULES_CORE
+/// Special plugin ID assigned to the Hercules core
+#define HPM_PID_CORE ((unsigned int)-1)
+
+#define CMDLINEARG_DEF(name, shortname, help, options) cmdline->arg_add(HPM_PID_CORE, "--" EXPAND_AND_QUOTE(name), shortname, cmdline_arg_ ## name, help, options)
+#define CMDLINEARG_DEF2(name, funcname, help, options) cmdline->arg_add(HPM_PID_CORE, "--" EXPAND_AND_QUOTE(name), '\0', cmdline_arg_ ## funcname, help, options)
+
+void cmdline_defaults(void);
+#endif // HERCULES_CORE
+
#endif /* COMMON_CORE_H */
diff --git a/src/common/malloc.c b/src/common/malloc.c
index 244b1114c..43fbe4ea1 100644
--- a/src/common/malloc.c
+++ b/src/common/malloc.c
@@ -769,12 +769,24 @@ void memmgr_report (int extra) {
}
-static void memmgr_init (void)
+/**
+ * Initializes the Memory Manager.
+ */
+static void memmgr_init(void)
+{
+#ifdef LOG_MEMMGR
+ memset(hash_unfill, 0, sizeof(hash_unfill));
+#endif /* LOG_MEMMGR */
+}
+
+/**
+ * Prints initialization messages from the Memory Manager.
+ */
+static void memmgr_init_messages(void)
{
#ifdef LOG_MEMMGR
sprintf(memmer_logfile, "log/%s.leaks", SERVER_NAME);
ShowStatus("Memory manager initialized: "CL_WHITE"%s"CL_RESET"\n", memmer_logfile);
- memset(hash_unfill, 0, sizeof(hash_unfill));
#endif /* LOG_MEMMGR */
}
#endif /* USE_MEMMGR */
@@ -821,7 +833,22 @@ void malloc_final (void) {
iMalloc->post_shutdown();
}
-void malloc_init (void) {
+/**
+ * Prints initialization status messages.
+ *
+ * This is separated from malloc_init() in order to be run after giving the
+ * chance to other modules to initialize, in case they want to silence any
+ * status messages, but at the same time require malloc.
+ */
+void malloc_init_messages(void)
+{
+#ifdef USE_MEMMGR
+ memmgr_init_messages();
+#endif
+}
+
+void malloc_init(void)
+{
#ifdef USE_MEMMGR
memmgr_usage_bytes_t = 0;
memmgr_usage_bytes = 0;
@@ -836,7 +863,7 @@ void malloc_init (void) {
GC_INIT();
#endif
#ifdef USE_MEMMGR
- memmgr_init ();
+ memmgr_init();
#endif
}
@@ -865,4 +892,5 @@ void malloc_defaults(void) {
iMalloc->free = aFree_;
#endif
iMalloc->post_shutdown = NULL;
+ iMalloc->init_messages = malloc_init_messages;
}
diff --git a/src/common/malloc.h b/src/common/malloc.h
index bc79ac65a..7ed2fb19c 100644
--- a/src/common/malloc.h
+++ b/src/common/malloc.h
@@ -59,12 +59,6 @@
////////////////////////////////////////////////
-//void malloc_memory_check(void);
-//bool malloc_verify_ptr(void* ptr);
-//size_t malloc_usage (void);
-//void malloc_init (void);
-//void malloc_final (void);
-
#ifdef HERCULES_CORE
void malloc_defaults(void);
@@ -87,6 +81,7 @@ struct malloc_interface {
size_t (*usage) (void);
/* */
void (*post_shutdown) (void);
+ void (*init_messages) (void);
};
struct malloc_interface *iMalloc;
diff --git a/src/login/login.c b/src/login/login.c
index ec5b2bb7c..036456a85 100644
--- a/src/login/login.c
+++ b/src/login/login.c
@@ -1899,6 +1899,9 @@ int do_final(void) {
HPM_login_do_final();
+ aFree(login->LOGIN_CONF_NAME);
+ aFree(login->LAN_CONF_NAME);
+
HPM->event(HPET_POST_FINAL);
ShowStatus("Finished.\n");
@@ -1939,6 +1942,39 @@ void login_hp_symbols(void) {
HPM->share(login,"login");
}
+/**
+ * --login-config handler
+ *
+ * Overrides the default login configuration file.
+ * @see cmdline->exec
+ */
+static CMDLINEARG(loginconfig)
+{
+ aFree(login->LOGIN_CONF_NAME);
+ login->LOGIN_CONF_NAME = aStrdup(params);
+ return true;
+}
+/**
+ * --lan-config handler
+ *
+ * Overrides the default subnet configuration file.
+ * @see cmdline->exec
+ */
+static CMDLINEARG(lanconfig)
+{
+ aFree(login->LAN_CONF_NAME);
+ login->LAN_CONF_NAME = aStrdup(params);
+ return true;
+}
+/**
+ * Defines the local command line arguments
+ */
+void cmdline_args_init_local(void)
+{
+ CMDLINEARG_DEF2(login-config, loginconfig, "Alternative login-server configuration.", CMDLINE_OPT_PARAM);
+ CMDLINEARG_DEF2(lan-config, lanconfig, "Alternative subnet configuration.", CMDLINE_OPT_PARAM);
+}
+
//------------------------------
// Login server initialization
//------------------------------
@@ -1959,31 +1995,18 @@ int do_init(int argc, char** argv)
// read login-server configuration
login_set_defaults();
+ login->LOGIN_CONF_NAME = aStrdup("conf/login-server.conf");
+ login->LAN_CONF_NAME = aStrdup("conf/subnet.conf");
+
HPM_login_do_init();
HPM->symbol_defaults_sub = login_hp_symbols;
- HPM->config_read(NULL, 0);
-#if 0
- /* TODO: Move to common code */
- for( i = 1; i < argc; i++ ) {
- const char* arg = argv[i];
- if( strcmp(arg, "--load-plugin") == 0 ) {
- if( map->arg_next_value(arg, i, argc, true) ) {
- RECREATE(load_extras, char *, ++load_extras_count);
- load_extras[load_extras_count-1] = argv[++i];
- }
- }
- }
- HPM->config_read((const char * const *)load_extras, load_extras_count);
- if (load_extras) {
- aFree(load_extras);
- load_extras = NULL;
- load_extras_count = 0;
- }
-#endif
+ cmdline->exec(argc, argv, CMDLINE_OPT_PREINIT);
+ HPM->config_read();
HPM->event(HPET_PRE_INIT);
- login_config_read((argc > 1) ? argv[1] : LOGIN_CONF_NAME);
- login->lan_config_read((argc > 2) ? argv[2] : LAN_CONF_NAME);
+ cmdline->exec(argc, argv, CMDLINE_OPT_NORMAL);
+ login_config_read(login->LOGIN_CONF_NAME);
+ login->lan_config_read(login->LAN_CONF_NAME);
for( i = 0; i < ARRAYLENGTH(server); ++i )
chrif_server_init(i);
@@ -2105,4 +2128,7 @@ void login_defaults(void) {
login->kick = login_kick;
login->login_error = login_login_error;
login->send_coding_key = login_send_coding_key;
+
+ login->LOGIN_CONF_NAME = NULL;
+ login->LAN_CONF_NAME = NULL;
}
diff --git a/src/login/login.h b/src/login/login.h
index 8a377927b..7254b5db2 100644
--- a/src/login/login.h
+++ b/src/login/login.h
@@ -18,9 +18,6 @@ enum E_LOGINSERVER_ST
LOGINSERVER_ST_LAST
};
-#define LOGIN_CONF_NAME "conf/login-server.conf"
-#define LAN_CONF_NAME "conf/subnet.conf"
-
// supported encryption types: 1- passwordencrypt, 2- passwordencrypt2, 3- both
#define PASSWORDENC 3
#define PASSWD_LEN (32+1) // 23+1 for plaintext, 32+1 for md5-ed passwords
@@ -200,6 +197,8 @@ struct login_interface {
void (*char_server_connection_status) (int fd, struct login_session_data* sd, uint8 status);
void (*parse_request_connection) (int fd, struct login_session_data* sd, const char *ip);
int (*parse_login) (int fd);
+ char *LOGIN_CONF_NAME;
+ char *LAN_CONF_NAME;
};
struct login_interface *login;
diff --git a/src/map/atcommand.c b/src/map/atcommand.c
index f750b307a..000192b62 100644
--- a/src/map/atcommand.c
+++ b/src/map/atcommand.c
@@ -3628,7 +3628,7 @@ ACMD(reloadscript) {
mapit->free(iter);
flush_fifos();
- map->reloadnpc(true, NULL, 0); // reload config files seeking for npcs
+ map->reloadnpc(true); // reload config files seeking for npcs
script->reload();
npc->reload();
diff --git a/src/map/map.c b/src/map/map.c
index 640dd0ce1..e71085fda 100644
--- a/src/map/map.c
+++ b/src/map/map.c
@@ -3689,7 +3689,12 @@ void map_reloadnpc_sub(char *cfgName) {
fclose(fp);
}
-void map_reloadnpc(bool clear, const char * const *extra_scripts, int extra_scripts_count) {
+/**
+ * Reloads all the scripts.
+ *
+ * @param clear whether to clear the script list before reloading.
+ */
+void map_reloadnpc(bool clear) {
int i;
if (clear)
npc->addsrcfile("clear"); // this will clear the current script list
@@ -3701,8 +3706,8 @@ void map_reloadnpc(bool clear, const char * const *extra_scripts, int extra_scri
#endif
// Append extra scripts
- for( i = 0; i < extra_scripts_count; i++ ) {
- npc->addsrcfile(extra_scripts[i]);
+ for( i = 0; i < map->extra_scripts_count; i++ ) {
+ npc->addsrcfile(map->extra_scripts[i]);
}
}
@@ -5381,6 +5386,14 @@ int do_final(void) {
}
ShowStatus("Cleaned up %d maps."CL_CLL"\n", map->count);
+ if (map->extra_scripts) {
+ for (i = 0; i < map->extra_scripts_count; i++)
+ aFree(map->extra_scripts[i]);
+ aFree(map->extra_scripts);
+ map->extra_scripts = NULL;
+ map->extra_scripts_count = 0;
+ }
+
map->id_db->foreach(map->id_db,map->cleanup_db_sub);
chrif->char_reset_offline();
chrif->flush();
@@ -5444,8 +5457,17 @@ int do_final(void) {
if( !map->enable_grf )
aFree(map->cache_buffer);
- HPM->event(HPET_POST_FINAL);
+ aFree(map->MAP_CONF_NAME);
+ aFree(map->BATTLE_CONF_FILENAME);
+ aFree(map->ATCOMMAND_CONF_FILENAME);
+ aFree(map->SCRIPT_CONF_NAME);
+ aFree(map->MSG_CONF_NAME);
+ aFree(map->GRF_PATH_FILENAME);
+ aFree(map->INTER_CONF_NAME);
+ aFree(map->LOG_CONF_NAME);
+ HPM->event(HPET_POST_FINAL);
+
ShowStatus("Finished.\n");
return map->retval;
}
@@ -5480,45 +5502,6 @@ void do_abort(void)
chrif->flush();
}
-/*======================================================
-* Map-Server Version Screen [MC Cameri]
-*------------------------------------------------------*/
-void map_helpscreen(bool do_exit)
-{
- ShowInfo("Usage: %s [options]\n", SERVER_NAME);
- ShowInfo("\n");
- ShowInfo("Options:\n");
- ShowInfo(" -?, -h [--help] Displays this help screen.\n");
- ShowInfo(" -v [--version] Displays the server's version.\n");
- ShowInfo(" --run-once Closes server after loading (testing).\n");
- ShowInfo(" --map-config <file> Alternative map-server configuration.\n");
- ShowInfo(" --battle-config <file> Alternative battle configuration.\n");
- ShowInfo(" --atcommand-config <file> Alternative atcommand configuration.\n");
- ShowInfo(" --script-config <file> Alternative script configuration.\n");
- ShowInfo(" --msg-config <file> Alternative message configuration.\n");
- ShowInfo(" --grf-path <file> Alternative GRF path configuration.\n");
- ShowInfo(" --inter-config <file> Alternative inter-server configuration.\n");
- ShowInfo(" --log-config <file> Alternative logging configuration.\n");
- ShowInfo(" --script-check Doesn't run the server, only tests the\n");
- ShowInfo(" scripts passed through --load-script.\n");
- ShowInfo(" --load-script <file> Loads an additional script (can be repeated).\n");
- ShowInfo(" --load-plugin <name> Loads an additional plugin (can be repeated).\n");
- HPM->arg_help(); /* display help for commands implemented through HPM */
- if( do_exit )
- exit(EXIT_SUCCESS);
-}
-
-/*======================================================
- * Map-Server Version Screen [MC Cameri]
- *------------------------------------------------------*/
-void map_versionscreen(bool do_exit) {
- ShowInfo(CL_GREEN"Website/Forum:"CL_RESET"\thttp://hercules.ws/\n");
- ShowInfo(CL_GREEN"IRC Channel:"CL_RESET"\tirc://irc.rizon.net/#Hercules\n");
- ShowInfo("Open "CL_WHITE"readme.txt"CL_RESET" for more information.\n");
- if( do_exit )
- exit(EXIT_SUCCESS);
-}
-
void set_server_type(void) {
SERVER_TYPE = SERVER_TYPE_MAP;
}
@@ -5543,17 +5526,6 @@ void do_shutdown(void)
}
}
-bool map_arg_next_value(const char* option, int i, int argc, bool must)
-{
- if( i >= argc-1 ) {
- if( must )
- ShowWarning("Missing value for option '%s'.\n", option);
- return false;
- }
-
- return true;
-}
-
CPCMD(gm_position) {
int x = 0, y = 0, m = 0;
char map_name[25];
@@ -5706,12 +5678,160 @@ void map_load_defaults(void) {
npc_chat_defaults();
#endif
}
+/**
+ * --run-once handler
+ *
+ * Causes the server to run its loop once, and shutdown. Useful for testing.
+ * @see cmdline->exec
+ */
+static CMDLINEARG(runonce)
+{
+ runflag = CORE_ST_STOP;
+ return true;
+}
+/**
+ * --map-config handler
+ *
+ * Overrides the default map-server configuration filename.
+ * @see cmdline->exec
+ */
+static CMDLINEARG(mapconfig)
+{
+ aFree(map->MAP_CONF_NAME);
+ map->MAP_CONF_NAME = aStrdup(params);
+ return true;
+}
+/**
+ * --battle-config handler
+ *
+ * Overrides the default battle configuration filename.
+ * @see cmdline->exec
+ */
+static CMDLINEARG(battleconfig)
+{
+ aFree(map->BATTLE_CONF_FILENAME);
+ map->BATTLE_CONF_FILENAME = aStrdup(params);
+ return true;
+}
+/**
+ * --atcommand-config handler
+ *
+ * Overrides the default atcommands configuration filename.
+ * @see cmdline->exec
+ */
+static CMDLINEARG(atcommandconfig)
+{
+ aFree(map->ATCOMMAND_CONF_FILENAME);
+ map->ATCOMMAND_CONF_FILENAME = aStrdup(params);
+ return true;
+}
+/**
+ * --script-config handler
+ *
+ * Overrides the default script configuration filename.
+ * @see cmdline->exec
+ */
+static CMDLINEARG(scriptconfig)
+{
+ aFree(map->SCRIPT_CONF_NAME);
+ map->SCRIPT_CONF_NAME = aStrdup(params);
+ return true;
+}
+/**
+ * --msg-config handler
+ *
+ * Overrides the default messages configuration filename.
+ * @see cmdline->exec
+ */
+static CMDLINEARG(msgconfig)
+{
+ aFree(map->MSG_CONF_NAME);
+ map->MSG_CONF_NAME = aStrdup(params);
+ return true;
+}
+/**
+ * --grf-path handler
+ *
+ * Overrides the default grf configuration filename.
+ * @see cmdline->exec
+ */
+static CMDLINEARG(grfpath)
+{
+ aFree(map->GRF_PATH_FILENAME);
+ map->GRF_PATH_FILENAME = aStrdup(params);
+ return true;
+}
+/**
+ * --inter-config handler
+ *
+ * Overrides the default inter-server configuration filename.
+ * @see cmdline->exec
+ */
+static CMDLINEARG(interconfig)
+{
+ aFree(map->INTER_CONF_NAME);
+ map->INTER_CONF_NAME = aStrdup(params);
+ return true;
+}
+/**
+ * --log-config handler
+ *
+ * Overrides the default log configuration filename.
+ * @see cmdline->exec
+ */
+static CMDLINEARG(logconfig)
+{
+ aFree(map->LOG_CONF_NAME);
+ map->LOG_CONF_NAME = aStrdup(params);
+ return true;
+}
+/**
+ * --script-check handler
+ *
+ * Enables script-check mode. Checks scripts and quits without running.
+ * @see cmdline->exec
+ */
+static CMDLINEARG(scriptcheck)
+{
+ map->minimal = true;
+ runflag = CORE_ST_STOP;
+ map->scriptcheck = true;
+ return true;
+}
+/**
+ * --load-script handler
+ *
+ * Adds a filename to the script auto-load list.
+ * @see cmdline->exec
+ */
+static CMDLINEARG(loadscript)
+{
+ RECREATE(map->extra_scripts, char *, ++map->extra_scripts_count);
+ map->extra_scripts[map->extra_scripts_count-1] = aStrdup(params);
+ return true;
+}
+/**
+ * Defines the local command line arguments
+ */
+void cmdline_args_init_local(void)
+{
+ CMDLINEARG_DEF2(run-once, runonce, "Closes server after loading (testing).", CMDLINE_OPT_NORMAL);
+ CMDLINEARG_DEF2(map-config, mapconfig, "Alternative map-server configuration.", CMDLINE_OPT_NORMAL|CMDLINE_OPT_PARAM);
+ CMDLINEARG_DEF2(battle-config, battleconfig, "Alternative battle configuration.", CMDLINE_OPT_NORMAL|CMDLINE_OPT_PARAM);
+ CMDLINEARG_DEF2(atcommand-config, atcommandconfig, "Alternative atcommand configuration.", CMDLINE_OPT_NORMAL|CMDLINE_OPT_PARAM);
+ CMDLINEARG_DEF2(script-config, scriptconfig, "Alternative script configuration.", CMDLINE_OPT_NORMAL|CMDLINE_OPT_PARAM);
+ CMDLINEARG_DEF2(msg-config, msgconfig, "Alternative message configuration.", CMDLINE_OPT_NORMAL|CMDLINE_OPT_PARAM);
+ CMDLINEARG_DEF2(grf-path, grfpath, "Alternative GRF path configuration.", CMDLINE_OPT_NORMAL|CMDLINE_OPT_PARAM);
+ CMDLINEARG_DEF2(inter-config, interconfig, "Alternative inter-server configuration.", CMDLINE_OPT_NORMAL|CMDLINE_OPT_PARAM);
+ CMDLINEARG_DEF2(log-config, logconfig, "Alternative logging configuration.", CMDLINE_OPT_NORMAL|CMDLINE_OPT_PARAM);
+ CMDLINEARG_DEF2(script-check, scriptcheck, "Doesn't run the server, only tests the scripts passed through --load-script.", CMDLINE_OPT_SILENT);
+ CMDLINEARG_DEF2(load-script, loadscript, "Loads an additional script (can be repeated).", CMDLINE_OPT_NORMAL|CMDLINE_OPT_PARAM);
+}
+
int do_init(int argc, char *argv[])
{
bool minimal = false;
- bool scriptcheck = false;
- int i, load_extras_count = 0;
- char **load_extras = NULL;
+ int i;
#ifdef GCOLLECT
GC_enable_incremental();
@@ -5719,98 +5839,23 @@ int do_init(int argc, char *argv[])
map_load_defaults();
+ map->INTER_CONF_NAME = aStrdup("conf/inter-server.conf");
+ map->LOG_CONF_NAME = aStrdup("conf/logs.conf");
+ map->MAP_CONF_NAME = aStrdup("conf/map-server.conf");
+ map->BATTLE_CONF_FILENAME = aStrdup("conf/battle.conf");
+ map->ATCOMMAND_CONF_FILENAME = aStrdup("conf/atcommand.conf");
+ map->SCRIPT_CONF_NAME = aStrdup("conf/script.conf");
+ map->MSG_CONF_NAME = aStrdup("conf/messages.conf");
+ map->GRF_PATH_FILENAME = aStrdup("conf/grf-files.txt");
+
HPM_map_do_init();
HPM->symbol_defaults_sub = map_hp_symbols;
- for( i = 1; i < argc; i++ ) {
- const char* arg = argv[i];
- if( strcmp(arg, "--load-plugin") == 0 ) {
- if( map->arg_next_value(arg, i, argc, true) ) {
- RECREATE(load_extras, char *, ++load_extras_count);
- load_extras[load_extras_count-1] = argv[++i];
- }
- }
- }
- HPM->config_read((const char * const *)load_extras, load_extras_count);
- if (load_extras) {
- aFree(load_extras);
- load_extras = NULL;
- load_extras_count = 0;
- }
+ cmdline->exec(argc, argv, CMDLINE_OPT_PREINIT);
+ HPM->config_read();
HPM->event(HPET_PRE_INIT);
- for( i = 1; i < argc ; i++ ) {
- const char* arg = argv[i];
-
- if( arg[0] != '-' && ( arg[0] != '/' || arg[1] == '-' ) ) {// -, -- and /
- ShowError("Unknown option '%s'.\n", argv[i]);
- exit(EXIT_FAILURE);
- } else if ( HPM->parse_arg(arg,&i,argv,map->arg_next_value(arg, i, argc, false)) ) {
- continue; /* HPM Triggered */
- } else if( (++arg)[0] == '-' ) {// long option
- arg++;
-
- if( strcmp(arg, "help") == 0 ) {
- map->helpscreen(true);
- } else if( strcmp(arg, "version") == 0 ) {
- map->versionscreen(true);
- } else if( strcmp(arg, "map-config") == 0 ) {
- if( map->arg_next_value(arg, i, argc, true) )
- map->MAP_CONF_NAME = argv[++i];
- } else if( strcmp(arg, "battle-config") == 0 ) {
- if( map->arg_next_value(arg, i, argc, true) )
- map->BATTLE_CONF_FILENAME = argv[++i];
- } else if( strcmp(arg, "atcommand-config") == 0 ) {
- if( map->arg_next_value(arg, i, argc, true) )
- map->ATCOMMAND_CONF_FILENAME = argv[++i];
- } else if( strcmp(arg, "script-config") == 0 ) {
- if( map->arg_next_value(arg, i, argc, true) )
- map->SCRIPT_CONF_NAME = argv[++i];
- } else if( strcmp(arg, "msg-config") == 0 ) {
- if( map->arg_next_value(arg, i, argc, true) )
- map->MSG_CONF_NAME = argv[++i];
- } else if( strcmp(arg, "grf-path-file") == 0 ) {
- if( map->arg_next_value(arg, i, argc, true) )
- map->GRF_PATH_FILENAME = argv[++i];
- } else if( strcmp(arg, "inter-config") == 0 ) {
- if( map->arg_next_value(arg, i, argc, true) )
- map->INTER_CONF_NAME = argv[++i];
- } else if( strcmp(arg, "log-config") == 0 ) {
- if( map->arg_next_value(arg, i, argc, true) )
- map->LOG_CONF_NAME = argv[++i];
- } else if( strcmp(arg, "run-once") == 0 ) { // close the map-server as soon as its done.. for testing [Celest]
- runflag = CORE_ST_STOP;
- } else if( strcmp(arg, "script-check") == 0 ) {
- map->minimal = true;
- runflag = CORE_ST_STOP;
- scriptcheck = true;
- } else if( strcmp(arg, "load-plugin") == 0 ) {
- if( map->arg_next_value(arg, i, argc, true) )
- i++;
- } else if( strcmp(arg, "load-script") == 0 ) {
- if( map->arg_next_value(arg, i, argc, true) ) {
- RECREATE(load_extras, char *, ++load_extras_count);
- load_extras[load_extras_count-1] = argv[++i];
- }
- } else {
- ShowError("Unknown option '%s'.\n", argv[i]);
- exit(EXIT_FAILURE);
- }
- } else {
- switch( arg[0] ) {// short option
- case '?':
- case 'h':
- map->helpscreen(true);
- break;
- case 'v':
- map->versionscreen(true);
- break;
- default:
- ShowError("Unknown option '%s'.\n", argv[i]);
- exit(EXIT_FAILURE);
- }
- }
- }
+ cmdline->exec(argc, argv, CMDLINE_OPT_NORMAL);
minimal = map->minimal;/* temp (perhaps make minimal a mask with options of what to load? e.g. plugin 1 does minimal |= mob_db; */
if (!minimal) {
map->config_read(map->MAP_CONF_NAME);
@@ -5819,7 +5864,7 @@ int do_init(int argc, char *argv[])
map->config_read_sub(map->MAP_CONF_NAME);
// loads npcs
- map->reloadnpc(false, (const char * const *)load_extras, load_extras_count);
+ map->reloadnpc(false);
chrif->checkdefaultlogin();
@@ -5928,23 +5973,16 @@ int do_init(int argc, char *argv[])
duel->init(minimal);
vending->init(minimal);
- if (scriptcheck) {
- if (load_extras) {
- bool failed = load_extras_count > 0 ? false : true;
- for (i = 0; i < load_extras_count; i++) {
- if (npc->parsesrcfile(load_extras[i], false) != EXIT_SUCCESS)
- failed = true;
- }
- if (failed)
- exit(EXIT_FAILURE);
+ if (map->scriptcheck) {
+ bool failed = map->extra_scripts_count > 0 ? false : true;
+ for (i = 0; i < map->extra_scripts_count; i++) {
+ if (npc->parsesrcfile(map->extra_scripts[i], false) != EXIT_SUCCESS)
+ failed = true;
}
+ if (failed)
+ exit(EXIT_FAILURE);
exit(EXIT_SUCCESS);
}
- if (load_extras) {
- aFree(load_extras);
- load_extras = NULL;
- //load_extras_count = 0; // Dead store. Uncomment if needed again.
- }
if( minimal ) {
HPM->event(HPET_READY);
@@ -5987,8 +6025,12 @@ void map_defaults(void) {
/* */
map->minimal = false;
+ map->scriptcheck = false;
map->count = 0;
map->retval = EXIT_SUCCESS;
+
+ map->extra_scripts = NULL;
+ map->extra_scripts_count = 0;
sprintf(map->db_path ,"db");
sprintf(map->help_txt ,"conf/help.txt");
@@ -6242,9 +6284,6 @@ void map_defaults(void) {
map->nick_db_final = nick_db_final;
map->cleanup_db_sub = cleanup_db_sub;
map->abort_sub = map_abort_sub;
- map->helpscreen = map_helpscreen;
- map->versionscreen = map_versionscreen;
- map->arg_next_value = map_arg_next_value;
map->update_cell_bl = map_update_cell_bl;
diff --git a/src/map/map.h b/src/map/map.h
index 9721b19f3..a1c6d2cde 100644
--- a/src/map/map.h
+++ b/src/map/map.h
@@ -812,7 +812,13 @@ struct map_cache_map_info {
struct map_interface {
/* vars */
- bool minimal;
+ bool minimal; ///< Starts the server in minimal initialization mode.
+ bool scriptcheck; ///< Starts the server in script-check mode.
+
+ /** Additional scripts requested through the command-line */
+ char **extra_scripts;
+ int extra_scripts_count;
+
int retval;
int count;
@@ -1005,7 +1011,7 @@ struct map_interface {
struct mob_data * (*getmob_boss) (int16 m);
struct mob_data * (*id2boss) (int id);
// reload config file looking only for npcs
- void (*reloadnpc) (bool clear, const char * const *extra_scripts, int extra_scripts_count);
+ void (*reloadnpc) (bool clear);
int (*check_dir) (int s_dir,int t_dir);
uint8 (*calc_dir) (struct block_list *src,int16 x,int16 y);
@@ -1068,9 +1074,6 @@ struct map_interface {
int (*nick_db_final) (DBKey key, DBData *data, va_list args);
int (*cleanup_db_sub) (DBKey key, DBData *data, va_list va);
int (*abort_sub) (struct map_session_data *sd, va_list ap);
- void (*helpscreen) (bool do_exit);
- void (*versionscreen) (bool do_exit);
- bool (*arg_next_value) (const char *option, int i, int argc, bool must);
void (*update_cell_bl) (struct block_list *bl, bool increase);
int (*get_new_bonus_id) (void);
void (*add_questinfo) (int m, struct questinfo *qi);
diff --git a/src/plugins/db2sql.c b/src/plugins/db2sql.c
index eda61d026..62ed80255 100644
--- a/src/plugins/db2sql.c
+++ b/src/plugins/db2sql.c
@@ -348,8 +348,10 @@ void do_db2sql(void) {
CPCMD(db2sql) {
do_db2sql();
}
-void db2sql_arg(char *param) {
+CMDLINEARG(db2sql)
+{
map->minimal = torun = true;
+ return true;
}
HPExport void server_preinit (void) {
SQL = GET_SYMBOL("SQL");
@@ -360,7 +362,7 @@ HPExport void server_preinit (void) {
libconfig = GET_SYMBOL("libconfig");
StrBuf = GET_SYMBOL("StrBuf");
- addArg("--db2sql",false,db2sql_arg,NULL);
+ addArg("--db2sql",false,db2sql,NULL);
}
HPExport void plugin_init (void) {
addCPCommand("server:tools:db2sql",db2sql);
diff --git a/src/tool/mapcache.c b/src/tool/mapcache.c
index 2cc70ebf3..5376458dc 100644
--- a/src/tool/mapcache.c
+++ b/src/tool/mapcache.c
@@ -10,6 +10,7 @@
#include <string.h>
#include "../common/cbasetypes.h"
+#include "../common/core.h"
#include "../common/grfio.h"
#include "../common/malloc.h"
#include "../common/mmo.h"
@@ -23,9 +24,9 @@
#define NO_WATER 1000000
-char grf_list_file[256] = "conf/grf-files.txt";
-char map_list_file[256] = "db/map_index.txt";
-char map_cache_file[256];
+char *grf_list_file;
+char *map_list_file;
+char *map_cache_file;
int rebuild = 0;
FILE *map_cache_fp;
@@ -184,25 +185,67 @@ char *remove_extension(char *mapname)
return mapname;
}
-// Processes command-line arguments
-void process_args(int argc, char *argv[])
+/**
+ * --grf-list handler
+ *
+ * Overrides the default grf list filename.
+ * @see cmdline->exec
+ */
+static CMDLINEARG(grflist)
{
- int i;
+ aFree(grf_list_file);
+ grf_list_file = aStrdup(params);
+ return true;
+}
- for(i = 0; i < argc; i++) {
- if(strcmp(argv[i], "-grf") == 0) {
- if(++i < argc)
- safestrncpy(grf_list_file, argv[i], sizeof(grf_list_file));
- } else if(strcmp(argv[i], "-list") == 0) {
- if(++i < argc)
- safestrncpy(map_list_file, argv[i], sizeof(map_list_file));
- } else if(strcmp(argv[i], "-cache") == 0) {
- if(++i < argc)
- safestrncpy(map_cache_file, argv[i], sizeof(map_cache_file));
- } else if(strcmp(argv[i], "-rebuild") == 0)
- rebuild = 1;
- }
+/**
+ * --map-list handler
+ *
+ * Overrides the default map list filename.
+ * @see cmdline->exec
+ */
+static CMDLINEARG(maplist)
+{
+ aFree(map_list_file);
+ map_list_file = aStrdup(params);
+ return true;
+}
+/**
+ * --map-cache handler
+ *
+ * Overrides the default map cache filename.
+ * @see cmdline->exec
+ */
+static CMDLINEARG(mapcache)
+{
+ aFree(map_cache_file);
+ map_cache_file = aStrdup(params);
+ return true;
+}
+
+/**
+ * --rebuild handler
+ *
+ * Forces a rebuild of the mapcache, rather than only adding missing maps.
+ * @see cmdline->exec
+ */
+static CMDLINEARG(rebuild)
+{
+ rebuild = 1;
+ return true;
+}
+
+/**
+ * Defines the local command line arguments
+ */
+void cmdline_args_init_local(void)
+{
+ CMDLINEARG_DEF2(grf-list, grflist, "Alternative grf list file", CMDLINE_OPT_NORMAL|CMDLINE_OPT_PARAM);
+ CMDLINEARG_DEF2(map-list, maplist, "Alternative map list file", CMDLINE_OPT_NORMAL|CMDLINE_OPT_PARAM);
+ CMDLINEARG_DEF2(map-cache, mapcache, "Alternative map cache file", CMDLINE_OPT_NORMAL|CMDLINE_OPT_PARAM);
+ CMDLINEARG_DEF2(rebuild, rebuild, "Forces a rebuild of the map cache, rather than only adding missing maps", CMDLINE_OPT_NORMAL);
+
}
int do_init(int argc, char** argv)
@@ -212,17 +255,13 @@ int do_init(int argc, char** argv)
struct map_data map;
char name[MAP_NAME_LENGTH_EXT];
+ grf_list_file = aStrdup("conf/grf-files.txt");
+ map_list_file = aStrdup("db/map_index.txt");
/* setup pre-defined, #define-dependant */
- sprintf(map_cache_file,"db/%s/map_cache.dat",
-#ifdef RENEWAL
- "re"
-#else
- "pre-re"
-#endif
- );
+ map_cache_file = aStrdup("db/"DBPATH"map_cache.dat");
- // Process the command-line arguments
- process_args(argc, argv);
+ cmdline->exec(argc, argv, CMDLINE_OPT_PREINIT);
+ cmdline->exec(argc, argv, CMDLINE_OPT_NORMAL);
ShowStatus("Initializing grfio with %s\n", grf_list_file);
grfio_init(grf_list_file);
@@ -302,9 +341,14 @@ int do_init(int argc, char** argv)
ShowInfo("%d maps now in cache\n", header.map_count);
+ aFree(grf_list_file);
+ aFree(map_list_file);
+ aFree(map_cache_file);
+
return 0;
}
-void do_final(void)
+int do_final(void)
{
+ return EXIT_SUCCESS;
}