From f102c913b2aa093ef40c7846e25850ebb1106d71 Mon Sep 17 00:00:00 2001 From: Your Name Date: Sat, 12 Dec 2015 21:44:27 +0200 Subject: - Fixed #723 now it's possible to retrieve Battle Config Settings from plugins into scripts - Fixed Possible Crash when null parse function pointer passed to HPMi->addConf - Now it's possible to use same parse function for all config entries - Now Battle Config entries must have a return function --- src/common/HPM.c | 40 +++++++++++++++++++++++++++++++++++++--- src/common/HPM.h | 4 +++- src/common/HPMi.h | 16 ++++++++-------- src/map/battle.c | 20 ++++++++++++++------ src/map/battle.h | 4 ++-- src/map/script.c | 14 +++++++++++++- src/plugins/sample.c | 31 +++++++++++++++++++++++++++---- 7 files changed, 104 insertions(+), 25 deletions(-) diff --git a/src/common/HPM.c b/src/common/HPM.c index 7d9a0b104..e5c3c47ba 100644 --- a/src/common/HPM.c +++ b/src/common/HPM.c @@ -389,11 +389,21 @@ bool hpm_add_arg(unsigned int pluginID, char *name, bool has_param, CmdlineExecF * @retval true if the listener was added successfully. * @retval false in case of error. */ -bool hplugins_addconf(unsigned int pluginID, enum HPluginConfType type, char *name, void (*func) (const char *val)) +bool hplugins_addconf(unsigned int pluginID, enum HPluginConfType type, char *name, void (*parse_func) (const char *key, const char *val), int (*return_func) (const char *key)) { struct HPConfListenStorage *conf; int i; + if (parse_func == NULL) { + ShowError("HPM->addConf:%s: missing setter function for config '%s'\n",HPM->pid2name(pluginID),name); + return false; + } + + if (type == HPCT_BATTLE && return_func == NULL) { + ShowError("HPM->addConf:%s: missing getter function for config '%s'\n",HPM->pid2name(pluginID),name); + return false; + } + if (type >= HPCT_MAX) { ShowError("HPM->addConf:%s: unknown point '%u' specified for config '%s'\n",HPM->pid2name(pluginID),type,name); return false; @@ -412,7 +422,8 @@ bool hplugins_addconf(unsigned int pluginID, enum HPluginConfType type, char *na conf->pluginID = pluginID; safestrncpy(conf->key, name, HPM_ADDCONF_LENGTH); - conf->func = func; + conf->parse_func = parse_func; + conf->return_func = return_func; return true; } @@ -798,7 +809,29 @@ bool hplugins_parse_conf(const char *w1, const char *w2, enum HPluginConfType po if (i == VECTOR_LENGTH(HPM->config_listeners[point])) return false; - VECTOR_INDEX(HPM->config_listeners[point], i).func(w2); + VECTOR_INDEX(HPM->config_listeners[point], i).parse_func(w1, w2); + return true; +} + +/** + * Get a battle configuration entry through the registered plugins. + * + * @param[in] w1 The configuration entry name. + * @param[out] value Where the config result will be saved + * @retval true in case of data found + * @retval false in case of no data found + */ +bool hplugins_get_battle_conf(const char *w1, int *value) +{ + int i; + + nullpo_retr(false, value); + + ARR_FIND(0, VECTOR_LENGTH(HPM->config_listeners[HPCT_BATTLE]), i, strcmpi(w1, VECTOR_INDEX(HPM->config_listeners[HPCT_BATTLE], i).key) == 0); + if (i == VECTOR_LENGTH(HPM->config_listeners[HPCT_BATTLE])) + return false; + + *value = VECTOR_INDEX(HPM->config_listeners[HPCT_BATTLE], i).return_func(w1); return true; } @@ -1020,6 +1053,7 @@ void hpm_defaults(void) HPM->load_sub = NULL; HPM->addhook_sub = NULL; HPM->parseConf = hplugins_parse_conf; + HPM->getBattleConf = hplugins_get_battle_conf; HPM->DataCheck = HPM_DataCheck; HPM->datacheck_init = HPM_datacheck_init; HPM->datacheck_final = HPM_datacheck_final; diff --git a/src/common/HPM.h b/src/common/HPM.h index 5420e5300..bcf831d0e 100644 --- a/src/common/HPM.h +++ b/src/common/HPM.h @@ -101,7 +101,8 @@ struct HPMFileNameCache { struct HPConfListenStorage { unsigned int pluginID; char key[HPM_ADDCONF_LENGTH]; - void (*func) (const char *val); + void (*parse_func) (const char *key, const char *val); + int (*return_func) (const char *key); }; /* Hercules Plugin Manager Interface */ @@ -145,6 +146,7 @@ struct HPM_interface { bool (*addhook_sub) (enum HPluginHookType type, const char *target, void *hook, unsigned int pID); /* for custom config parsing */ bool (*parseConf) (const char *w1, const char *w2, enum HPluginConfType point); + bool (*getBattleConf) (const char* w1, int *value); /* validates plugin data */ bool (*DataCheck) (struct s_HPMDataCheck *src, unsigned int size, int version, char *name); void (*datacheck_init) (const struct s_HPMDataCheck *src, unsigned int length, int version); diff --git a/src/common/HPMi.h b/src/common/HPMi.h index 9a61dd256..5b62f80d9 100644 --- a/src/common/HPMi.h +++ b/src/common/HPMi.h @@ -183,19 +183,19 @@ enum HPluginConfType { /* HPMi->addPacket */ #define addPacket(cmd,len,receive,point) HPMi->addPacket(cmd,len,receive,point,HPMi->pid) /* HPMi->addBattleConf */ -#define addBattleConf(bcname,funcname) HPMi->addConf(HPMi->pid,HPCT_BATTLE,bcname,funcname) +#define addBattleConf(bcname,funcname,returnfunc) HPMi->addConf(HPMi->pid,HPCT_BATTLE,bcname,funcname,returnfunc) /* HPMi->addLogin */ -#define addLoginConf(bcname,funcname) HPMi->addConf(HPMi->pid,HPCT_LOGIN,bcname,funcname) +#define addLoginConf(bcname,funcname) HPMi->addConf(HPMi->pid,HPCT_LOGIN,bcname,funcname,NULL) /* HPMi->addChar */ -#define addCharConf(bcname,funcname) HPMi->addConf(HPMi->pid,HPCT_CHAR,bcname,funcname) +#define addCharConf(bcname,funcname) HPMi->addConf(HPMi->pid,HPCT_CHAR,bcname,funcname,NULL) /* HPMi->addCharInter */ -#define addCharInterConf(bcname,funcname) HPMi->addConf(HPMi->pid,HPCT_CHAR_INTER,bcname,funcname) +#define addCharInterConf(bcname,funcname) HPMi->addConf(HPMi->pid,HPCT_CHAR_INTER,bcname,funcname,NULL) /* HPMi->addMapInter */ -#define addMapInterConf(bcname,funcname) HPMi->addConf(HPMi->pid,HPCT_MAP_INTER,bcname,funcname) +#define addMapInterConf(bcname,funcname) HPMi->addConf(HPMi->pid,HPCT_MAP_INTER,bcname,funcname,NULL) /* HPMi->addLog */ -#define addLogConf(bcname,funcname) HPMi->addConf(HPMi->pid,HPCT_LOG,bcname,funcname) +#define addLogConf(bcname,funcname) HPMi->addConf(HPMi->pid,HPCT_LOG,bcname,funcname,NULL) /* HPMi->addScript */ -#define addScriptConf(bcname,funcname) HPMi->addConf(HPMi->pid,HPCT_SCRIPT,bcname,funcname) +#define addScriptConf(bcname,funcname) HPMi->addConf(HPMi->pid,HPCT_SCRIPT,bcname,funcname,NULL) /* HPMi->addPCGPermission */ #define addGroupPermission(pcgname,maskptr) HPMi->addPCGPermission(HPMi->pid,pcgname,&maskptr) @@ -222,7 +222,7 @@ struct HPMi_interface { /* program --arg/-a */ 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)); + bool (*addConf) (unsigned int pluginID, enum HPluginConfType type, char *name, void (*parse_func) (const char *key, const char *val), int (*return_func) (const char *key)); /* pc group permission */ void (*addPCGPermission) (unsigned int pluginID, char *name, unsigned int *mask); diff --git a/src/map/battle.c b/src/map/battle.c index 7fbbcd0d5..1725d8c65 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -7329,15 +7329,23 @@ int battle_set_value(const char* w1, const char* w2) return 1; } -int battle_get_value(const char* w1) +bool battle_get_value(const char *w1, int *value) { int i; - nullpo_retr(1, w1); + + nullpo_retr(false, w1); + nullpo_retr(false, value); + ARR_FIND(0, ARRAYLENGTH(battle_data), i, strcmpi(w1, battle_data[i].str) == 0); - if (i == ARRAYLENGTH(battle_data)) - return 0; // not found - else - return *battle_data[i].val; + if (i == ARRAYLENGTH(battle_data)) { + if (HPM->getBattleConf(w1,value)) + return true; + } else { + *value = *battle_data[i].val; + return true; + } + + return false; } void battle_set_defaults(void) { diff --git a/src/map/battle.h b/src/map/battle.h index 68a427e72..595ed32bb 100644 --- a/src/map/battle.h +++ b/src/map/battle.h @@ -630,8 +630,8 @@ struct battle_interface { /* - battle_config */ int (*config_read) (const char *cfgName); void (*config_set_defaults) (void); - int (*config_set_value) (const char* w1, const char* w2); - int (*config_get_value) (const char* w1); + int (*config_set_value) (const char *w1, const char *w2); + bool (*config_get_value) (const char *w1, int *value); void (*config_adjust) (void); /* ----------------------------------------- */ /* picks a random enemy within the specified range */ diff --git a/src/map/script.c b/src/map/script.c index cfc7ed052..cc9552d60 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -14620,8 +14620,20 @@ BUILDIN(setbattleflag) BUILDIN(getbattleflag) { const char *flag; + int value; + flag = script_getstr(st,2); - script_pushint(st,battle->config_get_value(flag)); + + if (battle->config_get_value(flag, &value)) { + script_pushint(st,value); + return true; + } else { + script_pushint(st,0); + ShowWarning("buildin_getbattleflag: non-exist battle config requested %s \n", flag); + script->reportsrc(st); + return false; + } + return true; } diff --git a/src/plugins/sample.c b/src/plugins/sample.c index d7e5523d6..d1a00a70d 100644 --- a/src/plugins/sample.c +++ b/src/plugins/sample.c @@ -40,6 +40,8 @@ struct sample_data_struct { unsigned int someNumber; }; +int my_setting; + /* sample packet implementation */ /* cmd 0xf3 - it is a client-server existent id, for clif_parse_GlobalMessage */ /* in this sample we do nothing and simply redirect */ @@ -111,10 +113,31 @@ int my_pc_dropitem_post(int retVal, struct map_session_data *sd,int *n,int *amou } return 1; } -void parse_my_setting(const char *val) { - ShowDebug("Received 'my_setting:%s'\n",val); +/* +* Key is the setting name in our example it's 'my_setting' while val is the value of it. +* this way you can manage more than one setting in one function instead of define multiable ones +*/ + +void parse_my_setting(const char *key, const char *val) { + ShowDebug("Received '%s:%s'\n",key,val); /* do anything with the var e.g. config_switch(val) */ + /* for our example we will save it in global variable */ + + /* please note, battle settings can be only returned as int for scripts and other usage */ + if (strcmpi(key,"my_setting") == 0) + my_setting = atoi(val); +} + +/* Battle Config Settings need to have return function in-case scripts need to read it */ +int return_my_setting(const char *key) +{ + /* first we check the key to know what setting we need to return with strcmpi then return it */ + if (strcmpi(key, "my_setting") == 0) + return my_setting; + + return 0; } + /* run when server starts */ HPExport void plugin_init (void) { ShowInfo("Server type is "); @@ -171,8 +194,8 @@ HPExport void plugin_init (void) { HPExport void server_preinit (void) { /* makes map server listen to mysetting:value in any "battleconf" file (including imported or custom ones) */ /* value is not limited to numbers, its passed to our plugins handler (parse_my_setting) as const char *, - * and thus can be manipulated at will */ - addBattleConf("my_setting",parse_my_setting); + * however for battle config to be returned to our script engine we need it to be number (int) so keep use it as int only */ + addBattleConf("my_setting",parse_my_setting,return_my_setting); } /* run when server is ready (online) */ HPExport void server_online (void) { -- cgit v1.2.3-60-g2f50