|
@@ -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();
|