diff --git a/MCServer/Plugins/Core/web_chat.lua b/MCServer/Plugins/Core/web_chat.lua
index 66fe994eb..c8b5ded59 100644
--- a/MCServer/Plugins/Core/web_chat.lua
+++ b/MCServer/Plugins/Core/web_chat.lua
@@ -1,84 +1,91 @@
+local CHAT_HISTORY = 50
+
 local JavaScript = [[
-<script type="text/javascript">
-			function createXHR() 
-			{
-				var request = false;
-					try {
-						request = new ActiveXObject('Msxml2.XMLHTTP');
-					}
-					catch (err2) {
-						try {
-							request = new ActiveXObject('Microsoft.XMLHTTP');
-						}
-						catch (err3) {
+	<script type="text/javascript">
+		function createXHR() 
+		{
+			var request = false;
+			try {
+				request = new ActiveXObject('Msxml2.XMLHTTP');
+			}
+			catch (err2) {
+				try {
+					request = new ActiveXObject('Microsoft.XMLHTTP');
+				}
+				catch (err3) {
 					try {
 						request = new XMLHttpRequest();
 					}
-					catch (err1) 
-					{
+					catch (err1) {
 						request = false;
 					}
-						}
-					}
-				return request;
+				}
 			}
+			return request;
+		}
 		
-			function loadWholePage( url )
+		function OpenPage( url, callback ) 
+		{
+			var xhr = createXHR();
+			xhr.onreadystatechange=function()
+			{ 
+				if (xhr.readyState == 4)
+				{
+					callback( xhr )
+				} 
+			}; 
+			xhr.open("GET", url , true);
+			xhr.send(null); 
+		}
+
+		function LoadPageInto( url, storage ) 
+		{
+			OpenPage( url, function( xhr ) 
 			{
-				var storage = document.getElementById('ChatDiv');
-				var xhr = createXHR();
-				xhr.onreadystatechange=function()
-				{ 
-					if(xhr.readyState == 4)
-					{
-						//alert( xhr.status + " " + xhr.statusText );
-						//if(xhr.status == 200)
-						{
-							storage.innerHTML = xhr.responseText;//getBody(xhr.responseText);
-							storage.scrollTop = storage.scrollHeight;
-						}
-					} 
-				}; 
-				xhr.open("GET", url , true);
-				xhr.send(null); 
+				var ScrollBottom = storage.scrollTop + storage.offsetHeight;
+				var bAutoScroll = (ScrollBottom >= storage.scrollHeight); // Detect whether we scrolled to the bottom of the div
 				
-				return false;
-			}
-			
-			function SendChatMessage()
-			{
-				var MessageContainer = document.getElementById('ChatMessage');
-				if( MessageContainer.value == "" ) return;
+				storage.innerHTML = xhr.responseText;
 				
-				var xhr = createXHR();
-				xhr.onreadystatechange=function()
-				{ 
-					if(xhr.readyState == 4)
-					{
-						//alert( xhr.status + " " + xhr.statusText );
-						RefreshChat();
-					} 
-				}; 
-				xhr.open("GET", "/~webadmin/Core/Chat/?ChatMessage=" + MessageContainer.value, true);
-				xhr.send(null); 
-				MessageContainer.value = "";
-			}
+				if( bAutoScroll == true )
+				{
+					storage.scrollTop = storage.scrollHeight;
+				}
+			} );
 			
-			function RefreshChat()
+			return false;
+		}
+		
+		function SendChatMessage() 
+		{
+			var MessageContainer = document.getElementById('ChatMessage');
+			if( MessageContainer.value == "" ) return;
+			
+			OpenPage( "/~webadmin/Core/Chat/?ChatMessage=" + MessageContainer.value, function( xhr ) 
 			{
-				loadWholePage('/~webadmin/Core/Chat/?JustChat=true');
-			}
-			
-			setInterval(RefreshChat, 1000);
-			window.onload = RefreshChat;
-			
-		</script>
+				RefreshChat();
+			} );
+			MessageContainer.value = "";
+		}
+		
+		function RefreshChat() 
+		{
+			LoadPageInto('/~webadmin/Core/Chat/?JustChat=true', document.getElementById('ChatDiv'));
+		}
+		
+		setInterval(RefreshChat, 1000);
+		window.onload = RefreshChat;
+		
+	</script>
 ]]
 
 local ChatLogMessages = {}
 
 function AddMessage( PlayerName, Message )
 	table.insert( ChatLogMessages, { name = PlayerName, message = Message } )
+	while( #ChatLogMessages > CHAT_HISTORY ) do
+		table.remove( ChatLogMessages, 1 )
+	end
 end
 
 function OnChat( Player, Message )
@@ -95,6 +102,7 @@ function HandleRequest_Chat( Request )
 	end
 	
 	if( Request.Params["ChatMessage"] ~= nil ) then
+		LOG("Chat msg: " .. Request.Params["ChatMessage"] )
 		local Message = "[WebAdmin]: " .. Request.Params["ChatMessage"]
 		cRoot:Get():GetServer():SendMessage( Message )
 		AddMessage("WebAdmin", Request.Params["ChatMessage"] )
diff --git a/source/cRoot.cpp b/source/cRoot.cpp
index 0d6ff8369..5c0c08f7d 100644
--- a/source/cRoot.cpp
+++ b/source/cRoot.cpp
@@ -33,30 +33,23 @@
 
 cRoot* cRoot::s_Root = 0;
 
-typedef std::map< AString, cWorld* > WorldMap;
-struct cRoot::sRootState
-{
-	cWorld* pDefaultWorld;
-	WorldMap WorldsByName;
-};
-
 
 
 
 
 cRoot::cRoot()
-	: m_Server( 0 )
-	, m_MonsterConfig( 0 )
-	, m_GroupManager( 0 )
+	: m_Server( NULL )
+	, m_MonsterConfig( NULL )
+	, m_GroupManager( NULL )
 	, m_CraftingRecipes(NULL)
-	, m_FurnaceRecipe( 0 )
-	, m_WebAdmin( 0 )
-	, m_PluginManager( 0 )
-	, m_Log( 0 )
+	, m_FurnaceRecipe( NULL )
+	, m_WebAdmin( NULL )
+	, m_PluginManager( NULL )
+	, m_Log( NULL )
 	, m_bStop( false )
 	, m_bRestart( false )
-	, m_InputThread( 0 )
-	, m_pState( new sRootState )
+	, m_InputThread( NULL )
+	, m_pDefaultWorld( NULL )
 {
 	s_Root = this;
 }
@@ -68,7 +61,6 @@ cRoot::cRoot()
 cRoot::~cRoot()
 {
 	s_Root = 0;
-	delete m_pState;
 }
 
 
@@ -232,8 +224,8 @@ void cRoot::LoadWorlds(void)
 
 	// First get the default world
 	AString DefaultWorldName = IniFile.GetValueSet("Worlds", "DefaultWorld", "world");
-	m_pState->pDefaultWorld = new cWorld( DefaultWorldName.c_str() );
-	m_pState->WorldsByName[ DefaultWorldName ] = m_pState->pDefaultWorld;
+	m_pDefaultWorld = new cWorld( DefaultWorldName.c_str() );
+	m_WorldsByName[ DefaultWorldName ] = m_pDefaultWorld;
 
 	// Then load the other worlds
 	unsigned int KeyNum = IniFile.FindKey("Worlds");
@@ -256,7 +248,7 @@ void cRoot::LoadWorlds(void)
 			continue;
 		}
 		cWorld* NewWorld = new cWorld( WorldName.c_str() );
-		m_pState->WorldsByName[ WorldName ] = NewWorld;
+		m_WorldsByName[ WorldName ] = NewWorld;
 	}  // for i - Worlds
 }
 
@@ -266,7 +258,7 @@ void cRoot::LoadWorlds(void)
 
 void cRoot::StartWorlds(void)
 {
-	for( WorldMap::iterator itr = m_pState->WorldsByName.begin(); itr != m_pState->WorldsByName.end(); ++itr )
+	for( WorldMap::iterator itr = m_WorldsByName.begin(); itr != m_WorldsByName.end(); ++itr )
 	{
 		itr->second->InitializeSpawn();
 	}
@@ -278,7 +270,7 @@ void cRoot::StartWorlds(void)
 
 void cRoot::StopWorlds(void)
 {
-	for( WorldMap::iterator itr = m_pState->WorldsByName.begin(); itr != m_pState->WorldsByName.end(); ++itr )
+	for( WorldMap::iterator itr = m_WorldsByName.begin(); itr != m_WorldsByName.end(); ++itr )
 	{
 		itr->second->StopThreads();
 	}
@@ -290,11 +282,12 @@ void cRoot::StopWorlds(void)
 
 void cRoot::UnloadWorlds(void)
 {
-	for( WorldMap::iterator itr = m_pState->WorldsByName.begin(); itr != m_pState->WorldsByName.end(); ++itr )
+	m_pDefaultWorld = NULL;
+	for( WorldMap::iterator itr = m_WorldsByName.begin(); itr != m_WorldsByName.end(); ++itr )
 	{
 		delete itr->second;
 	}
-	m_pState->WorldsByName.clear();
+	m_WorldsByName.clear();
 }
 
 
@@ -303,7 +296,7 @@ void cRoot::UnloadWorlds(void)
 
 cWorld* cRoot::GetDefaultWorld()
 {
-	return m_pState->pDefaultWorld;
+	return m_pDefaultWorld;
 }
 
 
@@ -312,8 +305,8 @@ cWorld* cRoot::GetDefaultWorld()
 
 cWorld* cRoot::GetWorld( const AString & a_WorldName )
 {
-	WorldMap::iterator itr = m_pState->WorldsByName.find( a_WorldName );
-	if( itr != m_pState->WorldsByName.end() )
+	WorldMap::iterator itr = m_WorldsByName.find( a_WorldName );
+	if( itr != m_WorldsByName.end() )
 		return itr->second;
 	return 0;
 }
@@ -324,7 +317,7 @@ cWorld* cRoot::GetWorld( const AString & a_WorldName )
 
 bool cRoot::ForEachWorld(cWorldListCallback & a_Callback)
 {
-	for (WorldMap::iterator itr = m_pState->WorldsByName.begin(), itr2 = itr; itr != m_pState->WorldsByName.end(); itr = itr2)
+	for (WorldMap::iterator itr = m_WorldsByName.begin(), itr2 = itr; itr != m_WorldsByName.end(); itr = itr2)
 	{
 		++itr2;
 		if (a_Callback.Item(itr->second))
@@ -341,7 +334,7 @@ bool cRoot::ForEachWorld(cWorldListCallback & a_Callback)
 
 void cRoot::TickWorlds( float a_Dt )
 {
-	for( WorldMap::iterator itr = m_pState->WorldsByName.begin(); itr != m_pState->WorldsByName.end(); ++itr )
+	for( WorldMap::iterator itr = m_WorldsByName.begin(); itr != m_WorldsByName.end(); ++itr )
 	{
 		itr->second->Tick( a_Dt );
 	}
@@ -390,7 +383,7 @@ void cRoot::AuthenticateUser(int a_ClientID)
 int cRoot::GetTotalChunkCount(void)
 {
 	int res = 0;
-	for ( WorldMap::iterator itr = m_pState->WorldsByName.begin(); itr != m_pState->WorldsByName.end(); ++itr )
+	for ( WorldMap::iterator itr = m_WorldsByName.begin(); itr != m_WorldsByName.end(); ++itr )
 	{
 		res += itr->second->GetNumChunks();
 	}
@@ -403,7 +396,7 @@ int cRoot::GetTotalChunkCount(void)
 
 void cRoot::SaveAllChunks(void)
 {
-	for (WorldMap::iterator itr = m_pState->WorldsByName.begin(); itr != m_pState->WorldsByName.end(); ++itr)
+	for (WorldMap::iterator itr = m_WorldsByName.begin(); itr != m_WorldsByName.end(); ++itr)
 	{
 		itr->second->SaveAllChunks();
 	}
@@ -415,7 +408,7 @@ void cRoot::SaveAllChunks(void)
 
 bool cRoot::ForEachPlayer(cPlayerListCallback & a_Callback)
 {
-	for (WorldMap::iterator itr = m_pState->WorldsByName.begin(), itr2 = itr; itr != m_pState->WorldsByName.end(); itr = itr2)
+	for (WorldMap::iterator itr = m_WorldsByName.begin(), itr2 = itr; itr != m_WorldsByName.end(); itr = itr2)
 	{
 		++itr2;
 		if (!itr->second->ForEachPlayer(a_Callback))
@@ -437,7 +430,7 @@ void cRoot::LogChunkStats(void)
 	int SumNumInLighting = 0;
 	int SumNumInGenerator = 0;
 	int SumMem = 0;
-	for (WorldMap::iterator itr = m_pState->WorldsByName.begin(), end = m_pState->WorldsByName.end(); itr != end; ++itr)
+	for (WorldMap::iterator itr = m_WorldsByName.begin(), end = m_WorldsByName.end(); itr != end; ++itr)
 	{
 		cWorld * World = itr->second;
 		int NumInGenerator = World->GetGeneratorQueueLength();
diff --git a/source/cRoot.h b/source/cRoot.h
index a426207e8..b65c1d91d 100644
--- a/source/cRoot.h
+++ b/source/cRoot.h
@@ -102,8 +102,9 @@ private:
 	bool m_bStop;
 	bool m_bRestart;
 
-	struct sRootState;
-	sRootState* m_pState;
+	typedef std::map< AString, cWorld* > WorldMap;
+	cWorld*  m_pDefaultWorld;
+	WorldMap m_WorldsByName;
 
 	cThread* m_InputThread;
 	static void InputThread(void* a_Params);
diff --git a/source/cWebAdmin.cpp b/source/cWebAdmin.cpp
index dab6fe9e8..9bb8e8e27 100644
--- a/source/cWebAdmin.cpp
+++ b/source/cWebAdmin.cpp
@@ -237,8 +237,11 @@ void cWebAdmin::Request_Handler(webserver::http_request* r)
 
 			cPlayerAccum PlayerAccum;
 			cWorld * World = cRoot::Get()->GetDefaultWorld(); // TODO - Create a list of worlds and players
-			World->ForEachPlayer(PlayerAccum);
-			Content.append(PlayerAccum.m_Contents);
+			if( World != NULL )
+			{
+				World->ForEachPlayer(PlayerAccum);
+				Content.append(PlayerAccum.m_Contents);
+			}
 			Content += "</ul><br>";
 		}