summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/char/char.c2
-rw-r--r--src/common/HPM.c9
-rw-r--r--src/common/HPM.h2
-rw-r--r--src/login/login.c2
-rw-r--r--src/map/atcommand.c2
-rw-r--r--src/map/map.c62
-rw-r--r--src/map/map.h2
-rw-r--r--src/map/script.c97
-rw-r--r--src/map/script.h4
-rw-r--r--src/plugins/HPMHooking/HPMHooking.Hooks.inc12
10 files changed, 166 insertions, 28 deletions
diff --git a/src/char/char.c b/src/char/char.c
index a42524444..bf19a0012 100644
--- a/src/char/char.c
+++ b/src/char/char.c
@@ -5393,7 +5393,7 @@ int do_init(int argc, char **argv) {
online_char_db = idb_alloc(DB_OPT_RELEASE_DATA);
HPM->share(sql_handle,"sql_handle");
- HPM->config_read();
+ HPM->config_read(NULL, 0);
HPM->event(HPET_INIT);
mmo_char_sql_init();
diff --git a/src/common/HPM.c b/src/common/HPM.c
index a25a17782..971eb83bd 100644
--- a/src/common/HPM.c
+++ b/src/common/HPM.c
@@ -269,11 +269,12 @@ void hplugin_unload(struct hplugin* plugin) {
}
}
-void hplugins_config_read(void) {
+void hplugins_config_read(const char * const *extra_plugins, int extra_plugins_count) {
config_t plugins_conf;
config_setting_t *plist = NULL;
const char *config_filename = "conf/plugins.conf"; // FIXME hardcoded name
FILE *fp;
+ int i;
// uncomment once login/char support is wrapped up
// if( !HPM->DataCheck ) {
@@ -294,9 +295,13 @@ void hplugins_config_read(void) {
HPM->symbol_defaults_sub();
plist = libconfig->lookup(&plugins_conf, "plugins_list");
+ for (i = 0; i < extra_plugins_count; i++) {
+ config_setting_t *entry = libconfig->setting_add(plist, NULL, CONFIG_TYPE_STRING);
+ config_setting_set_string(entry, extra_plugins[i]);
+ }
if (plist != NULL) {
- int length = libconfig->setting_length(plist), i;
+ int length = libconfig->setting_length(plist);
char filename[60];
for(i = 0; i < length; i++) {
if( !strcmpi(libconfig->setting_get_string_elem(plist,i),"HPMHooking") ) {//must load it first
diff --git a/src/common/HPM.h b/src/common/HPM.h
index 52ad24a03..b466cb4f3 100644
--- a/src/common/HPM.h
+++ b/src/common/HPM.h
@@ -131,7 +131,7 @@ struct HPM_interface {
void *(*import_symbol) (char *name, unsigned int pID);
void (*share) (void *, char *);
void (*symbol_defaults) (void);
- void (*config_read) (void);
+ void (*config_read) (const char * const *extra_plugins, int extra_plugins_count);
bool (*populate) (struct hplugin *plugin,const char *filename);
void (*symbol_defaults_sub) (void);//TODO drop
char *(*pid2name) (unsigned int pid);
diff --git a/src/login/login.c b/src/login/login.c
index 252031bb8..cb30de2f3 100644
--- a/src/login/login.c
+++ b/src/login/login.c
@@ -1821,7 +1821,7 @@ int do_init(int argc, char** argv)
}
HPM->share(account_db_sql_up(accounts),"sql_handle");
- HPM->config_read();
+ HPM->config_read(NULL, 0);
HPM->event(HPET_INIT);
// server port open & binding
diff --git a/src/map/atcommand.c b/src/map/atcommand.c
index 50ec913c4..4c35999d6 100644
--- a/src/map/atcommand.c
+++ b/src/map/atcommand.c
@@ -3666,7 +3666,7 @@ ACMD(reloadscript) {
mapit->free(iter);
flush_fifos();
- map->reloadnpc(true); // reload config files seeking for npcs
+ map->reloadnpc(true, NULL, 0); // reload config files seeking for npcs
script->reload();
npc->reload();
diff --git a/src/map/map.c b/src/map/map.c
index 51b717a16..9e41bdca3 100644
--- a/src/map/map.c
+++ b/src/map/map.c
@@ -3559,8 +3559,8 @@ void map_reloadnpc_sub(char *cfgName)
fclose(fp);
}
-void map_reloadnpc(bool clear)
-{
+void map_reloadnpc(bool clear, const char * const *extra_scripts, int extra_scripts_count) {
+ int i;
if (clear)
npc->addsrcfile("clear"); // this will clear the current script list
@@ -3569,6 +3569,11 @@ void map_reloadnpc(bool clear)
#else
map->reloadnpc_sub("npc/pre-re/scripts_main.conf");
#endif
+
+ // Append extra scripts
+ for( i = 0; i < extra_scripts_count; i++ ) {
+ npc->addsrcfile(extra_scripts[i]);
+ }
}
int inter_config_read(char *cfgName) {
@@ -5355,7 +5360,10 @@ void map_helpscreen(bool do_exit)
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 <file> Tests a script for errors, without running the server.\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 thru HPM */
if( do_exit )
exit(EXIT_SUCCESS);
@@ -5565,8 +5573,9 @@ void map_load_defaults(void) {
int do_init(int argc, char *argv[])
{
bool minimal = false;
- char *scriptcheck = NULL;
- int i;
+ bool scriptcheck = false;
+ int i, load_extras_count = 0;
+ char **load_extras = NULL;
#ifdef GCOLLECT
GC_enable_incremental();
@@ -5579,7 +5588,21 @@ int do_init(int argc, char *argv[])
HPM->load_sub = HPM_map_plugin_load_sub;
HPM->symbol_defaults_sub = map_hp_symbols;
HPM->grabHPDataSub = HPM_map_grabHPData;
- HPM->config_read();
+ 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;
+ }
HPM->event(HPET_PRE_INIT);
@@ -5627,8 +5650,15 @@ int do_init(int argc, char *argv[])
} 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) )
- scriptcheck = argv[++i];
+ 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);
@@ -5656,7 +5686,7 @@ int do_init(int argc, char *argv[])
map->config_read_sub(map->MAP_CONF_NAME);
// loads npcs
- map->reloadnpc(false);
+ map->reloadnpc(false, (const char * const *)load_extras, load_extras_count);
chrif->checkdefaultlogin();
@@ -5766,9 +5796,19 @@ int do_init(int argc, char *argv[])
vending->init(minimal);
if (scriptcheck) {
- if (npc->parsesrcfile(scriptcheck, false) == 0)
- exit(EXIT_SUCCESS);
- exit(EXIT_FAILURE);
+ bool failed = load_extras_count > 0 ? false : true;
+ for (i = 0; i < load_extras_count; i++) {
+ if (npc->parsesrcfile(load_extras[i], false) != 0)
+ failed = true;
+ }
+ if (failed)
+ exit(EXIT_FAILURE);
+ exit(EXIT_SUCCESS);
+ }
+ if (load_extras) {
+ aFree(load_extras);
+ load_extras = NULL;
+ load_extras_count = 0;
}
if( minimal ) {
diff --git a/src/map/map.h b/src/map/map.h
index 270931689..c1eaeb40d 100644
--- a/src/map/map.h
+++ b/src/map/map.h
@@ -992,7 +992,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);
+ void (*reloadnpc) (bool clear, const char * const *extra_scripts, int extra_scripts_count);
int (*check_dir) (int s_dir,int t_dir);
uint8 (*calc_dir) (struct block_list *src,int16 x,int16 y);
diff --git a/src/map/script.c b/src/map/script.c
index 01a7e6410..d3d98ad06 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -112,6 +112,10 @@ const char* script_op2name(int op) {
RETURN_OP_NAME(C_SUB_POST);
RETURN_OP_NAME(C_ADD_PRE);
RETURN_OP_NAME(C_SUB_PRE);
+#ifdef PCRE_SUPPORT
+ RETURN_OP_NAME(C_RE_EQ);
+ RETURN_OP_NAME(C_RE_NE);
+#endif // PCRE_SUPPORT
default:
ShowDebug("script_op2name: unexpected op=%d\n", op);
@@ -1224,6 +1228,10 @@ const char* script_parse_subexpr(const char* p,int limit) {
|| (op=C_XOR, opl=4, len=1,*p=='^') // ^
|| (op=C_EQ, opl=6, len=2,*p=='=' && p[1]=='=') // ==
|| (op=C_NE, opl=6, len=2,*p=='!' && p[1]=='=') // !=
+#ifdef PCRE_SUPPORT
+ || (op=C_RE_EQ, opl=6, len=2,*p=='~' && p[1]=='=') // ~=
+ || (op=C_RE_NE, opl=6, len=2,*p=='~' && p[1]=='!') // ~!
+#endif // PCRE_SUPPORT
|| (op=C_R_SHIFT,opl=8, len=2,*p=='>' && p[1]=='>') // >>
|| (op=C_GE, opl=7, len=2,*p=='>' && p[1]=='=') // >=
|| (op=C_GT, opl=7, len=1,*p=='>') // >
@@ -3405,6 +3413,8 @@ void op_3(struct script_state* st, int op)
/// s1 GE s2 -> i
/// s1 LT s2 -> i
/// s1 LE s2 -> i
+/// s1 RE_EQ s2 -> i
+/// s1 RE_NE s2 -> i
/// s1 ADD s2 -> s
void op_2str(struct script_state* st, int op, const char* s1, const char* s2)
{
@@ -3417,6 +3427,72 @@ void op_2str(struct script_state* st, int op, const char* s1, const char* s2)
case C_GE: a = (strcmp(s1,s2) >= 0); break;
case C_LT: a = (strcmp(s1,s2) < 0); break;
case C_LE: a = (strcmp(s1,s2) <= 0); break;
+#ifdef PCRE_SUPPORT
+ case C_RE_EQ:
+ case C_RE_NE:
+ {
+ int inputlen = (int)strlen(s1);
+ pcre *compiled_regex;
+ pcre_extra *extra_regex;
+ const char *pcre_error, *pcre_match;
+ int pcre_erroroffset, offsetcount, i;
+ int offsets[256*3]; // (max_capturing_groups+1)*3
+
+ compiled_regex = libpcre->compile(s2, 0, &pcre_error, &pcre_erroroffset, NULL);
+
+ if( compiled_regex == NULL ) {
+ ShowError("script:op2_str: Invalid regex '%s'.\n", s2);
+ script->reportsrc(st);
+ script_pushnil(st);
+ st->state = END;
+ return;
+ }
+
+ extra_regex = libpcre->study(compiled_regex, 0, &pcre_error);
+
+ if( pcre_error != NULL ) {
+ libpcre->free(compiled_regex);
+ ShowError("script:op2_str: Unable to optimize the regex '%s': %s\n", s2, pcre_error);
+ script->reportsrc(st);
+ script_pushnil(st);
+ st->state = END;
+ return;
+ }
+
+ offsetcount = libpcre->exec(compiled_regex, extra_regex, s1, inputlen, 0, 0, offsets, 256*3);
+
+ if( offsetcount == 0 ) {
+ offsetcount = 256;
+ } else if( offsetcount == PCRE_ERROR_NOMATCH ) {
+ offsetcount = 0;
+ } else if( offsetcount < 0 ) {
+ libpcre->free(compiled_regex);
+ if( extra_regex != NULL )
+ libpcre->free(extra_regex);
+ ShowWarning("script:op2_str: Unable to process the regex '%s'.\n", s2);
+ script->reportsrc(st);
+ script_pushnil(st);
+ st->state = END;
+ return;
+ }
+
+ if( op == C_RE_EQ ) {
+ for( i = 0; i < offsetcount; i++ ) {
+ libpcre->get_substring(s1, offsets, offsetcount, i, &pcre_match);
+ mapreg->setregstr(reference_uid(script->add_str("$@regexmatch$"), i), pcre_match);
+ libpcre->free_substring(pcre_match);
+ }
+ mapreg->setreg(script->add_str("$@regexmatchcount"), i);
+ a = offsetcount;
+ } else { // C_RE_NE
+ a = (offsetcount == 0);
+ }
+ libpcre->free(compiled_regex);
+ if( extra_regex != NULL )
+ libpcre->free(extra_regex);
+ }
+ break;
+#endif // PCRE_SUPPORT
case C_ADD:
{
char* buf = (char *)aMalloc((strlen(s1)+strlen(s2)+1)*sizeof(char));
@@ -3988,6 +4064,10 @@ void run_script_main(struct script_state *st) {
case C_LOR:
case C_R_SHIFT:
case C_L_SHIFT:
+#ifdef PCRE_SUPPORT
+ case C_RE_EQ:
+ case C_RE_NE:
+#endif // PCRE_SUPPORT
script->op_2(st, c);
break;
@@ -18500,10 +18580,18 @@ BUILDIN(shopcount) {
// declarations that were supposed to be exported from npc_chat.c
#ifdef PCRE_SUPPORT
- BUILDIN(defpattern);
- BUILDIN(activatepset);
- BUILDIN(deactivatepset);
- BUILDIN(deletepset);
+BUILDIN(defpattern);
+BUILDIN(activatepset);
+BUILDIN(deactivatepset);
+BUILDIN(deletepset);
+
+BUILDIN(pcre_match) {
+ const char *input = script_getstr(st, 2);
+ const char *regex = script_getstr(st, 3);
+
+ script->op_2str(st, C_RE_EQ, input, regex);
+ return true;
+}
#endif
/**
@@ -18867,6 +18955,7 @@ void script_parse_builtin(void) {
BUILDIN_DEF(activatepset,"i"), // Activate a pattern set [MouseJstr]
BUILDIN_DEF(deactivatepset,"i"), // Deactive a pattern set [MouseJstr]
BUILDIN_DEF(deletepset,"i"), // Delete a pattern set [MouseJstr]
+ BUILDIN_DEF(pcre_match,"ss"),
#endif
BUILDIN_DEF(dispbottom,"s"), //added from jA [Lupus]
BUILDIN_DEF(getusersname,""),
diff --git a/src/map/script.h b/src/map/script.h
index cf7f22aa9..eed0dbf1d 100644
--- a/src/map/script.h
+++ b/src/map/script.h
@@ -213,6 +213,10 @@ typedef enum c_op {
C_SUB_POST, // a--
C_ADD_PRE, // ++a
C_SUB_PRE, // --a
+#ifdef PCRE_SUPPORT
+ C_RE_EQ, // ~=
+ C_RE_NE, // ~!
+#endif // PCRE_SUPPORT
} c_op;
enum hQueueOpt {
diff --git a/src/plugins/HPMHooking/HPMHooking.Hooks.inc b/src/plugins/HPMHooking/HPMHooking.Hooks.inc
index 78987f81a..396b241b0 100644
--- a/src/plugins/HPMHooking/HPMHooking.Hooks.inc
+++ b/src/plugins/HPMHooking/HPMHooking.Hooks.inc
@@ -35401,13 +35401,13 @@ struct mob_data* HP_map_id2boss(int id) {
}
return retVal___;
}
-void HP_map_reloadnpc(bool clear) {
+void HP_map_reloadnpc(bool clear, const char *const *extra_scripts, int extra_scripts_count) {
int hIndex = 0;
if( HPMHooks.count.HP_map_reloadnpc_pre ) {
- void (*preHookFunc) (bool *clear);
+ void (*preHookFunc) (bool *clear, const char *const *extra_scripts, int *extra_scripts_count);
for(hIndex = 0; hIndex < HPMHooks.count.HP_map_reloadnpc_pre; hIndex++ ) {
preHookFunc = HPMHooks.list.HP_map_reloadnpc_pre[hIndex].func;
- preHookFunc(&clear);
+ preHookFunc(&clear, extra_scripts, &extra_scripts_count);
}
if( *HPMforce_return ) {
*HPMforce_return = false;
@@ -35415,13 +35415,13 @@ void HP_map_reloadnpc(bool clear) {
}
}
{
- HPMHooks.source.map.reloadnpc(clear);
+ HPMHooks.source.map.reloadnpc(clear, extra_scripts, extra_scripts_count);
}
if( HPMHooks.count.HP_map_reloadnpc_post ) {
- void (*postHookFunc) (bool *clear);
+ void (*postHookFunc) (bool *clear, const char *const *extra_scripts, int *extra_scripts_count);
for(hIndex = 0; hIndex < HPMHooks.count.HP_map_reloadnpc_post; hIndex++ ) {
postHookFunc = HPMHooks.list.HP_map_reloadnpc_post[hIndex].func;
- postHookFunc(&clear);
+ postHookFunc(&clear, extra_scripts, &extra_scripts_count);
}
}
return;