From 1041b3bbad62766df85393254a93602a1851895a Mon Sep 17 00:00:00 2001 From: FlavioJS Date: Tue, 25 Sep 2007 01:58:31 +0000 Subject: * Disabled tick cache (to enable it: define TICK_CACHE to the number of calls that should be cached). * Added a charid2sd database for fast charid searches. * Reworked the nick cache to only contain offline characters. Note: The tick cache was causing _some_ of the desync problems in eA. Gameplay should be much smother, but desync problems still exist. git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@11290 54d463be-8e91-2dee-dedb-b68131a5f0ec --- src/common/timer.c | 29 +++++++-- src/common/timer.h | 4 ++ src/map/chrif.c | 2 +- src/map/clif.c | 52 +++++---------- src/map/clif.h | 4 +- src/map/map.c | 184 +++++++++++++++++++++++++++++++++++------------------ src/map/map.h | 11 ++-- src/map/pc.c | 3 +- 8 files changed, 177 insertions(+), 112 deletions(-) (limited to 'src') diff --git a/src/common/timer.c b/src/common/timer.c index 15e50a05d..a24e2da8f 100644 --- a/src/common/timer.c +++ b/src/common/timer.c @@ -109,19 +109,21 @@ char* search_timer_func_list(TimerFunc func) /*---------------------------- * Get tick time *----------------------------*/ -static unsigned int gettick_cache; -static int gettick_count; +////////////////////////////////////////////////////////////////////////// +#if defined(TICK_CACHE) && TICK_CACHE > 1 +////////////////////////////////////////////////////////////////////////// +// tick is cached for TICK_CACHE calls unsigned int gettick_nocache(void) { -#ifdef _WIN32 - gettick_count = 256; +#ifdef WIN32 + gettick_count = TICK_CACHE; return gettick_cache = GetTickCount(); #else struct timeval tval; gettimeofday(&tval, NULL); - gettick_count = 256; + gettick_count = TICK_CACHE; return gettick_cache = tval.tv_sec * 1000 + tval.tv_usec / 1000; #endif @@ -134,6 +136,23 @@ unsigned int gettick(void) return gettick_cache; } +////////////////////////////// +#else +////////////////////////////// +// tick doesn't get cached +unsigned int gettick(void) +{ +#ifdef WIN32 + return GetTickCount(); +#else + struct timeval tval; + gettimeofday(&tval, NULL); + return tval.tv_sec * 1000 + tval.tv_usec / 1000; +#endif +} +////////////////////////////////////////////////////////////////////////// +#endif +////////////////////////////////////////////////////////////////////////// /*====================================== * CORE : Timer Heap diff --git a/src/common/timer.h b/src/common/timer.h index b75cc6641..cbefbe158 100644 --- a/src/common/timer.h +++ b/src/common/timer.h @@ -41,7 +41,11 @@ struct TimerData { // Function prototype declaration +#if defined(TICK_CACHE) && TICK_CACHE > 1 unsigned int gettick_nocache(void); +#else +#define gettick_nocache gettick +#endif unsigned int gettick(void); int add_timer(unsigned int,TimerFunc f,int,int); diff --git a/src/map/chrif.c b/src/map/chrif.c index b333dbeaf..1f86a6b88 100644 --- a/src/map/chrif.c +++ b/src/map/chrif.c @@ -1302,7 +1302,7 @@ int chrif_parse(int fd) case 0x2b04: chrif_recvmap(fd); break; case 0x2b06: chrif_changemapserverack(RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10), RFIFOL(fd,14), RFIFOW(fd,18), RFIFOW(fd,20), RFIFOW(fd,22), RFIFOL(fd,24), RFIFOW(fd,28)); break; case 0x2b07: clif_updatemaxid(RFIFOL(fd,2), RFIFOL(fd,6)); break; - case 0x2b09: map_addchariddb(RFIFOL(fd,2), (char*)RFIFOP(fd,6)); break; + case 0x2b09: map_addnickdb(RFIFOL(fd,2), (char*)RFIFOP(fd,6)); break; case 0x2b0b: chrif_changedgm(fd); break; case 0x2b0d: chrif_changedsex(fd); break; case 0x2b0f: chrif_char_ask_name_answer(fd); break; diff --git a/src/map/clif.c b/src/map/clif.c index e10a95d99..e9258e317 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -5160,24 +5160,13 @@ int clif_wis_end(int fd, int flag) /*========================================== * キャラID名前引き結果を送信する *------------------------------------------*/ -int clif_solved_charname(struct map_session_data *sd,int char_id) +int clif_solved_charname(int fd, int charid, const char* name) { - char *p= map_charid2nick(char_id); - int fd; - - nullpo_retr(0, sd); - - fd=sd->fd; - if(p!=NULL){ - WFIFOHEAD(fd,packet_len(0x194)); - WFIFOW(fd,0)=0x194; - WFIFOL(fd,2)=char_id; - memcpy(WFIFOP(fd,6), p, NAME_LENGTH); - WFIFOSET(fd,packet_len(0x194)); - }else{ - map_reqchariddb(sd,char_id); - chrif_searchcharid(char_id); - } + WFIFOHEAD(fd,packet_len(0x194)); + WFIFOW(fd,0)=0x194; + WFIFOL(fd,2)=charid; + safestrncpy(WFIFOP(fd,6), name, NAME_LENGTH); + WFIFOSET(fd,packet_len(0x194)); return 0; } @@ -6039,25 +6028,18 @@ int clif_movetoattack(struct map_session_data *sd,struct block_list *bl) /*========================================== * 製造エフェクト *------------------------------------------*/ -int clif_produceeffect(struct map_session_data *sd,int flag,int nameid) +int clif_produceeffect(struct map_session_data* sd,int flag,int nameid) { - int view,fd; + int fd; nullpo_retr(0, sd); - fd=sd->fd; - // 名前の登録と送信を先にしておく - if( map_charid2nick(sd->status.char_id)==NULL ) - map_addchariddb(sd->status.char_id,sd->status.name); - clif_solved_charname(sd,sd->status.char_id); - + fd = sd->fd; + clif_solved_charname(fd, sd->status.char_id, sd->status.name); WFIFOHEAD(fd,packet_len(0x18f)); WFIFOW(fd, 0)=0x18f; WFIFOW(fd, 2)=flag; - if((view = itemdb_viewid(nameid)) > 0) - WFIFOW(fd, 4)=view; - else - WFIFOW(fd, 4)=nameid; + WFIFOW(fd, 4)=(itemdb_viewid(nameid)||nameid); WFIFOSET(fd,packet_len(0x18f)); return 0; } @@ -9915,10 +9897,10 @@ void clif_parse_InsertCard(int fd,struct map_session_data *sd) *------------------------------------------*/ void clif_parse_SolveCharName(int fd, struct map_session_data *sd) { - int char_id; + int charid; - char_id = RFIFOL(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0]); - clif_solved_charname(sd, char_id); + charid = RFIFOL(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0]); + map_reqnickdb(sd, charid); } /*========================================== @@ -11263,7 +11245,7 @@ void clif_parse_PVPInfo(int fd,struct map_session_data *sd) void clif_parse_Blacksmith(int fd,struct map_session_data *sd) { int i; - char *name; + const char* name; WFIFOHEAD(fd,packet_len(0x219)); WFIFOW(fd,0) = 0x219; @@ -11306,7 +11288,7 @@ int clif_fame_blacksmith(struct map_session_data *sd, int points) void clif_parse_Alchemist(int fd,struct map_session_data *sd) { int i; - char *name; + const char* name; WFIFOHEAD(fd,packet_len(0x21a)); WFIFOW(fd,0) = 0x21a; @@ -11349,7 +11331,7 @@ int clif_fame_alchemist(struct map_session_data *sd, int points) void clif_parse_Taekwon(int fd,struct map_session_data *sd) { int i; - char *name; + const char* name; WFIFOHEAD(fd,packet_len(0x226)); WFIFOW(fd,0) = 0x226; diff --git a/src/map/clif.h b/src/map/clif.h index 0d33810b9..79f69c87d 100644 --- a/src/map/clif.h +++ b/src/map/clif.h @@ -216,7 +216,7 @@ int clif_skill_memo(struct map_session_data *sd,int flag); int clif_skill_teleportmessage(struct map_session_data *sd,int flag); int clif_skill_produce_mix_list(struct map_session_data *sd, int trigger); -int clif_produceeffect(struct map_session_data *sd,int flag,int nameid); +int clif_produceeffect(struct map_session_data* sd,int flag,int nameid); int clif_skill_setunit(struct skill_unit *unit); int clif_skill_delunit(struct skill_unit *unit); @@ -237,7 +237,7 @@ int clif_status_change(struct block_list *bl,int type,int flag); int clif_wis_message(int fd, const char* nick, const char* mes, int mes_len); int clif_wis_end(int fd,int flag); -int clif_solved_charname(struct map_session_data *sd,int char_id); +int clif_solved_charname(int fd, int charid, const char* name); int clif_charnameack(int fd, struct block_list *bl); int clif_charnameupdate(struct map_session_data *ssd); diff --git a/src/map/map.c b/src/map/map.c index 8084881ca..9fc3d9fca 100644 --- a/src/map/map.c +++ b/src/map/map.c @@ -115,10 +115,11 @@ char *SCRIPT_CONF_NAME; char *MSG_CONF_NAME; // 極力 staticでロ?カルに?める -static struct dbt * id_db=NULL; -static struct dbt * pc_db=NULL; +static struct dbt * id_db=NULL;// id -> struct block_list +static struct dbt * pc_db=NULL;// id -> struct map_session_data static struct dbt * map_db=NULL; -static struct dbt * charid_db=NULL; +static struct dbt * nick_db=NULL;// charid -> struct charid2nick (requested names of offline characters) +static struct dbt * charid_db=NULL;// charid -> struct map_session_data static int map_users=0; static struct block_list *objects[MAX_FLOORITEM]; @@ -143,9 +144,13 @@ int save_settings = 0xFFFF; int agit_flag = 0; int night_flag = 0; // 0=day, 1=night [Yor] +struct charid_request { + struct charid_request* next; + int charid;// who want to be notified of the nick +}; struct charid2nick { char nick[NAME_LENGTH]; - int req_id; + struct charid_request* requests;// requests of notification on this nick }; // This is the main header found at the very beginning of the map cache @@ -1589,45 +1594,88 @@ int map_addflooritem(struct item *item_data,int amount,int m,int x,int y,int fir static void* create_charid2nick(DBKey key, va_list args) { struct charid2nick *p; - p = (struct charid2nick *)aCallocA(1, sizeof (struct charid2nick)); + CREATE(p, struct charid2nick, 1); return p; } -/*========================================== - * charid_dbへ追加(返信待ちがあれば返信) - *------------------------------------------*/ -void map_addchariddb(int charid, char* name) +/// Adds(or replaces) the nick of charid to nick_db and fullfils pending requests. +/// Does nothing if the character is online. +void map_addnickdb(int charid, const char* nick) { struct charid2nick* p; - int req = 0; + struct charid_request* req; + struct map_session_data* sd; + + if( map_charid2sd(charid) ) + return;// already online - p = idb_ensure(charid_db, charid, create_charid2nick); - req = p->req_id; - p->req_id = 0; - //We overwrite the nick anyway in case a different one arrived. - memcpy(p->nick, name, NAME_LENGTH); + p = idb_ensure(nick_db, charid, create_charid2nick); + safestrncpy(p->nick, nick, sizeof(p->nick)); - if (req) { - struct map_session_data* sd = map_id2sd(req); - if (sd) clif_solved_charname(sd,charid); + while( p->requests ) + { + req = p->requests; + p->requests = req->next; + sd = map_charid2sd(req->charid); + if( sd ) + clif_solved_charname(sd->fd, charid, p->nick); + aFree(req); } } -/*========================================== - * charid_dbへ追加(返信要求のみ) - *------------------------------------------*/ -int map_reqchariddb(struct map_session_data * sd,int charid) +/// Removes the nick of charid from nick_db. +/// Sends name to all pending requests on charid. +void map_delnickdb(int charid, const char* name) { - struct charid2nick *p=NULL; + struct charid2nick* p; + struct charid_request* req; + struct map_session_data* sd; - nullpo_retr(0, sd); + p = idb_remove(nick_db, charid); + if( p == NULL ) + return; - p = (struct charid2nick*)idb_get(charid_db,charid); - if(p) return 0; //Nothing to request, we already have the name! - p = (struct charid2nick *)aCalloc(1,sizeof(struct charid2nick)); - p->req_id=sd->bl.id; - idb_put(charid_db,charid,p); - return 0; + while( p->requests ) + { + req = p->requests; + p->requests = req->next; + sd = map_charid2sd(req->charid); + if( sd ) + clif_solved_charname(sd->fd, charid, name); + aFree(req); + } + aFree(p); +} + +/// Notifies sd of the nick of charid. +/// Uses the name in the character if online. +/// Uses the name in nick_db if offline. +void map_reqnickdb(struct map_session_data * sd, int charid) +{ + struct charid2nick* p; + struct charid_request* req; + struct map_session_data* tsd; + + nullpo_retv(sd); + + tsd = map_charid2sd(charid); + if( tsd ) + { + clif_solved_charname(sd->fd, charid, tsd->status.name); + return; + } + + p = (struct charid2nick*)idb_ensure(nick_db, charid, create_charid2nick); + if( *p->nick ) + { + clif_solved_charname(sd->fd, charid, p->nick); + return; + } + // not in cache, request it + CREATE(req, struct charid_request, 1); + req->next = p->requests; + p->requests = req; + chrif_searchcharid(charid); } /*========================================== @@ -1638,7 +1686,11 @@ void map_addiddb(struct block_list *bl) nullpo_retv(bl); if (bl->type == BL_PC) - idb_put(pc_db,bl->id,bl); + { + TBL_PC* sd = (TBL_PC*)bl; + idb_put(pc_db,sd->bl.id,sd); + idb_put(charid_db,sd->status.char_id,sd); + } idb_put(id_db,bl->id,bl); } @@ -1650,7 +1702,11 @@ void map_deliddb(struct block_list *bl) nullpo_retv(bl); if (bl->type == BL_PC) - idb_remove(pc_db,bl->id); + { + TBL_PC* sd = (TBL_PC*)bl; + idb_remove(pc_db,sd->bl.id); + idb_remove(charid_db,sd->status.char_id); + } idb_remove(id_db,bl->id); } @@ -1668,9 +1724,7 @@ int map_quit(struct map_session_data *sd) //Double login, let original do the cleanups below. if (sd2 && sd2 != sd) return 0; - idb_remove(id_db,sd->bl.id); - idb_remove(pc_db,sd->status.account_id); - idb_remove(charid_db,sd->status.char_id); + map_deliddb(&sd->bl); return 0; } if(!sd->state.waitingdisconnect) { @@ -1693,8 +1747,6 @@ int map_quit(struct map_session_data *sd) unit_remove_map(&sd->hd->bl, 0); } - //Do we really need to remove the name? - idb_remove(charid_db,sd->status.char_id); idb_remove(id_db,sd->bl.id); if(sd->reg) @@ -1729,6 +1781,7 @@ void map_quit_ack(struct map_session_data *sd) { if (sd && sd->state.finalsave) { idb_remove(pc_db,sd->status.account_id); + idb_remove(charid_db,sd->status.char_id); aFree(sd); } } @@ -1758,33 +1811,30 @@ struct map_session_data * map_id2sd(int id) return (struct map_session_data*)idb_get(pc_db,id); } -/*========================================== - * char_id番?の名前を探す - *------------------------------------------*/ -char * map_charid2nick(int id) -{ - struct charid2nick *p = (struct charid2nick*)idb_get(charid_db,id); - - if(p==NULL) - return NULL; - return p->nick; -} - -struct map_session_data * map_charid2sd(int id) +/// Returns the nick of the target charid or NULL if unknown (requests the nick to the char server). +const char* map_charid2nick(int charid) { - int i, users; - struct map_session_data **all_sd; + struct charid2nick *p; + struct map_session_data* sd; - if (id <= 0) return 0; + sd = map_charid2sd(charid); + if( sd ) + return sd->status.name;// character is online, return it's name - all_sd = map_getallusers(&users); - for(i = 0; i < users; i++) - if (all_sd[i] && all_sd[i]->status.char_id == id) - return all_sd[i]; + p = (struct charid2nick*)idb_ensure(nick_db, charid, create_charid2nick); + if( *p->nick ) + return p->nick;// name in nick_db + chrif_searchcharid(charid);// request the name return NULL; } +/// Returns the struct map_session_data of the charid or NULL if the char is not online. +struct map_session_data* map_charid2sd(int charid) +{ + return (struct map_session_data*)idb_get(charid_db, charid); +} + /*========================================== * Search session data from a nick name * (without sensitive case if necessary) @@ -3040,10 +3090,20 @@ int map_db_final(DBKey k,void *d,va_list ap) return 0; } -int nick_db_final(void *k,void *d,va_list ap) +int nick_db_final(DBKey key, void *data, va_list args) { - char *p = (char *) d; - if (p) aFree(p); + struct charid2nick* p = (struct charid2nick*)data; + struct charid_request* req; + + if( p == NULL ) + return 0; + while( p->requests ) + { + req = p->requests; + p->requests = req->next; + aFree(req); + } + aFree(p); return 0; } @@ -3161,6 +3221,7 @@ void do_final(void) id_db->destroy(id_db, NULL); pc_db->destroy(pc_db, NULL); + nick_db->destroy(nick_db, nick_db_final); charid_db->destroy(charid_db, NULL); #ifndef TXT_ONLY @@ -3197,7 +3258,7 @@ void do_abort(void) if (!chrif_isconnected()) { if (pc_db->size(pc_db)) - ShowFatalError("Server has crashed without a connection to the char-server, character data can't be saved!\n"); + ShowFatalError("Server has crashed without a connection to the char-server, %u characters can't be saved!\n", pc_db->size(pc_db)); return; } ShowError("Server received crash signal! Attempting to save all online characters!\n"); @@ -3339,6 +3400,7 @@ int do_init(int argc, char *argv[]) id_db = db_alloc(__FILE__,__LINE__,DB_INT,DB_OPT_BASE,sizeof(int)); pc_db = db_alloc(__FILE__,__LINE__,DB_INT,DB_OPT_BASE,sizeof(int)); //Added for reliable map_id2sd() use. [Skotlex] map_db = db_alloc(__FILE__,__LINE__,DB_UINT,DB_OPT_BASE,sizeof(int)); + nick_db = db_alloc(__FILE__,__LINE__,DB_INT,DB_OPT_RELEASE_DATA,sizeof(int)); charid_db = db_alloc(__FILE__,__LINE__,DB_INT,DB_OPT_RELEASE_DATA,sizeof(int)); #ifndef TXT_ONLY map_sql_init(); diff --git a/src/map/map.h b/src/map/map.h index b91e91d51..b33f8f1d1 100644 --- a/src/map/map.h +++ b/src/map/map.h @@ -1327,11 +1327,11 @@ int map_removemobs_timer(int,unsigned int,int,int); int map_addflooritem(struct item *item_data,int amount,int m,int x,int y,int first_id,int second_id,int third_id,int flags); // キャラid=>キャラ名 変換関連 -void map_addchariddb(int charid,char *name); -void map_delchariddb(int charid); -int map_reqchariddb(struct map_session_data * sd,int charid); -char * map_charid2nick(int); -struct map_session_data * map_charid2sd(int); +void map_addnickdb(int charid, const char* nick); +void map_delnickdb(int charid, const char* nick); +void map_reqnickdb(struct map_session_data* sd,int charid); +const char* map_charid2nick(int charid); +struct map_session_data* map_charid2sd(int charid); struct map_session_data * map_id2sd(int); struct block_list * map_id2bl(int); @@ -1346,7 +1346,6 @@ void map_deliddb(struct block_list *bl); struct map_session_data** map_getallusers(int *users); void map_foreachpc(int (*func)(DBKey,void*,va_list),...); int map_foreachiddb(int (*)(DBKey,void*,va_list),...); -void map_addnickdb(struct map_session_data *); struct map_session_data * map_nick2sd(const char*); // その他 diff --git a/src/map/pc.c b/src/map/pc.c index 0423ffb78..cd071445a 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -696,8 +696,7 @@ int pc_authok(struct map_session_data *sd, int login_id2, time_t connect_until_t clif_authok(sd); map_addiddb(&sd->bl); - if (map_charid2nick(sd->status.char_id) == NULL) - map_addchariddb(sd->status.char_id, sd->status.name); + map_delnickdb(sd->status.char_id, sd->status.name); //Prevent S. Novices from getting the no-death bonus just yet. [Skotlex] sd->die_counter=-1; -- cgit v1.2.3-70-g09d2