浏览代码

- Made waiting_disconnect on the char server be an int to hold the timer ID of the timeout timer. It is now deleted when a player is successfully set offline/online.
- Corrected @unjail having the GM level check backwards.
- chrif_authok will now reject to store the newly received status data when the player it was received from is still online, should prevent losing data in certain situations.


git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@10060 54d463be-8e91-2dee-dedb-b68131a5f0ec

skotlex 18 年之前
父节点
当前提交
50af14ce15
共有 4 个文件被更改,包括 55 次插入26 次删除
  1. 21 12
      src/char/char.c
  2. 22 13
      src/char_sql/char.c
  3. 1 1
      src/map/atcommand.c
  4. 11 0
      src/map/chrif.c

+ 21 - 12
src/char/char.c

@@ -157,8 +157,8 @@ struct online_char_data {
 	int account_id;
 	int char_id;
 	int fd;
+	int waiting_disconnect;
 	short server;
-	unsigned waiting_disconnect :1;
 };
 
 struct dbt *online_char_db; //Holds all online characters.
@@ -290,6 +290,7 @@ static void * create_online_char_data(DBKey key, va_list args) {
 	character->char_id = -1;
   	character->server = -1;
 	character->fd = -1;
+	character->waiting_disconnect = -1;
 	return character;
 }
 
@@ -321,7 +322,10 @@ void set_char_online(int map_id, int char_id, int account_id) {
 				character->account_id, character->char_id, character->server, map_id, account_id, char_id);
 		mapif_disconnectplayer(server_fd[character->server], character->account_id, character->char_id, 2);
 	}
-	character->waiting_disconnect = 0;
+	if(character->waiting_disconnect != -1){
+		delete_timer(character->waiting_disconnect, chardb_waiting_disconnect);
+		character->waiting_disconnect = -1;
+	}
 	character->char_id = (char_id==99)?-1:char_id;
 	character->server = (char_id==99)?-1:map_id;
 
@@ -341,7 +345,10 @@ void set_char_offline(int char_id, int account_id) {
 	{	//We don't free yet to avoid aCalloc/aFree spamming during char change. [Skotlex]
 		character->char_id = -1;
 		character->server = -1;
-		character->waiting_disconnect = 0;
+		if(character->waiting_disconnect != -1){
+			delete_timer(character->waiting_disconnect, chardb_waiting_disconnect);
+			character->waiting_disconnect = -1;
+		}
 	}
 	if (login_fd <= 0 || session[login_fd]->eof)
 		return;
@@ -358,7 +365,10 @@ static int char_db_setoffline(DBKey key, void* data, va_list ap) {
 	if (server == -1) {
 		character->char_id = -1;
 		character->server = -1;
-		character->waiting_disconnect = 0;	
+		if(character->waiting_disconnect != -1){
+			delete_timer(character->waiting_disconnect, chardb_waiting_disconnect);
+			character->waiting_disconnect = -1;
+		}
 	} else if (character->server == server)
 		character->server = -2; //In some map server that we aren't connected to.
 	return 0;
@@ -375,7 +385,7 @@ static int char_db_kickoffline(DBKey key, void* data, va_list ap) {
 	if (character->server > -1)
 		mapif_disconnectplayer(server_fd[character->server],
 			character->account_id, character->char_id, 1);
-	else if (!character->waiting_disconnect)
+	else if (character->waiting_disconnect == -1)
 		set_char_offline(character->char_id, character->account_id);
 	else return 0;
 	return 1;
@@ -1945,9 +1955,8 @@ static void char_auth_ok(int fd, struct char_session_data *sd)
 		{	//Character already online. KICK KICK KICK
 			mapif_disconnectplayer(server_fd[character->server],
 				character->account_id, character->char_id, 2);
-			if (!character->waiting_disconnect)
-				add_timer(gettick()+20000, chardb_waiting_disconnect, character->account_id, 0);
-			character->waiting_disconnect = 1;
+			if (character->waiting_disconnect == -1)
+				character->waiting_disconnect = add_timer(gettick()+20000, chardb_waiting_disconnect, character->account_id, 0);
 			WFIFOW(fd,0) = 0x81;
 			WFIFOB(fd,2) = 8;
 			WFIFOSET(fd,3);
@@ -2438,9 +2447,8 @@ int parse_tologin(int fd) {
 					if (character->server > -1)
 					{	//Kick it from the map server it is on.
 						mapif_disconnectplayer(server_fd[character->server], character->account_id, character->char_id, 2);
-						if (!character->waiting_disconnect)
-							add_timer(gettick()+15000, chardb_waiting_disconnect, character->account_id, 0);
-						character->waiting_disconnect = 1;
+						if (character->waiting_disconnect == -1)
+							character->waiting_disconnect = add_timer(gettick()+15000, chardb_waiting_disconnect, character->account_id, 0);
 					} else { //Manual kick from char server.
 						struct char_session_data *tsd;
 						int i;
@@ -3984,8 +3992,9 @@ int check_connect_login_server(int tid, unsigned int tick, int id, int data) {
 static int chardb_waiting_disconnect(int tid, unsigned int tick, int id, int data)
 {
 	struct online_char_data* character;
-	if ((character = idb_get(online_char_db, id)) != NULL && character->waiting_disconnect)
+	if ((character = idb_get(online_char_db, id)) != NULL && character->waiting_disconnect == tid)
 	{	//Mark it offline due to timeout.
+		character->waiting_disconnect = -1;
 		set_char_offline(character->char_id, character->account_id);
 	}
 	return 0;

+ 22 - 13
src/char_sql/char.c

@@ -179,8 +179,8 @@ struct online_char_data {
 	int account_id;
 	int char_id;
 	int fd;
+	int waiting_disconnect;
 	short server;
-	unsigned waiting_disconnect :1;
 };
 
 struct dbt *online_char_db; //Holds all online characters.
@@ -204,6 +204,7 @@ static void * create_online_char_data(DBKey key, va_list args) {
 	character->char_id = -1;
   	character->server = -1;
 	character->fd = -1;
+	character->waiting_disconnect = -1;
 	return character;
 }
 
@@ -223,7 +224,7 @@ void set_char_online(int map_id, int char_id, int account_id) {
 		if (max_account_id < account_id || max_char_id < char_id)
 		{	//Notify map-server of the new max IDs [Skotlex]
 			if (account_id > max_account_id)
-				max_account_id = account_id;
+				 max_account_id = account_id;
 			if (char_id > max_char_id)
 				max_char_id = char_id;
 			mapif_send_maxid(max_account_id, max_char_id);
@@ -243,7 +244,10 @@ void set_char_online(int map_id, int char_id, int account_id) {
 	}
 	character->char_id = (char_id==99)?-1:char_id;
 	character->server = (char_id==99)?-1:map_id;
-	character->waiting_disconnect = 0;
+	if(character->waiting_disconnect != -1){
+		delete_timer(character->waiting_disconnect, chardb_waiting_disconnect);
+		character->waiting_disconnect = -1;
+	}
 	if (char_id != 99)
 	{	//Set char online in guild cache. If char is in memory, use the guild id on it, otherwise seek it.
 		struct mmo_charstatus *cp;
@@ -284,7 +288,10 @@ void set_char_offline(int char_id, int account_id) {
 	{	//We don't free yet to avoid aCalloc/aFree spamming during char change. [Skotlex]
 		character->char_id = -1;
 		character->server = -1;
-		character->waiting_disconnect = 0;
+		if(character->waiting_disconnect != -1){
+			delete_timer(character->waiting_disconnect, chardb_waiting_disconnect);
+			character->waiting_disconnect = -1;
+		}
 	}
 	
    if (login_fd > 0 && !session[login_fd]->eof)
@@ -302,7 +309,10 @@ static int char_db_setoffline(DBKey key, void* data, va_list ap) {
 	if (server == -1) {
 		character->char_id = -1;
 		character->server = -1;
-		character->waiting_disconnect = 0;	
+		if(character->waiting_disconnect != -1){
+			delete_timer(character->waiting_disconnect, chardb_waiting_disconnect);
+			character->waiting_disconnect = -1;
+		}
 	} else if (character->server == server)
 		character->server = -2; //In some map server that we aren't connected to.
 	return 0;
@@ -318,7 +328,7 @@ static int char_db_kickoffline(DBKey key, void* data, va_list ap) {
 	if (character->server > -1)
 		mapif_disconnectplayer(server_fd[character->server],
 			character->account_id, character->char_id, 1);
-	else if (!character->waiting_disconnect)
+	else if (character->waiting_disconnect == -1)
 		set_char_offline(character->char_id, character->account_id);
 	else return 0;
 	return 1;
@@ -1805,9 +1815,8 @@ static void char_auth_ok(int fd, struct char_session_data *sd)
 		{	//Character already online. KICK KICK KICK
 			mapif_disconnectplayer(server_fd[character->server],
 				character->account_id, character->char_id, 2);
-			if (!character->waiting_disconnect)
-				add_timer(gettick()+20000, chardb_waiting_disconnect, character->account_id, 0);
-			character->waiting_disconnect = 1;
+			if (character->waiting_disconnect == -1)
+				character->waiting_disconnect = add_timer(gettick()+20000, chardb_waiting_disconnect, character->account_id, 0);
 			WFIFOW(fd,0) = 0x81;
 			WFIFOB(fd,2) = 8;
 			WFIFOSET(fd,3);
@@ -2204,9 +2213,8 @@ int parse_tologin(int fd) {
 					if (character->server > -1)
 					{	//Kick it from the map server it is on.
 						mapif_disconnectplayer(server_fd[character->server], character->account_id, character->char_id, 2);
-						if (!character->waiting_disconnect)
-							add_timer(gettick()+15000, chardb_waiting_disconnect, character->account_id, 0);
-						character->waiting_disconnect = 1;
+						if (character->waiting_disconnect == -1)
+							character->waiting_disconnect = add_timer(gettick()+15000, chardb_waiting_disconnect, character->account_id, 0);
 					} else { //Manual kick from char server.
 						struct char_session_data *tsd;
 						int i;
@@ -3783,8 +3791,9 @@ int check_connect_login_server(int tid, unsigned int tick, int id, int data) {
 static int chardb_waiting_disconnect(int tid, unsigned int tick, int id, int data)
 {
 	struct online_char_data* character;
-	if ((character = idb_get(online_char_db, id)) != NULL && character->waiting_disconnect)
+	if ((character = idb_get(online_char_db, id)) != NULL && character->waiting_disconnect == tid)
 	{	//Mark it offline due to timeout.
+		character->waiting_disconnect = -1;
 		set_char_offline(character->char_id, character->account_id);
 	}
 	return 0;

+ 1 - 1
src/map/atcommand.c

@@ -6440,7 +6440,7 @@ int atcommand_charjailtime(const int fd, struct map_session_data* sd, const char
 		clif_displaymessage(fd, msg_txt(3)); // Character not found.
 		return -1;
 	}
-	if (pc_isGM(pl_sd) < pc_isGM(sd)) {
+	if (pc_isGM(pl_sd) >= pc_isGM(sd)) {
 		clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorize you to do this action on this player.
 		return -1;
 	}

+ 11 - 0
src/map/chrif.c

@@ -496,7 +496,18 @@ void chrif_authreq(struct map_session_data *sd)
 //character selected, insert into auth db
 void chrif_authok(int fd) {
 	struct auth_node *auth_data;
+	TBL_PC* sd;
 	RFIFOHEAD(fd);
+	//Check if we don't already have player data in our server
+	//(prevents data that is to be saved from being overwritten by
+	//this received status data if this auth is later successful) [Skotlex]
+	if ((sd = map_id2sd(RFIFOL(fd, 4))) != NULL)
+	{
+		struct mmo_charstatus *status = (struct mmo_charstatus *)RFIFOP(fd, 20);
+		//Auth check is because this could be the very same sd that is waiting char-server authorization.
+		if (sd->state.auth && sd->status.char_id == status->char_id)
+			return;
+	}
 	
 	if ((auth_data =uidb_get(auth_db, RFIFOL(fd, 4))) != NULL)
 	{	//Is the character already awaiting authorization?