Index: Unreal3.2.orig/include/struct.h
===================================================================
--- Unreal3.2.orig.orig/include/struct.h
+++ Unreal3.2.orig/include/struct.h
@@ -941,7 +941,7 @@ typedef struct {
 #define SSLFLAG_VERIFYCERT 	0x2
 #define SSLFLAG_DONOTACCEPTSELFSIGNED 0x4
 struct Client {
-	struct Client *next, *prev, *hnext;
+	struct Client *next, *prev;
 	anUser *user;		/* ...defined, if this is a User */
 	aServer *serv;		/* ...defined, if this is a server */
 	TS   lastnick;		/* TimeStamp on nick */
Index: Unreal3.2.orig/src/hash.c
===================================================================
--- Unreal3.2.orig.orig/src/hash.c
+++ Unreal3.2.orig/src/hash.c
@@ -30,7 +30,7 @@
 ID_Copyright("(C) 1991 Darren Reed");
 ID_Notes("2.10 7/3/93");
 
-static aHashEntry clientTable[U_MAX];
+SplayTree *clientTree = NULL;
 static aHashEntry channelTable[CH_MAX];
 
 /*
@@ -160,7 +160,10 @@ unsigned int hash_whowas_name(char *name
  */
 void clear_client_hash_table(void)
 {
-	memset((char *)clientTable, '\0', sizeof(aHashEntry) * U_MAX);
+	if (clientTree != NULL)
+		return;
+
+	clientTree = splaytree_create(smycmp);
 }
 
 void clear_channel_hash_table(void)
@@ -174,7 +177,6 @@ void clear_channel_hash_table(void)
  */
 int  add_to_client_hash_table(char *name, aClient *cptr)
 {
-	unsigned int  hashv;
 	/*
 	 * If you see this, you have probably found your way to why changing the 
 	 * base version made the IRCd become weird. This has been the case in all
@@ -190,11 +192,8 @@ int  add_to_client_hash_table(char *name
 	*/
 	if (loop.tainted)
 		return 0;
-	hashv = hash_nick_name(name);
-	cptr->hnext = (aClient *)clientTable[hashv].list;
-	clientTable[hashv].list = (void *)cptr;
-	clientTable[hashv].links++;
-	clientTable[hashv].hits++;
+
+	splaytree_add(clientTree, name, cptr);
 	return 0;
 }
 /*
@@ -216,33 +215,8 @@ int  add_to_channel_hash_table(char *nam
  */
 int  del_from_client_hash_table(char *name, aClient *cptr)
 {
-	aClient *tmp, *prev = NULL;
-	unsigned int  hashv;
+	splaytree_delete(clientTree, name);
 
-	hashv = hash_nick_name(name);
-	for (tmp = (aClient *)clientTable[hashv].list; tmp; tmp = tmp->hnext)
-	{
-		if (tmp == cptr)
-		{
-			if (prev)
-				prev->hnext = tmp->hnext;
-			else
-				clientTable[hashv].list = (void *)tmp->hnext;
-			tmp->hnext = NULL;
-			if (clientTable[hashv].links > 0)
-			{
-				clientTable[hashv].links--;
-				return 1;
-			}
-			else
-				/*
-				 * Should never actually return from here and if we do it
-				 * is an error/inconsistency in the hash table.
-				 */
-				return -1;
-		}
-		prev = tmp;
-	}
 	return 0;
 }
 /*
@@ -283,33 +257,11 @@ int  del_from_channel_hash_table(char *n
 aClient *hash_find_client(char *name, aClient *cptr)
 {
 	aClient *tmp;
-	aHashEntry *tmp3;
-	unsigned int  hashv;
 
-	hashv = hash_nick_name(name);
-	tmp3 = &clientTable[hashv];
-	/*
-	 * Got the bucket, now search the chain.
-	 */
-	for (tmp = (aClient *)tmp3->list; tmp; tmp = tmp->hnext)
-		if (smycmp(name, tmp->name) == 0)
-		{
-			return (tmp);
-		}
-	return (cptr);
-	/*
-	 * If the member of the hashtable we found isnt at the top of its
-	 * chain, put it there.  This builds a most-frequently used order
-	 * into the chains of the hash table, giving speedier lookups on
-	 * those nicks which are being used currently.  This same block of
-	 * code is also used for channels and servers for the same
-	 * performance reasons.
-	 * 
-	 * I don't believe it does.. it only wastes CPU, lets try it and
-	 * see....
-	 * 
-	 * - Dianora
-	 */
+	if ((tmp = splaytree_retrieve(clientTree, name)) != NULL)
+		return tmp;
+
+	return cptr;
 }
 
 /*
@@ -318,27 +270,22 @@ aClient *hash_find_client(char *name, aC
 aClient *hash_find_nickserver(char *name, aClient *cptr)
 {
 	aClient *tmp;
-	aHashEntry *tmp3;
 	unsigned int  hashv;
 	char *serv;
 
 	serv = (char *)strchr(name, '@');
 	*serv++ = '\0';
-	hashv = hash_nick_name(name);
-	tmp3 = &clientTable[hashv];
-	/*
-	 * Got the bucket, now search the chain.
-	 */
-	for (tmp = (aClient *)tmp3->list; tmp; tmp = tmp->hnext)
-		if (smycmp(name, tmp->name) == 0 && tmp->user &&
-		    smycmp(serv, tmp->user->server) == 0)
-		{
-			*--serv = '\0';
-			return (tmp);
-		}
+
+	tmp = splaytree_retrieve(clientTree, name);
+	if (tmp && smycmp(name, tmp->name) == 0 && tmp->user &&
+	    smycmp(serv, tmp->user->server) == 0)
+	{
+		*--serv = '\0';
+		return tmp;
+	}
 
 	*--serv = '\0';
-	return (cptr);
+	return cptr;
 }
 /*
  * hash_find_server
@@ -346,64 +293,12 @@ aClient *hash_find_nickserver(char *name
 aClient *hash_find_server(char *server, aClient *cptr)
 {
 	aClient *tmp;
-#if 0
-	char *t;
-	char ch;
-#endif
-	aHashEntry *tmp3;
-
-	unsigned int  hashv;
-
-	hashv = hash_nick_name(server);
-	tmp3 = &clientTable[hashv];
-
-	for (tmp = (aClient *)tmp3->list; tmp; tmp = tmp->hnext)
-	{
-		if (!IsServer(tmp) && !IsMe(tmp))
-			continue;
-		if (smycmp(server, tmp->name) == 0)
-		{
-			return (tmp);
-		}
-	}
-
-	/*
-	 * Whats happening in this next loop ? Well, it takes a name like
-	 * foo.bar.edu and proceeds to earch for *.edu and then *.bar.edu.
-	 * This is for checking full server names against masks although it
-	 * isnt often done this way in lieu of using matches().
-	 */
-
-	/* why in god's name would we ever want to do something like this?
-	 * commented out, probably to be removed sooner or later - lucas 
-	 */
 
-#if 0
-	t = ((char *)server + strlen(server));
+	tmp = splaytree_retrieve(clientTree, server);
+	if (tmp && IsServer(tmp) && !IsMe(tmp))
+		return tmp;
 
-	for (;;)
-	{
-		t--;
-		for (; t > server; t--)
-			if (*(t + 1) == '.')
-				break;
-		if (*t == '*' || t == server)
-			break;
-		ch = *t;
-		*t = '*';
-		/*
-		 * Dont need to check IsServer() here since nicknames cant have
-		 * *'s in them anyway.
-		 */
-		if (((tmp = hash_find_client(t, cptr))) != cptr)
-		{
-			*t = ch;
-			return (tmp);
-		}
-		*t = ch;
-	}
-#endif
-	return (cptr);
+	return cptr;
 }
 
 /*
Index: Unreal3.2.orig/src/list.c
===================================================================
--- Unreal3.2.orig.orig/src/list.c
+++ Unreal3.2.orig/src/list.c
@@ -127,7 +127,6 @@ aClient *make_client(aClient *from, aCli
 	cptr->from = from ? from : cptr;	/* 'from' of local client is self! */
 	cptr->next = NULL;	/* For machines with NON-ZERO NULL pointers >;) */
 	cptr->prev = NULL;
-	cptr->hnext = NULL;
 	cptr->user = NULL;
 	cptr->serv = NULL;
 	cptr->srvptr = servr;
Index: Unreal3.2.orig/src/modules/m_nick.c
===================================================================
--- Unreal3.2.orig.orig/src/modules/m_nick.c
+++ Unreal3.2.orig/src/modules/m_nick.c
@@ -343,6 +343,7 @@ DLLFUNC CMD_FUNC(m_nick)
 
 	if (!(acptr = find_client(nick, NULL)))
 		goto nickkilldone;	/* No collisions, all clear... */
+
 	/*
 	   ** If the older one is "non-person", the new entry is just
 	   ** allowed to overwrite it. Just silently drop non-person,
@@ -770,7 +771,7 @@ DLLFUNC CMD_FUNC(m_nick)
 			hash_check_watch(sptr, RPL_LOGOFF);
 	}
 	(void)strcpy(sptr->name, nick);
-	(void)add_to_client_hash_table(nick, sptr);
+	(void)add_to_client_hash_table(sptr->name, sptr);
 	if (IsServer(cptr) && parc > 7)
 	{
 		parv[3] = nick;
@@ -1047,6 +1048,13 @@ int _register_user(aClient *cptr, aClien
 
 	if (MyConnect(sptr))
 	{
+		/*
+		 * we're connecting for the first time so add ourself to the client splaytree.
+		 * without this, everything gets totally fucked up, so we really want to do this
+		 * like right now and stuff.  --nenolod
+		 */
+		(void)add_to_client_hash_table(sptr->name, sptr);
+
 		IRCstats.unknown--;
 		IRCstats.me_clients++;
 		if (IsHidden(sptr))
