From 918b1123963ac2f91a4d074b092ceef1db71b4e8 Mon Sep 17 00:00:00 2001 From: shennetsind Date: Fri, 28 Jun 2013 18:45:38 -0300 Subject: BG Queue Testing http://hercules.ws/board/topic/1302-bg-queue-debug/ Signed-off-by: shennetsind --- src/common/socket.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/common/socket.h') diff --git a/src/common/socket.h b/src/common/socket.h index b58cbdccf..82f8b84c3 100644 --- a/src/common/socket.h +++ b/src/common/socket.h @@ -50,7 +50,7 @@ } while(0) /* [Ind/Hercules] */ -#define RFIFO2PTR(fd,len) (void*)(session[fd]->rdata + len) +#define RFIFO2PTR(fd) (void*)(session[fd]->rdata + session[fd]->rdata_pos) // buffer I/O macros #define RBUFP(p,pos) (((uint8*)(p)) + (pos)) -- cgit v1.2.3-70-g09d2 From ea5a413cdf7eec37141a7fe124cad38d66464ac4 Mon Sep 17 00:00:00 2001 From: Matheus Macabu Date: Fri, 5 Jul 2013 14:02:21 -0300 Subject: Implemented real-time server stats (in and out data and ram usage), made by Ai4rei; thanks! Another follow up, now to fix maximum value of chatdori setting; And fixed a bug where warping to a disable map would cause the map-server to crash. Signed-off-by: Matheus Macabu --- src/common/socket.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/common/socket.h | 1 + src/config/core.h | 3 +++ src/map/atcommand.c | 2 +- src/map/battle.c | 2 +- 5 files changed, 59 insertions(+), 2 deletions(-) (limited to 'src/common/socket.h') diff --git a/src/common/socket.c b/src/common/socket.c index 15b20b16f..a039006f0 100644 --- a/src/common/socket.c +++ b/src/common/socket.c @@ -221,6 +221,13 @@ int naddr_ = 0; // # of ip addresses // Larger packets cause a buffer overflow and stack corruption. static size_t socket_max_client_packet = 24576; +#ifdef SHOW_SERVER_STATS +// Data I/O statistics +static size_t socket_data_i = 0, socket_data_ci = 0, socket_data_qi = 0; +static size_t socket_data_o = 0, socket_data_co = 0, socket_data_qo = 0; +static time_t socket_data_last_tick = 0; +#endif + // initial recv buffer size (this will also be the max. size) // biggest known packet: S 0153 .w .?B -> 24x24 256 color .bmp (0153 + len.w + 1618/1654/1756 bytes) #define RFIFO_SIZE (2*1024) @@ -357,6 +364,14 @@ int recv_to_fifo(int fd) session[fd]->rdata_size += len; session[fd]->rdata_tick = last_tick; +#ifdef SHOW_SERVER_STATS + socket_data_i += len; + socket_data_qi += len; + if (!session[fd]->flag.server) + { + socket_data_ci += len; + } +#endif return 0; } @@ -376,6 +391,9 @@ int send_from_fifo(int fd) {//An exception has occured if( sErrno != S_EWOULDBLOCK ) { //ShowDebug("send_from_fifo: %s, ending connection #%d\n", error_msg(), fd); +#ifdef SHOW_SERVER_STATS + socket_data_qo -= session[fd]->wdata_size; +#endif session[fd]->wdata_size = 0; //Clear the send queue as we can't send anymore. [Skotlex] set_eof(fd); } @@ -390,6 +408,14 @@ int send_from_fifo(int fd) memmove(session[fd]->wdata, session[fd]->wdata + len, session[fd]->wdata_size - len); session[fd]->wdata_size -= len; +#ifdef SHOW_SERVER_STATS + socket_data_o += len; + socket_data_qo -= len; + if (!session[fd]->flag.server) + { + socket_data_co += len; + } +#endif } return 0; @@ -573,6 +599,10 @@ static void delete_session(int fd) { if( session_isValid(fd) ) { +#ifdef SHOW_SERVER_STATS + socket_data_qi -= session[fd]->rdata_size - session[fd]->rdata_pos; + socket_data_qo -= session[fd]->wdata_size; +#endif aFree(session[fd]->rdata); aFree(session[fd]->wdata); aFree(session[fd]->session_data); @@ -641,6 +671,9 @@ int RFIFOSKIP(int fd, size_t len) } s->rdata_pos = s->rdata_pos + len; +#ifdef SHOW_SERVER_STATS + socket_data_qi -= len; +#endif return 0; } @@ -694,6 +727,9 @@ int WFIFOSET(int fd, size_t len) } s->wdata_size += len; +#ifdef SHOW_SERVER_STATS + socket_data_qo += len; +#endif //If the interserver has 200% of its normal size full, flush the data. if( s->flag.server && s->wdata_size >= 2*FIFOSIZE_SERVERLINK ) flush_fifo(fd); @@ -820,6 +856,23 @@ int do_sockets(int next) RFIFOFLUSH(i); } +#ifdef SHOW_SERVER_STATS + if (last_tick != socket_data_last_tick) + { + char buf[1024]; + + sprintf(buf, "In: %.03f kB/s (%.03f kB/s, Q: %.03f kB) | Out: %.03f kB/s (%.03f kB/s, Q: %.03f kB) | RAM: %.03f MB", socket_data_i/1024., socket_data_ci/1024., socket_data_qi/1024., socket_data_o/1024., socket_data_co/1024., socket_data_qo/1024., iMalloc->usage()/1024.); +#ifdef _WIN32 + SetConsoleTitle(buf); +#else + ShowMessage("\033[s\033[1;1H\033[2K%s\033[u", buf); +#endif + socket_data_last_tick = last_tick; + socket_data_i = socket_data_ci = 0; + socket_data_o = socket_data_co = 0; + } +#endif + return 0; } diff --git a/src/common/socket.h b/src/common/socket.h index 82f8b84c3..0870c9d4e 100644 --- a/src/common/socket.h +++ b/src/common/socket.h @@ -6,6 +6,7 @@ #define _SOCKET_H_ #include "../common/cbasetypes.h" +#include "../config/core.h" #ifdef WIN32 #include "../common/winapi.h" diff --git a/src/config/core.h b/src/config/core.h index bec6cb507..b5ad1b794 100644 --- a/src/config/core.h +++ b/src/config/core.h @@ -61,6 +61,9 @@ /// By enabling it, the system will create an unique id for each new non stackable item created //#define NSI_UNIQUE_ID +/// Uncomment to enable real-time server stats (in and out data and ram usage). [Ai4rei] +//#define SHOW_SERVER_STATS + /** * No settings past this point **/ diff --git a/src/map/atcommand.c b/src/map/atcommand.c index 8423467c6..2aaf89107 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -407,7 +407,7 @@ ACMD(mapmove) if (mapindex) m = iMap->mapindex2mapid(mapindex); - if (!mapindex) { // m < 0 means on different server! [Kevin] + if (!mapindex || m < 0) { // m < 0 means on different server or that map is disabled! [Kevin] clif->message(fd, msg_txt(1)); // Map not found. return false; } diff --git a/src/map/battle.c b/src/map/battle.c index d03afc431..aeed4c2b0 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -6461,7 +6461,7 @@ static const struct _battle_data { { "item_enabled_npc", &battle_config.item_enabled_npc, 1, 0, 1, }, { "gm_ignore_warpable_area", &battle_config.gm_ignore_warpable_area, 0, 2, 100, }, { "packet_obfuscation", &battle_config.packet_obfuscation, 1, 0, 3, }, - { "client_accept_chatdori", &battle_config.client_accept_chatdori, 0, 0, 1, }, + { "client_accept_chatdori", &battle_config.client_accept_chatdori, 0, 0, INT_MAX, }, }; #ifndef STATS_OPT_OUT /** -- cgit v1.2.3-70-g09d2 From 713bc4da082e8b240ca6e0d9551c21c2931eece5 Mon Sep 17 00:00:00 2001 From: malufett Date: Mon, 8 Jul 2013 07:12:58 -0700 Subject: Follow up ea5a413cdf7eec37141a7fe124cad38d66464ac4 -where it breaks some skills & in game behaviors. --- src/common/socket.c | 1 + src/common/socket.h | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) (limited to 'src/common/socket.h') diff --git a/src/common/socket.c b/src/common/socket.c index ea8a2cfcc..f6d5849be 100644 --- a/src/common/socket.c +++ b/src/common/socket.c @@ -8,6 +8,7 @@ #include "../common/malloc.h" #include "../common/showmsg.h" #include "../common/strlib.h" +#include "../config/core.h" #include "socket.h" #include diff --git a/src/common/socket.h b/src/common/socket.h index 0870c9d4e..82f8b84c3 100644 --- a/src/common/socket.h +++ b/src/common/socket.h @@ -6,7 +6,6 @@ #define _SOCKET_H_ #include "../common/cbasetypes.h" -#include "../config/core.h" #ifdef WIN32 #include "../common/winapi.h" -- cgit v1.2.3-70-g09d2 From 6b9f58446c46877ecfc5fe40847636145acf5af8 Mon Sep 17 00:00:00 2001 From: shennetsind Date: Sun, 4 Aug 2013 12:19:25 -0300 Subject: HPM Update - Custom Packet Support - Custom Data Struct Support (currently append-able to map_session_data and socket_data) - Char Server Support - Login Server Support http://hercules.ws/board/topic/1934-hercules-plugin-manager-update/ Documentation will soon be updated in http://hercules.ws/wiki/HPM Signed-off-by: shennetsind --- src/char/char.c | 34 ++++++ src/common/HPM.c | 267 +++++++++++++++++++++++++++++++++++++++++++----- src/common/HPM.h | 32 +++++- src/common/HPMi.h | 29 +++++- src/common/malloc.c | 7 +- src/common/malloc.h | 11 +- src/common/socket.c | 26 ++++- src/common/socket.h | 7 +- src/login/account.h | 2 +- src/login/account_sql.c | 3 +- src/login/login.c | 49 ++++++--- src/map/HPMmap.c | 89 ++++++++++++++++ src/map/HPMmap.h | 18 ++++ src/map/Makefile.in | 4 +- src/map/chrif.c | 14 ++- src/map/clif.c | 9 ++ src/map/map.c | 5 + src/map/pc.h | 3 + src/map/pc_groups.c | 1 + src/map/unit.c | 11 ++ src/plugins/sample.c | 82 ++++++++++++++- 21 files changed, 639 insertions(+), 64 deletions(-) create mode 100644 src/map/HPMmap.c create mode 100644 src/map/HPMmap.h (limited to 'src/common/socket.h') diff --git a/src/char/char.c b/src/char/char.c index b6ea8e2f6..e6e8732db 100644 --- a/src/char/char.c +++ b/src/char/char.c @@ -14,6 +14,7 @@ #include "../common/timer.h" #include "../common/utils.h" #include "../common/console.h" +#include "../common/HPM.h" #include "int_guild.h" #include "int_homun.h" #include "int_mercenary.h" @@ -2150,6 +2151,14 @@ int parse_fromlogin(int fd) { while(RFIFOREST(fd) >= 2) { uint16 command = RFIFOW(fd,0); + + if( HPM->packetsc[hpParse_FromLogin] ) { + if( (i = HPM->parse_packets(fd,hpParse_FromLogin)) ) { + if( i == 1 ) continue; + if( i == 2 ) return 0; + } + } + switch( command ) { // acknowledgement of connect-to-loginserver request @@ -2704,6 +2713,14 @@ int parse_frommap(int fd) } while(RFIFOREST(fd) >= 2) { + + if( HPM->packetsc[hpParse_FromMap] ) { + if( (i = HPM->parse_packets(fd,hpParse_FromMap)) ) { + if( i == 1 ) continue; + if( i == 2 ) return 0; + } + } + switch(RFIFOW(fd,0)) { case 0x2b0a: @@ -3752,6 +3769,13 @@ int parse_char(int fd) //For use in packets that depend on an sd being present [Skotlex] #define FIFOSD_CHECK(rest) { if(RFIFOREST(fd) < rest) return 0; if (sd==NULL || !sd->auth) { RFIFOSKIP(fd,rest); return 0; } } + if( HPM->packetsc[hpParse_Char] ) { + if( (i = HPM->parse_packets(fd,hpParse_Char)) ) { + if( i == 1 ) continue; + if( i == 2 ) return 0; + } + } + cmd = RFIFOW(fd,0); switch( cmd ) { @@ -4874,8 +4898,11 @@ int char_config_read(const char* cfgName) void do_final(void) { int i; + ShowStatus("Terminating...\n"); + HPM->event(HPET_FINAL); + set_all_offline(-1); set_all_offline_sql(); @@ -4967,6 +4994,11 @@ int do_init(int argc, char **argv) { auth_db = idb_alloc(DB_OPT_RELEASE_DATA); online_char_db = idb_alloc(DB_OPT_RELEASE_DATA); + + HPM->share(sql_handle,"sql_handle"); + HPM->config_read(); + HPM->event(HPET_INIT); + mmo_char_sql_init(); char_read_fame_list(); //Read fame lists. @@ -5034,5 +5066,7 @@ int do_init(int argc, char **argv) { runflag = CHARSERVER_ST_RUNNING; } + HPM->event(HPET_READY); + return 0; } diff --git a/src/common/HPM.c b/src/common/HPM.c index 53059d224..3b79febd7 100644 --- a/src/common/HPM.c +++ b/src/common/HPM.c @@ -22,6 +22,9 @@ #include #endif +struct malloc_interface iMalloc_HPM; +struct malloc_interface *HPMiMalloc; + void hplugin_trigger_event(enum hp_event_types type) { unsigned int i; for( i = 0; i < HPM->plugin_count; i++ ) { @@ -189,12 +192,17 @@ void hplugin_load(const char* filename) { if( !HPM->populate(plugin,filename) ) return; - - if( SERVER_TYPE == SERVER_TYPE_MAP ) { - plugin->hpi->addCommand = HPM->import_symbol("addCommand"); - plugin->hpi->addScript = HPM->import_symbol("addScript"); - plugin->hpi->addCPCommand = HPM->import_symbol("addCPCommand"); - } + /* id */ + plugin->hpi->pid = plugin->idx; + /* core */ + plugin->hpi->addCPCommand = HPM->import_symbol("addCPCommand"); + plugin->hpi->addPacket = HPM->import_symbol("addPacket"); + plugin->hpi->addToSession = HPM->import_symbol("addToSession"); + plugin->hpi->getFromSession = HPM->import_symbol("getFromSession"); + plugin->hpi->removeFromSession = HPM->import_symbol("removeFromSession"); + /* server specific */ + if( HPM->load_sub ) + HPM->load_sub(plugin); plugin->info = info; plugin->filename = aStrdup(filename); @@ -209,7 +217,8 @@ void hplugin_unload(struct hplugin* plugin) { aFree(plugin->filename); if( plugin->dll ) plugin_close(plugin->dll); - + /* TODO: for manual packet unload */ + /* - Go thru known packets and unlink any belonging to the plugin being removed */ aFree(plugin); if( !HPM->off ) { HPM->plugins[i] = NULL; @@ -253,11 +262,191 @@ void hplugins_config_read(void) { if( HPM->plugin_count ) ShowStatus("HPM: There are '"CL_WHITE"%d"CL_RESET"' plugins loaded, type '"CL_WHITE"plugins"CL_RESET"' to list them\n", HPM->plugin_count); } +CPCMD(plugins) { + if( HPM->plugin_count == 0 ) { + ShowInfo("HPC: there are no plugins loaded\n"); + } else { + unsigned int i; + + ShowInfo("HPC: There are '"CL_WHITE"%d"CL_RESET"' plugins loaded\n",HPM->plugin_count); + + for(i = 0; i < HPM->plugin_count; i++) { + ShowInfo("HPC: - '"CL_WHITE"%s"CL_RESET"' (%s)\n",HPM->plugins[i]->info->name,HPM->plugins[i]->filename); + } + } +} + +void hplugins_addToSession(struct socket_data *sess, void *data, unsigned int id, unsigned int type, bool autofree) { + struct HPluginData *HPData; + unsigned int i; + + for(i = 0; i < sess->hdatac; i++) { + if( sess->hdata[i]->pluginID == id && sess->hdata[i]->type == type ) { + ShowError("HPM->addToSession:%s: error! attempting to insert duplicate struct of id %u and type %u\n",HPM->pid2name(id),id,type); + return; + } + } + + //HPluginData is always same size, probably better to use the ERS + CREATE(HPData, struct HPluginData, 1); + + HPData->pluginID = id; + HPData->type = type; + HPData->flag.free = autofree ? 1 : 0; + HPData->data = data; + + RECREATE(sess->hdata,struct HPluginData *,++sess->hdatac); + sess->hdata[sess->hdatac - 1] = HPData; +} +void *hplugins_getFromSession(struct socket_data *sess, unsigned int id, unsigned int type) { + unsigned int i; + + for(i = 0; i < sess->hdatac; i++) { + if( sess->hdata[i]->pluginID == id && sess->hdata[i]->type == type ) { + break; + } + } + + if( i != sess->hdatac ) + return sess->hdata[i]->data; + + return NULL; +} +void hplugins_removeFromSession(struct socket_data *sess, unsigned int id, unsigned int type) { + unsigned int i; + + for(i = 0; i < sess->hdatac; i++) { + if( sess->hdata[i]->pluginID == id && sess->hdata[i]->type == type ) { + break; + } + } + + if( i != sess->hdatac ) { + unsigned int cursor; + + aFree(sess->hdata[i]->data); + aFree(sess->hdata[i]); + sess->hdata[i] = NULL; + + for(i = 0, cursor = 0; i < sess->hdatac; i++) { + if( sess->hdata[i] == NULL ) + continue; + if( i != cursor ) + sess->hdata[cursor] = sess->hdata[i]; + cursor++; + } + sess->hdatac = cursor; + } + +} + +bool hplugins_addpacket(unsigned short cmd, short length,void (*receive) (int fd),unsigned int point,unsigned int pluginID) { + struct HPluginPacket *packet; + unsigned int i; + + if( point >= hpPHP_MAX ) { + ShowError("HPM->addPacket:%s: unknown point '%u' specified for packet 0x%04x (len %d)\n",HPM->pid2name(pluginID),point,cmd,length); + return false; + } + + for(i = 0; i < HPM->packetsc[point]; i++) { + if( HPM->packets[point][i].cmd == cmd ) { + ShowError("HPM->addPacket:%s: can't add packet 0x%04x, already in use by '%s'!",HPM->pid2name(pluginID),cmd,HPM->pid2name(HPM->packets[point][i].pluginID)); + return false; + } + } + + RECREATE(HPM->packets[point], struct HPluginPacket, ++HPM->packetsc[point]); + packet = &HPM->packets[point][HPM->packetsc[point] - 1]; + + packet->pluginID = pluginID; + packet->cmd = cmd; + packet->len = length; + packet->receive = receive; + + return true; +} +/* + 0 = unknown + 1 = OK + 2 = incomplete + */ +unsigned char hplugins_parse_packets(int fd, enum HPluginPacketHookingPoints point) { + unsigned int i; + + for(i = 0; i < HPM->packetsc[point]; i++) { + if( HPM->packets[point][i].cmd == RFIFOW(fd,0) ) + break; + } + + if( i != HPM->packetsc[point] ) { + struct HPluginPacket *packet = &HPM->packets[point][i]; + short length; + + if( (length = packet->len) == -1 ) { + if( (length = RFIFOW(fd, 2)) < (int)RFIFOREST(fd) ) + return 2; + } + + packet->receive(fd); + RFIFOSKIP(fd, length); + return 1; + } + + return 0; +} + +char *hplugins_id2name (unsigned int pid) { + unsigned int i; + + for( i = 0; i < HPM->plugin_count; i++ ) { + if( HPM->plugins[i]->idx == pid ) + return HPM->plugins[i]->info->name; + } + + return "UnknownPlugin"; +} +char* HPM_file2ptr(const char *file) { + unsigned int i; + + for(i = 0; i < HPM->fnamec; i++) { + if( HPM->fnames[i].addr == file ) + return HPM->fnames[i].name; + } + + i = HPM->fnamec; + + /* we handle this memory outside of the server's memory manager because we need it to exist after the memory manager goes down */ + HPM->fnames = realloc(HPM->fnames,(++HPM->fnamec)*sizeof(struct HPMFileNameCache)); + + HPM->fnames[i].addr = file; + HPM->fnames[i].name = strdup(file); + + return HPM->fnames[i].name; +} +void* HPM_mmalloc(size_t size, const char *file, int line, const char *func) { + return iMalloc->malloc(size,HPM_file2ptr(file),line,func); +} +void* HPM_calloc(size_t num, size_t size, const char *file, int line, const char *func) { + return iMalloc->calloc(num,size,HPM_file2ptr(file),line,func); +} +void* HPM_realloc(void *p, size_t size, const char *file, int line, const char *func) { + return iMalloc->realloc(p,size,HPM_file2ptr(file),line,func); +} +char* HPM_astrdup(const char *p, const char *file, int line, const char *func) { + return iMalloc->astrdup(p,HPM_file2ptr(file),line,func); +} + void hplugins_share_defaults(void) { /* console */ #ifdef CONSOLE_INPUT HPM->share(console->addCommand,"addCPCommand"); #endif + /* our own */ + HPM->share(hplugins_addpacket,"addPacket"); + HPM->share(hplugins_addToSession,"addToSession"); + HPM->share(hplugins_getFromSession,"getFromSession"); + HPM->share(hplugins_removeFromSession,"removeFromSession"); /* core */ HPM->share(&runflag,"runflag"); HPM->share(arg_v,"arg_v"); @@ -267,15 +456,13 @@ void hplugins_share_defaults(void) { HPM->share((void*)get_svn_revision,"get_svn_revision"); HPM->share((void*)get_git_hash,"get_git_hash"); HPM->share(DB, "DB"); - HPM->share(iMalloc, "iMalloc"); + HPM->share(HPMiMalloc, "iMalloc"); /* socket */ HPM->share(RFIFOSKIP,"RFIFOSKIP"); HPM->share(WFIFOSET,"WFIFOSET"); HPM->share(do_close,"do_close"); HPM->share(make_connection,"make_connection"); - HPM->share(session,"session"); - HPM->share(&fd_max,"fd_max"); - HPM->share(addr_,"addr"); + //session,fd_max and addr_ are shared from within socket.c /* strlib */ HPM->share(strlib,"strlib"); HPM->share(sv,"sv"); @@ -286,31 +473,34 @@ void hplugins_share_defaults(void) { HPM->share(iTimer,"iTimer"); } -CPCMD(plugins) { - if( HPM->plugin_count == 0 ) { - ShowInfo("HPC: there are no plugins loaded\n"); - } else { - unsigned int i; - - ShowInfo("HPC: There are '"CL_WHITE"%d"CL_RESET"' plugins loaded\n",HPM->plugin_count); - - for(i = 0; i < HPM->plugin_count; i++) { - ShowInfo("HPC: - '"CL_WHITE"%s"CL_RESET"' (%s)\n",HPM->plugins[i]->info->name,HPM->plugins[i]->filename); - } - } -} + void hpm_init(void) { + unsigned int i; + HPM->symbols = NULL; HPM->plugins = NULL; HPM->plugin_count = HPM->symbol_count = 0; HPM->off = false; + memcpy(&iMalloc_HPM, iMalloc, sizeof(struct malloc_interface)); + HPMiMalloc = &iMalloc_HPM; + HPMiMalloc->malloc = HPM_mmalloc; + HPMiMalloc->calloc = HPM_calloc; + HPMiMalloc->realloc = HPM_realloc; + HPMiMalloc->astrdup = HPM_astrdup; + sscanf(HPM_VERSION, "%d.%d", &HPM->version[0], &HPM->version[1]); if( HPM->version[0] == 0 && HPM->version[1] == 0 ) { ShowError("HPM:init:failed to retrieve HPM version!!\n"); return; } + + for(i = 0; i < hpPHP_MAX; i++) { + HPM->packets[i] = NULL; + HPM->packetsc[i] = 0; + } + HPM->symbol_defaults(); #ifdef CONSOLE_INPUT @@ -318,7 +508,18 @@ void hpm_init(void) { #endif return; } - +void hpm_memdown(void) { + unsigned int i; + + /* this memory is handled outside of the server's memory manager and thus cleared after memory manager goes down */ + + for( i = 0; i < HPM->fnamec; i++ ) { + free(HPM->fnames[i].name); + } + + if( HPM->fnames ) + free(HPM->fnames); +} void hpm_final(void) { unsigned int i; @@ -337,12 +538,23 @@ void hpm_final(void) { if( HPM->symbols ) aFree(HPM->symbols); - + + for( i = 0; i < hpPHP_MAX; i++ ) { + if( HPM->packets[i] ) + aFree(HPM->packets[i]); + } + + /* HPM->fnames is cleared after the memory manager goes down */ + iMalloc->post_shutdown = hpm_memdown; + return; } void hpm_defaults(void) { HPM = &HPM_s; + HPM->fnames = NULL; + HPM->fnamec = 0; + HPM->init = hpm_init; HPM->final = hpm_final; @@ -358,4 +570,7 @@ void hpm_defaults(void) { HPM->config_read = hplugins_config_read; HPM->populate = hplugin_populate; HPM->symbol_defaults_sub = NULL; + HPM->pid2name = hplugins_id2name; + HPM->parse_packets = hplugins_parse_packets; + HPM->load_sub = NULL; } diff --git a/src/common/HPM.h b/src/common/HPM.h index 10b1f0e79..d2a1308f2 100644 --- a/src/common/HPM.h +++ b/src/common/HPM.h @@ -49,6 +49,27 @@ struct hpm_symbol { void *ptr; }; +struct HPluginData { + unsigned int pluginID; + unsigned int type; + struct { + unsigned int free : 1; + } flag; + void *data; +}; + +struct HPluginPacket { + unsigned int pluginID; + unsigned short cmd; + short len; + void (*receive) (int fd); +}; + +struct HPMFileNameCache { + const char *addr; + char *name; +}; + /* Hercules Plugin Manager Interface */ struct HPM_interface { /* vars */ @@ -59,6 +80,12 @@ struct HPM_interface { unsigned int plugin_count; struct hpm_symbol **symbols; unsigned int symbol_count; + /* packet hooking points */ + struct HPluginPacket *packets[hpPHP_MAX]; + unsigned int packetsc[hpPHP_MAX]; + /* plugin file ptr caching */ + struct HPMFileNameCache *fnames; + unsigned int fnamec; /* funcs */ void (*init) (void); void (*final) (void); @@ -73,7 +100,10 @@ struct HPM_interface { void (*symbol_defaults) (void); void (*config_read) (void); bool (*populate) (struct hplugin *plugin,const char *filename); - void (*symbol_defaults_sub) (void); + 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); } HPM_s; struct HPM_interface *HPM; diff --git a/src/common/HPMi.h b/src/common/HPMi.h index 3cdb804e0..5e44b80c7 100644 --- a/src/common/HPMi.h +++ b/src/common/HPMi.h @@ -11,6 +11,8 @@ struct script_state; struct AtCommandInfo; +struct socket_data; +struct map_session_data; #ifdef WIN32 #define HPExport __declspec(dllexport) @@ -33,7 +35,7 @@ struct AtCommandInfo; /* after */ #include "../common/showmsg.h" -#define HPM_VERSION "0.1" +#define HPM_VERSION "0.2" struct hplugin_info { char* name; @@ -56,12 +58,37 @@ enum hp_event_types { HPET_MAX, }; +enum HPluginPacketHookingPoints { + hpClif_Parse, /* map-server (client-map) */ + hpChrif_Parse, /* map-server (char-map) */ + hpParse_FromMap, /* char-server (map-char) */ + hpParse_FromLogin, /* char-server (login-char) */ + hpParse_Char, /* char-server (client-char) */ + hpParse_FromChar, /* login-server (char-login) */ + hpParse_Login, /* login-server (client-login) */ + /* */ + hpPHP_MAX, +}; + /* Hercules Plugin Mananger Include Interface */ HPExport struct HPMi_interface { + /* */ + unsigned int pid; + /* */ void (*event[HPET_MAX]) (void); bool (*addCommand) (char *name, bool (*func)(const int fd, struct map_session_data* sd, const char* command, const char* message,struct AtCommandInfo *info)); bool (*addScript) (char *name, char *args, bool (*func)(struct script_state *st)); void (*addCPCommand) (char *name, CParseFunc func); + /* map_session_data */ + void (*addToMSD) (struct map_session_data *sd, void *data, unsigned int id, unsigned int type, bool autofree); + void *(*getFromMSD) (struct map_session_data *sd, unsigned int id, unsigned int type); + void (*removeFromMSD) (struct map_session_data *sd, unsigned int id, unsigned int type); + /* session[] */ + void (*addToSession) (struct socket_data *sess, void *data, unsigned int id, unsigned int type, bool autofree); + void *(*getFromSession) (struct socket_data *sess, unsigned int id, unsigned int type); + void (*removeFromSession) (struct socket_data *sess, unsigned int id, unsigned int type); + /* packet */ + bool (*addPacket) (unsigned short cmd, unsigned short length, void (*receive)(int fd), unsigned int point, unsigned int pluginID); } HPMi_s; #ifndef _HPM_H_ HPExport struct HPMi_interface *HPMi; diff --git a/src/common/malloc.c b/src/common/malloc.c index d629aa63f..4d2c93b77 100644 --- a/src/common/malloc.c +++ b/src/common/malloc.c @@ -11,6 +11,8 @@ #include #include +struct malloc_interface iMalloc_s; + ////////////// Memory Libraries ////////////////// #if defined(MEMWATCH) @@ -672,7 +674,7 @@ void memmgr_report (int extra) { if( extra != 0 ) msize = extra; - + while (block) { if (block->unit_used) { int i; @@ -784,6 +786,8 @@ void malloc_final (void) { memmgr_final (); #endif MEMORY_CHECK(); + if( iMalloc->post_shutdown ) + iMalloc->post_shutdown(); } void malloc_init (void) { @@ -825,4 +829,5 @@ void malloc_defaults(void) { iMalloc->astrdup = aStrdup_; iMalloc->free = aFree_; #endif + iMalloc->post_shutdown = NULL; } diff --git a/src/common/malloc.h b/src/common/malloc.h index 834781905..bc8aa9a20 100644 --- a/src/common/malloc.h +++ b/src/common/malloc.h @@ -67,18 +67,21 @@ void malloc_defaults(void); struct malloc_interface { + void (*init) (void); + void (*final) (void); + /* */ void* (*malloc )(size_t size, const char *file, int line, const char *func); void* (*calloc )(size_t num, size_t size, const char *file, int line, const char *func); void* (*realloc )(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); void (*free )(void *p, const char *file, int line, const char *func); - + /* */ void (*memory_check)(void); bool (*verify_ptr)(void* ptr); size_t (*usage) (void); - void (*init) (void); - void (*final) (void); -} iMalloc_s; + /* */ + void (*post_shutdown) (void); +}; void memmgr_report (int extra); diff --git a/src/common/socket.c b/src/common/socket.c index f6d5849be..4f2e386ec 100644 --- a/src/common/socket.c +++ b/src/common/socket.c @@ -9,6 +9,7 @@ #include "../common/showmsg.h" #include "../common/strlib.h" #include "../config/core.h" +#include "../common/HPM.h" #include "socket.h" #include @@ -239,8 +240,6 @@ static time_t socket_data_last_tick = 0; // The connection is closed if it goes over the limit. #define WFIFO_MAX (1*1024*1024) -struct socket_data* session[FD_SETSIZE]; - #ifdef SEND_SHORTLIST int send_shortlist_array[FD_SETSIZE];// we only support FD_SETSIZE sockets, limit the array to that int send_shortlist_count = 0;// how many fd's are in the shortlist @@ -594,13 +593,15 @@ static int create_session(int fd, RecvFunc func_recv, SendFunc func_send, ParseF session[fd]->func_parse = func_parse; session[fd]->rdata_tick = last_tick; session[fd]->session_data = NULL; + session[fd]->hdata = NULL; + session[fd]->hdatac = 0; return 0; } static void delete_session(int fd) { - if( session_isValid(fd) ) - { + if( session_isValid(fd) ) { + unsigned int i; #ifdef SHOW_SERVER_STATS socket_data_qi -= session[fd]->rdata_size - session[fd]->rdata_pos; socket_data_qo -= session[fd]->wdata_size; @@ -609,6 +610,14 @@ static void delete_session(int fd) aFree(session[fd]->wdata); if( session[fd]->session_data ) aFree(session[fd]->session_data); + for(i = 0; i < session[fd]->hdatac; i++) { + if( session[fd]->hdata[i]->flag.free ) { + aFree(session[fd]->hdata[i]->data); + aFree(session[fd]->hdata[i]); + } + } + if( session[fd]->hdata ) + aFree(session[fd]->hdata); aFree(session[fd]); session[fd] = NULL; } @@ -1214,6 +1223,8 @@ void socket_final(void) aFree(session[0]->rdata); aFree(session[0]->wdata); aFree(session[0]); + + aFree(session); } /// Closes a socket. @@ -1375,6 +1386,8 @@ void socket_init(void) memset(send_shortlist_set, 0, sizeof(send_shortlist_set)); #endif + CREATE(session, struct socket_data *, FD_SETSIZE); + socket_config_read(SOCKET_CONF_FILENAME); // initialise last send-receive tick @@ -1392,6 +1405,11 @@ void socket_init(void) #endif ShowInfo("Server supports up to '"CL_WHITE"%u"CL_RESET"' concurrent connections.\n", rlim_cur); + + /* Hercules Plugin Manager */ + HPM->share(session,"session"); + HPM->share(&fd_max,"fd_max"); + HPM->share(addr_,"addr"); } bool session_isValid(int fd) diff --git a/src/common/socket.h b/src/common/socket.h index 82f8b84c3..0e34da660 100644 --- a/src/common/socket.h +++ b/src/common/socket.h @@ -18,6 +18,8 @@ #include +struct HPluginData; + #define FIFOSIZE_SERVERLINK 256*1024 // socket I/O macros @@ -96,6 +98,9 @@ struct socket_data ParseFunc func_parse; void* session_data; // stores application-specific data related to the session + + struct HPluginData **hdata; + unsigned int hdatac; }; struct hSockOpt { @@ -105,7 +110,7 @@ struct hSockOpt { // Data prototype declaration -extern struct socket_data* session[FD_SETSIZE]; +struct socket_data **session; extern int fd_max; diff --git a/src/login/account.h b/src/login/account.h index 999c93075..f55e38b0c 100644 --- a/src/login/account.h +++ b/src/login/account.h @@ -135,6 +135,6 @@ struct AccountDB AccountDBIterator* (*iterator)(AccountDB* self); }; -void account_db_sql_up(AccountDB* self); +Sql *account_db_sql_up(AccountDB* self); #endif // __ACCOUNT_H_INCLUDED__ diff --git a/src/login/account_sql.c b/src/login/account_sql.c index 218248c82..533b3d860 100644 --- a/src/login/account_sql.c +++ b/src/login/account_sql.c @@ -687,10 +687,11 @@ static bool mmo_auth_tosql(AccountDB_SQL* db, const struct mmo_account* acc, boo return result; } -void account_db_sql_up(AccountDB* self) { +Sql* account_db_sql_up(AccountDB* self) { AccountDB_SQL* db = (AccountDB_SQL*)self; Sql_HerculesUpdateCheck(db->accounts); #ifdef CONSOLE_INPUT console->setSQL(db->accounts); #endif + return db->accounts; } diff --git a/src/login/login.c b/src/login/login.c index a17faa058..f92f0094d 100644 --- a/src/login/login.c +++ b/src/login/login.c @@ -11,6 +11,7 @@ #include "../common/socket.h" #include "../common/strlib.h" #include "../common/timer.h" +#include "../common/HPM.h" #include "account.h" #include "ipban.h" #include "login.h" @@ -372,12 +373,17 @@ int parse_fromchar(int fd) ipl = server[id].ip; ip2str(ipl, ip); - while( RFIFOREST(fd) >= 2 ) - { + while( RFIFOREST(fd) >= 2 ) { uint16 command = RFIFOW(fd,0); - switch( command ) - { + if( HPM->packetsc[hpParse_FromChar] ) { + if( (j = HPM->parse_packets(fd,hpParse_FromChar)) ) { + if( j == 1 ) continue; + if( j == 2 ) return 0; + } + } + + switch( command ) { case 0x2712: // request from char-server to authenticate an account if( RFIFOREST(fd) < 23 ) @@ -1324,12 +1330,17 @@ int parse_login(int fd) sd->fd = fd; } - while( RFIFOREST(fd) >= 2 ) - { + while( RFIFOREST(fd) >= 2 ) { uint16 command = RFIFOW(fd,0); - switch( command ) - { + if( HPM->packetsc[hpParse_Login] ) { + if( (result = HPM->parse_packets(fd,hpParse_Login)) ) { + if( result == 1 ) continue; + if( result == 2 ) return 0; + } + } + + switch( command ) { case 0x0200: // New alive packet: structure: 0x200 .24B. used to verify if client is always alive. if (RFIFOREST(fd) < 26) @@ -1688,15 +1699,17 @@ void do_final(void) int i; struct client_hash_node *hn = login_config.client_hash_nodes; - while (hn) - { + ShowStatus("Terminating...\n"); + + HPM->event(HPET_FINAL); + + while (hn) { struct client_hash_node *tmp = hn; hn = hn->next; aFree(tmp); } login_log(0, "login server", 100, "login server shutdown"); - ShowStatus("Terminating...\n"); if( login_config.log_login ) loginlog_final(); @@ -1770,7 +1783,7 @@ int do_init(int argc, char** argv) login_lan_config_read((argc > 2) ? argv[2] : LAN_CONF_NAME); rnd_init(); - + for( i = 0; i < ARRAYLENGTH(server); ++i ) chrif_server_init(i); @@ -1780,7 +1793,7 @@ int do_init(int argc, char** argv) // initialize static and dynamic ipban system ipban_init(); - + // Online user database init online_db = idb_alloc(DB_OPT_RELEASE_DATA); iTimer->add_timer_func_list(waiting_disconnect_timer, "waiting_disconnect_timer"); @@ -1814,6 +1827,10 @@ int do_init(int argc, char** argv) } } + HPM->share(account_db_sql_up(accounts),"sql_handle"); + HPM->config_read(); + HPM->event(HPET_INIT); + // server port open & binding if( (login_fd = make_listen_bind(login_config.login_ip,login_config.login_port)) == -1 ) { ShowFatalError("Failed to bind to port '"CL_WHITE"%d"CL_RESET"'\n",login_config.login_port); @@ -1824,11 +1841,11 @@ int do_init(int argc, char** argv) shutdown_callback = do_shutdown; runflag = LOGINSERVER_ST_RUNNING; } - - account_db_sql_up(accounts); ShowStatus("The login-server is "CL_GREEN"ready"CL_RESET" (Server is listening on the port %u).\n\n", login_config.login_port); login_log(0, "login server", 100, "login server started"); - + + HPM->event(HPET_READY); + return 0; } diff --git a/src/map/HPMmap.c b/src/map/HPMmap.c new file mode 100644 index 000000000..17d72bc98 --- /dev/null +++ b/src/map/HPMmap.c @@ -0,0 +1,89 @@ +// Copyright (c) Hercules Dev Team, licensed under GNU GPL. +// See the LICENSE file + +#include "../common/cbasetypes.h" +#include "../common/malloc.h" +#include "../common/showmsg.h" +#include "../common/HPM.h" + +#include "HPMmap.h" +#include "pc.h" +#include "map.h" + +#include +#include +#include +#include + + +void HPM_map_addToMSD(struct map_session_data *sd, void *data, unsigned int id, unsigned int type, bool autofree) { + struct HPluginData *HPData; + unsigned int i; + + for(i = 0; i < sd->hdatac; i++) { + if( sd->hdata[i]->pluginID == id && sd->hdata[i]->type == type ) { + ShowError("HPMi->addToMSD:%s: error! attempting to insert duplicate struct of type %u on '%s'\n",HPM->pid2name(id),type,sd->status.name); + return; + } + } + + CREATE(HPData, struct HPluginData, 1); + + HPData->pluginID = id; + HPData->type = type; + HPData->flag.free = autofree ? 1 : 0; + HPData->data = data; + + RECREATE(sd->hdata,struct HPluginData *,++sd->hdatac); + sd->hdata[sd->hdatac - 1] = HPData; +} +void *HPM_map_getFromMSD(struct map_session_data *sd, unsigned int id, unsigned int type) { + unsigned int i; + + for(i = 0; i < sd->hdatac; i++) { + if( sd->hdata[i]->pluginID == id && sd->hdata[i]->type == type ) { + break; + } + } + + if( i != sd->hdatac ) + return sd->hdata[i]->data; + + return NULL; +} +void HPM_map_removeFromMSD(struct map_session_data *sd, unsigned int id, unsigned int type) { + unsigned int i; + + for(i = 0; i < sd->hdatac; i++) { + if( sd->hdata[i]->pluginID == id && sd->hdata[i]->type == type ) { + break; + } + } + + if( i != sd->hdatac ) { + unsigned int cursor; + + aFree(sd->hdata[i]->data); + aFree(sd->hdata[i]); + sd->hdata[i] = NULL; + + for(i = 0, cursor = 0; i < sd->hdatac; i++) { + if( sd->hdata[i] == NULL ) + continue; + if( i != cursor ) + sd->hdata[cursor] = sd->hdata[i]; + cursor++; + } + + sd->hdatac = cursor; + } + +} +void HPM_map_plugin_load_sub(struct hplugin *plugin) { + plugin->hpi->addCommand = HPM->import_symbol("addCommand"); + plugin->hpi->addScript = HPM->import_symbol("addScript"); + /* */ + plugin->hpi->addToMSD = HPM->import_symbol("addToMSD"); + plugin->hpi->getFromMSD = HPM->import_symbol("getFromMSD"); + plugin->hpi->removeFromMSD = HPM->import_symbol("removeFromMSD"); +} diff --git a/src/map/HPMmap.h b/src/map/HPMmap.h new file mode 100644 index 000000000..a6cac4ace --- /dev/null +++ b/src/map/HPMmap.h @@ -0,0 +1,18 @@ +// Copyright (c) Hercules Dev Team, licensed under GNU GPL. +// See the LICENSE file + +#ifndef _HPM_MAP_ +#define _HPM_MAP_ + +#include "../common/cbasetypes.h" + +struct hplugin; +struct map_session_data; + +void HPM_map_addToMSD(struct map_session_data *sd, void *data, unsigned int id, unsigned int type, bool autofree); +void *HPM_map_getFromMSD(struct map_session_data *sd, unsigned int id, unsigned int type); +void HPM_map_removeFromMSD(struct map_session_data *sd, unsigned int id, unsigned int type); + +void HPM_map_plugin_load_sub(struct hplugin *plugin); + +#endif /* _HPM_MAP_ */ diff --git a/src/map/Makefile.in b/src/map/Makefile.in index 70c0cd900..588d19eae 100644 --- a/src/map/Makefile.in +++ b/src/map/Makefile.in @@ -17,7 +17,7 @@ MAP_OBJ = map.o chrif.o clif.o pc.o status.o npc.o \ storage.o skill.o atcommand.o battle.o battleground.o \ intif.o trade.o party.o vending.o guild.o pet.o \ log.o mail.o date.o unit.o homunculus.o mercenary.o quest.o instance.o \ - buyingstore.o searchstore.o duel.o pc_groups.o elemental.o irc-bot.o + buyingstore.o searchstore.o duel.o pc_groups.o elemental.o irc-bot.o HPMmap.o MAP_SQL_OBJ = $(MAP_OBJ:%=obj_sql/%) \ obj_sql/mapreg_sql.o MAP_H = map.h chrif.h clif.h pc.h status.h npc.h \ @@ -27,7 +27,7 @@ MAP_H = map.h chrif.h clif.h pc.h status.h npc.h \ log.h mail.h date.h unit.h homunculus.h mercenary.h quest.h instance.h mapreg.h \ buyingstore.h searchstore.h duel.h pc_groups.h \ ../config/core.h ../config/renewal.h ../config/secure.h ../config/const.h \ - ../config/classes/general.h elemental.h packets.h packets_struct.h irc-bot.h + ../config/classes/general.h elemental.h packets.h packets_struct.h irc-bot.h HPMmap.h HAVE_MYSQL=@HAVE_MYSQL@ ifeq ($(HAVE_MYSQL),yes) diff --git a/src/map/chrif.c b/src/map/chrif.c index d44ccf721..6b0397b56 100644 --- a/src/map/chrif.c +++ b/src/map/chrif.c @@ -10,6 +10,7 @@ #include "../common/showmsg.h" #include "../common/strlib.h" #include "../common/ers.h" +#include "../common/HPM.h" #include "map.h" #include "battle.h" @@ -1396,7 +1397,7 @@ void chrif_skillid2idx(int fd) { * *------------------------------------------*/ int chrif_parse(int fd) { - int packet_len, cmd; + int packet_len, cmd, r; // only process data from the char-server if ( fd != char_fd ) { @@ -1421,9 +1422,18 @@ int chrif_parse(int fd) { } while ( RFIFOREST(fd) >= 2 ) { + + if( HPM->packetsc[hpChrif_Parse] ) { + if( (r = HPM->parse_packets(fd,hpChrif_Parse)) ) { + if( r == 1 ) continue; + if( r == 2 ) return 0; + } + } + cmd = RFIFOW(fd,0); + if (cmd < 0x2af8 || cmd >= 0x2af8 + ARRAYLENGTH(packet_len_table) || packet_len_table[cmd-0x2af8] == 0) { - int r = intif->parse(fd); // Passed on to the intif + r = intif->parse(fd); // Passed on to the intif if (r == 1) continue; // Treated in intif if (r == 2) return 0; // Didn't have enough data (len==-1) diff --git a/src/map/clif.c b/src/map/clif.c index 44df5b607..7171a48be 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -14,6 +14,7 @@ #include "../common/utils.h" #include "../common/ers.h" #include "../common/conf.h" +#include "../common/HPM.h" #include "map.h" #include "chrif.h" @@ -17621,6 +17622,14 @@ int clif_parse(int fd) { if (RFIFOREST(fd) < 2) return 0; + + if( HPM->packetsc[hpClif_Parse] ) { + int r; + if( (r = HPM->parse_packets(fd,hpClif_Parse)) ) { + if( r == 1 ) continue; + if( r == 2 ) return 0; + } + } if( sd ) parse_cmd_func = sd->parse_cmd_func; diff --git a/src/map/map.c b/src/map/map.c index 713577495..5753fbc1d 100644 --- a/src/map/map.c +++ b/src/map/map.c @@ -51,6 +51,7 @@ #include "log.h" #include "mail.h" #include "irc-bot.h" +#include "HPMmap.h" #include #include @@ -5172,6 +5173,9 @@ void map_hp_symbols(void) { /* specific */ HPM->share(atcommand->create,"addCommand"); HPM->share(script->addScript,"addScript"); + HPM->share(HPM_map_addToMSD,"addToMSD"); + HPM->share(HPM_map_getFromMSD,"getFromMSD"); + HPM->share(HPM_map_removeFromMSD,"removeFromMSD"); /* vars */ HPM->share(map,"map"); } @@ -5379,6 +5383,7 @@ int do_init(int argc, char *argv[]) iTimer->add_timer_func_list(map_removemobs_timer, "map_removemobs_timer"); iTimer->add_timer_interval(iTimer->gettick()+1000, map_freeblock_timer, 0, 0, 60*1000); + HPM->load_sub = HPM_map_plugin_load_sub; HPM->symbol_defaults_sub = map_hp_symbols; HPM->config_read(); HPM->event(HPET_INIT); diff --git a/src/map/pc.h b/src/map/pc.h index 1f1538e1f..c2e834d1c 100644 --- a/src/map/pc.h +++ b/src/map/pc.h @@ -507,6 +507,9 @@ struct map_session_data { unsigned char delayed_damage;//ref. counter bugreport:7307 [Ind/Hercules] + struct HPluginData **hdata; + unsigned int hdatac; + // temporary debugging of bug #3504 const char* delunit_prevfile; int delunit_prevline; diff --git a/src/map/pc_groups.c b/src/map/pc_groups.c index 9ca0fd17a..be02b5f15 100644 --- a/src/map/pc_groups.c +++ b/src/map/pc_groups.c @@ -2,6 +2,7 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams +#include "../common/cbasetypes.h" #include "../common/conf.h" #include "../common/db.h" #include "../common/malloc.h" diff --git a/src/map/unit.c b/src/map/unit.c index 9becb128e..41d661169 100644 --- a/src/map/unit.c +++ b/src/map/unit.c @@ -8,6 +8,7 @@ #include "../common/db.h" #include "../common/malloc.h" #include "../common/random.h" +#include "../common/HPM.h" #include "map.h" #include "path.h" @@ -2330,6 +2331,7 @@ int unit_free(struct block_list *bl, clr_type clrtype) { struct map_session_data *sd = (struct map_session_data*)bl; int i; + unsigned int k; if( iStatus->isdead(bl) ) pc->setrestartvalue(sd,2); @@ -2397,6 +2399,15 @@ int unit_free(struct block_list *bl, clr_type clrtype) aFree(sd->queues); sd->queues = NULL; } + + for( k = 0; k < sd->hdatac; k++ ) { + if( sd->hdata[k]->flag.free ) { + aFree(sd->hdata[k]->data); + aFree(sd->hdata[k]); + } + } + if( sd->hdata ) + aFree(sd->hdata); break; } case BL_PET: diff --git a/src/plugins/sample.c b/src/plugins/sample.c index 7f7528cb7..4a8402560 100644 --- a/src/plugins/sample.c +++ b/src/plugins/sample.c @@ -4,9 +4,15 @@ #include #include +#include + #include "../common/HPMi.h" +#include "../common/mmo.h" +#include "../common/socket.h" +#include "../common/malloc.h" #include "../map/script.h" #include "../map/pc.h" +#include "../map/clif.h" HPExport struct hplugin_info pinfo = { "Sample", // Plugin name @@ -26,18 +32,81 @@ BUILDIN(sample) {//script command 'sample(num);' - 1 param: struct script_state* CPCMD(sample) {//console command 'sample' - 1 param: char *line ShowInfo("I'm being run! arg -> '%s'\n",line?line:"NONE"); } -struct script_interface *script;/* used by script commands */ +struct sample_data_struct { + struct point lastMSGPosition; + unsigned int someNumber; +}; +/* 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 */ +void sample_packet0f3(int fd) { + struct map_session_data *sd = session[fd]->session_data; + struct sample_data_struct *data; + + if( !sd ) return;/* socket didn't fully log-in? this packet shouldn't do anything then! */ + + ShowInfo("sample_packet0f3: Hello World! received 0xf3 for '%s', redirecting!\n",sd->status.name); + + /* sample usage of appending data to a socket_data (session[]) entry */ + if( !(data = HPMi->getFromSession(session[fd],HPMi->pid,0)) ) { + CREATE(data,struct sample_data_struct,1); + + data->lastMSGPosition.map = sd->status.last_point.map; + data->lastMSGPosition.x = sd->status.last_point.x; + data->lastMSGPosition.y = sd->status.last_point.y; + data->someNumber = rand()%777; + + ShowInfo("Created Appended session[] data, %d %d %d %d\n",data->lastMSGPosition.map,data->lastMSGPosition.x,data->lastMSGPosition.y,data->someNumber); + HPMi->addToSession(session[fd],data,HPMi->pid,0,true); + } else { + ShowInfo("Existent Appended session[] data, %d %d %d %d\n",data->lastMSGPosition.map,data->lastMSGPosition.x,data->lastMSGPosition.y,data->someNumber); + if( rand()%4 == 2 ) { + ShowInfo("Removing Appended session[] data\n"); + HPMi->removeFromSession(session[fd],HPMi->pid,0); + } + } + + /* sample usage of appending data to a map_session_data (sd) entry */ + if( !(data = HPMi->getFromMSD(sd,HPMi->pid,0)) ) { + CREATE(data,struct sample_data_struct,1); + + data->lastMSGPosition.map = sd->status.last_point.map; + data->lastMSGPosition.x = sd->status.last_point.x; + data->lastMSGPosition.y = sd->status.last_point.y; + data->someNumber = rand()%777; + + ShowInfo("Created Appended map_session_data data, %d %d %d %d\n",data->lastMSGPosition.map,data->lastMSGPosition.x,data->lastMSGPosition.y,data->someNumber); + HPMi->addToMSD(sd,data,HPMi->pid,0,true); + } else { + ShowInfo("Existent Appended map_session_data data, %d %d %d %d\n",data->lastMSGPosition.map,data->lastMSGPosition.x,data->lastMSGPosition.y,data->someNumber); + if( rand()%4 == 2 ) { + ShowInfo("Removing Appended map_session_data data\n"); + HPMi->removeFromMSD(sd,HPMi->pid,0); + } + } + + + clif->pGlobalMessage(fd,sd); +} /* run when server starts */ HPExport void plugin_init (void) { char *server_type; char *server_name; - - //get the symbols from the server + + /* core vars */ server_type = GET_SYMBOL("SERVER_TYPE"); server_name = GET_SYMBOL("SERVER_NAME"); + /* core interfaces */ + iMalloc = GET_SYMBOL("iMalloc"); + + /* map-server interfaces */ script = GET_SYMBOL("script"); - + clif = GET_SYMBOL("clif"); + + /* session[] */ + session = GET_SYMBOL("session"); + ShowInfo ("Server type is "); switch (*server_type) { @@ -59,6 +128,11 @@ HPExport void plugin_init (void) { if( HPMi->addCPCommand != NULL ) {//link our 'sample' console command HPMi->addCPCommand("this:is:a:sample",CPCMD_A(sample)); } + + if( HPMi->addPacket != NULL ) {//link our 'sample' packet to map-server + HPMi->addPacket(0xf3,-1,sample_packet0f3,hpClif_Parse,HPMi->pid); + } + } /* run when server is ready (online) */ HPExport void server_online (void) { -- cgit v1.2.3-70-g09d2 From 44c33fda3614d588e6bf6cee1cf884e98f1531f0 Mon Sep 17 00:00:00 2001 From: Haru Date: Fri, 11 Oct 2013 05:07:45 +0200 Subject: Changed 'tick' variables to 64 bit - This fixes an issue with timers that stop working after about 24-49 days when the tick overflows (note that this may happen much earlier than that, and at hard to predict times, on some systems) - Updated the RDTSC help message in the configure script to also warn users about issues with SpeedStep enabled systems. - On Windows, tick() still has a resolution of 10~15ms (or even as low as 100ms on some systems). A TODO comment (thanks, Ai4rei) was added for a follow-up patch, as I want this one to be as small as possible) - Note: on Windows versions earlier than 6.x (Vista, Server 2008), the tick overflow issue is NOT fixed, since they don't support the function used to retrieve a 64 bit tick. This isn't a big issue, since those platforms are already - or going soon to be - out of their extended support period, and it's already advisable to upgrade, for other reasons. If you're the unfortunate user of such a system, it is recommended that you reboot your machine at least once every 49 days for Hercules to work reliably. - Note: To clear some doubts, since I've already been asked, this has absolutely NOTHING to do with 32/64 bit CPUs or OSes. It's all about a variable's size, not the size of registers of your CPU, and your 32bit CPU will be able to handle this just fine. Signed-off-by: Haru --- configure | 14 ++- configure.in | 8 +- src/char/char.c | 22 ++--- src/char/int_auction.c | 11 ++- src/char/int_guild.c | 5 +- src/char/inter.c | 8 +- src/common/console.c | 2 +- src/common/console.h | 2 +- src/common/random.c | 12 +-- src/common/socket.c | 5 +- src/common/socket.h | 3 +- src/common/sql.c | 2 +- src/common/timer.c | 86 +++++++++++++----- src/common/timer.h | 21 ++--- src/login/ipban_sql.c | 5 +- src/login/login.c | 15 ++-- src/map/atcommand.c | 30 ++++--- src/map/battle.c | 18 ++-- src/map/battle.h | 8 +- src/map/battleground.c | 6 +- src/map/battleground.h | 6 +- src/map/chrif.c | 10 +-- src/map/chrif.h | 16 ++-- src/map/clif.c | 72 +++++++-------- src/map/clif.h | 28 +++--- src/map/elemental.c | 14 +-- src/map/elemental.h | 10 +-- src/map/guild.c | 6 +- src/map/guild.h | 4 +- src/map/homunculus.c | 2 +- src/map/homunculus.h | 2 +- src/map/instance.c | 2 +- src/map/instance.h | 2 +- src/map/irc-bot.c | 6 +- src/map/irc-bot.h | 8 +- src/map/map.c | 10 +-- src/map/map.h | 10 +-- src/map/mapreg.h | 2 +- src/map/mapreg_sql.c | 2 +- src/map/mercenary.c | 4 +- src/map/mercenary.h | 4 +- src/map/mob.c | 81 ++++++++--------- src/map/mob.h | 30 +++---- src/map/npc.c | 23 +++-- src/map/npc.h | 12 +-- src/map/party.c | 3 +- src/map/party.h | 2 +- src/map/pc.c | 41 +++++---- src/map/pc.h | 54 ++++++------ src/map/pet.c | 27 +++--- src/map/pet.h | 20 ++--- src/map/script.c | 12 +-- src/map/script.h | 2 +- src/map/skill.c | 231 ++++++++++++++++++++++++------------------------- src/map/skill.h | 58 ++++++------- src/map/status.c | 37 +++++--- src/map/status.h | 9 +- src/map/unit.c | 30 +++---- src/map/unit.h | 24 ++--- 59 files changed, 609 insertions(+), 590 deletions(-) (limited to 'src/common/socket.h') diff --git a/configure b/configure index abba75ea1..919d6f883 100755 --- a/configure +++ b/configure @@ -1,5 +1,5 @@ #! /bin/sh -# From configure.in d26927e. +# From configure.in c4af60e. # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.69. # @@ -1333,9 +1333,15 @@ Optional Features: in conjunction with XEN or Other Virtualization mechanisms) Note: Please ensure that you've disabled dynamic CPU-Frequencys, such as power saving - options. (On the most modern Dedicated Servers - cpufreq is preconfigured, see your distribution's - manual how to disable it) + options. (On most modern Dedicated Servers cpufreq + is preconfigured, see your distribution's manual how + to disable it). Furthermore, If your CPU has + built-in CPU-Frequency scaling features (such as + Intel's SpeedStep(R)), do not enable this option. + Recent CPUs (Intel Core or newer) guarantee a fixed + increment rate for their TSC, so it should be safe + to use, but please doublecheck the documentation of + both your CPU and OS before enabling this option. --enable-profiler=ARG Profilers: no, gprof (disabled by default) --disable-64bit Enforce 32bit output on x86_64 systems. --enable-lto Enables or Disables Linktime Code Optimization (LTO diff --git a/configure.in b/configure.in index bd80bd43f..b79e51f6d 100644 --- a/configure.in +++ b/configure.in @@ -112,8 +112,12 @@ AC_ARG_ENABLE( Note: Please ensure that you've disabled dynamic CPU-Frequencys, such as power saving options. - (On the most modern Dedicated Servers cpufreq is preconfigured, see your distribution's manual - how to disable it) + (On most modern Dedicated Servers cpufreq is preconfigured, see your distribution's + manual how to disable it). + Furthermore, If your CPU has built-in CPU-Frequency scaling features (such as Intel's + SpeedStep(R)), do not enable this option. Recent CPUs (Intel Core or newer) guarantee + a fixed increment rate for their TSC, so it should be safe to use, but please doublecheck + the documentation of both your CPU and OS before enabling this option. ] ), [ diff --git a/src/char/char.c b/src/char/char.c index 0b35c0143..2c126836c 100644 --- a/src/char/char.c +++ b/src/char/char.c @@ -179,7 +179,7 @@ static DBMap* auth_db; // int account_id -> struct auth_node* // Online User Database //----------------------------------------------------- -static int chardb_waiting_disconnect(int tid, unsigned int tick, int id, intptr_t data); +static int chardb_waiting_disconnect(int tid, int64 tick, int id, intptr_t data); int delete_char_sql(int char_id); /** @@ -2097,7 +2097,7 @@ static void char_auth_ok(int fd, struct char_session_data *sd) // continues when account data is received... } -int send_accounts_tologin(int tid, unsigned int tick, int id, intptr_t data); +int send_accounts_tologin(int tid, int64 tick, int id, intptr_t data); void mapif_server_reset(int id); @@ -2491,8 +2491,7 @@ int parse_fromlogin(int fd) { return 0; } -int check_connect_login_server(int tid, unsigned int tick, int id, intptr_t data); -int send_accounts_tologin(int tid, unsigned int tick, int id, intptr_t data); +int check_connect_login_server(int tid, int64 tick, int id, intptr_t data); void do_init_loginif(void) { @@ -4488,8 +4487,7 @@ int mapif_send(int fd, unsigned char *buf, unsigned int len) return 0; } -int broadcast_user_count(int tid, unsigned int tick, int id, intptr_t data) -{ +int broadcast_user_count(int tid, int64 tick, int id, intptr_t data) { uint8 buf[6]; int users = count_users(); @@ -4534,8 +4532,7 @@ static int send_accounts_tologin_sub(DBKey key, DBData *data, va_list ap) return 0; } -int send_accounts_tologin(int tid, unsigned int tick, int id, intptr_t data) -{ +int send_accounts_tologin(int tid, int64 tick, int id, intptr_t data) { if (login_fd > 0 && session[login_fd]) { // send account list to login server @@ -4552,8 +4549,7 @@ int send_accounts_tologin(int tid, unsigned int tick, int id, intptr_t data) return 0; } -int check_connect_login_server(int tid, unsigned int tick, int id, intptr_t data) -{ +int check_connect_login_server(int tid, int64 tick, int id, intptr_t data) { if (login_fd > 0 && session[login_fd] != NULL) return 0; @@ -4588,8 +4584,7 @@ int check_connect_login_server(int tid, unsigned int tick, int id, intptr_t data //Invoked 15 seconds after mapif_disconnectplayer in case the map server doesn't //replies/disconnect the player we tried to kick. [Skotlex] //------------------------------------------------ -static int chardb_waiting_disconnect(int tid, unsigned int tick, int id, intptr_t data) -{ +static int chardb_waiting_disconnect(int tid, int64 tick, int id, intptr_t data) { struct online_char_data* character; if ((character = (struct online_char_data*)idb_get(online_char_db, id)) != NULL && character->waiting_disconnect == tid) { //Mark it offline due to timeout. @@ -4615,8 +4610,7 @@ static int online_data_cleanup_sub(DBKey key, DBData *data, va_list ap) return 0; } -static int online_data_cleanup(int tid, unsigned int tick, int id, intptr_t data) -{ +static int online_data_cleanup(int tid, int64 tick, int id, intptr_t data) { online_char_db->foreach(online_char_db, online_data_cleanup_sub); return 0; } diff --git a/src/char/int_auction.c b/src/char/int_auction.c index 0dad9d2de..47f3421c3 100644 --- a/src/char/int_auction.c +++ b/src/char/int_auction.c @@ -22,7 +22,7 @@ static DBMap* auction_db_ = NULL; // int auction_id -> struct auction_data* void auction_delete(struct auction_data *auction); -static int auction_end_timer(int tid, unsigned int tick, int id, intptr_t data); +static int auction_end_timer(int tid, int64 tick, int id, intptr_t data); static int auction_count(int char_id, bool buy) { @@ -108,7 +108,7 @@ unsigned int auction_create(struct auction_data *auction) else { struct auction_data *auction_; - unsigned int tick = auction->hours * 3600000; + int64 tick = auction->hours * 3600000; auction->item.amount = 1; auction->item.identify = 1; @@ -139,8 +139,7 @@ static void mapif_Auction_message(int char_id, unsigned char result) mapif_sendall(buf,7); } -static int auction_end_timer(int tid, unsigned int tick, int id, intptr_t data) -{ +static int auction_end_timer(int tid, int64 tick, int id, intptr_t data) { struct auction_data *auction; if( (auction = (struct auction_data *)idb_get(auction_db_, id)) != NULL ) { @@ -182,7 +181,7 @@ void inter_auctions_fromsql(void) struct item *item; char *data; StringBuf buf; - unsigned int tick = timer->gettick(), endtick; + int64 tick = timer->gettick(), endtick; time_t now = time(NULL); StrBuf->Init(&buf); @@ -230,7 +229,7 @@ void inter_auctions_fromsql(void) } if( auction->timestamp > now ) - endtick = ((unsigned int)(auction->timestamp - now) * 1000) + tick; + endtick = ((int64)(auction->timestamp - now) * 1000) + tick; else endtick = tick + 10000; // 10 Second's to process ended auctions diff --git a/src/char/int_guild.c b/src/char/int_guild.c index fab63894e..5f033f4d7 100644 --- a/src/char/int_guild.c +++ b/src/char/int_guild.c @@ -46,8 +46,7 @@ int mapif_guild_info(int fd,struct guild *g); int guild_break_sub(int key,void *data,va_list ap); int inter_guild_tosql(struct guild *g,int flag); -static int guild_save_timer(int tid, unsigned int tick, int id, intptr_t data) -{ +static int guild_save_timer(int tid, int64 tick, int id, intptr_t data) { static int last_id = 0; //To know in which guild we were. int state = 0; //0: Have not reached last guild. 1: Reached last guild, ready for save. 2: Some guild saved, don't do further saving. DBIterator *iter = db_iterator(guild_db_); @@ -86,7 +85,7 @@ static int guild_save_timer(int tid, unsigned int tick, int id, intptr_t data) state = guild_db_->size(guild_db_); if( state < 1 ) state = 1; //Calculate the time slot for the next save. - timer->add(tick + autosave_interval/state, guild_save_timer, 0, 0); + timer->add(tick + autosave_interval/state, guild_save_timer, 0, 0); return 0; } diff --git a/src/char/inter.c b/src/char/inter.c index 2dc15933b..040246c31 100644 --- a/src/char/inter.c +++ b/src/char/inter.c @@ -61,7 +61,7 @@ int inter_recv_packet_length[] = { struct WisData { int id, fd, count, len; - unsigned long tick; + int64 tick; unsigned char src[24], dst[24], msg[512]; }; static DBMap* wis_db = NULL; // int wis_id -> struct WisData* @@ -974,9 +974,9 @@ int mapif_disconnectplayer(int fd, int account_id, int char_id, int reason) */ int check_ttl_wisdata_sub(DBKey key, DBData *data, va_list ap) { - unsigned long tick; + int64 tick; struct WisData *wd = DB->data2ptr(data); - tick = va_arg(ap, unsigned long); + tick = va_arg(ap, int64); if (DIFF_TICK(tick, wd->tick) > WISDATA_TTL && wis_delnum < WISDELLIST_MAX) wis_dellist[wis_delnum++] = wd->id; @@ -986,7 +986,7 @@ int check_ttl_wisdata_sub(DBKey key, DBData *data, va_list ap) int check_ttl_wisdata(void) { - unsigned long tick = timer->gettick(); + int64 tick = timer->gettick(); int i; do { diff --git a/src/common/console.c b/src/common/console.c index b25de84b3..cb8ed5917 100644 --- a/src/common/console.c +++ b/src/common/console.c @@ -344,7 +344,7 @@ void *cThread_main(void *x) { return NULL; } -int console_parse_timer(int tid, unsigned int tick, int id, intptr_t data) { +int console_parse_timer(int tid, int64 tick, int id, intptr_t data) { int i; EnterSpinLock(&console->ptlock); for(i = 0; i < cinput.count; i++) { diff --git a/src/common/console.h b/src/common/console.h index cef898f17..1beed964a 100644 --- a/src/common/console.h +++ b/src/common/console.h @@ -56,7 +56,7 @@ struct console_interface { /* */ void (*parse_init) (void); void (*parse_final) (void); - int (*parse_timer) (int tid, unsigned int tick, int id, intptr_t data); + int (*parse_timer) (int tid, int64 tick, int id, intptr_t data); void *(*pthread_main) (void *x); void (*parse) (char* line); void (*parse_sub) (char* line); diff --git a/src/common/random.c b/src/common/random.c index 2f1b62934..e46c52cad 100644 --- a/src/common/random.c +++ b/src/common/random.c @@ -17,17 +17,17 @@ /// Initializes the random number generator with an appropriate seed. void rnd_init(void) { - uint32 seed = timer->gettick(); - seed += (uint32)time(NULL); + unsigned long seed = (unsigned long)timer->gettick(); + seed += (unsigned long)time(NULL); #if defined(WIN32) - seed += GetCurrentProcessId(); - seed += GetCurrentThreadId(); + seed += (unsigned long)GetCurrentProcessId(); + seed += (unsigned long)GetCurrentThreadId(); #else #if defined(HAVE_GETPID) - seed += (uint32)getpid(); + seed += (unsigned long)getpid(); #endif // HAVE_GETPID #if defined(HAVE_GETTID) - seed += (uint32)gettid(); + seed += (unsigned long)gettid(); #endif // HAVE_GETTID #endif init_genrand(seed); diff --git a/src/common/socket.c b/src/common/socket.c index 7c8b3738b..c66153550 100644 --- a/src/common/socket.c +++ b/src/common/socket.c @@ -896,7 +896,7 @@ int do_sockets(int next) typedef struct _connect_history { struct _connect_history* next; uint32 ip; - uint32 tick; + int64 tick; int count; unsigned ddos : 1; } ConnectHistory; @@ -1043,8 +1043,7 @@ static int connect_check_(uint32 ip) /// Timer function. /// Deletes old connection history records. -static int connect_check_clear(int tid, unsigned int tick, int id, intptr_t data) -{ +static int connect_check_clear(int tid, int64 tick, int id, intptr_t data) { int i; int clear = 0; int list = 0; diff --git a/src/common/socket.h b/src/common/socket.h index 0e34da660..923fa2515 100644 --- a/src/common/socket.h +++ b/src/common/socket.h @@ -77,8 +77,7 @@ typedef int (*RecvFunc)(int fd); typedef int (*SendFunc)(int fd); typedef int (*ParseFunc)(int fd); -struct socket_data -{ +struct socket_data { struct { unsigned char eof : 1; unsigned char server : 1; diff --git a/src/common/sql.c b/src/common/sql.c index 9b7fe4108..dc6c4c569 100644 --- a/src/common/sql.c +++ b/src/common/sql.c @@ -180,7 +180,7 @@ int Sql_Ping(Sql* self) /// Wrapper function for Sql_Ping. /// /// @private -static int Sql_P_KeepaliveTimer(int tid, unsigned int tick, int id, intptr_t data) +static int Sql_P_KeepaliveTimer(int tid, int64 tick, int id, intptr_t data) { Sql* self = (Sql*)data; ShowInfo("Pinging SQL server to keep connection alive...\n"); diff --git a/src/common/timer.c b/src/common/timer.c index a2378a5aa..ccd91f9c7 100644 --- a/src/common/timer.c +++ b/src/common/timer.c @@ -65,8 +65,7 @@ struct timer_func_list { } *tfl_root = NULL; /// Sets the name of a timer function. -int timer_add_func_list(TimerFunc func, char* name) -{ +int timer_add_func_list(TimerFunc func, char* name) { struct timer_func_list* tfl; if (name) { @@ -139,22 +138,62 @@ static void rdtsc_calibrate(){ #endif -/// platform-abstracted tick retrieval -static unsigned int tick(void) { +/** + * platform-abstracted tick retrieval + * @return server's current tick + */ +static int64 tick(void) { #if defined(WIN32) - return GetTickCount(); + // Windows: GetTickCount/GetTickCount64: Return the number of + // milliseconds that have elapsed since the system was started. + + // TODO: GetTickCount/GetTickCount64 has a resolution of only 10~15ms. + // Ai4rei recommends that we replace it with either performance + // counters or multimedia timers if we want it to be more accurate. + // I'm leaving this for a future follow-up patch. + + // GetTickCount64 is only available in Windows Vista / Windows Server + // 2008 or newer. Since we still support older versions, this runtime + // check is required in order not to crash. + // http://msdn.microsoft.com/en-us/library/windows/desktop/ms724411%28v=vs.85%29.aspx + static bool first = true; + static ULONGLONG (WINAPI *pGetTickCount64)(void) = NULL; + + if( first ) { + HMODULE hlib = GetModuleHandle(TEXT("KERNEL32.DLL")); + if( hlib != NULL ) + pGetTickCount64 = (ULONGLONG (WINAPI *)(void))GetProcAddress(hlib, "GetTickCount64"); + first = false; + } + if (pGetTickCount64) + return (int64)pGetTickCount64(); + // 32-bit fallback. Note: This will wrap around every ~49 days since system startup!!! + return (int64)GetTickCount(); #elif defined(ENABLE_RDTSC) - // - return (unsigned int)((_rdtsc() - RDTSC_BEGINTICK) / RDTSC_CLOCK); - // + // RDTSC: Returns the number of CPU cycles since reset. Unreliable if + // the CPU frequency is variable. + return (int64)((_rdtsc() - RDTSC_BEGINTICK) / RDTSC_CLOCK); #elif defined(HAVE_MONOTONIC_CLOCK) + // Monotinic clock: Implementation-defined. + // Clock that cannot be set and represents monotonic time since some + // unspecified starting point. This clock is not affected by + // discontinâ€uous jumps in the system time (e.g., if the system + // administrator manually changes the clock), but is affected by + // the incremental adjustments performed by adjtime(3) and NTP. struct timespec tval; clock_gettime(CLOCK_MONOTONIC, &tval); - return tval.tv_sec * 1000 + tval.tv_nsec / 1000000; + // int64 cast to avoid overflows on platforms where time_t is 32 bit + return (int64)tval.tv_sec * 1000 + tval.tv_nsec / 1000000; #else + // Fallback, regular clock: Number of milliseconds since epoch. + // The time returned by gettimeofday() is affected by discontinuous + // jumps in the system time (e.g., if the system administrator + // manually changes the system time). If you need a monotonically + // increasing clock, see clock_gettime(2). struct timeval tval; gettimeofday(&tval, NULL); - return tval.tv_sec * 1000 + tval.tv_usec / 1000; + // int64 cast to avoid overflows on platforms where time_t is 32 bit + return (int64)tval.tv_sec * 1000 + tval.tv_usec / 1000; #endif } @@ -162,28 +201,28 @@ static unsigned int tick(void) { #if defined(TICK_CACHE) && TICK_CACHE > 1 ////////////////////////////////////////////////////////////////////////// // tick is cached for TICK_CACHE calls -static unsigned int gettick_cache; +static int64 gettick_cache; static int gettick_count = 1; -unsigned int timer_gettick_nocache(void) { +int64 timer_gettick_nocache(void) { gettick_count = TICK_CACHE; gettick_cache = tick(); return gettick_cache; } -unsigned int timer_gettick(void) { +int64 timer_gettick(void) { return ( --gettick_count == 0 ) ? gettick_nocache() : gettick_cache; } ////////////////////////////// #else ////////////////////////////// // tick doesn't get cached -unsigned int timer_gettick_nocache(void) +int64 timer_gettick_nocache(void) { return tick(); } -unsigned int timer_gettick(void) { +int64 timer_gettick(void) { return tick(); } ////////////////////////////////////////////////////////////////////////// @@ -237,7 +276,7 @@ static int acquire_timer(void) { /// Starts a new timer that is deleted once it expires (single-use). /// Returns the timer's id. -int timer_add(unsigned int tick, TimerFunc func, int id, intptr_t data) { +int timer_add(int64 tick, TimerFunc func, int id, intptr_t data) { int tid; tid = acquire_timer(); @@ -254,12 +293,11 @@ int timer_add(unsigned int 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(unsigned int 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; if( interval < 1 ) { - ShowError("timer_add_interval: invalid interval (tick=%u %p[%s] id=%d data=%d diff_tick=%d)\n", tick, func, search_timer_func_list(func), id, data, DIFF_TICK(tick, timer->gettick())); + ShowError("timer_add_interval: invalid interval (tick=%"PRId64" %p[%s] id=%d data=%d diff_tick=%"PRId64")\n", tick, func, search_timer_func_list(func), id, data, DIFF_TICK(tick, timer->gettick())); return INVALID_TIMER; } @@ -301,13 +339,13 @@ int timer_do_delete(int tid, TimerFunc func) { /// Adjusts a timer's expiration time. /// Returns the new tick value, or -1 if it fails. -int timer_addtick(int tid, unsigned int tick) { +int64 timer_addtick(int tid, int64 tick) { return timer->settick(tid, timer_data[tid].tick+tick); } /// Modifies a timer's expiration time (an alternative to deleting a timer and starting a new one). /// Returns the new tick value, or -1 if it fails. -int timer_settick(int tid, unsigned int tick) { +int64 timer_settick(int tid, int64 tick) { size_t i; // search timer position @@ -332,8 +370,8 @@ int timer_settick(int tid, unsigned int tick) { /// Executes all expired timers. /// Returns the value of the smallest non-expired timer (or 1 second if there aren't any). -int do_timer(unsigned int tick) { - int diff = TIMER_MAX_INTERVAL; // return value +int do_timer(int64 tick) { + int64 diff = TIMER_MAX_INTERVAL; // return value // process all timers one by one while( BHEAP_LENGTH(timer_heap) ) { @@ -381,7 +419,7 @@ int do_timer(unsigned int tick) { } } - return cap_value(diff, TIMER_MIN_INTERVAL, TIMER_MAX_INTERVAL); + return (int)cap_value(diff, TIMER_MIN_INTERVAL, TIMER_MAX_INTERVAL); } unsigned long timer_get_uptime(void) { diff --git a/src/common/timer.h b/src/common/timer.h index 600f9fd02..4a2bebe7d 100644 --- a/src/common/timer.h +++ b/src/common/timer.h @@ -5,7 +5,8 @@ #define _TIMER_H_ #include "../common/cbasetypes.h" -#define DIFF_TICK(a,b) ((int)((a)-(b))) +#define DIFF_TICK(a,b) ((a)-(b)) +#define DIFF_TICK32(a,b) ((int32)((a)-(b))) #define INVALID_TIMER -1 @@ -18,10 +19,10 @@ enum { // Struct declaration -typedef int (*TimerFunc)(int tid, unsigned int tick, int id, intptr_t data); +typedef int (*TimerFunc)(int tid, int64 tick, int id, intptr_t data); struct TimerData { - unsigned int tick; + int64 tick; TimerFunc func; unsigned char type; int interval; @@ -40,22 +41,22 @@ struct TimerData { struct timer_interface { /* funcs */ - unsigned int (*gettick) (void); - unsigned int (*gettick_nocache) (void); + int64 (*gettick) (void); + int64 (*gettick_nocache) (void); - int (*add) (unsigned int tick, TimerFunc func, int id, intptr_t data); - int (*add_interval) (unsigned int tick, TimerFunc func, int id, intptr_t data, int interval); + int (*add) (int64 tick, TimerFunc func, int id, intptr_t data); + int (*add_interval) (int64 tick, TimerFunc func, int id, intptr_t data, int interval); const struct TimerData *(*get) (int tid); int (*delete) (int tid, TimerFunc func); - int (*addtick) (int tid, unsigned int tick); - int (*settick) (int tid, unsigned int tick); + int64 (*addtick) (int tid, int64 tick); + int64 (*settick) (int tid, int64 tick); int (*add_func_list) (TimerFunc func, char* name); unsigned long (*get_uptime) (void); - int (*do_timer) (unsigned int tick); + int (*do_timer) (int64 tick); void (*init) (void); void (*final) (void); }; diff --git a/src/login/ipban_sql.c b/src/login/ipban_sql.c index 9b074b368..74f45e418 100644 --- a/src/login/ipban_sql.c +++ b/src/login/ipban_sql.c @@ -36,7 +36,7 @@ static Sql* sql_handle = NULL; static int cleanup_timer_id = INVALID_TIMER; static bool ipban_inited = false; -int ipban_cleanup(int tid, unsigned int tick, int id, intptr_t data); +int ipban_cleanup(int tid, int64 tick, int id, intptr_t data); // initialize @@ -247,8 +247,7 @@ void ipban_log(uint32 ip) } // remove expired bans -int ipban_cleanup(int tid, unsigned int tick, int id, intptr_t data) -{ +int ipban_cleanup(int tid, int64 tick, int id, intptr_t data) { if( !login_config.ipban ) return 0;// ipban disabled diff --git a/src/login/login.c b/src/login/login.c index 7de5dbb76..f47f1519c 100644 --- a/src/login/login.c +++ b/src/login/login.c @@ -81,7 +81,7 @@ struct online_login_data { }; static DBMap* online_db; // int account_id -> struct online_login_data* -static int waiting_disconnect_timer(int tid, unsigned int tick, int id, intptr_t data); +static int waiting_disconnect_timer(int tid, int64 tick, int id, intptr_t data); /** * @see DBCreateData @@ -121,8 +121,7 @@ void remove_online_user(int account_id) idb_remove(online_db, account_id); } -static int waiting_disconnect_timer(int tid, unsigned int tick, int id, intptr_t data) -{ +static int waiting_disconnect_timer(int tid, int64 tick, int id, intptr_t data) { struct online_login_data* p = (struct online_login_data*)idb_get(online_db, id); if( p != NULL && p->waiting_disconnect == tid && p->account_id == id ) { @@ -165,8 +164,7 @@ static int online_data_cleanup_sub(DBKey key, DBData *data, va_list ap) return 0; } -static int online_data_cleanup(int tid, unsigned int tick, int id, intptr_t data) -{ +static int online_data_cleanup(int tid, int64 tick, int id, intptr_t data) { online_db->foreach(online_db, online_data_cleanup_sub); return 0; } @@ -234,8 +232,7 @@ void chrif_on_disconnect(int id) //----------------------------------------------------- // periodic ip address synchronization //----------------------------------------------------- -static int sync_ip_addresses(int tid, unsigned int tick, int id, intptr_t data) -{ +static int sync_ip_addresses(int tid, int64 tick, int id, intptr_t data) { uint8 buf[2]; ShowInfo("IP Sync in progress...\n"); WBUFW(buf,0) = 0x2735; @@ -901,8 +898,8 @@ int parse_fromchar(int fd) //------------------------------------- int mmo_auth_new(const char* userid, const char* pass, const char sex, const char* last_ip) { static int num_regs = 0; // registration counter - static unsigned int new_reg_tick = 0; - unsigned int tick = timer->gettick(); + static int64 new_reg_tick = 0; + int64 tick = timer->gettick(); struct mmo_account acc; //Account Registration Flood Protection by [Kevin] diff --git a/src/map/atcommand.c b/src/map/atcommand.c index c815967c2..7ec589956 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -4260,7 +4260,8 @@ ACMD(servertime) { } else if (battle_config.night_duration == 0) { if (map->night_flag == 1) { // we start with night timer_data = timer->get(pc->day_timer_tid); - sprintf(temp, msg_txt(233), txt_time(DIFF_TICK(timer_data->tick,timer->gettick())/1000)); // Game time: The game is actualy in night for %s. + sprintf(temp, msg_txt(233), // Game time: The game is actually in night for %s. + txt_time((unsigned int)(DIFF_TICK(timer_data->tick,timer->gettick())/1000))); clif->message(fd, temp); clif->message(fd, msg_txt(234)); // Game time: After, the game will be in permanent daylight. } else @@ -4268,7 +4269,8 @@ ACMD(servertime) { } else if (battle_config.day_duration == 0) { if (map->night_flag == 0) { // we start with day timer_data = timer->get(pc->night_timer_tid); - sprintf(temp, msg_txt(235), txt_time(DIFF_TICK(timer_data->tick,timer->gettick())/1000)); // Game time: The game is actualy in daylight for %s. + sprintf(temp, msg_txt(235), // Game time: The game is actualy in daylight for %s. + txt_time((unsigned int)(DIFF_TICK(timer_data->tick,timer->gettick())/1000))); clif->message(fd, temp); clif->message(fd, msg_txt(236)); // Game time: After, the game will be in permanent night. } else @@ -4277,22 +4279,28 @@ ACMD(servertime) { if (map->night_flag == 0) { timer_data = timer->get(pc->night_timer_tid); timer_data2 = timer->get(pc->day_timer_tid); - sprintf(temp, msg_txt(235), txt_time(DIFF_TICK(timer_data->tick,timer->gettick())/1000)); // Game time: The game is actualy in daylight for %s. + sprintf(temp, msg_txt(235), // Game time: The game is actualy in daylight for %s. + txt_time((unsigned int)(DIFF_TICK(timer_data->tick,timer->gettick())/1000))); clif->message(fd, temp); if (DIFF_TICK(timer_data->tick, timer_data2->tick) > 0) - sprintf(temp, msg_txt(237), txt_time(DIFF_TICK(timer_data->interval,DIFF_TICK(timer_data->tick,timer_data2->tick)) / 1000)); // Game time: After, the game will be in night for %s. + sprintf(temp, msg_txt(237), // Game time: After, the game will be in night for %s. + txt_time((unsigned int)(DIFF_TICK(timer_data->interval,DIFF_TICK(timer_data->tick,timer_data2->tick)) / 1000))); else - sprintf(temp, msg_txt(237), txt_time(DIFF_TICK(timer_data2->tick,timer_data->tick)/1000)); // Game time: After, the game will be in night for %s. + sprintf(temp, msg_txt(237), // Game time: After, the game will be in night for %s. + txt_time((unsigned int)(DIFF_TICK(timer_data2->tick,timer_data->tick)/1000))); clif->message(fd, temp); } else { timer_data = timer->get(pc->day_timer_tid); timer_data2 = timer->get(pc->night_timer_tid); - sprintf(temp, msg_txt(233), txt_time(DIFF_TICK(timer_data->tick,timer->gettick()) / 1000)); // Game time: The game is actualy in night for %s. + sprintf(temp, msg_txt(233), // Game time: The game is actualy in night for %s. + txt_time((unsigned int)(DIFF_TICK(timer_data->tick,timer->gettick()) / 1000))); clif->message(fd, temp); if (DIFF_TICK(timer_data->tick,timer_data2->tick) > 0) - sprintf(temp, msg_txt(239), txt_time((timer_data->interval - DIFF_TICK(timer_data->tick, timer_data2->tick)) / 1000)); // Game time: After, the game will be in daylight for %s. + sprintf(temp, msg_txt(239), // Game time: After, the game will be in daylight for %s. + txt_time((unsigned int)((timer_data->interval - DIFF_TICK(timer_data->tick, timer_data2->tick)) / 1000))); else - sprintf(temp, msg_txt(239), txt_time(DIFF_TICK(timer_data2->tick, timer_data->tick) / 1000)); // Game time: After, the game will be in daylight for %s. + sprintf(temp, msg_txt(239), // Game time: After, the game will be in daylight for %s. + txt_time((unsigned int)(DIFF_TICK(timer_data2->tick, timer_data->tick) / 1000))); clif->message(fd, temp); } sprintf(temp, msg_txt(238), txt_time(timer_data->interval / 1000)); // Game time: A day cycle has a normal duration of %s. @@ -5250,7 +5258,7 @@ ACMD(useskill) { *------------------------------------------*/ ACMD(displayskill) { struct status_data *st; - unsigned int tick; + int64 tick; uint16 skill_id; uint16 skill_lv = 1; @@ -6086,8 +6094,8 @@ ACMD(summon) int mob_id = 0; int duration = 0; struct mob_data *md; - unsigned int tick=timer->gettick(); - + int64 tick=timer->gettick(); + if (!message || !*message || sscanf(message, "%23s %d", name, &duration) < 1) { clif->message(fd, msg_txt(1225)); // Please enter a monster name (usage: @summon {duration}). diff --git a/src/map/battle.c b/src/map/battle.c index 050f3f26e..94222f663 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -196,7 +196,7 @@ struct block_list* battle_getenemyarea(struct block_list *src, int x, int y, int return bl_list[rnd()%c]; } -int battle_delay_damage_sub(int tid, unsigned int tick, int id, intptr_t data) { +int battle_delay_damage_sub(int tid, int64 tick, int id, intptr_t data) { struct delay_damage *dat = (struct delay_damage *)data; if ( dat ) { @@ -244,7 +244,7 @@ int battle_delay_damage_sub(int tid, unsigned int tick, int id, intptr_t data) { return 0; } -int battle_delay_damage (unsigned int tick, int amotion, struct block_list *src, struct block_list *target, int attack_type, uint16 skill_id, uint16 skill_lv, int64 damage, enum damage_lv dmg_lv, int ddelay, bool additional_effects) { +int battle_delay_damage(int64 tick, int amotion, struct block_list *src, struct block_list *target, int attack_type, uint16 skill_id, uint16 skill_lv, int64 damage, enum damage_lv dmg_lv, int ddelay, bool additional_effects) { struct delay_damage *dat; struct status_change *sc; nullpo_ret(src); @@ -349,7 +349,7 @@ int64 battle_attr_fix(struct block_list *src, struct block_list *target, int64 d y = sg->val3 & 0xffff; skill->unitsetting(src,su->group->skill_id,su->group->skill_lv,x,y,1); sg->val3 = -1; - sg->limit = DIFF_TICK(timer->gettick(),sg->tick)+300; + sg->limit = DIFF_TICK32(timer->gettick(),sg->tick)+300; } } } @@ -5269,14 +5269,14 @@ void battle_drain(TBL_PC *sd, struct block_list *tbl, int64 rdamage, int64 ldama status_zap(tbl, rhp, rsp); } // Deals the same damage to targets in area. [pakpil] -int battle_damage_area( struct block_list *bl, va_list ap) { - unsigned int tick; +int battle_damage_area(struct block_list *bl, va_list ap) { + int64 tick; int amotion, dmotion, damage; struct block_list *src; nullpo_ret(bl); - tick=va_arg(ap, unsigned int); + tick = va_arg(ap, int64); src=va_arg(ap,struct block_list *); amotion=va_arg(ap,int); dmotion=va_arg(ap,int); @@ -5302,7 +5302,7 @@ int battle_damage_area( struct block_list *bl, va_list ap) { /*========================================== * Do a basic physical attack (call trough unit_attack_timer) *------------------------------------------*/ -enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* target, unsigned int tick, int flag) { +enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* target, int64 tick, int flag) { struct map_session_data *sd = NULL, *tsd = NULL; struct status_data *sstatus, *tstatus; struct status_change *sc, *tsc; @@ -6617,7 +6617,7 @@ void Hercules_report(char* date, char *time_c) { #undef BFLAG_LENGTH } -static int Hercules_report_timer(int tid, unsigned int tick, int id, intptr_t data) { +static int Hercules_report_timer(int tid, int64 tick, int id, intptr_t data) { if( chrif->isconnected() ) {/* char server relays it, so it must be online. */ Hercules_report(__DATE__,__TIME__); } @@ -6761,7 +6761,7 @@ int battle_config_read(const char* cfgName) void do_init_battle(void) { battle->delay_damage_ers = ers_new(sizeof(struct delay_damage),"battle.c::delay_damage_ers",ERS_OPT_CLEAR); - timer->add_func_list(battle_delay_damage_sub, "battle_delay_damage_sub"); + timer->add_func_list(battle->delay_damage_sub, "battle_delay_damage_sub"); #ifndef STATS_OPT_OUT timer->add_func_list(Hercules_report_timer, "Hercules_report_timer"); diff --git a/src/map/battle.h b/src/map/battle.h index a2212a647..bf08ab8d6 100644 --- a/src/map/battle.h +++ b/src/map/battle.h @@ -518,11 +518,11 @@ struct battle_interface { /* battlegrounds final damage calculation */ int64 (*calc_bg_damage) (struct block_list *src, struct block_list *bl, int64 damage, int div_, uint16 skill_id, uint16 skill_lv, int flag); /* normal weapon attack */ - enum damage_lv (*weapon_attack) (struct block_list *bl, struct block_list *target, unsigned int tick, int flag); + enum damage_lv (*weapon_attack) (struct block_list *bl, struct block_list *target, int64 tick, int flag); /* calculate weapon attack */ struct Damage (*calc_weapon_attack) (struct block_list *src,struct block_list *target,uint16 skill_id,uint16 skill_lv,int wflag); /* delays damage or skills by a timer */ - int (*delay_damage) (unsigned int tick, int amotion, struct block_list *src, struct block_list *target, int attack_type, uint16 skill_id, uint16 skill_lv, int64 damage, enum damage_lv dmg_lv, int ddelay, bool additional_effects); + int (*delay_damage) (int64 tick, int amotion, struct block_list *src, struct block_list *target, int attack_type, uint16 skill_id, uint16 skill_lv, int64 damage, enum damage_lv dmg_lv, int ddelay, bool additional_effects); /* drain damage */ void (*drain) (struct map_session_data *sd, struct block_list *tbl, int64 rdamage, int64 ldamage, int race, int boss); /* damage return/reflect */ @@ -566,7 +566,7 @@ struct battle_interface { int (*get_targeted_sub) (struct block_list *bl, va_list ap); int (*get_enemy_sub) (struct block_list *bl, va_list ap); int (*get_enemy_area_sub) (struct block_list *bl, va_list ap); - int (*delay_damage_sub) (int tid, unsigned int tick, int id, intptr_t data); + int (*delay_damage_sub) (int tid, int64 tick, int id, intptr_t data); int (*blewcount_bonus) (struct map_session_data *sd, uint16 skill_id); /* skill range criteria */ int (*range_type) (struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv); @@ -587,7 +587,7 @@ struct battle_interface { /* picks a random enemy within the specified range */ struct block_list* (*get_enemy_area) (struct block_list *src, int x, int y, int range, int type, int ignore_id); /* damages area, originally for royal guard's reflect damage */ - int (*damage_area) ( struct block_list *bl, va_list ap); + int (*damage_area) (struct block_list *bl, va_list ap); }; struct battle_interface *battle; diff --git a/src/map/battleground.c b/src/map/battleground.c index e7fe4085b..62688659e 100644 --- a/src/map/battleground.c +++ b/src/map/battleground.c @@ -249,7 +249,7 @@ int bg_send_xy_timer_sub(DBKey key, DBData *data, va_list ap) { return 0; } -int bg_send_xy_timer(int tid, unsigned int tick, int id, intptr_t data) { +int bg_send_xy_timer(int tid, int64 tick, int id, intptr_t data) { bg->team_db->foreach(bg->team_db, bg->send_xy_timer_sub, tick); return 0; } @@ -534,7 +534,7 @@ void bg_begin(struct bg_arena *arena) { /* currently running only on solo mode so we do it evenly */ } } -int bg_begin_timer(int tid, unsigned int tick, int id, intptr_t data) { +int bg_begin_timer(int tid, int64 tick, int id, intptr_t data) { bg->begin(bg->arena[id]); bg->arena[id]->begin_timer = INVALID_TIMER; return 0; @@ -553,7 +553,7 @@ void bg_queue_pregame(struct bg_arena *arena) { } arena->begin_timer = timer->add( timer->gettick() + (arena->pregame_duration*1000), bg->begin_timer, arena->id, 0 ); } -int bg_fillup_timer(int tid, unsigned int tick, int id, intptr_t data) { +int bg_fillup_timer(int tid, int64 tick, int id, intptr_t data) { bg->queue_pregame(bg->arena[id]); bg->arena[id]->fillup_timer = INVALID_TIMER; return 0; diff --git a/src/map/battleground.h b/src/map/battleground.h index 1c224e1c2..a5e540924 100644 --- a/src/map/battleground.h +++ b/src/map/battleground.h @@ -84,9 +84,9 @@ struct battleground_interface { int (*id2pos) (int queue_id, int account_id); void (*queue_pc_cleanup) (struct map_session_data *sd); void (*begin) (struct bg_arena *arena); - int (*begin_timer) (int tid, unsigned int tick, int id, intptr_t data); + int (*begin_timer) (int tid, int64 tick, int id, intptr_t data); void (*queue_pregame) (struct bg_arena *arena); - int (*fillup_timer) (int tid, unsigned int tick, int id, intptr_t data); + int (*fillup_timer) (int tid, int64 tick, int id, intptr_t data); void (*queue_ready_ack) (struct bg_arena *arena, struct map_session_data *sd, bool response); void (*match_over) (struct bg_arena *arena, bool canceled); void (*queue_check) (struct bg_arena *arena); @@ -102,7 +102,7 @@ struct battleground_interface { int (*team_get_id) (struct block_list *bl); int (*send_message) (struct map_session_data *sd, const char *mes, int len); int (*send_xy_timer_sub) (DBKey key, DBData *data, va_list ap); - int (*send_xy_timer) (int tid, unsigned int tick, int id, intptr_t data); + int (*send_xy_timer) (int tid, int64 tick, int id, intptr_t data); /* */ void (*config_read) (void); }; diff --git a/src/map/chrif.c b/src/map/chrif.c index 5308eada9..4efc5bce4 100644 --- a/src/map/chrif.c +++ b/src/map/chrif.c @@ -682,7 +682,7 @@ int auth_db_cleanup_sub(DBKey key, DBData *data, va_list ap) { return 0; } -int auth_db_cleanup(int tid, unsigned int tick, int id, intptr_t data) { +int auth_db_cleanup(int tid, int64 tick, int id, intptr_t data) { chrif_check(0); chrif->auth_db->foreach(chrif->auth_db, chrif->auth_db_cleanup_sub); return 0; @@ -1139,7 +1139,7 @@ int chrif_save_scdata(struct map_session_data *sd) { //parses the sc_data of the #ifdef ENABLE_SC_SAVING int i, count=0; - unsigned int tick; + int64 tick; struct status_change_data data; struct status_change *sc = &sd->sc; const struct TimerData *td; @@ -1159,7 +1159,7 @@ int chrif_save_scdata(struct map_session_data *sd) { //parses the sc_data of the td = timer->get(sc->data[i]->timer); if (td == NULL || td->func != status->change_timer || DIFF_TICK(td->tick,tick) < 0) continue; - data.tick = DIFF_TICK(td->tick,tick); //Duration that is left before ending. + data.tick = DIFF_TICK32(td->tick,tick); //Duration that is left before ending. } else data.tick = -1; //Infinite duration data.type = i; @@ -1462,7 +1462,7 @@ int chrif_parse(int fd) { return 0; } -int send_usercount_tochar(int tid, unsigned int tick, int id, intptr_t data) { +int send_usercount_tochar(int tid, int64 tick, int id, intptr_t data) { chrif_check(-1); WFIFOHEAD(chrif->fd,4); @@ -1509,7 +1509,7 @@ int send_users_tochar(void) { * timerFunction * Chk the connection to char server, (if it down) *------------------------------------------*/ -int check_connect_char_server(int tid, unsigned int tick, int id, intptr_t data) { +int check_connect_char_server(int tid, int64 tick, int id, intptr_t data) { static int displayed = 0; if ( chrif->fd <= 0 || session[chrif->fd] == NULL ) { if ( !displayed ) { diff --git a/src/map/chrif.h b/src/map/chrif.h index 0617a6702..9df4b9931 100644 --- a/src/map/chrif.h +++ b/src/map/chrif.h @@ -30,11 +30,11 @@ enum sd_state { ST_LOGIN, ST_LOGOUT, ST_MAPCHANGE }; struct auth_node { int account_id, char_id; int login_id1, login_id2, sex, fd; - time_t expiration_time; // # of seconds 1/1/1970 (timestamp): Validity limit of the account (0 = unlimited) - struct map_session_data *sd; //Data from logged on char. - struct mmo_charstatus *char_dat; //Data from char server. - unsigned int node_created; //timestamp for node timeouts - enum sd_state state; //To track whether player was login in/out or changing maps. + time_t expiration_time; // # of seconds 1/1/1970 (timestamp): Validity limit of the account (0 = unlimited) + struct map_session_data *sd; //Data from logged on char. + struct mmo_charstatus *char_dat; //Data from char server. + int64 node_created; //timestamp for node timeouts + enum sd_state state; //To track whether player was login in/out or changing maps. }; /*===================================== @@ -109,15 +109,15 @@ struct chrif_interface { void (*skillid2idx) (int fd); bool (*sd_to_auth) (TBL_PC* sd, enum sd_state state); - int (*check_connect_char_server) (int tid, unsigned int tick, int id, intptr_t data); + int (*check_connect_char_server) (int tid, int64 tick, int id, intptr_t data); bool (*auth_logout) (TBL_PC* sd, enum sd_state state); void (*save_ack) (int fd); int (*reconnect) (DBKey key, DBData *data, va_list ap); int (*auth_db_cleanup_sub) (DBKey key, DBData *data, va_list ap); void (*char_ask_name_answer) (int acc, const char* player_name, uint16 type, uint16 answer); int (*auth_db_final) (DBKey key, DBData *data, va_list ap); - int (*send_usercount_tochar) (int tid, unsigned int tick, int id, intptr_t data); - int (*auth_db_cleanup) (int tid, unsigned int tick, int id, intptr_t data); + int (*send_usercount_tochar) (int tid, int64 tick, int id, intptr_t data); + int (*auth_db_cleanup) (int tid, int64 tick, int id, intptr_t data); int (*connect) (int fd); int (*connectack) (int fd); diff --git a/src/map/clif.c b/src/map/clif.c index decdfc2ce..9810e2a17 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -595,7 +595,7 @@ void clif_authok(struct map_session_data *sd) struct packet_authok p; p.PacketType = authokType; - p.startTime = timer->gettick(); + p.startTime = (unsigned int)timer->gettick(); WBUFPOS(&p.PosDir[0],0,sd->bl.x,sd->bl.y,sd->ud.dir); /* do the stupid client math */ p.xSize = p.ySize = 5; /* not-used */ @@ -787,14 +787,13 @@ void clif_clearunit_area(struct block_list* bl, clr_type type) /// Used to make monsters with player-sprites disappear after dying /// like normal monsters, because the client does not remove those /// automatically. -int clif_clearunit_delayed_sub(int tid, unsigned int tick, int id, intptr_t data) { +int clif_clearunit_delayed_sub(int tid, int64 tick, int id, intptr_t data) { struct block_list *bl = (struct block_list *)data; clif->clearunit_area(bl, (clr_type) id); ers_free(clif->delay_clearunit_ers,bl); return 0; } -void clif_clearunit_delayed(struct block_list* bl, clr_type type, unsigned int tick) -{ +void clif_clearunit_delayed(struct block_list* bl, clr_type type, int64 tick) { struct block_list *tbl = ers_alloc(clif->delay_clearunit_ers, struct block_list); memcpy (tbl, bl, sizeof (struct block_list)); timer->add(tick, clif->clearunit_delayed_sub, (int)type, (intptr_t)tbl); @@ -1156,7 +1155,7 @@ void clif_set_unit_walking(struct block_list* bl, struct map_session_data *tsd, p.head = vd->hair_style; p.weapon = vd->weapon; p.accessory = vd->head_bottom; - p.moveStartTime = timer->gettick(); + p.moveStartTime = (unsigned int)timer->gettick(); #if PACKETVER < 7 p.shield = vd->shield; #endif @@ -1526,7 +1525,7 @@ void clif_walkok(struct map_session_data *sd) WFIFOHEAD(fd, packet_len(0x87)); WFIFOW(fd,0)=0x87; - WFIFOL(fd,2)=timer->gettick(); + WFIFOL(fd,2)=(unsigned int)timer->gettick(); WFIFOPOS2(fd,6,sd->bl.x,sd->bl.y,sd->ud.to_x,sd->ud.to_y,8,8); WFIFOSET(fd,packet_len(0x87)); } @@ -1597,7 +1596,7 @@ void clif_move(struct unit_data *ud) WBUFW(buf,0)=0x86; WBUFL(buf,2)=bl->id; WBUFPOS2(buf,6,bl->x,bl->y,ud->to_x,ud->to_y,8,8); - WBUFL(buf,12)=timer->gettick(); + WBUFL(buf,12)=(unsigned int)timer->gettick(); clif->send(buf, packet_len(0x86), bl, AREA_WOS); if (disguised(bl)) { WBUFL(buf,2)=-bl->id; @@ -1609,7 +1608,7 @@ void clif_move(struct unit_data *ud) /*========================================== * Delays the map->quit of a player after they are disconnected. [Skotlex] *------------------------------------------*/ -int clif_delayquit(int tid, unsigned int tick, int id, intptr_t data) { +int clif_delayquit(int tid, int64 tick, int id, intptr_t data) { struct map_session_data *sd = NULL; //Remove player from map server @@ -4430,8 +4429,7 @@ int clif_calc_walkdelay(struct block_list *bl,int delay, int type, int damage, i /// 10 = critical hit /// 11 = lucky dodge /// 12 = (touch skill?) -int clif_damage(struct block_list* src, struct block_list* dst, unsigned int tick, int sdelay, int ddelay, int64 in_damage, int div, int type, int64 in_damage2) -{ +int clif_damage(struct block_list* src, struct block_list* dst, int64 tick, int sdelay, int ddelay, int64 in_damage, int div, int type, int64 in_damage2) { unsigned char buf[33]; struct status_change *sc; int damage,damage2; @@ -4459,7 +4457,7 @@ int clif_damage(struct block_list* src, struct block_list* dst, unsigned int tic WBUFW(buf,0)=cmd; WBUFL(buf,2)=src->id; WBUFL(buf,6)=dst->id; - WBUFL(buf,10)=tick; + WBUFL(buf,10)=(uint32)tick; WBUFL(buf,14)=sdelay; WBUFL(buf,18)=ddelay; #if PACKETVER < 20071113 @@ -4516,7 +4514,7 @@ int clif_damage(struct block_list* src, struct block_list* dst, unsigned int tic *------------------------------------------*/ void clif_takeitem(struct block_list* src, struct block_list* dst) { - //clif_damage(src,dst,0,0,0,0,0,1,0); + //clif->damage(src,dst,0,0,0,0,0,1,0); unsigned char buf[32]; nullpo_retv(src); @@ -5097,7 +5095,7 @@ void clif_skill_fail(struct map_session_data *sd,uint16 skill_id,enum useskill_f /// Skill cooldown display icon (ZC_SKILL_POSTDELAY). /// 043d .W .L -void clif_skill_cooldown(struct map_session_data *sd, uint16 skill_id, unsigned int tick) +void clif_skill_cooldown(struct map_session_data *sd, uint16 skill_id, unsigned int duration) { #if PACKETVER>=20081112 int fd; @@ -5108,7 +5106,7 @@ void clif_skill_cooldown(struct map_session_data *sd, uint16 skill_id, unsigned WFIFOHEAD(fd,packet_len(0x43d)); WFIFOW(fd,0) = 0x43d; WFIFOW(fd,2) = skill_id; - WFIFOL(fd,4) = tick; + WFIFOL(fd,4) = duration; WFIFOSET(fd,packet_len(0x43d)); #endif } @@ -5117,7 +5115,7 @@ void clif_skill_cooldown(struct map_session_data *sd, uint16 skill_id, unsigned /// Skill attack effect and damage. /// 0114 .W .L .L .L .L .L .W .W
.W .B (ZC_NOTIFY_SKILL) /// 01de .W .L .L .L .L .L .L .W
.W .B (ZC_NOTIFY_SKILL2) -int clif_skill_damage(struct block_list *src,struct block_list *dst,unsigned int tick,int sdelay,int ddelay,int64 in_damage,int div,uint16 skill_id,uint16 skill_lv,int type) { +int clif_skill_damage(struct block_list *src, struct block_list *dst, int64 tick, int sdelay, int ddelay, int64 in_damage, int div, uint16 skill_id, uint16 skill_lv, int type) { unsigned char buf[64]; struct status_change *sc; int damage; @@ -5138,7 +5136,7 @@ int clif_skill_damage(struct block_list *src,struct block_list *dst,unsigned int WBUFW(buf,2)=skill_id; WBUFL(buf,4)=src->id; WBUFL(buf,8)=dst->id; - WBUFL(buf,12)=tick; + WBUFL(buf,12)=(uint32)tick; WBUFL(buf,16)=sdelay; WBUFL(buf,20)=ddelay; if (battle_config.hide_woe_damage && map_flag_gvg2(src->m)) { @@ -5169,7 +5167,7 @@ int clif_skill_damage(struct block_list *src,struct block_list *dst,unsigned int WBUFW(buf,2)=skill_id; WBUFL(buf,4)=src->id; WBUFL(buf,8)=dst->id; - WBUFL(buf,12)=tick; + WBUFL(buf,12)=(uint32)tick; WBUFL(buf,16)=sdelay; WBUFL(buf,20)=ddelay; if (battle_config.hide_woe_damage && map_flag_gvg2(src->m)) { @@ -5205,7 +5203,7 @@ int clif_skill_damage(struct block_list *src,struct block_list *dst,unsigned int /// Ground skill attack effect and damage (ZC_NOTIFY_SKILL_POSITION). /// 0115 .W .L .L .L .L .L .W .W .W .W
.W .B #if 0 -int clif_skill_damage2(struct block_list *src,struct block_list *dst,unsigned int tick,int sdelay,int ddelay,int damage,int div,uint16 skill_id,uint16 skill_lv,int type) { +int clif_skill_damage2(struct block_list *src, struct block_list *dst, int64 tick, int sdelay, int ddelay, int damage, int div, uint16 skill_id, uint16 skill_lv, int type) { unsigned char buf[64]; struct status_change *sc; @@ -5225,7 +5223,7 @@ int clif_skill_damage2(struct block_list *src,struct block_list *dst,unsigned in WBUFW(buf,2)=skill_id; WBUFL(buf,4)=src->id; WBUFL(buf,8)=dst->id; - WBUFL(buf,12)=tick; + WBUFL(buf,12)=(uint32)tick; WBUFL(buf,16)=sdelay; WBUFL(buf,20)=ddelay; WBUFW(buf,24)=dst->x; @@ -5295,8 +5293,7 @@ int clif_skill_nodamage(struct block_list *src,struct block_list *dst,uint16 ski /// Non-damaging ground skill effect (ZC_NOTIFY_GROUNDSKILL). /// 0117 .W .L .W .W .W .L -void clif_skill_poseffect(struct block_list *src,uint16 skill_id,int val,int x,int y,int tick) -{ +void clif_skill_poseffect(struct block_list *src, uint16 skill_id, int val, int x, int y, int64 tick) { unsigned char buf[32]; nullpo_retv(src); @@ -5307,7 +5304,7 @@ void clif_skill_poseffect(struct block_list *src,uint16 skill_id,int val,int x,i WBUFW(buf,8)=val; WBUFW(buf,10)=x; WBUFW(buf,12)=y; - WBUFL(buf,14)=tick; + WBUFL(buf,14)=(uint32)tick; if(disguised(src)) { clif->send(buf,packet_len(0x117),src,AREA_WOS); WBUFL(buf,4)=-src->id; @@ -9431,7 +9428,7 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) { clif->spawn(&sd->pd->bl); clif->send_petdata(sd,sd->pd,0,0); clif->send_petstatus(sd); -// skill->unit_move(&sd->pd->bl,gettick(),1); +// skill->unit_move(&sd->pd->bl,timer->gettick(),1); } } @@ -9649,12 +9646,12 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) { /// Server's tick (ZC_NOTIFY_TIME). /// 007f