Browse Source

Improved friend removal process to avoid inconsistent state if char-server was offline, fixed wrong packet size check (follow-up to r15119).

git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@15397 54d463be-8e91-2dee-dedb-b68131a5f0ec
gepard1984 13 years ago
parent
commit
2415501270
2 changed files with 19 additions and 12 deletions
  1. 1 1
      src/char_sql/char.c
  2. 18 11
      src/map/clif.c

+ 1 - 1
src/char_sql/char.c

@@ -2789,7 +2789,7 @@ int parse_frommap(int fd)
 		break;
 
 		case 0x2b07: // Remove RFIFOL(fd,6) (friend_id) from RFIFOL(fd,2) (char_id) friend list [Ind]
-			if (RFIFOREST(fd) < 6)
+			if (RFIFOREST(fd) < 10)
 				return 0;
 			{
 				int char_id, friend_id;

+ 18 - 11
src/map/clif.c

@@ -12387,21 +12387,14 @@ void clif_parse_FriendsListRemove(int fd, struct map_session_data *sd)
 		clif_displaymessage(fd, "Name not found in list.");
 		return;
 	}
-		
-	// move all chars down
-	for(j = i + 1; j < MAX_FRIENDS; j++)
-		memcpy(&sd->status.friends[j-1], &sd->status.friends[j], sizeof(sd->status.friends[0]));
 
-	memset(&sd->status.friends[MAX_FRIENDS-1], 0, sizeof(sd->status.friends[MAX_FRIENDS-1]));
-	clif_displaymessage(fd, "Friend removed");
-	
-	//remove from friends list
-	if( (f_sd = map_id2sd(account_id)) ) {
+	//remove from friend's list first
+	if( (f_sd = map_id2sd(account_id)) && f_sd->status.char_id == char_id) {
 		for (i = 0; i < MAX_FRIENDS &&
 			(f_sd->status.friends[i].char_id != sd->status.char_id || f_sd->status.friends[i].account_id != sd->status.account_id); i++);
 
 		if (i != MAX_FRIENDS) {
-			// move all chars down
+			// move all chars up
 			for(j = i + 1; j < MAX_FRIENDS; j++)
 				memcpy(&f_sd->status.friends[j-1], &f_sd->status.friends[j], sizeof(f_sd->status.friends[0]));
 
@@ -12415,8 +12408,22 @@ void clif_parse_FriendsListRemove(int fd, struct map_session_data *sd)
 		}
 
 	} else { //friend not online -- ask char server to delete from his friendlist
-		chrif_removefriend(char_id,sd->status.char_id);
+		if(chrif_removefriend(char_id,sd->status.char_id)) { // char-server offline, abort
+			clif_displaymessage(fd, "This action can't be performed at the moment. Please try again later.");
+			return;
+		}
 	}
+
+	// We can now delete from original requester
+	for (i = 0; i < MAX_FRIENDS &&
+		(sd->status.friends[i].char_id != char_id || sd->status.friends[i].account_id != account_id); i++);
+	// move all chars up
+	for(j = i + 1; j < MAX_FRIENDS; j++)
+		memcpy(&sd->status.friends[j-1], &sd->status.friends[j], sizeof(sd->status.friends[0]));
+
+	memset(&sd->status.friends[MAX_FRIENDS-1], 0, sizeof(sd->status.friends[MAX_FRIENDS-1]));
+	clif_displaymessage(fd, "Friend removed");	
+
 	WFIFOHEAD(fd,packet_len(0x20a));
 	WFIFOW(fd,0) = 0x20a;
 	WFIFOL(fd,2) = account_id;