Browse Source

* RFIFOREST returns 0 when the session is eof (input data is implicitly discarted).
* Reworked the player fame update:
- would crash if an invalid pos was received
- the wrong player could be updated on certain conditions

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

FlavioJS 18 years ago
parent
commit
f3bb9a322d
5 changed files with 120 additions and 95 deletions
  1. 6 0
      Changelog-Trunk.txt
  2. 59 48
      src/char/char.c
  3. 53 44
      src/char_sql/char.c
  4. 1 1
      src/common/socket.h
  5. 1 2
      src/map/chrif.c

+ 6 - 0
Changelog-Trunk.txt

@@ -3,6 +3,12 @@ Date	Added
 AS OF SVN REV. 5091, WE ARE NOW USING TRUNK.  ALL UNTESTED BUGFIXES/FEATURES GO INTO TRUNK.
 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.
 IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.
 
 
+2007/05/28
+	* RFIFOREST returns 0 when the session is eof (input data is implicitly 
+	  discarted).
+	* Reworked the player fame update: [FlavioJS]
+	- would crash if an invalid pos was received
+	- the wrong player could be updated on certain conditions
 2007/05/26
 2007/05/26
 	* Identified several more glitches, too tired to fix these...
 	* Identified several more glitches, too tired to fix these...
 	* Fixed server not removing member minimap dot when you leave a guild
 	* Fixed server not removing member minimap dot when you leave a guild

+ 59 - 48
src/char/char.c

@@ -3104,68 +3104,79 @@ int parse_frommap(int fd)
 //		case 0x2b0f: Not used anymore, available for future use
 //		case 0x2b0f: Not used anymore, available for future use
 
 
 		case 0x2b10: // Update and send fame ranking list
 		case 0x2b10: // Update and send fame ranking list
-			if (RFIFOREST(fd) < 12)
+			if (RFIFOREST(fd) < 11)
 				return 0;
 				return 0;
 		{
 		{
 			int cid = RFIFOL(fd, 2);
 			int cid = RFIFOL(fd, 2);
 			int fame = RFIFOL(fd, 6);
 			int fame = RFIFOL(fd, 6);
 			char type = RFIFOB(fd, 10);
 			char type = RFIFOB(fd, 10);
-			char pos = RFIFOB(fd, 11);
 			int size;
 			int size;
 			struct fame_list *list = NULL;
 			struct fame_list *list = NULL;
 			
 			
-			switch(type) {
-				case 1:
-					size = fame_list_size_smith;
-					list = smith_fame_list;
-					break;
-				case 2:
-					size = fame_list_size_chemist;
-					list = chemist_fame_list;
-					break;
-				case 3:
-					size = fame_list_size_taekwon;
-					list = taekwon_fame_list;
-					break;
-				default:
-					size = 0;
-					break;
+			switch(type)
+			{
+				case 1 : size = fame_list_size_smith;   list = smith_fame_list; break;
+				case 2 : size = fame_list_size_chemist; list = chemist_fame_list; break;
+				case 3 : size = fame_list_size_taekwon; list = taekwon_fame_list; break;
+				default: size = 0; break;
 			}
 			}
-			if(!size) break; //No list.
-			if(pos)
+			if( size == 0 )
+				break;// No list
+			for( i = 0; i < size; ++i )
 			{
 			{
-			 	pos--; //Convert from pos to index.
-				if(
-					(pos == 0 || fame < list[pos-1].fame) &&
-					(pos == size-1 || fame > list[pos+1].fame)
-				) { //No change in order.
-					list[(int)pos].fame = fame;
-					char_update_fame_list(type, pos, fame);
-					break;
+				if( list[i].id != cid )
+					continue;
+				// player found, update position
+				if( i > 0 && fame >= list[i - 1].fame )
+				{// moved up
+					struct fame_list entry;
+					int t;
+					for( t = 0; fame < list[t].fame ; ++t )
+						;// get target position (always < i)
+					memcpy(&entry, &list[i], sizeof(struct fame_list));
+					entry.fame = fame;
+					memmove(&list[t + 1], &list[t], (t - i)*sizeof(struct fame_list));
+					memcpy(&list[t], &entry, sizeof(struct fame_list));
+					char_send_fame_list(-1);
 				}
 				}
-				// If the player's already in the list, remove the entry and shift the following ones 1 step up
-				memmove(list+pos, list+pos+1, (size-pos-1) * sizeof(struct fame_list));
-				//Clear out last entry.
-				list[size-1].id = 0;
-				list[size-1].fame = 0;
+				else if( i < size - 1 && fame < list[i + 1].fame )
+				{// moved down - always stays in the list
+					struct fame_list entry;
+					int t;
+					for( t = i + 2; t < size && fame < list[t].fame ; ++t )
+						;// get target position
+					--t;
+					memcpy(&entry, &list[i], sizeof(struct fame_list));
+					entry.fame = fame;
+					memmove(&list[i], &list[i + 1], (t - i)*sizeof(struct fame_list));
+					memcpy(&list[t], &entry, sizeof(struct fame_list));
+					char_send_fame_list(-1);
+				}
+				else
+				{// same position
+					list[i].fame = fame;
+					char_update_fame_list(type, i, fame);
+				}
+				break;
 			}
 			}
 
 
-			// Find the position where the player has to be inserted
-			for(i = 0; i < size && fame < list[i].fame; i++);
-			if(i >= size) break; //Out of ranking.
-			// When found someone with less or as much fame, insert just above
-			memmove(list+i+1, list+i, (size-i-1) * sizeof(struct fame_list));
-			list[i].id = cid;
-			list[i].fame = fame;
-			// Look for the player's name
-			for(j = 0; j < char_num && char_dat[j].status.char_id != id; j++);
-			if(j < char_num)
-				strncpy(list[i].name, char_dat[j].status.name, NAME_LENGTH);
-			else //Not found??
-				strncpy(list[i].name, "Unknown", NAME_LENGTH);
-			char_send_fame_list(-1);
+			if( i == size && fame >= list[size - 1].fame )
+			{// not on list and has enough fame
+				size_t j;
+				for( i = 0; fame < list[i].fame; ++i )
+					;// get target position
+				list[i].id = cid;
+				list[i].fame = fame;
+				for( j = 0; j < char_num && char_dat[j].status.char_id != cid; ++j )
+					;// find char
+				if( j < char_num )
+					strncpy(list[i].name, char_dat[j].status.name, NAME_LENGTH);
+				else
+					strncpy(list[i].name, "Unknown", NAME_LENGTH);
+				char_send_fame_list(-1);
+			}
 
 
-			RFIFOSKIP(fd,12);
+			RFIFOSKIP(fd,11);
 		}
 		}
 		break;
 		break;
 
 

+ 53 - 44
src/char_sql/char.c

@@ -2816,64 +2816,73 @@ int parse_frommap(int fd)
 //		case 0x2b0f: Not used anymore, available for future use
 //		case 0x2b0f: Not used anymore, available for future use
 
 
 		case 0x2b10: // Update and send fame ranking list
 		case 0x2b10: // Update and send fame ranking list
-			if (RFIFOREST(fd) < 12)
+			if (RFIFOREST(fd) < 11)
 				return 0;
 				return 0;
 		{
 		{
 			int cid = RFIFOL(fd, 2);
 			int cid = RFIFOL(fd, 2);
 			int fame = RFIFOL(fd, 6);
 			int fame = RFIFOL(fd, 6);
 			char type = RFIFOB(fd, 10);
 			char type = RFIFOB(fd, 10);
-			char pos = RFIFOB(fd, 11);
 			int size;
 			int size;
 			struct fame_list *list = NULL;
 			struct fame_list *list = NULL;
 			
 			
-			switch(type) {
-				case 1:
-					size = fame_list_size_smith;
-					list = smith_fame_list;
-					break;
-				case 2:
-					size = fame_list_size_chemist;
-					list = chemist_fame_list;
-					break;
-				case 3:
-					size = fame_list_size_taekwon;
-					list = taekwon_fame_list;
-					break;
-				default:
-					size = 0;
-					break;
+			switch(type)
+			{
+				case 1 : size = fame_list_size_smith;   list = smith_fame_list; break;
+				case 2 : size = fame_list_size_chemist; list = chemist_fame_list; break;
+				case 3 : size = fame_list_size_taekwon; list = taekwon_fame_list; break;
+				default: size = 0; break;
 			}
 			}
-			if(!size) break; //No list.
-			if(pos)
+			if( size == 0 )
+				break;// No list
+			for( i = 0; i < size; ++i )
 			{
 			{
-			 	pos--; //Convert from pos to index.
-				if(
-					(pos == 0 || fame < list[pos-1].fame) &&
-					(pos == size-1 || fame > list[pos+1].fame)
-				) { //No change in order.
-					list[(int)pos].fame = fame;
-					char_update_fame_list(type, pos, fame);
-					break;
+				if( list[i].id != cid )
+					continue;
+				// player found, update position
+				if( i > 0 && fame >= list[i - 1].fame )
+				{// moved up
+					struct fame_list entry;
+					int t;
+					for( t = 0; fame < list[t].fame ; ++t )
+						;// get target position (always < i)
+					memcpy(&entry, &list[i], sizeof(struct fame_list));
+					entry.fame = fame;
+					memmove(&list[t + 1], &list[t], (t - i)*sizeof(struct fame_list));
+					memcpy(&list[t], &entry, sizeof(struct fame_list));
+					char_send_fame_list(-1);
+				}
+				else if( i < size - 1 && fame < list[i + 1].fame )
+				{// moved down - always stays in the list
+					struct fame_list entry;
+					int t;
+					for( t = i + 2; t < size && fame < list[t].fame ; ++t )
+						;// get target position
+					--t;
+					memcpy(&entry, &list[i], sizeof(struct fame_list));
+					entry.fame = fame;
+					memmove(&list[i], &list[i + 1], (t - i)*sizeof(struct fame_list));
+					memcpy(&list[t], &entry, sizeof(struct fame_list));
+					char_send_fame_list(-1);
 				}
 				}
-				// If the player's already in the list, remove the entry and shift the following ones 1 step up
-				memmove(list+pos, list+pos+1, (size-pos-1) * sizeof(struct fame_list));
-				//Clear out last entry.
-				list[size-1].id = 0;
-				list[size-1].fame = 0;
+				else
+				{// same position
+					list[i].fame = fame;
+					char_update_fame_list(type, i, fame);
+				}
+				break;
 			}
 			}
 
 
-			// Find the position where the player has to be inserted
-			for(i = 0; i < size && fame < list[i].fame; i++);
-			if(i >= size) break; //Out of ranking.
-			// When found someone with less or as much fame, insert just above
-			memmove(list+i+1, list+i, (size-i-1) * sizeof(struct fame_list));
-			list[i].id = cid;
-			list[i].fame = fame;
-			// Look for the player's name
-			char_loadName(list[i].id, list[i].name);
-			char_send_fame_list(-1);
+			if( i == size && fame >= list[size - 1].fame )
+			{// not on list and has enough fame
+				for( i = 0; fame < list[i].fame; ++i )
+					;// get target position
+				list[i].id = cid;
+				list[i].fame = fame;
+				char_loadName(list[i].id, list[i].name);
+				char_send_fame_list(-1);
+			}
 
 
-			RFIFOSKIP(fd,12);
+			RFIFOSKIP(fd,11);
 		}
 		}
 		break;
 		break;
 
 

+ 1 - 1
src/common/socket.h

@@ -35,7 +35,7 @@
 #define RFIFOSPACE(fd) (session[fd]->max_rdata - session[fd]->rdata_size)
 #define RFIFOSPACE(fd) (session[fd]->max_rdata - session[fd]->rdata_size)
 #define WFIFOSPACE(fd) (session[fd]->max_wdata - session[fd]->wdata_size)
 #define WFIFOSPACE(fd) (session[fd]->max_wdata - session[fd]->wdata_size)
 
 
-#define RFIFOREST(fd)  (session[fd]->rdata_size - session[fd]->rdata_pos)
+#define RFIFOREST(fd)  (session[fd]->eof ? 0 : session[fd]->rdata_size - session[fd]->rdata_pos)
 #define RFIFOFLUSH(fd) \
 #define RFIFOFLUSH(fd) \
 	do { \
 	do { \
 		if(session[fd]->rdata_size == session[fd]->rdata_pos){ \
 		if(session[fd]->rdata_size == session[fd]->rdata_pos){ \

+ 1 - 2
src/map/chrif.c

@@ -1071,8 +1071,7 @@ int chrif_updatefamelist(struct map_session_data *sd)
 	WFIFOL(char_fd,2) = sd->status.char_id;
 	WFIFOL(char_fd,2) = sd->status.char_id;
 	WFIFOL(char_fd,6) = sd->status.fame;
 	WFIFOL(char_fd,6) = sd->status.fame;
 	WFIFOB(char_fd,10) = type;
 	WFIFOB(char_fd,10) = type;
-	WFIFOB(char_fd,11) = pc_famerank(sd->status.char_id, sd->class_&MAPID_UPPERMASK);
-	WFIFOSET(char_fd,12);
+	WFIFOSET(char_fd,11);
 
 
 	return 0;
 	return 0;
 }
 }