about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMagnus Auvinen <magnus.auvinen@gmail.com>2008-03-29 17:20:21 +0000
committerMagnus Auvinen <magnus.auvinen@gmail.com>2008-03-29 17:20:21 +0000
commit370cbbe79f8dbc8ef00dca28e27480c05789670f (patch)
treef8adbab00c2a8e8e506f0f47beb753c47d592fb2
parentfcd9709c36ff014c270ef14f236e0141c8266695 (diff)
downloadzcatch-370cbbe79f8dbc8ef00dca28e27480c05789670f.tar.gz
zcatch-370cbbe79f8dbc8ef00dca28e27480c05789670f.zip
server browser improvements. much improved quick search. sorted the player list.
-rw-r--r--src/engine/client/ec_client.c21
-rw-r--r--src/engine/client/ec_srvbrowse.c26
-rw-r--r--src/engine/e_if_client.h19
-rw-r--r--src/engine/e_system.c29
-rw-r--r--src/engine/e_system.h2
-rw-r--r--src/game/client/gc_menu.cpp109
6 files changed, 142 insertions, 64 deletions
diff --git a/src/engine/client/ec_client.c b/src/engine/client/ec_client.c
index b12fa503..142c8b70 100644
--- a/src/engine/client/ec_client.c
+++ b/src/engine/client/ec_client.c
@@ -643,6 +643,18 @@ static const char *client_load_map_search(const char *mapname, int wanted_crc)
 	return error;
 }
 
+
+static int player_score_comp(const void *a, const void *b)
+{
+	SERVER_INFO_PLAYER *p0 = (SERVER_INFO_PLAYER *)a;
+	SERVER_INFO_PLAYER *p1 = (SERVER_INFO_PLAYER *)b;
+	if(p0->score == p1->score)
+		return 0;
+	if(p0->score < p1->score)
+		return 1;
+	return -1;
+}
+
 static void client_process_packet(NETPACKET *packet)
 {
 	if(packet->client_id == -1)
@@ -721,13 +733,16 @@ static void client_process_packet(NETPACKET *packet)
 				
 				for(i = 0; i < info.num_players; i++)
 				{
-					str_copy(info.player_names[i], unpacker_get_string(&up), sizeof(info.player_names[i]));
-					info.player_scores[i] = atol(unpacker_get_string(&up));
+					str_copy(info.players[i].name, unpacker_get_string(&up), sizeof(info.players[i].name));
+					info.players[i].score = atol(unpacker_get_string(&up));
 				}
 				
-				/* TODO: unpack players aswell */
 				if(!up.error)
+				{
+					/* sort players */
+					qsort(info.players, info.num_players, sizeof(*info.players), player_score_comp);
 					client_serverbrowse_set(&packet->address, 0, &info);
+				}
 			}
 		}
 	}
diff --git a/src/engine/client/ec_srvbrowse.c b/src/engine/client/ec_srvbrowse.c
index c4fe3080..fcab2fc8 100644
--- a/src/engine/client/ec_srvbrowse.c
+++ b/src/engine/client/ec_srvbrowse.c
@@ -128,7 +128,7 @@ static int client_serverbrowse_sort_compare_numplayers(const void *ai, const voi
 
 static void client_serverbrowse_filter()
 {
-	int i = 0;
+	int i = 0, p = 0;
 	num_sorted_servers = 0;
 
 	/* allocate the sorted list */	
@@ -159,7 +159,29 @@ static void client_serverbrowse_filter()
 			filtered = 1;
 		else if(config.b_filter_string[0] != 0)
 		{
-			if(strstr(serverlist[i]->info.name, config.b_filter_string) == 0)
+			int matchfound = 0;
+			
+			serverlist[i]->info.quicksearch_hit = 0;
+
+			/* match against server name */
+			if(str_find_nocase(serverlist[i]->info.name, config.b_filter_string))
+			{
+				matchfound = 1;
+				serverlist[i]->info.quicksearch_hit |= BROWSEQUICK_SERVERNAME;
+			}
+
+			/* match against players */				
+			for(p = 0; p < serverlist[i]->info.num_players; p++)
+			{
+				if(str_find_nocase(serverlist[i]->info.players[p].name, config.b_filter_string))
+				{
+					matchfound = 1;
+					serverlist[i]->info.quicksearch_hit |= BROWSEQUICK_PLAYERNAME;
+					break;
+				}
+			}
+			
+			if(!matchfound)
 				filtered = 1;
 		}
 			
diff --git a/src/engine/e_if_client.h b/src/engine/e_if_client.h
index 3f490079..e06d3e6b 100644
--- a/src/engine/e_if_client.h
+++ b/src/engine/e_if_client.h
@@ -51,7 +51,10 @@ enum
 	BROWSESORT_MAP,
 	BROWSESORT_GAMETYPE,
 	BROWSESORT_PROGRESSION,
-	BROWSESORT_NUMPLAYERS
+	BROWSESORT_NUMPLAYERS,
+	
+	BROWSEQUICK_SERVERNAME=1,
+	BROWSEQUICK_PLAYERNAME=2
 };
 
 /*
@@ -59,6 +62,15 @@ enum
 */
 
 /*
+	Structure: SERVER_INFO_PLAYER
+*/
+typedef struct
+{
+	char name[48];
+	int score;
+} SERVER_INFO_PLAYER;
+
+/*
 	Structure: SERVER_INFO
 */
 typedef struct
@@ -66,6 +78,8 @@ typedef struct
 	int sorted_index;
 	int server_index;
 	
+	int quicksearch_hit;
+	
 	int progression;
 	int game_type;
 	int max_players;
@@ -76,8 +90,7 @@ typedef struct
 	char map[32];
 	char version[32];
 	char address[24];
-	char player_names[16][48];
-	int player_scores[16];
+	SERVER_INFO_PLAYER players[16];
 } SERVER_INFO;
 
 /*
diff --git a/src/engine/e_system.c b/src/engine/e_system.c
index 2b24ab7c..9545369d 100644
--- a/src/engine/e_system.c
+++ b/src/engine/e_system.c
@@ -911,6 +911,35 @@ void str_sanitize(char *str_in)
 	}
 }
 
+/* case */
+int str_comp_nocase(const char *a, const char *b)
+{
+#if defined(CONF_FAMILY_WINDOWS)
+	return _stricmp(a,b);
+#else
+	return strcasecmp(a,b);
+#endif
+}
+
+const char *str_find_nocase(const char *haystack, const char *needle)
+{
+	while(*haystack) /* native implementation */
+	{
+		const char *a = haystack;
+		const char *b = needle;
+		while(*a && *b && tolower(*a) == tolower(*b))
+		{
+			a++;
+			b++;
+		}
+		if(!(*b))
+			return haystack;
+		haystack++;
+	}
+	
+	return 0;
+}
+
 #if defined(__cplusplus)
 }
 #endif
diff --git a/src/engine/e_system.h b/src/engine/e_system.h
index 0f79908d..9902cb24 100644
--- a/src/engine/e_system.h
+++ b/src/engine/e_system.h
@@ -539,6 +539,8 @@ void str_copy(char *dst, const char *src, int dst_size);
 void str_format(char *buffer, int buffer_size, const char *format, ...);
 void str_sanitize_strong(char *str);
 void str_sanitize(char *str);
+int str_comp_nocase(const char *a, const char *b);
+const char *str_find_nocase(const char *haystack, const char *needle);
 
 typedef void (*DBG_LOGGER)(const char *line);
 void dbg_logger(DBG_LOGGER logger);
diff --git a/src/game/client/gc_menu.cpp b/src/game/client/gc_menu.cpp
index c6c21a66..083cbcbf 100644
--- a/src/game/client/gc_menu.cpp
+++ b/src/game/client/gc_menu.cpp
@@ -809,59 +809,9 @@ static void menu2_render_serverbrowser(RECT main_view)
 		int selected = strcmp(item->address, config.ui_server_address) == 0; //selected_index==item_index;
 		
 		
-			/*
-		if(selected)
-		{
-			selected_index = i;
-			
-			// selected server, draw the players on it
-			RECT whole;
-			int h = (item->num_players+2)/3;
-			
-			ui_hsplit_t(&view, 25.0f+h*15.0f, &whole, &view);
-
-            select_hit_box = whole;
-			
-			RECT r = whole;
-			ui_margin(&r, 1.5f, &r);
-			ui_draw_rect(&r, vec4(1,1,1,0.5f), CORNER_ALL, 4.0f);
-			
-			ui_hsplit_t(&whole, 20.0f, &row, &whole);
-			ui_vsplit_l(&whole, 50.0f, 0, &whole);
-
-			
-			for(int p = 0; p < item->num_players; p+=3)
-			{
-				RECT player_row;
-				RECT player_rect;
-				RECT player_score;
-				RECT player_name;
-				ui_hsplit_t(&whole, 15.0f, &player_row, &whole);
-				
-				for(int a = 0; a < 3; a++)
-				{
-					if(p+a >= item->num_players)
-						break;
-						
-					ui_vsplit_l(&player_row, 170.0f, &player_rect, &player_row);
-					ui_vsplit_l(&player_rect, 30.0f, &player_score, &player_name);
-					ui_vsplit_l(&player_name, 10.0f, 0, &player_name);
-					char buf[32];
-					sprintf(buf, "%d", item->player_scores[p+a]);
-					ui_do_label(&player_score, buf, 12.0f, 1);
-					ui_do_label(&player_name, item->player_names[p+a], 12.0f, -1);
-				}
-			}
-			
-			//k += h*3/4;
-		}
-		else
-        {
-			*/
-			ui_hsplit_t(&view, 17.0f, &row, &view);
-            select_hit_box = row;
-		//}
-
+		ui_hsplit_t(&view, 17.0f, &row, &view);
+		select_hit_box = row;
+	
 		if(selected)
 		{
 			selected_index = i;
@@ -910,13 +860,37 @@ static void menu2_render_serverbrowser(RECT main_view)
 					ui_draw_browse_icon(0x100, &button);
 			}
 			else if(id == COL_NAME)
-				ui_do_label(&button, item->name, 12.0f, -1);
+			{
+				TEXT_CURSOR cursor;
+				gfx_text_set_cursor(&cursor, button.x, button.y, 12.0f, TEXTFLAG_RENDER);
+				
+				if(config.b_filter_string[0] && (item->quicksearch_hit&BROWSEQUICK_SERVERNAME))
+				{
+					// highlight the parts that matches
+					const char *s = str_find_nocase(item->name, config.b_filter_string);
+					if(s)
+					{
+						gfx_text_ex(&cursor, item->name, (int)(s-item->name));
+						gfx_text_color(1,0.4f,0.4f,1);
+						gfx_text_ex(&cursor, s, strlen(config.b_filter_string));
+						gfx_text_color(1,1,1,1);
+						gfx_text_ex(&cursor, s+strlen(config.b_filter_string), -1);
+					}
+					else
+						gfx_text_ex(&cursor, item->name, -1);
+				}
+				else
+					gfx_text_ex(&cursor, item->name, -1);
+			}
 			else if(id == COL_MAP)
 				ui_do_label(&button, item->map, 12.0f, -1);
 			else if(id == COL_PLAYERS)
 			{
 				str_format(temp, sizeof(temp), "%i/%i", item->num_players, item->max_players);
+				if(config.b_filter_string[0] && (item->quicksearch_hit&BROWSEQUICK_PLAYERNAME))
+					gfx_text_color(1,0.4f,0.4f,1);
 				ui_do_label(&button, temp, 12.0f, 1);
+				gfx_text_color(1,1,1,1);
 			}
 			else if(id == COL_PING)
 			{
@@ -1038,11 +1012,34 @@ static void menu2_render_serverbrowser(RECT main_view)
 			char temp[16];
 			ui_hsplit_t(&server_scoreboard, 16.0f, &row, &server_scoreboard);
 
-			str_format(temp, sizeof(temp), "%d", selected_server->player_scores[i]);
+			str_format(temp, sizeof(temp), "%d", selected_server->players[i].score);
 			ui_do_label(&row, temp, font_size, -1);
 
 			ui_vsplit_l(&row, 25.0f, 0x0, &row);
-			ui_do_label(&row, selected_server->player_names[i], font_size, -1);
+		
+			TEXT_CURSOR cursor;
+			gfx_text_set_cursor(&cursor, row.x, row.y, 12.0f, TEXTFLAG_RENDER);
+			
+			const char *name = selected_server->players[i].name;
+			if(config.b_filter_string[0])
+			{
+				// highlight the parts that matches
+				const char *s = str_find_nocase(name, config.b_filter_string);
+				if(s)
+				{
+					gfx_text_ex(&cursor, name, (int)(s-name));
+					gfx_text_color(1,0.4f,0.4f,1);
+					gfx_text_ex(&cursor, s, strlen(config.b_filter_string));
+					gfx_text_color(1,1,1,1);
+					gfx_text_ex(&cursor, s+strlen(config.b_filter_string), -1);
+				}
+				else
+					gfx_text_ex(&cursor, name, -1);
+			}
+			else
+				gfx_text_ex(&cursor, name, -1);
+			
+			/*ui_do_label(&row, selected_server->player_names[i], font_size, -1);*/
 		}
 	}