diff options
Diffstat (limited to 'src/map/map.c')
-rw-r--r-- | src/map/map.c | 184 |
1 files changed, 123 insertions, 61 deletions
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(); |