summaryrefslogtreecommitdiff
path: root/src/common
diff options
context:
space:
mode:
Diffstat (limited to 'src/common')
-rw-r--r--src/common/HPM.c24
-rw-r--r--src/common/HPM.h2
-rw-r--r--src/common/HPMDataCheck.h2
-rw-r--r--src/common/Makefile.in2
-rw-r--r--src/common/cbasetypes.h2
-rw-r--r--src/common/conf.c288
-rw-r--r--src/common/conf.h154
-rw-r--r--src/common/console.c1
-rw-r--r--src/common/core.c5
-rw-r--r--src/common/ers.c6
-rw-r--r--src/common/md5calc.c6
-rw-r--r--src/common/memmgr.c77
-rw-r--r--src/common/memmgr.h2
-rw-r--r--src/common/mmo.h20
-rw-r--r--src/common/showmsg.c9
-rw-r--r--src/common/showmsg.h7
-rw-r--r--src/common/socket.c25
-rw-r--r--src/common/socket.h48
-rw-r--r--src/common/sql.c7
-rw-r--r--src/common/sysinfo.c15
-rw-r--r--src/common/sysinfo.h1
-rw-r--r--src/common/thread.c2
-rw-r--r--src/common/timer.c64
-rw-r--r--src/common/utils.c43
-rw-r--r--src/common/utils.h6
25 files changed, 650 insertions, 168 deletions
diff --git a/src/common/HPM.c b/src/common/HPM.c
index 62ef54499..fa4025fb8 100644
--- a/src/common/HPM.c
+++ b/src/common/HPM.c
@@ -214,11 +214,11 @@ bool hplugin_data_store_validate(enum HPluginDataTypes type, struct hplugin_data
break;
default:
if (HPM->data_store_validate_sub == NULL) {
- ShowError("HPM:validateHPData failed, type %d needs sub-handler!\n",type);
+ ShowError("HPM:validateHPData failed, type %u needs sub-handler!\n", type);
return false;
}
if (!HPM->data_store_validate_sub(type, storeptr, initialize)) {
- ShowError("HPM:HPM:validateHPData failed, unknown type %d!\n",type);
+ ShowError("HPM:HPM:validateHPData failed, unknown type %u!\n", type);
return false;
}
break;
@@ -228,7 +228,7 @@ bool hplugin_data_store_validate(enum HPluginDataTypes type, struct hplugin_data
store = *storeptr;
}
if (store->type != type) {
- ShowError("HPM:HPM:validateHPData failed, store type mismatch %d != %d.\n",store->type, type);
+ ShowError("HPM:HPM:validateHPData failed, store type mismatch %u != %u.\n", store->type, type);
return false;
}
return true;
@@ -253,7 +253,7 @@ void hplugins_addToHPData(enum HPluginDataTypes type, uint32 pluginID, struct hp
if (!HPM->data_store_validate(type, storeptr, true)) {
/* woo it failed! */
- ShowError("HPM:addToHPData:%s: failed, type %d (%u|%u)\n", HPM->pid2name(pluginID), type, pluginID, classid);
+ ShowError("HPM:addToHPData:%s: failed, type %u (%u|%u)\n", HPM->pid2name(pluginID), type, pluginID, classid);
return;
}
store = *storeptr;
@@ -294,7 +294,7 @@ void *hplugins_getFromHPData(enum HPluginDataTypes type, uint32 pluginID, struct
if (!HPM->data_store_validate(type, &store, false)) {
/* woo it failed! */
- ShowError("HPM:getFromHPData:%s: failed, type %d (%u|%u)\n", HPM->pid2name(pluginID), type, pluginID, classid);
+ ShowError("HPM:getFromHPData:%s: failed, type %u (%u|%u)\n", HPM->pid2name(pluginID), type, pluginID, classid);
return NULL;
}
if (!store)
@@ -322,7 +322,7 @@ void hplugins_removeFromHPData(enum HPluginDataTypes type, uint32 pluginID, stru
if (!HPM->data_store_validate(type, &store, false)) {
/* woo it failed! */
- ShowError("HPM:removeFromHPData:%s: failed, type %d (%u|%u)\n", HPM->pid2name(pluginID), type, pluginID, classid);
+ ShowError("HPM:removeFromHPData:%s: failed, type %u (%u|%u)\n", HPM->pid2name(pluginID), type, pluginID, classid);
return;
}
if (!store)
@@ -616,8 +616,8 @@ CMDLINEARG(loadplugin)
* Reads the plugin configuration and loads the plugins as necessary.
*/
void hplugins_config_read(void) {
- config_t plugins_conf;
- config_setting_t *plist = NULL;
+ struct config_t plugins_conf;
+ struct config_setting_t *plist = NULL;
const char *config_filename = "conf/plugins.conf"; // FIXME hardcoded name
FILE *fp;
int i;
@@ -628,12 +628,12 @@ void hplugins_config_read(void) {
fclose(fp);
}
- if (libconfig->read_file(&plugins_conf, config_filename))
+ if (!libconfig->load_file(&plugins_conf, config_filename))
return;
plist = libconfig->lookup(&plugins_conf, "plugins_list");
for (i = 0; i < VECTOR_LENGTH(HPM->cmdline_load_plugins); i++) {
- config_setting_t *entry = libconfig->setting_add(plist, NULL, CONFIG_TYPE_STRING);
+ struct config_setting_t *entry = libconfig->setting_add(plist, NULL, CONFIG_TYPE_STRING);
config_setting_set_string(entry, VECTOR_INDEX(HPM->cmdline_load_plugins, i));
}
@@ -718,13 +718,13 @@ CPCMD(plugins)
* @retval 1 OK
* @retval 2 incomplete packet
*/
-unsigned char hplugins_parse_packets(int fd, enum HPluginPacketHookingPoints point)
+unsigned char hplugins_parse_packets(int fd, int packet_id, enum HPluginPacketHookingPoints point)
{
struct HPluginPacket *packet = NULL;
int i;
int16 length;
- ARR_FIND(0, VECTOR_LENGTH(HPM->packets[point]), i, VECTOR_INDEX(HPM->packets[point], i).cmd == RFIFOW(fd,0));
+ ARR_FIND(0, VECTOR_LENGTH(HPM->packets[point]), i, VECTOR_INDEX(HPM->packets[point], i).cmd == packet_id);
if (i == VECTOR_LENGTH(HPM->packets[point]))
return 0;
diff --git a/src/common/HPM.h b/src/common/HPM.h
index 215161a86..109549aad 100644
--- a/src/common/HPM.h
+++ b/src/common/HPM.h
@@ -157,7 +157,7 @@ struct HPM_interface {
void (*share) (void *value, const char *name);
void (*config_read) (void);
char *(*pid2name) (unsigned int pid);
- unsigned char (*parse_packets) (int fd, enum HPluginPacketHookingPoints point);
+ unsigned char (*parse_packets) (int fd, int packet_id, enum HPluginPacketHookingPoints point);
void (*load_sub) (struct hplugin *plugin);
bool (*addhook_sub) (enum HPluginHookType type, const char *target, void *hook, unsigned int pID);
/* for custom config parsing */
diff --git a/src/common/HPMDataCheck.h b/src/common/HPMDataCheck.h
index 666d306db..7e88b5a34 100644
--- a/src/common/HPMDataCheck.h
+++ b/src/common/HPMDataCheck.h
@@ -402,6 +402,8 @@ HPExport const struct s_HPMDataCheck HPMDataCheck[] = {
{ "item_package_rand_entry", sizeof(struct item_package_rand_entry), SERVER_TYPE_MAP },
{ "item_package_rand_group", sizeof(struct item_package_rand_group), SERVER_TYPE_MAP },
{ "itemdb_interface", sizeof(struct itemdb_interface), SERVER_TYPE_MAP },
+ { "itemlist", sizeof(struct itemlist), SERVER_TYPE_MAP },
+ { "itemlist_entry", sizeof(struct itemlist_entry), SERVER_TYPE_MAP },
#else
#define MAP_ITEMDB_H
#endif // MAP_ITEMDB_H
diff --git a/src/common/Makefile.in b/src/common/Makefile.in
index df3ecaf2d..9d4b2d044 100644
--- a/src/common/Makefile.in
+++ b/src/common/Makefile.in
@@ -135,7 +135,7 @@ obj_all/sysinfo.o: sysinfo.c $(COMMON_H) $(CONFIG_H) $(MT19937AR_H) $(LIBCONFIG_
obj_all/%.o: %.c $(COMMON_H) $(CONFIG_H) $(MT19937AR_H) $(LIBCONFIG_H) | $(SYSINFO_INC) obj_all
@echo " CC $<"
- @$(CC) @CFLAGS@ @DEFS@ $(COMMON_INCLUDE) $(THIRDPARTY_INCLUDE) @PCRE_CFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $<
+ @$(CC) @CFLAGS@ @DEFS@ $(COMMON_INCLUDE) $(THIRDPARTY_INCLUDE) @CPPFLAGS@ -c $(OUTPUT_OPTION) $<
obj_all/mini%.o: %.c $(COMMON_H) $(CONFIG_H) $(MT19937AR_H) $(LIBCONFIG_H) | $(SYSINFO_INC) obj_all
@echo " CC $<"
diff --git a/src/common/cbasetypes.h b/src/common/cbasetypes.h
index 61d0646eb..6843ce486 100644
--- a/src/common/cbasetypes.h
+++ b/src/common/cbasetypes.h
@@ -94,7 +94,7 @@
// debug function name
#ifndef __NETBSD__
-#if __STDC_VERSION__ < 199901L
+#if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L
# if __GNUC__ >= 2
# define __func__ __FUNCTION__
# else
diff --git a/src/common/conf.c b/src/common/conf.c
index 3e8c08963..25f1013f5 100644
--- a/src/common/conf.c
+++ b/src/common/conf.c
@@ -23,6 +23,7 @@
#include "conf.h"
#include "common/showmsg.h" // ShowError
+#include "common/strlib.h" // safestrncpy
#include <libconfig/libconfig.h>
@@ -30,26 +31,39 @@
struct libconfig_interface libconfig_s;
struct libconfig_interface *libconfig;
-int conf_read_file(config_t *config, const char *config_filename) {
+/**
+ * Initializes 'config' and loads a configuration file.
+ *
+ * Shows error and destroys 'config' in case of failure.
+ * It is the caller's care to destroy 'config' in case of success.
+ *
+ * @param config The config file to initialize.
+ * @param config_filename The file to read.
+ *
+ * @retval CONFIG_TRUE in case of success.
+ * @retval CONFIG_FALSE in case of failure.
+ */
+int config_load_file(struct config_t *config, const char *config_filename)
+{
libconfig->init(config);
- if (!libconfig->read_file_src(config, config_filename)) {
+ if (libconfig->read_file_src(config, config_filename) != CONFIG_TRUE) {
ShowError("%s:%d - %s\n", config_error_file(config),
config_error_line(config), config_error_text(config));
libconfig->destroy(config);
- return 1;
+ return CONFIG_FALSE;
}
- return 0;
+ return CONFIG_TRUE;
}
//
// Functions to copy settings from libconfig/contrib
//
-void config_setting_copy_simple(config_setting_t *parent, const config_setting_t *src) {
+void config_setting_copy_simple(struct config_setting_t *parent, const struct config_setting_t *src)
+{
if (config_setting_is_aggregate(src)) {
libconfig->setting_copy_aggregate(parent, src);
- }
- else {
- config_setting_t *set;
+ } else {
+ struct config_setting_t *set;
if( libconfig->setting_get_member(parent, config_setting_name(src)) != NULL )
return;
@@ -73,8 +87,9 @@ void config_setting_copy_simple(config_setting_t *parent, const config_setting_t
}
}
-void config_setting_copy_elem(config_setting_t *parent, const config_setting_t *src) {
- config_setting_t *set = NULL;
+void config_setting_copy_elem(struct config_setting_t *parent, const struct config_setting_t *src)
+{
+ struct config_setting_t *set = NULL;
if (config_setting_is_aggregate(src))
libconfig->setting_copy_aggregate(parent, src);
@@ -93,8 +108,9 @@ void config_setting_copy_elem(config_setting_t *parent, const config_setting_t *
}
}
-void config_setting_copy_aggregate(config_setting_t *parent, const config_setting_t *src) {
- config_setting_t *newAgg;
+void config_setting_copy_aggregate(struct config_setting_t *parent, const struct config_setting_t *src)
+{
+ struct config_setting_t *newAgg;
int i, n;
if( libconfig->setting_get_member(parent, config_setting_name(src)) != NULL )
@@ -116,7 +132,8 @@ void config_setting_copy_aggregate(config_setting_t *parent, const config_settin
}
}
-int config_setting_copy(config_setting_t *parent, const config_setting_t *src) {
+int config_setting_copy(struct config_setting_t *parent, const struct config_setting_t *src)
+{
if (!config_setting_is_group(parent) && !config_setting_is_list(parent))
return CONFIG_FALSE;
@@ -128,14 +145,237 @@ int config_setting_copy(config_setting_t *parent, const config_setting_t *src) {
return CONFIG_TRUE;
}
+/**
+ * Converts the value of a setting that is type CONFIG_TYPE_BOOL to bool.
+ *
+ * @param setting The setting to read.
+ *
+ * @return The converted value.
+ * @retval false in case of failure.
+ */
+bool config_setting_get_bool_real(const struct config_setting_t *setting)
+{
+ if (setting == NULL || setting->type != CONFIG_TYPE_BOOL)
+ return false;
+
+ return setting->value.ival ? true : false;
+}
+
+/**
+ * Same as config_setting_lookup_bool, but uses bool instead of int.
+ *
+ * @param[in] setting The setting to read.
+ * @param[in] name The setting name to lookup.
+ * @param[out] value The output value.
+ *
+ * @retval CONFIG_TRUE in case of success.
+ * @retval CONFIG_FALSE in case of failure.
+ */
+int config_setting_lookup_bool_real(const struct config_setting_t *setting, const char *name, bool *value)
+{
+ struct config_setting_t *member = config_setting_get_member(setting, name);
+
+ if (!member)
+ return CONFIG_FALSE;
+
+ if (config_setting_type(member) != CONFIG_TYPE_BOOL)
+ return CONFIG_FALSE;
+
+ *value = config_setting_get_bool_real(member);
+
+ return CONFIG_TRUE;
+}
+
+/**
+ * Converts and returns a configuration that is CONFIG_TYPE_INT to unsigned int (uint32).
+ *
+ * @param setting The setting to read.
+ *
+ * @return The converted value.
+ * @retval 0 in case of failure.
+ */
+uint32 config_setting_get_uint32(const struct config_setting_t *setting)
+{
+ if (setting == NULL || setting->type != CONFIG_TYPE_INT)
+ return 0;
+
+ if (setting->value.ival < 0)
+ return 0;
+
+ return (uint32)setting->value.ival;
+}
+
+/**
+ * Looks up a configuration entry of type CONFIG_TYPE_INT and reads it as uint32.
+ *
+ * @param[in] setting The setting to read.
+ * @param[in] name The setting name to lookup.
+ * @param[out] value The output value.
+ *
+ * @retval CONFIG_TRUE in case of success.
+ * @retval CONFIG_FALSE in case of failure.
+ */
+int config_setting_lookup_uint32(const struct config_setting_t *setting, const char *name, uint32 *value)
+{
+ struct config_setting_t *member = config_setting_get_member(setting, name);
+
+ if (!member)
+ return CONFIG_FALSE;
+
+ if (config_setting_type(member) != CONFIG_TYPE_INT)
+ return CONFIG_FALSE;
+
+ *value = config_setting_get_uint32(member);
+
+ return CONFIG_TRUE;
+}
+
+/**
+ * Converts and returns a configuration that is CONFIG_TYPE_INT to uint16
+ *
+ * @param setting The setting to read.
+ *
+ * @return The converted value.
+ * @retval 0 in case of failure.
+ */
+uint16 config_setting_get_uint16(const struct config_setting_t *setting)
+{
+ if (setting == NULL || setting->type != CONFIG_TYPE_INT)
+ return 0;
+
+ if (setting->value.ival > UINT16_MAX)
+ return UINT16_MAX;
+ if (setting->value.ival < UINT16_MIN)
+ return UINT16_MIN;
+
+ return (uint16)setting->value.ival;
+}
+
+/**
+ * Looks up a configuration entry of type CONFIG_TYPE_INT and reads it as uint16.
+ *
+ * @param[in] setting The setting to read.
+ * @param[in] name The setting name to lookup.
+ * @param[out] value The output value.
+ *
+ * @retval CONFIG_TRUE in case of success.
+ * @retval CONFIG_FALSE in case of failure.
+ */
+int config_setting_lookup_uint16(const struct config_setting_t *setting, const char *name, uint16 *value)
+{
+ struct config_setting_t *member = config_setting_get_member(setting, name);
+
+ if (!member)
+ return CONFIG_FALSE;
+
+ if (config_setting_type(member) != CONFIG_TYPE_INT)
+ return CONFIG_FALSE;
+
+ *value = config_setting_get_uint16(member);
+
+ return CONFIG_TRUE;
+}
+
+/**
+ * Converts and returns a configuration that is CONFIG_TYPE_INT to int16
+ *
+ * @param setting The setting to read.
+ *
+ * @return The converted value.
+ * @retval 0 in case of failure.
+ */
+int16 config_setting_get_int16(const struct config_setting_t *setting)
+{
+ if (setting == NULL || setting->type != CONFIG_TYPE_INT)
+ return 0;
+
+ if (setting->value.ival > INT16_MAX)
+ return INT16_MAX;
+ if (setting->value.ival < INT16_MIN)
+ return INT16_MIN;
+
+ return (int16)setting->value.ival;
+}
+
+/**
+ * Looks up a configuration entry of type CONFIG_TYPE_INT and reads it as int16.
+ *
+ * @param[in] setting The setting to read.
+ * @param[in] name The setting name to lookup.
+ * @param[out] value The output value.
+ *
+ * @retval CONFIG_TRUE in case of success.
+ * @retval CONFIG_FALSE in case of failure.
+ */
+int config_setting_lookup_int16(const struct config_setting_t *setting, const char *name, int16 *value)
+{
+ struct config_setting_t *member = config_setting_get_member(setting, name);
+
+ if (!member)
+ return CONFIG_FALSE;
+
+ if (config_setting_type(member) != CONFIG_TYPE_INT)
+ return CONFIG_FALSE;
+
+ *value = config_setting_get_int16(member);
+
+ return CONFIG_TRUE;
+}
+
+/**
+ * Looks up a configuration entry of type CONFIG_TYPE_STRING inside a struct config_setting_t and copies it into a (non-const) char buffer.
+ *
+ * @param[in] setting The setting to read.
+ * @param[in] name The setting name to lookup.
+ * @param[out] out The output buffer.
+ * @param[in] out_size The size of the output buffer.
+ *
+ * @retval CONFIG_TRUE in case of success.
+ * @retval CONFIG_FALSE in case of failure.
+ */
+int config_setting_lookup_mutable_string(const struct config_setting_t *setting, const char *name, char *out, size_t out_size)
+{
+ const char *str = NULL;
+
+ if (libconfig->setting_lookup_string(setting, name, &str) == CONFIG_TRUE) {
+ safestrncpy(out, str, out_size);
+ return CONFIG_TRUE;
+ }
+
+ return CONFIG_FALSE;
+}
+
+/**
+ * Looks up a configuration entry of type CONFIG_TYPE_STRING inside a struct config_t and copies it into a (non-const) char buffer.
+ *
+ * @param[in] config The configuration to read.
+ * @param[in] name The setting name to lookup.
+ * @param[out] out The output buffer.
+ * @param[in] out_size The size of the output buffer.
+ *
+ * @retval CONFIG_TRUE in case of success.
+ * @retval CONFIG_FALSE in case of failure.
+ */
+int config_lookup_mutable_string(const struct config_t *config, const char *name, char *out, size_t out_size)
+{
+ const char *str = NULL;
+
+ if (libconfig->lookup_string(config, name, &str) == CONFIG_TRUE) {
+ safestrncpy(out, str, out_size);
+ return CONFIG_TRUE;
+ }
+
+ return CONFIG_FALSE;
+}
+
void libconfig_defaults(void) {
libconfig = &libconfig_s;
libconfig->read = config_read;
libconfig->write = config_write;
/* */
- libconfig->set_auto_convert = config_set_auto_convert;
- libconfig->get_auto_convert = config_get_auto_convert;
+ libconfig->set_options = config_set_options;
+ libconfig->get_options = config_get_options;
/* */
libconfig->read_string = config_read_string;
libconfig->read_file_src = config_read_file;
@@ -153,6 +393,7 @@ void libconfig_defaults(void) {
libconfig->setting_get_bool = config_setting_get_bool;
libconfig->setting_get_string = config_setting_get_string;
/* */
+ libconfig->setting_lookup = config_setting_lookup;
libconfig->setting_lookup_int = config_setting_lookup_int;
libconfig->setting_lookup_int64 = config_setting_lookup_int64;
libconfig->setting_lookup_float = config_setting_lookup_float;
@@ -193,7 +434,6 @@ void libconfig_defaults(void) {
libconfig->setting_set_hook = config_setting_set_hook;
/* */
libconfig->lookup = config_lookup;
- libconfig->lookup_from = config_lookup_from;
/* */
libconfig->lookup_int = config_lookup_int;
libconfig->lookup_int64 = config_lookup_int64;
@@ -201,9 +441,23 @@ void libconfig_defaults(void) {
libconfig->lookup_bool = config_lookup_bool;
libconfig->lookup_string = config_lookup_string;
/* those are custom and are from src/common/conf.c */
- libconfig->read_file = conf_read_file;
+ libconfig->load_file = config_load_file;
libconfig->setting_copy_simple = config_setting_copy_simple;
libconfig->setting_copy_elem = config_setting_copy_elem;
libconfig->setting_copy_aggregate = config_setting_copy_aggregate;
libconfig->setting_copy = config_setting_copy;
+
+ /* Functions to get different types */
+ libconfig->setting_get_bool_real = config_setting_get_bool_real;
+ libconfig->setting_get_uint32 = config_setting_get_uint32;
+ libconfig->setting_get_uint16 = config_setting_get_uint16;
+ libconfig->setting_get_int16 = config_setting_get_int16;
+
+ /* Functions to lookup different types */
+ libconfig->setting_lookup_int16 = config_setting_lookup_int16;
+ libconfig->setting_lookup_bool_real = config_setting_lookup_bool_real;
+ libconfig->setting_lookup_uint32 = config_setting_lookup_uint32;
+ libconfig->setting_lookup_uint16 = config_setting_lookup_uint16;
+ libconfig->setting_lookup_mutable_string = config_setting_lookup_mutable_string;
+ libconfig->lookup_mutable_string = config_lookup_mutable_string;
}
diff --git a/src/common/conf.h b/src/common/conf.h
index 19b13c51a..f2bfcac62 100644
--- a/src/common/conf.h
+++ b/src/common/conf.h
@@ -29,82 +29,94 @@
* The libconfig interface -- specially for plugins, but we enforce it throughout the core to be consistent
**/
struct libconfig_interface {
- int (*read) (config_t *config, FILE *stream);
- void (*write) (const config_t *config, FILE *stream);
+ int (*read) (struct config_t *config, FILE *stream);
+ void (*write) (const struct config_t *config, FILE *stream);
/* */
- void (*set_auto_convert) (config_t *config, int flag); // TODO: Replace with config_set_options
- int (*get_auto_convert) (const config_t *config); // TODO: Replace with config_get_options
+ void (*set_options) (struct config_t *config, int options);
+ int (*get_options) (const struct config_t *config);
/* */
- int (*read_string) (config_t *config, const char *str);
- int (*read_file_src) (config_t *config, const char *filename);
- int (*write_file) (config_t *config, const char *filename);
-
- void (*set_destructor) (config_t *config, void (*destructor)(void *));
- void (*set_include_dir) (config_t *config, const char *include_dir);
-
- void (*init) (config_t *config);
- void (*destroy) (config_t *config);
-
- int (*setting_get_int) (const config_setting_t *setting);
- long long (*setting_get_int64) (const config_setting_t *setting);
- double (*setting_get_float) (const config_setting_t *setting);
-
- int (*setting_get_bool) (const config_setting_t *setting);
-
- const char * (*setting_get_string) (const config_setting_t *setting);
-
- int (*setting_lookup_int) (const config_setting_t *setting, const char *name, int *value);
- int (*setting_lookup_int64) (const config_setting_t *setting, const char *name, long long *value);
- int (*setting_lookup_float) (const config_setting_t *setting, const char *name, double *value);
- int (*setting_lookup_bool) (const config_setting_t *setting, const char *name, int *value);
- int (*setting_lookup_string) (const config_setting_t *setting, const char *name, const char **value);
- int (*setting_set_int) (config_setting_t *setting ,int value);
- int (*setting_set_int64) (config_setting_t *setting, long long value);
- int (*setting_set_float) (config_setting_t *setting, double value);
- int (*setting_set_bool) (config_setting_t *setting, int value);
- int (*setting_set_string) (config_setting_t *setting, const char *value);
-
- int (*setting_set_format) (config_setting_t *setting, short format);
- short (*setting_get_format) (const config_setting_t *setting);
-
- int (*setting_get_int_elem) (const config_setting_t *setting, int idx);
- long long (*setting_get_int64_elem) (const config_setting_t *setting, int idx);
- double (*setting_get_float_elem) (const config_setting_t *setting, int idx);
- int (*setting_get_bool_elem) (const config_setting_t *setting, int idx);
- const char * (*setting_get_string_elem) (const config_setting_t *setting, int idx);
- config_setting_t * (*setting_set_int_elem) (config_setting_t *setting, int idx, int value);
- config_setting_t * (*setting_set_int64_elem) (config_setting_t *setting, int idx, long long value);
- config_setting_t * (*setting_set_float_elem) (config_setting_t *setting, int idx, double value);
- config_setting_t * (*setting_set_bool_elem) (config_setting_t *setting, int idx, int value);
- config_setting_t * (*setting_set_string_elem) (config_setting_t *setting, int idx, const char *value);
-
- int (*setting_index) (const config_setting_t *setting);
- int (*setting_length) (const config_setting_t *setting);
-
- config_setting_t * (*setting_get_elem) (const config_setting_t *setting, unsigned int idx);
- config_setting_t * (*setting_get_member) (const config_setting_t *setting, const char *name);
-
- config_setting_t * (*setting_add) (config_setting_t *parent, const char *name, int type);
- int (*setting_remove) (config_setting_t *parent, const char *name);
-
- int (*setting_remove_elem) (config_setting_t *parent, unsigned int idx);
- void (*setting_set_hook) (config_setting_t *setting, void *hook);
-
- config_setting_t * (*lookup) (const config_t *config, const char *filepath);
- config_setting_t * (*lookup_from) (config_setting_t *setting, const char *filepath);
- int (*lookup_int) (const config_t *config, const char *filepath, int *value);
- int (*lookup_int64) (const config_t *config, const char *filepath, long long *value);
- int (*lookup_float) (const config_t *config, const char *filepath, double *value);
- int (*lookup_bool) (const config_t *config, const char *filepath, int *value);
- int (*lookup_string) (const config_t *config, const char *filepath, const char **value);
+ int (*read_string) (struct config_t *config, const char *str);
+ int (*read_file_src) (struct config_t *config, const char *filename);
+ int (*write_file) (struct config_t *config, const char *filename);
+
+ void (*set_destructor) (struct config_t *config, void (*destructor)(void *));
+ void (*set_include_dir) (struct config_t *config, const char *include_dir);
+
+ void (*init) (struct config_t *config);
+ void (*destroy) (struct config_t *config);
+
+ int (*setting_get_int) (const struct config_setting_t *setting);
+ long long (*setting_get_int64) (const struct config_setting_t *setting);
+ double (*setting_get_float) (const struct config_setting_t *setting);
+
+ int (*setting_get_bool) (const struct config_setting_t *setting);
+
+ const char * (*setting_get_string) (const struct config_setting_t *setting);
+
+ struct config_setting_t * (*setting_lookup) (struct config_setting_t *setting, const char *name);
+ int (*setting_lookup_int) (const struct config_setting_t *setting, const char *name, int *value);
+ int (*setting_lookup_int64) (const struct config_setting_t *setting, const char *name, long long *value);
+ int (*setting_lookup_float) (const struct config_setting_t *setting, const char *name, double *value);
+ int (*setting_lookup_bool) (const struct config_setting_t *setting, const char *name, int *value);
+ int (*setting_lookup_string) (const struct config_setting_t *setting, const char *name, const char **value);
+ int (*setting_set_int) (struct config_setting_t *setting ,int value);
+ int (*setting_set_int64) (struct config_setting_t *setting, long long value);
+ int (*setting_set_float) (struct config_setting_t *setting, double value);
+ int (*setting_set_bool) (struct config_setting_t *setting, int value);
+ int (*setting_set_string) (struct config_setting_t *setting, const char *value);
+
+ int (*setting_set_format) (struct config_setting_t *setting, short format);
+ short (*setting_get_format) (const struct config_setting_t *setting);
+
+ int (*setting_get_int_elem) (const struct config_setting_t *setting, int idx);
+ long long (*setting_get_int64_elem) (const struct config_setting_t *setting, int idx);
+ double (*setting_get_float_elem) (const struct config_setting_t *setting, int idx);
+ int (*setting_get_bool_elem) (const struct config_setting_t *setting, int idx);
+ const char * (*setting_get_string_elem) (const struct config_setting_t *setting, int idx);
+ struct config_setting_t * (*setting_set_int_elem) (struct config_setting_t *setting, int idx, int value);
+ struct config_setting_t * (*setting_set_int64_elem) (struct config_setting_t *setting, int idx, long long value);
+ struct config_setting_t * (*setting_set_float_elem) (struct config_setting_t *setting, int idx, double value);
+ struct config_setting_t * (*setting_set_bool_elem) (struct config_setting_t *setting, int idx, int value);
+ struct config_setting_t * (*setting_set_string_elem) (struct config_setting_t *setting, int idx, const char *value);
+
+ int (*setting_index) (const struct config_setting_t *setting);
+ int (*setting_length) (const struct config_setting_t *setting);
+
+ struct config_setting_t * (*setting_get_elem) (const struct config_setting_t *setting, unsigned int idx);
+ struct config_setting_t * (*setting_get_member) (const struct config_setting_t *setting, const char *name);
+
+ struct config_setting_t * (*setting_add) (struct config_setting_t *parent, const char *name, int type);
+ int (*setting_remove) (struct config_setting_t *parent, const char *name);
+
+ int (*setting_remove_elem) (struct config_setting_t *parent, unsigned int idx);
+ void (*setting_set_hook) (struct config_setting_t *setting, void *hook);
+
+ struct config_setting_t * (*lookup) (const struct config_t *config, const char *filepath);
+ int (*lookup_int) (const struct config_t *config, const char *filepath, int *value);
+ int (*lookup_int64) (const struct config_t *config, const char *filepath, long long *value);
+ int (*lookup_float) (const struct config_t *config, const char *filepath, double *value);
+ int (*lookup_bool) (const struct config_t *config, const char *filepath, int *value);
+ int (*lookup_string) (const struct config_t *config, const char *filepath, const char **value);
/* those are custom and are from src/common/conf.c */
/* Functions to copy settings from libconfig/contrib */
- int (*read_file) (config_t *config, const char *config_filename);
- void (*setting_copy_simple) (config_setting_t *parent, const config_setting_t *src);
- void (*setting_copy_elem) (config_setting_t *parent, const config_setting_t *src);
- void (*setting_copy_aggregate) (config_setting_t *parent, const config_setting_t *src);
- int (*setting_copy) (config_setting_t *parent, const config_setting_t *src);
+ int (*load_file) (struct config_t *config, const char *config_filename);
+ void (*setting_copy_simple) (struct config_setting_t *parent, const struct config_setting_t *src);
+ void (*setting_copy_elem) (struct config_setting_t *parent, const struct config_setting_t *src);
+ void (*setting_copy_aggregate) (struct config_setting_t *parent, const struct config_setting_t *src);
+ int (*setting_copy) (struct config_setting_t *parent, const struct config_setting_t *src);
+ /* Functions to get other types */
+ bool (*setting_get_bool_real) (const struct config_setting_t *setting);
+ uint32 (*setting_get_uint32) (const struct config_setting_t *setting);
+ uint16 (*setting_get_uint16) (const struct config_setting_t *setting);
+ int16 (*setting_get_int16) (const struct config_setting_t *setting);
+
+ int (*setting_lookup_bool_real) (const struct config_setting_t *setting, const char *name, bool *value);
+ int (*setting_lookup_uint32) (const struct config_setting_t *setting, const char *name, uint32 *value);
+ int (*setting_lookup_uint16) (const struct config_setting_t *setting, const char *name, uint16 *value);
+ int (*setting_lookup_int16) (const struct config_setting_t *setting, const char *name, int16 *value);
+ int (*setting_lookup_mutable_string) (const struct config_setting_t *setting, const char *name, char *out, size_t out_size);
+ int (*lookup_mutable_string) (const struct config_t *config, const char *name, char *out, size_t out_size);
};
#ifdef HERCULES_CORE
diff --git a/src/common/console.c b/src/common/console.c
index f0702d0da..10e1bee1a 100644
--- a/src/common/console.c
+++ b/src/common/console.c
@@ -90,6 +90,7 @@ void display_title(void) {
ShowInfo("CPU: '"CL_WHITE"%s [%d]"CL_RESET"'\n", sysinfo->cpu(), sysinfo->cpucores());
ShowInfo("Compiled with %s\n", sysinfo->compiler());
ShowInfo("Compile Flags: %s\n", sysinfo->cflags());
+ ShowInfo("Timer Function Type: %s\n", sysinfo->time());
}
/**
diff --git a/src/common/core.c b/src/common/core.c
index 201d4f5e8..ccd80c44b 100644
--- a/src/common/core.c
+++ b/src/common/core.c
@@ -230,7 +230,10 @@ bool cmdline_arg_add(unsigned int pluginID, const char *name, char shortname, Cm
data->name = aStrdup(name);
data->shortname = shortname;
data->func = func;
- data->help = aStrdup(help);
+ if (help)
+ data->help = aStrdup(help);
+ else
+ data->help = NULL;
data->options = options;
return true;
diff --git a/src/common/ers.c b/src/common/ers.c
index 85e1fb759..8970fefc2 100644
--- a/src/common/ers.c
+++ b/src/common/ers.c
@@ -288,7 +288,7 @@ static void ers_obj_destroy(ERS *self)
if (instance->Count > 0)
if (!(instance->Options & ERS_OPT_CLEAR))
- ShowWarning("Memory leak detected at ERS '%s', %d objects not freed.\n", instance->Name, instance->Count);
+ ShowWarning("Memory leak detected at ERS '%s', %u objects not freed.\n", instance->Name, instance->Count);
if (--instance->Cache->ReferenceCount <= 0)
ers_free_cache(instance->Cache, true);
@@ -313,7 +313,7 @@ void ers_cache_size(ERS *self, unsigned int new_size) {
nullpo_retv(instance);
if( !(instance->Cache->Options&ERS_OPT_FLEX_CHUNK) ) {
- ShowWarning("ers_cache_size: '%s' has adjusted its chunk size to '%d', however ERS_OPT_FLEX_CHUNK is missing!\n",instance->Name,new_size);
+ ShowWarning("ers_cache_size: '%s' has adjusted its chunk size to '%u', however ERS_OPT_FLEX_CHUNK is missing!\n", instance->Name, new_size);
}
instance->Cache->ChunkSize = new_size;
@@ -382,7 +382,7 @@ void ers_report(void) {
for (cache = CacheList; cache; cache = cache->Next) {
cache_c++;
ShowMessage(CL_BOLD"[ERS Cache of size '"CL_NORMAL""CL_WHITE"%u"CL_NORMAL""CL_BOLD"' report]\n"CL_NORMAL, cache->ObjectSize);
- ShowMessage("\tinstances : %u\n", cache->ReferenceCount);
+ ShowMessage("\tinstances : %d\n", cache->ReferenceCount);
ShowMessage("\tblocks in use : %u/%u\n", cache->UsedObjs, cache->UsedObjs+cache->Free);
ShowMessage("\tblocks unused : %u\n", cache->Free);
ShowMessage("\tmemory in use : %.2f MB\n", cache->UsedObjs == 0 ? 0. : (double)((cache->UsedObjs * cache->ObjectSize)/1024)/1024);
diff --git a/src/common/md5calc.c b/src/common/md5calc.c
index 44f912992..bc70d9006 100644
--- a/src/common/md5calc.c
+++ b/src/common/md5calc.c
@@ -169,7 +169,7 @@ static void MD5_String2binary(const char * string, unsigned char * output)
//var
/*8bit*/
unsigned char padding_message[64]; //Extended message 512bit 64byte
- unsigned char *pstring; //The position of string in the present scanning notes is held.
+ const unsigned char *pstring; //The position of string in the present scanning notes is held.
/*32bit*/
unsigned int string_byte_len, //The byte chief of string is held.
@@ -192,7 +192,7 @@ static void MD5_String2binary(const char * string, unsigned char * output)
//Step 1.Append Padding Bits (extension of a mark bit)
//1-1
string_byte_len = (unsigned int)strlen(string); //The byte chief of a character sequence is acquired.
- pstring = (unsigned char *)string; //The position of the present character sequence is set.
+ pstring = (const unsigned char *)string; //The position of the present character sequence is set.
//1-2 Repeat calculation until length becomes less than 64 bytes.
for (i=string_byte_len; 64<=i; i-=64,pstring+=64)
@@ -200,7 +200,7 @@ static void MD5_String2binary(const char * string, unsigned char * output)
//1-3
copy_len = string_byte_len % 64; //The number of bytes which remained is computed.
- strncpy((char *)padding_message, (char *)pstring, copy_len); //A message is copied to an extended bit sequence.
+ strncpy((char *)padding_message, (const char *)pstring, copy_len); //A message is copied to an extended bit sequence.
memset(padding_message+copy_len, 0, 64 - copy_len); //It buries by 0 until it becomes extended bit length.
padding_message[copy_len] |= 0x80; //The next of a message is 1.
diff --git a/src/common/memmgr.c b/src/common/memmgr.c
index 93c23ff18..15e55fbeb 100644
--- a/src/common/memmgr.c
+++ b/src/common/memmgr.c
@@ -97,10 +97,10 @@ struct malloc_interface *iMalloc;
#ifndef USE_MEMMGR
-#ifdef __APPLE__
+#if defined __APPLE__
#include <malloc/malloc.h>
#define BUFFER_SIZE(ptr) malloc_size(ptr)
-#elif __FreeBSD__
+#elif defined __FreeBSD__
#include <malloc_np.h>
#define BUFFER_SIZE(ptr) malloc_usable_size(ptr)
#elif defined __linux__ || defined __linux || defined CYGWIN
@@ -149,7 +149,7 @@ void* aRealloc_(void *p, size_t size, const char *file, int line, const char *fu
void* aReallocz_(void *p, size_t size, const char *file, int line, const char *func)
{
- void *ret;
+ unsigned char *ret = NULL;
// ShowMessage("%s:%d: in func %s: aReallocz %p %ld\n",file,line,func,p,size);
#ifdef USE_MEMMGR
ret = REALLOC(p, size, file, line, func);
@@ -159,11 +159,11 @@ void* aReallocz_(void *p, size_t size, const char *file, int line, const char *f
size_t oldSize = BUFFER_SIZE(p);
ret = REALLOC(p, size, file, line, func);
newSize = BUFFER_SIZE(ret);
- if (ret && newSize > oldSize)
+ if (ret != NULL && newSize > oldSize)
memset(ret + oldSize, 0, newSize - oldSize);
} else {
ret = REALLOC(p, size, file, line, func);
- if (ret)
+ if (ret != NULL)
memset(ret, 0, BUFFER_SIZE(ret));
}
#endif
@@ -184,6 +184,36 @@ char* aStrdup_(const char *p, const char *file, int line, const char *func)
}
return ret;
}
+
+/**
+ * Copies a string to a newly allocated buffer, setting a maximum length.
+ *
+ * The string is always NULL-terminated. If the string is longer than `size`,
+ * then `size` bytes are copied, not including the appended NULL terminator.
+ *
+ * @warning
+ * If malloc is out of memory, throws a fatal error and aborts the program.
+ *
+ * @param p the source string to copy.
+ * @param size The maximum string length to copy.
+ * @param file @see ALC_MARK.
+ * @param line @see ALC_MARK.
+ * @param func @see ALC_MARK.
+ * @return the copied string.
+ */
+char *aStrndup_(const char *p, size_t size, const char *file, int line, const char *func)
+{
+ size_t len = strnlen(p, size);
+ char *ret = MALLOC(len + 1, file, line, func);
+ if (ret == NULL) {
+ ShowFatalError("%s:%d: in func %s: aStrndup error out of memory!\n", file, line, func);
+ exit(EXIT_FAILURE);
+ }
+ memcpy(ret, p, len);
+ ret[len] = '\0';
+ return ret;
+}
+
void aFree_(void *p, const char *file, int line, const char *func)
{
// ShowMessage("%s:%d: in func %s: aFree %p\n",file,line,func,p);
@@ -305,7 +335,7 @@ void *mmalloc_(size_t size, const char *file, int line, const char *func) {
struct unit_head *head;
if (((long) size) < 0) {
- ShowError("mmalloc_: %"PRIdS"\n", size);
+ ShowError("mmalloc_: %"PRIuS"\n", size);
return NULL;
}
@@ -478,6 +508,37 @@ char *mstrdup_(const char *p, const char *file, int line, const char *func) {
}
}
+/**
+ * Copies a string to a newly allocated buffer, setting a maximum length.
+ *
+ * The string is always NULL-terminated. If the string is longer than `size`,
+ * then `size` bytes are copied, not including the appended NULL terminator.
+ *
+ * @warning
+ * If malloc is out of memory, throws a fatal error and aborts the program.
+ *
+ * @param p the source string to copy.
+ * @param size The maximum string length to copy.
+ * @param file @see ALC_MARK.
+ * @param line @see ALC_MARK.
+ * @param func @see ALC_MARK.
+ * @return the copied string.
+ * @retval NULL if the source string is NULL or in case of error.
+ */
+char *mstrndup_(const char *p, size_t size, const char *file, int line, const char *func)
+{
+ if (p == NULL) {
+ return NULL;
+ } else {
+ size_t len = strnlen(p, size);
+ char *string = iMalloc->malloc(len + 1, file, line, func);
+ memcpy(string, p, len);
+ string[len] = '\0';
+ return string;
+ }
+}
+
+
void mfree_(void *ptr, const char *file, int line, const char *func) {
struct unit_head *head;
@@ -820,7 +881,7 @@ void memmgr_report (int extra) {
}
for( j = 0; j < 100; j++ ) {
if( data[j].size != 0 ) {
- ShowMessage("[malloc] : "CL_WHITE"%s"CL_RESET":"CL_WHITE"%d"CL_RESET" %d instances => %.2f MB\n",data[j].file,data[j].line,data[j].count,(double)((data[j].size)/1024)/1024);
+ ShowMessage("[malloc] : "CL_WHITE"%s"CL_RESET":"CL_WHITE"%d"CL_RESET" %u instances => %.2f MB\n",data[j].file,data[j].line,data[j].count,(double)((data[j].size)/1024)/1024);
}
}
ShowMessage("[malloc] : reporting %u instances | %.2f MB\n",count,(double)((size)/1024)/1024);
@@ -947,6 +1008,7 @@ void malloc_defaults(void) {
iMalloc->realloc = mrealloc_;
iMalloc->reallocz = mreallocz_;
iMalloc->astrdup = mstrdup_;
+ iMalloc->astrndup = mstrndup_;
iMalloc->free = mfree_;
#else
iMalloc->malloc = aMalloc_;
@@ -954,6 +1016,7 @@ void malloc_defaults(void) {
iMalloc->realloc = aRealloc_;
iMalloc->reallocz = aReallocz_;/* not using memory manager huhum o.o perhaps we could still do something about */
iMalloc->astrdup = aStrdup_;
+ iMalloc->astrndup = aStrndup_;
iMalloc->free = aFree_;
#endif
iMalloc->post_shutdown = NULL;
diff --git a/src/common/memmgr.h b/src/common/memmgr.h
index 5975f55c4..680947466 100644
--- a/src/common/memmgr.h
+++ b/src/common/memmgr.h
@@ -52,6 +52,7 @@
# define aRealloc(p,n) (iMalloc->realloc((p),(n),ALC_MARK))
# define aReallocz(p,n) (iMalloc->reallocz((p),(n),ALC_MARK))
# define aStrdup(p) (iMalloc->astrdup((p),ALC_MARK))
+# define aStrndup(p,n) (iMalloc->astrndup((p),(n),ALC_MARK))
# define aFree(p) (iMalloc->free((p),ALC_MARK))
/////////////// Buffer Creation /////////////////
@@ -85,6 +86,7 @@ struct malloc_interface {
void* (*realloc)(void *p, size_t size, const char *file, int line, const char *func);
void* (*reallocz)(void *p, size_t size, const char *file, int line, const char *func);
char* (*astrdup)(const char *p, const char *file, int line, const char *func);
+ char *(*astrndup)(const char *p, size_t size, const char *file, int line, const char *func);
void (*free)(void *p, const char *file, int line, const char *func);
/* */
void (*memory_check)(void);
diff --git a/src/common/mmo.h b/src/common/mmo.h
index 37fc63e29..77b9abab6 100644
--- a/src/common/mmo.h
+++ b/src/common/mmo.h
@@ -213,8 +213,15 @@
#define JOBL_BABY 0x2000 //8192
#define JOBL_THIRD 0x4000 //16384
+//Packet DB
+#define MIN_PACKET_DB 0x0064 //what's the point of minimum packet id ? [hemagx]
+#define MAX_PACKET_DB 0x0F00
+#define MAX_PACKET_POS 20
+
#define SCRIPT_VARNAME_LENGTH 32 ///< Maximum length of a script variable
+#define INFINITE_DURATION (-1) // Infinite duration for status changes
+
struct hplugin_data_store;
enum item_types {
@@ -387,11 +394,11 @@ struct script_reg_str {
char *value;
};
-// For saving status changes across sessions. [Skotlex]
+/// For saving status changes across sessions. [Skotlex]
struct status_change_data {
- unsigned short type; //SC_type
- int val1, val2, val3, val4;
- unsigned int tick; //Remaining duration.
+ unsigned short type; ///< Status change type (@see enum sc_type)
+ int val1, val2, val3, val4; ///< Parameters (meaning depends on type).
+ int tick; ///< Remaining duration.
};
struct storage_data {
@@ -468,7 +475,7 @@ struct s_elemental {
int elemental_id;
int char_id;
short class_;
- int mode;
+ uint32 mode;
int hp, sp, max_hp, max_sp, matk, atk, atk2;
short hit, flee, amotion, def, mdef;
int life_time;
@@ -749,7 +756,8 @@ enum { //Change Member Infos
enum guild_permission { // Guild permissions
GPERM_INVITE = 0x01,
GPERM_EXPEL = 0x10,
- GPERM_BOTH = GPERM_INVITE|GPERM_EXPEL,
+ GPERM_ALL = GPERM_INVITE|GPERM_EXPEL,
+ GPERM_MASK = GPERM_ALL,
};
enum {
diff --git a/src/common/showmsg.c b/src/common/showmsg.c
index 956222a7d..1c1d4ca8b 100644
--- a/src/common/showmsg.c
+++ b/src/common/showmsg.c
@@ -23,11 +23,10 @@
#include "showmsg.h"
#include "common/cbasetypes.h"
+#include "common/conf.h"
#include "common/core.h" //[Ind] - For SERVER_TYPE
#include "common/strlib.h" // StringBuf
-#include <libconfig/libconfig.h>
-
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h> // atexit
@@ -799,14 +798,14 @@ void showmsg_showWarning(const char *string, ...)
vShowMessage_(MSG_WARNING, string, ap);
va_end(ap);
}
-void showmsg_showConfigWarning(config_setting_t *config, const char *string, ...) __attribute__((format(printf, 2, 3)));
-void showmsg_showConfigWarning(config_setting_t *config, const char *string, ...)
+void showmsg_showConfigWarning(struct config_setting_t *config, const char *string, ...) __attribute__((format(printf, 2, 3)));
+void showmsg_showConfigWarning(struct config_setting_t *config, const char *string, ...)
{
StringBuf buf;
va_list ap;
StrBuf->Init(&buf);
StrBuf->AppendStr(&buf, string);
- StrBuf->Printf(&buf, " (%s:%d)\n", config_setting_source_file(config), config_setting_source_line(config));
+ StrBuf->Printf(&buf, " (%s:%u)\n", config_setting_source_file(config), config_setting_source_line(config));
va_start(ap, string);
vShowMessage_(MSG_WARNING, StrBuf->Value(&buf), ap);
va_end(ap);
diff --git a/src/common/showmsg.h b/src/common/showmsg.h
index ed8776fb0..7b48d0df2 100644
--- a/src/common/showmsg.h
+++ b/src/common/showmsg.h
@@ -23,10 +23,11 @@
#include "common/hercules.h"
-#include <libconfig/libconfig.h>
-
#include <stdarg.h>
+/* Forward Declarations */
+struct config_setting_t;
+
// for help with the console colors look here:
// http://www.edoceo.com/liberum/?doc=printf-with-color
// some code explanation (used here):
@@ -118,7 +119,7 @@ struct showmsg_interface {
void (*showDebug) (const char *, ...) __attribute__((format(printf, 1, 2)));
void (*showError) (const char *, ...) __attribute__((format(printf, 1, 2)));
void (*showFatalError) (const char *, ...) __attribute__((format(printf, 1, 2)));
- void (*showConfigWarning) (config_setting_t *config, const char *string, ...) __attribute__((format(printf, 2, 3)));
+ void (*showConfigWarning) (struct config_setting_t *config, const char *string, ...) __attribute__((format(printf, 2, 3)));
};
/* the purpose of these macros is simply to not make calling them be an annoyance */
diff --git a/src/common/socket.c b/src/common/socket.c
index 740c07bdc..10712c78b 100644
--- a/src/common/socket.c
+++ b/src/common/socket.c
@@ -25,6 +25,7 @@
#include "common/HPM.h"
#include "common/cbasetypes.h"
+#include "common/conf.h"
#include "common/db.h"
#include "common/memmgr.h"
#include "common/mmo.h"
@@ -624,7 +625,7 @@ int make_connection(uint32 ip, uint16 port, struct hSockOpt *opt) {
remote_address.sin_port = htons(port);
if( !( opt && opt->silent ) )
- ShowStatus("Connecting to %d.%d.%d.%d:%i\n", CONVIP(ip), port);
+ ShowStatus("Connecting to %u.%u.%u.%u:%i\n", CONVIP(ip), port);
result = sConnect(fd, (struct sockaddr *)(&remote_address), sizeof(struct sockaddr_in));
if( result == SOCKET_ERROR ) {
@@ -757,7 +758,7 @@ int wfifoset(int fd, size_t len)
if (s->wdata_size+len > s->max_wdata) {
// actually there was a buffer overflow already
uint32 ip = s->client_addr;
- ShowFatalError("WFIFOSET: Write Buffer Overflow. Connection %d (%d.%d.%d.%d) has written %u bytes on a %u/%u bytes buffer.\n", fd, CONVIP(ip), (unsigned int)len, (unsigned int)s->wdata_size, (unsigned int)s->max_wdata);
+ ShowFatalError("WFIFOSET: Write Buffer Overflow. Connection %d (%u.%u.%u.%u) has written %u bytes on a %u/%u bytes buffer.\n", fd, CONVIP(ip), (unsigned int)len, (unsigned int)s->wdata_size, (unsigned int)s->max_wdata);
ShowDebug("Likely command that caused it: 0x%x\n", (*(uint16*)(s->wdata + s->wdata_size)));
// no other chance, make a better fifo model
exit(EXIT_FAILURE);
@@ -767,7 +768,7 @@ int wfifoset(int fd, size_t len)
{
// dynamic packets allow up to UINT16_MAX bytes (<packet_id>.W <packet_len>.W ...)
// all known fixed-size packets are within this limit, so use the same limit
- ShowFatalError("WFIFOSET: Packet 0x%x is too big. (len=%u, max=%u)\n", (*(uint16*)(s->wdata + s->wdata_size)), (unsigned int)len, 0xFFFF);
+ ShowFatalError("WFIFOSET: Packet 0x%x is too big. (len=%u, max=%u)\n", (*(uint16*)(s->wdata + s->wdata_size)), (unsigned int)len, 0xFFFFU);
exit(EXIT_FAILURE);
}
else if( len == 0 )
@@ -984,7 +985,7 @@ static int connect_check(uint32 ip)
{
int result = connect_check_(ip);
if( access_debug ) {
- ShowInfo("connect_check: Connection from %d.%d.%d.%d %s\n", CONVIP(ip),result ? "allowed." : "denied!");
+ ShowInfo("connect_check: Connection from %u.%u.%u.%u %s\n", CONVIP(ip),result ? "allowed." : "denied!");
}
return result;
}
@@ -1004,7 +1005,7 @@ static int connect_check_(uint32 ip)
for( i=0; i < access_allownum; ++i ){
if (SUBNET_MATCH(ip, access_allow[i].ip, access_allow[i].mask)) {
if( access_debug ){
- ShowInfo("connect_check: Found match from allow list:%d.%d.%d.%d IP:%d.%d.%d.%d Mask:%d.%d.%d.%d\n",
+ ShowInfo("connect_check: Found match from allow list:%u.%u.%u.%u IP:%u.%u.%u.%u Mask:%u.%u.%u.%u\n",
CONVIP(ip),
CONVIP(access_allow[i].ip),
CONVIP(access_allow[i].mask));
@@ -1017,7 +1018,7 @@ static int connect_check_(uint32 ip)
for( i=0; i < access_denynum; ++i ){
if (SUBNET_MATCH(ip, access_deny[i].ip, access_deny[i].mask)) {
if( access_debug ){
- ShowInfo("connect_check: Found match from deny list:%d.%d.%d.%d IP:%d.%d.%d.%d Mask:%d.%d.%d.%d\n",
+ ShowInfo("connect_check: Found match from deny list:%u.%u.%u.%u IP:%u.%u.%u.%u Mask:%u.%u.%u.%u\n",
CONVIP(ip),
CONVIP(access_deny[i].ip),
CONVIP(access_deny[i].mask));
@@ -1064,7 +1065,7 @@ static int connect_check_(uint32 ip)
hist->tick = timer->gettick();
if( ++hist->count >= ddos_count ) {// DDoS attack detected
hist->ddos = 1;
- ShowWarning("connect_check: DDoS Attack detected from %d.%d.%d.%d!\n", CONVIP(ip));
+ ShowWarning("connect_check: DDoS Attack detected from %u.%u.%u.%u!\n", CONVIP(ip));
return (connect_ok == 2 ? 1 : 0);
}
return connect_ok;
@@ -1152,7 +1153,7 @@ int access_ipmask(const char* str, AccessControl* acc)
}
}
if( access_debug ){
- ShowInfo("access_ipmask: Loaded IP:%d.%d.%d.%d mask:%d.%d.%d.%d\n", CONVIP(ip), CONVIP(mask));
+ ShowInfo("access_ipmask: Loaded IP:%u.%u.%u.%u mask:%u.%u.%u.%u\n", CONVIP(ip), CONVIP(mask));
}
acc->ip = ip;
acc->mask = mask;
@@ -1428,7 +1429,7 @@ void socket_init(void)
timer->add_interval(timer->gettick()+1000, connect_check_clear, 0, 0, 5*60*1000);
#endif
- ShowInfo("Server supports up to '"CL_WHITE"%"PRId64""CL_RESET"' concurrent connections.\n", rlim_cur);
+ ShowInfo("Server supports up to '"CL_WHITE"%"PRIu64""CL_RESET"' concurrent connections.\n", rlim_cur);
}
bool session_is_valid(int fd)
@@ -1686,7 +1687,7 @@ bool socket_trusted_ip_check(uint32 ip)
* @param[in] groupname Current group name, for output/logging reasons.
* @return The amount of entries read, zero in case of errors.
*/
-int socket_net_config_read_sub(config_setting_t *t, struct s_subnet_vector *list, const char *filename, const char *groupname)
+int socket_net_config_read_sub(struct config_setting_t *t, struct s_subnet_vector *list, const char *filename, const char *groupname)
{
int i, len;
char ipbuf[64], maskbuf[64];
@@ -1722,11 +1723,11 @@ int socket_net_config_read_sub(config_setting_t *t, struct s_subnet_vector *list
*/
void socket_net_config_read(const char *filename)
{
- config_t network_config;
+ struct config_t network_config;
int i;
nullpo_retv(filename);
- if (libconfig->read_file(&network_config, filename)) {
+ if (!libconfig->load_file(&network_config, filename)) {
ShowError("LAN Support configuration file is not found: '%s'. This server won't be able to accept connections from any servers.\n", filename);
return;
}
diff --git a/src/common/socket.h b/src/common/socket.h
index b33fd2acf..947ea8d3e 100644
--- a/src/common/socket.h
+++ b/src/common/socket.h
@@ -22,7 +22,6 @@
#define COMMON_SOCKET_H
#include "common/hercules.h"
-#include "common/conf.h"
#include "common/db.h"
#ifdef WIN32
@@ -34,7 +33,9 @@
# include <sys/types.h>
#endif
+/* Forward Declarations */
struct hplugin_data_store;
+struct config_setting_t;
#define FIFOSIZE_SERVERLINK 256*1024
@@ -46,16 +47,16 @@ struct hplugin_data_store;
sockt->realloc_writefifo((fd), (size)); \
} while(0)
-#define RFIFOP(fd,pos) (sockt->session[fd]->rdata + sockt->session[fd]->rdata_pos + (pos))
-#define WFIFOP(fd,pos) (sockt->session[fd]->wdata + sockt->session[fd]->wdata_size + (pos))
+#define RFIFOP(fd,pos) ((const void *)(sockt->session[fd]->rdata + sockt->session[fd]->rdata_pos + (pos)))
+#define WFIFOP(fd,pos) ((void *)(sockt->session[fd]->wdata + sockt->session[fd]->wdata_size + (pos)))
-#define RFIFOB(fd,pos) (*(uint8*)RFIFOP((fd),(pos)))
+#define RFIFOB(fd,pos) (*(const uint8*)RFIFOP((fd),(pos)))
#define WFIFOB(fd,pos) (*(uint8*)WFIFOP((fd),(pos)))
-#define RFIFOW(fd,pos) (*(uint16*)RFIFOP((fd),(pos)))
+#define RFIFOW(fd,pos) (*(const uint16*)RFIFOP((fd),(pos)))
#define WFIFOW(fd,pos) (*(uint16*)WFIFOP((fd),(pos)))
-#define RFIFOL(fd,pos) (*(uint32*)RFIFOP((fd),(pos)))
+#define RFIFOL(fd,pos) (*(const uint32*)RFIFOP((fd),(pos)))
#define WFIFOL(fd,pos) (*(uint32*)WFIFOP((fd),(pos)))
-#define RFIFOQ(fd,pos) (*(uint64*)RFIFOP((fd),(pos)))
+#define RFIFOQ(fd,pos) (*(const uint64*)RFIFOP((fd),(pos)))
#define WFIFOQ(fd,pos) (*(uint64*)WFIFOP((fd),(pos)))
#define RFIFOSPACE(fd) (sockt->session[fd]->max_rdata - sockt->session[fd]->rdata_size)
#define WFIFOSPACE(fd) (sockt->session[fd]->max_wdata - sockt->session[fd]->wdata_size)
@@ -76,16 +77,31 @@ struct hplugin_data_store;
#define RFIFOSKIP(fd, len) (sockt->rfifoskip(fd, len))
/* [Ind/Hercules] */
-#define RFIFO2PTR(fd) (void*)(sockt->session[fd]->rdata + sockt->session[fd]->rdata_pos)
+#define RFIFO2PTR(fd) ((const void *)(sockt->session[fd]->rdata + sockt->session[fd]->rdata_pos))
+#define RP2PTR(fd) RFIFO2PTR(fd)
-// buffer I/O macros
-#define RBUFP(p,pos) (((uint8*)(p)) + (pos))
-#define RBUFB(p,pos) (*(uint8*)RBUFP((p),(pos)))
-#define RBUFW(p,pos) (*(uint16*)RBUFP((p),(pos)))
-#define RBUFL(p,pos) (*(uint32*)RBUFP((p),(pos)))
-#define RBUFQ(p,pos) (*(uint64*)RBUFP((p),(pos)))
+/* [Hemagx/Hercules] */
+#define WFIFO2PTR(fd) ((void *)(sockt->session[fd]->wdata + sockt->session[fd]->wdata_size))
+#define WP2PTR(fd) WFIFO2PTR(fd)
-#define WBUFP(p,pos) (((uint8*)(p)) + (pos))
+// buffer I/O macros
+static inline const void *RBUFP_(const void *p, int pos) __attribute__((const, unused));
+static inline const void *RBUFP_(const void *p, int pos)
+{
+ return ((const uint8 *)p) + pos;
+}
+#define RBUFP(p,pos) RBUFP_(p, (int)(pos))
+#define RBUFB(p,pos) (*(const uint8 *)RBUFP((p),(pos)))
+#define RBUFW(p,pos) (*(const uint16 *)RBUFP((p),(pos)))
+#define RBUFL(p,pos) (*(const uint32 *)RBUFP((p),(pos)))
+#define RBUFQ(p,pos) (*(const uint64 *)RBUFP((p),(pos)))
+
+static inline void *WBUFP_(void *p, int pos) __attribute__((const, unused));
+static inline void *WBUFP_(void *p, int pos)
+{
+ return ((uint8 *)p) + pos;
+}
+#define WBUFP(p,pos) WBUFP_(p, (int)(pos))
#define WBUFB(p,pos) (*(uint8*)WBUFP((p),(pos)))
#define WBUFW(p,pos) (*(uint16*)WBUFP((p),(pos)))
#define WBUFL(p,pos) (*(uint32*)WBUFP((p),(pos)))
@@ -209,7 +225,7 @@ struct socket_interface {
uint32 (*lan_subnet_check) (uint32 ip, struct s_subnet *info);
bool (*allowed_ip_check) (uint32 ip);
bool (*trusted_ip_check) (uint32 ip);
- int (*net_config_read_sub) (config_setting_t *t, struct s_subnet_vector *list, const char *filename, const char *groupname);
+ int (*net_config_read_sub) (struct config_setting_t *t, struct s_subnet_vector *list, const char *filename, const char *groupname);
void (*net_config_read) (const char *filename);
};
diff --git a/src/common/sql.c b/src/common/sql.c
index f6280c436..ed93169ea 100644
--- a/src/common/sql.c
+++ b/src/common/sql.c
@@ -32,6 +32,7 @@
# include "common/winapi.h" // Needed before mysql.h
#endif
#include <mysql.h>
+#include <stdio.h>
#include <stdlib.h> // strtoul
void hercules_mysql_error_handler(unsigned int ecode);
@@ -466,7 +467,7 @@ static int Sql_P_BindSqlDataType(MYSQL_BIND* bind, enum SqlDataType buffer_type,
case SQLDT_BLOB: bind->buffer_type = MYSQL_TYPE_BLOB;
break;
default:
- ShowDebug("Sql_P_BindSqlDataType: unsupported buffer type (%d)\n", buffer_type);
+ ShowDebug("Sql_P_BindSqlDataType: unsupported buffer type (%u)\n", buffer_type);
return SQL_ERROR;
}
bind->buffer = buffer;
@@ -869,7 +870,7 @@ void hercules_mysql_error_handler(unsigned int ecode) {
case 2003:/* Can't connect to MySQL (this error only happens here when failing to reconnect) */
if( mysql_reconnect_type == 1 ) {
if( ++retry > mysql_reconnect_count ) {
- ShowFatalError("MySQL has been unreachable for too long, %d reconnects were attempted. Shutting Down\n", retry);
+ ShowFatalError("MySQL has been unreachable for too long, %u reconnects were attempted. Shutting Down\n", retry);
exit(EXIT_FAILURE);
}
}
@@ -971,7 +972,7 @@ void Sql_HerculesUpdateCheck(Sql* self) {
fclose(ifp);
if( performed ) {
- ShowSQL("- detected %d new "CL_WHITE"SQL updates"CL_RESET"\n",performed);
+ ShowSQL("- detected %u new "CL_WHITE"SQL updates"CL_RESET"\n",performed);
ShowMessage("%s",StrBuf->Value(&buf));
ShowSQL("To manually skip, type: 'sql update skip <file name>'\n");
}
diff --git a/src/common/sysinfo.c b/src/common/sysinfo.c
index 7cc4cd16a..95f423ff7 100644
--- a/src/common/sysinfo.c
+++ b/src/common/sysinfo.c
@@ -38,6 +38,7 @@
#ifdef WIN32
# include <windows.h>
#else
+# include <sys/time.h> // time constants
# include <unistd.h>
#endif
@@ -1052,6 +1053,19 @@ void sysinfo_final(void) {
sysinfo->p->vcstype_name = NULL;
}
+static const char *sysinfo_time(void)
+{
+#if defined(WIN32)
+ return "ticks count";
+#elif defined(ENABLE_RDTSC)
+ return "rdtsc";
+#elif defined(HAVE_MONOTONIC_CLOCK)
+ return "monotonic clock";
+#else
+ return "time of day";
+#endif
+}
+
/**
* Interface default values initialization.
*/
@@ -1072,6 +1086,7 @@ void sysinfo_defaults(void) {
sysinfo->is64bit = sysinfo_is64bit;
sysinfo->compiler = sysinfo_compiler;
sysinfo->cflags = sysinfo_cflags;
+ sysinfo->time = sysinfo_time;
sysinfo->vcstype = sysinfo_vcstype;
sysinfo->vcstypeid = sysinfo_vcstypeid;
sysinfo->vcsrevision_src = sysinfo_vcsrevision_src;
diff --git a/src/common/sysinfo.h b/src/common/sysinfo.h
index 904be832f..2a391bfa4 100644
--- a/src/common/sysinfo.h
+++ b/src/common/sysinfo.h
@@ -52,6 +52,7 @@ struct sysinfo_interface {
bool (*is64bit) (void);
const char *(*compiler) (void);
const char *(*cflags) (void);
+ const char *(*time) (void);
const char *(*vcstype) (void);
int (*vcstypeid) (void);
const char *(*vcsrevision_src) (void);
diff --git a/src/common/thread.c b/src/common/thread.c
index 6012791e2..b724344e6 100644
--- a/src/common/thread.c
+++ b/src/common/thread.c
@@ -263,7 +263,7 @@ int rathread_get_tid(void) {
#ifdef WIN32
return (int)GetCurrentThreadId();
#else
- return (intptr_t)pthread_self();
+ return (int)pthread_self();
#endif
#endif
diff --git a/src/common/timer.c b/src/common/timer.c
index 7f71157ae..e7a57481a 100644
--- a/src/common/timer.c
+++ b/src/common/timer.c
@@ -25,6 +25,7 @@
#include "common/cbasetypes.h"
#include "common/db.h"
#include "common/memmgr.h"
+#include "common/nullpo.h"
#include "common/showmsg.h"
#include "common/utils.h"
@@ -87,6 +88,8 @@ struct timer_func_list {
int timer_add_func_list(TimerFunc func, char* name) {
struct timer_func_list* tfl;
+ nullpo_ret(func);
+ nullpo_ret(name);
if (name) {
for( tfl=tfl_root; tfl != NULL; tfl=tfl->next )
{// check suspicious cases
@@ -303,7 +306,19 @@ static int acquire_timer(void) {
int timer_add(int64 tick, TimerFunc func, int id, intptr_t data) {
int tid;
+ nullpo_retr(INVALID_TIMER, func);
+
tid = acquire_timer();
+ if (timer_data[tid].type != 0 && timer_data[tid].type != TIMER_REMOVE_HEAP)
+ {
+ ShowError("timer_add error: wrong tid type: %d, [%d]%p(%s) -> %p(%s)\n", timer_data[tid].type, tid, func, search_timer_func_list(func), timer_data[tid].func, search_timer_func_list(timer_data[tid].func));
+ Assert_retr(INVALID_TIMER, 0);
+ }
+ if (timer_data[tid].func != NULL)
+ {
+ ShowError("timer_add error: func non NULL: [%d]%p(%s) -> %p(%s)\n", tid, func, search_timer_func_list(func), timer_data[tid].func, search_timer_func_list(timer_data[tid].func));
+ Assert_retr(INVALID_TIMER, 0);
+ }
timer_data[tid].tick = tick;
timer_data[tid].func = func;
timer_data[tid].id = id;
@@ -317,9 +332,11 @@ int timer_add(int64 tick, TimerFunc func, int id, intptr_t data) {
/// Starts a new timer that automatically restarts itself (infinite loop until manually removed).
/// Returns the timer's id, or INVALID_TIMER if it fails.
-int timer_add_interval(int64 tick, TimerFunc func, int id, intptr_t data, int interval) {
+int timer_add_interval(int64 tick, TimerFunc func, int id, intptr_t data, int interval)
+{
int tid;
+ nullpo_retr(INVALID_TIMER, func);
if (interval < 1) {
ShowError("timer_add_interval: invalid interval (tick=%"PRId64" %p[%s] id=%d data=%"PRIdPTR" diff_tick=%"PRId64")\n",
tick, func, search_timer_func_list(func), id, data, DIFF_TICK(tick, timer->gettick()));
@@ -327,6 +344,18 @@ int timer_add_interval(int64 tick, TimerFunc func, int id, intptr_t data, int in
}
tid = acquire_timer();
+ if (timer_data[tid].type != 0 && timer_data[tid].type != TIMER_REMOVE_HEAP)
+ {
+ ShowError("timer_add_interval: wrong tid type: %d, [%d]%p(%s) -> %p(%s)\n", timer_data[tid].type, tid, func, search_timer_func_list(func), timer_data[tid].func, search_timer_func_list(timer_data[tid].func));
+ Assert_retr(INVALID_TIMER, 0);
+ return INVALID_TIMER;
+ }
+ if (timer_data[tid].func != NULL)
+ {
+ ShowError("timer_add_interval: func non NULL: [%d]%p(%s) -> %p(%s)\n", tid, func, search_timer_func_list(func), timer_data[tid].func, search_timer_func_list(timer_data[tid].func));
+ Assert_retr(INVALID_TIMER, 0);
+ return INVALID_TIMER;
+ }
timer_data[tid].tick = tick;
timer_data[tid].func = func;
timer_data[tid].id = id;
@@ -346,16 +375,28 @@ const struct TimerData* timer_get(int tid) {
/// Marks a timer specified by 'id' for immediate deletion once it expires.
/// Param 'func' is used for debug/verification purposes.
/// Returns 0 on success, < 0 on failure.
-int timer_do_delete(int tid, TimerFunc func) {
+int timer_do_delete(int tid, TimerFunc func)
+{
+ nullpo_ret(func);
+
if( tid < 0 || tid >= timer_data_num ) {
- ShowError("timer_do_delete error : no such timer %d (%p(%s))\n", tid, func, search_timer_func_list(func));
+ ShowError("timer_do_delete error : no such timer [%d](%p(%s))\n", tid, func, search_timer_func_list(func));
+ Assert_retr(-1, 0);
return -1;
}
if( timer_data[tid].func != func ) {
- ShowError("timer_do_delete error : function mismatch %p(%s) != %p(%s)\n", timer_data[tid].func, search_timer_func_list(timer_data[tid].func), func, search_timer_func_list(func));
+ ShowError("timer_do_delete error : function mismatch [%d]%p(%s) != %p(%s)\n", tid, timer_data[tid].func, search_timer_func_list(timer_data[tid].func), func, search_timer_func_list(func));
+ Assert_retr(-2, 0);
return -2;
}
+ if (timer_data[tid].type == 0 || timer_data[tid].type == TIMER_REMOVE_HEAP)
+ {
+ ShowError("timer_do_delete: timer already deleted: %d, [%d]%p(%s) -> %p(%s)\n", timer_data[tid].type, tid, func, search_timer_func_list(func), func, search_timer_func_list(func));
+ Assert_retr(-3, 0);
+ return -3;
+ }
+
timer_data[tid].func = NULL;
timer_data[tid].type = TIMER_ONCE_AUTODEL;
@@ -383,7 +424,19 @@ int64 timer_settick(int tid, int64 tick)
// search timer position
ARR_FIND(0, BHEAP_LENGTH(timer_heap), i, BHEAP_DATA(timer_heap)[i] == tid);
if (i == BHEAP_LENGTH(timer_heap)) {
- ShowError("timer_settick: no such timer %d (%p(%s))\n", tid, timer_data[tid].func, search_timer_func_list(timer_data[tid].func));
+ ShowError("timer_settick: no such timer [%d](%p(%s))\n", tid, timer_data[tid].func, search_timer_func_list(timer_data[tid].func));
+ Assert_retr(-1, 0);
+ return -1;
+ }
+
+ if (timer_data[tid].type == 0 || timer_data[tid].type == TIMER_REMOVE_HEAP) {
+ ShowError("timer_settick error: set tick for deleted timer %d, [%d](%p(%s))\n", timer_data[tid].type, tid, timer_data[tid].func, search_timer_func_list(timer_data[tid].func));
+ Assert_retr(-1, 0);
+ return -1;
+ }
+ if (timer_data[tid].func == NULL) {
+ ShowError("timer_settick error: set tick for timer with wrong func [%d](%p(%s))\n", tid, timer_data[tid].func, search_timer_func_list(timer_data[tid].func));
+ Assert_retr(-1, 0);
return -1;
}
@@ -438,6 +491,7 @@ int do_timer(int64 tick)
default:
case TIMER_ONCE_AUTODEL:
timer_data[tid].type = 0;
+ timer_data[tid].func = NULL;
if (free_timer_list_pos >= free_timer_list_max) {
free_timer_list_max += 256;
RECREATE(free_timer_list,int,free_timer_list_max);
diff --git a/src/common/utils.c b/src/common/utils.c
index dcf0a749a..73df3aae1 100644
--- a/src/common/utils.c
+++ b/src/common/utils.c
@@ -25,6 +25,7 @@
#include "common/cbasetypes.h"
#include "common/core.h"
#include "common/mmo.h"
+#include "common/nullpo.h"
#include "common/showmsg.h"
#include "common/socket.h"
#include "common/strlib.h"
@@ -352,6 +353,48 @@ unsigned int get_percentage(const unsigned int A, const unsigned int B)
return (unsigned int)floor(result);
}
+/**
+ * Applies a percentual rate modifier.
+ *
+ * @param value The base value.
+ * @param rate The rate modifier to apply.
+ * @param stdrate The rate modifier's divider (rate == stdrate => 100%).
+ * @return The modified value.
+ */
+int64 apply_percentrate64(int64 value, int rate, int stdrate)
+{
+ Assert_ret(stdrate > 0);
+ Assert_ret(rate >= 0);
+ if (rate == stdrate)
+ return value;
+ if (rate == 0)
+ return 0;
+ if (INT64_MAX / rate < value) {
+ // Give up some precision to prevent overflows
+ return value / stdrate * rate;
+ }
+ return value * rate / stdrate;
+}
+
+/**
+ * Applies a percentual rate modifier.
+ *
+ * @param value The base value.
+ * @param rate The rate modifier to apply. Must be <= maxrate.
+ * @param maxrate The rate modifier's divider (maxrate = 100%).
+ * @return The modified value.
+ */
+int apply_percentrate(int value, int rate, int maxrate)
+{
+ Assert_ret(maxrate > 0);
+ Assert_ret(rate >= 0);
+ if (rate == maxrate)
+ return value;
+ if (rate == 0)
+ return 0;
+ return (int)(value * (int64)rate / maxrate);
+}
+
//-----------------------------------------------------
// custom timestamp formatting (from eApp)
//-----------------------------------------------------
diff --git a/src/common/utils.h b/src/common/utils.h
index da2a29317..c5f64124f 100644
--- a/src/common/utils.h
+++ b/src/common/utils.h
@@ -24,6 +24,9 @@
#include "common/hercules.h"
#include <stdio.h> // FILE*
+#ifndef WIN32
+# include <unistd.h> // sleep()
+#endif
/* [HCache] 1-byte key to ensure our method is the latest, we can modify to ensure the method matches */
#define HCACHE_KEY 'k'
@@ -42,6 +45,9 @@ bool exists(const char* filename);
/// calculates the value of A / B, in percent (rounded down)
unsigned int get_percentage(const unsigned int A, const unsigned int B);
+int64 apply_percentrate64(int64 value, int rate, int maxrate);
+int apply_percentrate(int value, int rate, int maxrate);
+
const char* timestamp2string(char* str, size_t size, time_t timestamp, const char* format);
//////////////////////////////////////////////////////////////////////////