summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlavioJS <FlavioJS@54d463be-8e91-2dee-dedb-b68131a5f0ec>2007-09-25 01:58:31 +0000
committerFlavioJS <FlavioJS@54d463be-8e91-2dee-dedb-b68131a5f0ec>2007-09-25 01:58:31 +0000
commit1041b3bbad62766df85393254a93602a1851895a (patch)
tree0c3e433ec1b0c8b2bed7371ef9c65aa5c112755b
parent02ff54ba1d0b87b29f19c29524ba77a2f30a6d85 (diff)
downloadhercules-1041b3bbad62766df85393254a93602a1851895a.tar.gz
hercules-1041b3bbad62766df85393254a93602a1851895a.tar.bz2
hercules-1041b3bbad62766df85393254a93602a1851895a.tar.xz
hercules-1041b3bbad62766df85393254a93602a1851895a.zip
* 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
-rw-r--r--Changelog-Trunk.txt5
-rw-r--r--src/common/timer.c29
-rw-r--r--src/common/timer.h4
-rw-r--r--src/map/chrif.c2
-rw-r--r--src/map/clif.c52
-rw-r--r--src/map/clif.h4
-rw-r--r--src/map/map.c184
-rw-r--r--src/map/map.h11
-rw-r--r--src/map/pc.c3
9 files changed, 182 insertions, 112 deletions
diff --git a/Changelog-Trunk.txt b/Changelog-Trunk.txt
index 93ab05b42..713e12601 100644
--- a/Changelog-Trunk.txt
+++ b/Changelog-Trunk.txt
@@ -3,6 +3,11 @@ Date Added
AS OF SVN REV. 5091, WE ARE NOW USING TRUNK. ALL UNTESTED BUGFIXES/FEATURES GO INTO TRUNK.
IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.
+2007/09/25
+ * 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. [FlavioJS]
2007/09/24
* Ignore %MDef bonuses now only reduce target's base MDEF, not MDEF2.
* Updated the 'skills that cause no damage are blocked now if the skill
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;