Index: Daodan/MSVC/Flatline.c
===================================================================
--- Daodan/MSVC/Flatline.c	(revision 587)
+++ Daodan/MSVC/Flatline.c	(revision 588)
@@ -27,15 +27,5 @@
 
 
-bool FLrServer_Run()
-{
-	// Get the local hostname
-	char szHostName[255];
-	struct hostent *host_entry;
-	gethostname(szHostName, 255);
-
-	host_entry=gethostbyname(szHostName);
-	DDrConsole_PrintF("Server started at %s...", inet_ntoa (*(struct in_addr *)*host_entry->h_addr_list));
-	return NetUDPServer_Listen(27777, FLrServer_PacketCallback);
-}
+
 
 short TRrAnimation_GetType(char* anim)
Index: Daodan/MSVC/Flatline_BSL.c
===================================================================
--- Daodan/MSVC/Flatline_BSL.c	(revision 587)
+++ Daodan/MSVC/Flatline_BSL.c	(revision 588)
@@ -63,4 +63,7 @@
 		sprintf(message.data, "%s", args[0].value_str32);
 		NetUDPSocket_Send(client_sock, (sockaddr*)&address, (char*)&message, 257);
+	}
+	else if(MsNet_Running) {
+		MSNet_SendChat( args[0].value_str32 );
 	}
 	else {
Index: Daodan/MSVC/Flatline_Net.h
===================================================================
--- Daodan/MSVC/Flatline_Net.h	(revision 588)
+++ Daodan/MSVC/Flatline_Net.h	(revision 588)
@@ -0,0 +1,32 @@
+#ifndef FLATLINE_NET_H
+#define FLATLINE_NET_H
+
+#define pad1_size (sizeof(int64_t) - sizeof(short))
+#define pad2_size (128 - (sizeof(short) + pad1_size + sizeof(int64_t)))
+
+
+
+
+typedef struct {
+	short ss_family;
+	char pad1[pad1_size];
+	uint64_t pad64;
+	char pad2[pad2_size];
+} sockaddr_storage;
+
+typedef struct sockaddr sockaddr;
+typedef struct sockaddr_in sockaddr_in;
+typedef sockaddr_storage sockaddr_in6;
+
+void NetCatchError();
+
+bool NetUDPServer_Listen(uint16_t port, bool (*packet_callback)(char* data, int datalen, int from));
+bool NetUDPServer_Send(sockaddr* address, char* data, int datalen);
+
+int NetUDPSocket_Create(uint16_t port, sockaddr_in* address);
+int NetTCPSocket_Create(uint16_t port, sockaddr_in* address);
+int NetUDPSocket_Send(int socket, const sockaddr* address, const char* data, int datalen);
+void NetUDPSocket_Close(int sock);
+bool NetUDPSocket_Recieve(int socket, sockaddr_storage* address, char* data, uint16_t* datalen);
+
+#endif
Index: Daodan/MSVC/Flatline_Server.c
===================================================================
--- Daodan/MSVC/Flatline_Server.c	(revision 587)
+++ Daodan/MSVC/Flatline_Server.c	(revision 588)
@@ -2,5 +2,5 @@
 #include "Flatline_Server.h"
 #include <Windows.h>
-
+#include "PortForwardWrapper.h"
 //I hereby apologize for the uglyness of the below code. 
 //It was never intended to be "final" code, much less shared with anyone
@@ -376,2 +376,41 @@
 	return true;
 }
+
+
+
+bool FLrServer_Run()
+{
+	HRESULT ret;
+	PortMappingContainer_C PMC = 
+	{
+		"", 
+		"27777",
+		"27777",
+		"UDP",
+		"",
+		"",
+		"Flatline!"
+	};
+	// Get the local hostname
+	char szHostName[255];
+	struct hostent *host_entry;
+	gethostname(szHostName, 255);
+
+	host_entry=gethostbyname(szHostName);
+
+	strcpy( PMC.InternalClient, inet_ntoa (*(struct in_addr *)*host_entry->h_addr_list) );
+	ret = uPnP_Forward( &PMC );
+	if(!ret)
+	{
+		DDrConsole_Print( "Port Forwarded" );
+	}
+	else
+	{
+		LPSTR Message;
+		FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM, &ret,0,0,&Message,0,NULL);
+		DDrConsole_Print( Message );
+	}
+
+	DDrConsole_PrintF("Server started at %s...", inet_ntoa (*(struct in_addr *)*host_entry->h_addr_list));
+	return NetUDPServer_Listen(27777, FLrServer_PacketCallback);
+}
Index: Daodan/MSVC/Mariusnet.c
===================================================================
--- Daodan/MSVC/Mariusnet.c	(revision 587)
+++ Daodan/MSVC/Mariusnet.c	(revision 588)
@@ -20,12 +20,25 @@
 bool RoomListGotten = 0;
 
-bool Are_We_Logged_In = 0;
-
-RGBA blue =		{0xFF, 0, 0, 0};
+bool MariusNet_LoggedIn = 0;
+
+bool MsNet_Running = 0;
+int Marius_Socket = -1;
+int Room_Socket = -1;
+sockaddr_in RoomAddr = {0};
+int PlayerID = 0;
+/*
+
 RGBA green =	{0, 0xFF, 0, 0};
 RGBA red =		{0, 0, 0xFF, 0};
 
 RGBA grey = {0x80,0x80,0x80,0x80};
-
+*/
+extern RGBA red;
+//extern RGBA blue;
+RGBA blue =		{0xFF, 0, 0, 0};
+RGBA cyan =		{0xFF, 0xFF, 0, 0};
+RGBA white =		{0xFF, 0xFF, 0xFF, 0};
+extern RGBA green;
+extern RGBA grey;
 int MariusNet_OutgoingPacketWrapper(int socket, const sockaddr* address, marius_packet* data, short datalen)
 {
@@ -259,4 +272,75 @@
 
 }
+
+void MSNet_HandleChat( m_message* msg )
+{
+	//BGRA *cough*
+	/*RGBA chatcolor;
+	chatcolor.R = (msg->PrimaryColor.Red);
+	chatcolor.G = (msg->PrimaryColor.Green);
+	chatcolor.B = (msg->PrimaryColor.Blue);
+	chatcolor.A = 0;*/
+	char Message[1024];
+	int NameLen = sprintf_s( Message, 1024, "%s", msg->Message ) + 1;
+	sprintf_s( Message, 1024 - NameLen, "%s: %s", Message, msg->Message + NameLen );
+	//DDrConsole_PrintColored( msg->Message, 0, chatcolor,white );
+	DDrConsole_Print(Message);
+}
+
+void MSNet_SendChat( char* msg )
+{
+	marius_packet mPacket = {0}; 
+	int len;
+	if(!MsNet_Running || !MariusNet_LoggedIn) return;
+	
+	Initialize_MPacket(&mPacket, pt_ChatMessage);
+
+	
+	mPacket.message.SecondaryColor.Red = mPacket.message.SecondaryColor.Flags = -1;
+	
+
+
+	//mPacket.message.Message = 'Gumby';
+	len = sprintf(mPacket.message.Message, "O %s", msg );
+	mPacket.message.Message[1] = 0;
+	mPacket.message.SenderId = htonl(PlayerID);
+	//mPacket.message.TargetId = -1;
+	MariusNet_OutgoingPacketWrapper(Room_Socket, (sockaddr*)&RoomAddr, (char*)&mPacket, 
+		sizeof(marius_header) + sizeof(m_message) - (255 - len) );
+
+
+}
+
+int MSNet_Cleanup()
+{
+	if( Marius_Socket != -1) closesocket(Marius_Socket);
+	Marius_Socket = -1;
+	if( Room_Socket != -1) closesocket(Room_Socket);
+	Room_Socket = -1;
+	memset(RoomList, 0, sizeof(m_room) * 64 );
+	DDrConsole_PrintF("The metaserver connection will now close." );
+	MsNet_Running = 0;
+	MariusNet_LoggedIn = 0;
+	return 1;
+}
+
+void MSNet_HandleGameList( m_gameinfo* PacketGames, int PacketSize )
+{
+	m_gameinfo TempGameList[64] = {0};
+	int i ;
+	for( i = 0; PacketSize > 0; i++ )
+	{
+		int ThisSize = sizeof(m_gameinfo) + ntohs(PacketGames->len) - sizeof(m_gamedescription);
+		
+		memcpy(TempGameList + i,PacketGames, sizeof(m_gameinfo) - 128);
+
+		sprintf_s( TempGameList[i].g.Buffer, 128, "%s", PacketGames->g.Buffer);
+		PacketSize -= ThisSize;
+		PacketGames = (m_gameinfo*)((char*)PacketGames + ThisSize);
+		
+	}
+	//Do stuff with the games.
+}
+
 int MSNet_Room_Join( short Room, char* Key)
 {
@@ -268,12 +352,9 @@
 
 	sockaddr_in SockAddr;
-	int Room_Socket = NetTCPSocket_Create(RoomList[Room].Port, &SockAddr);
-
-	sockaddr_in RoomAddr = {0};
 	RoomAddr.sin_port = RoomList[Room].Port;
 	RoomAddr.sin_family = AF_INET;
 	RoomAddr.sin_addr.S_un.S_addr = RoomList[Room].IPAddress;
 	
-
+	Room_Socket = NetTCPSocket_Create(RoomList[Room].Port, &SockAddr);
 
 	DDrConsole_PrintF("Joining room %hi", Room);
@@ -282,4 +363,5 @@
 	{
 		DDrConsole_PrintF("Failed to initialize room socket!");
+		return MSNet_Cleanup();
 	}
 	
@@ -287,5 +369,6 @@
 	{
 		NetCatchError();
-		return 1;
+		MariusNet_LoggedIn = 0;
+		return MSNet_Cleanup();
 	}
 	
@@ -306,5 +389,5 @@
 	if(MariusNet_IncomingPacketWrapper(Room_Socket, incomingData, 1400, 0) == SOCKET_ERROR)
 	{
-		return 0;
+		return MSNet_Cleanup();
 	}
 
@@ -313,7 +396,19 @@
 		//DDrConsole_PrintF("Login failed: %s", incomingPacket->login_denied.DenialMessage );
 		MSNet_LoginError_Output(ntohl(incomingPacket->login_denied.code));
-		return 0;
-	}
-
+		return MSNet_Cleanup();
+	}
+
+	MariusNet_LoggedIn = 1;
+
+	/*
+	Initialize_MPacket(&mPacket, 104);
+	mPacket.newgame.g.maxplayers = -1;
+	mPacket.newgame.g.clientversion = htonl(0xc136e436);
+	mPacket.newgame.g.maxteams = -1;
+	//sprintf(mPacket.newgame.g.Buffer, "Oni!");
+	memcpy(mPacket.newgame.g.Buffer, "Blam!\0This is Oni, bitch.\0", 50);
+	sent_bytes = MariusNet_OutgoingPacketWrapper(Room_Socket, (sockaddr*)&RoomAddr, (char*)&mPacket, 
+		sizeof(marius_header) + sizeof(m_announcegame) + 50);
+	*/
 	while(1)
 	{
@@ -326,12 +421,16 @@
 		case pt_RoomList:
 		case pt_PlayerInfo:
-		case pt_GameList:
 		case pt_PlayerList:
 			//Do nothing for now
 			break;
+		case pt_GameList:
+			MSNet_HandleGameList( incomingPacket->gamelist.Games,  
+				ntohl(incomingPacket->header.PacketSize) - sizeof(marius_header)); 
+			break;
 		case pt_BlueBarMsg:
-			DDrConsole_PrintColored(incomingPacket->motd.Message, 0, blue, grey );
+			DDrConsole_PrintColored(incomingPacket->motd.Message, 0, cyan, grey );
 			break;
 		case pt_ChatMessage:
+			MSNet_HandleChat(&incomingPacket->message);
 			break;
 		case pt_KeepAlive:
@@ -351,17 +450,22 @@
 {
 	int Port = 4156;
-	int Marius_Socket = -1;
-	int PlayerID;
+	
+	
 	char RoomToken[33] = {0};
 	int i = 0;
-
+	
 	
 	
 	sockaddr_in Marius_Addr = {0};
-	
-	if(Are_We_Logged_In) 
+	if(MsNet_Running)
+	{
+		DDrConsole_PrintF("The metaserver handler is already running!");
+	}
+	MsNet_Running = 1;
+
+	if(MariusNet_LoggedIn) 
 	{
 		DDrConsole_PrintF("You're already logged in!");
-		return 0;
+		return MSNet_Cleanup();
 	}
 
@@ -371,5 +475,5 @@
 	if(MariusNet_Initialize())
 	{
-		return 0;
+		return MSNet_Cleanup();
 	}
 
@@ -398,5 +502,5 @@
 		{
 			NetCatchError();
-			return 0;
+			return MSNet_Cleanup();
 		}
 		DDrConsole_PrintF("Sending Player Info...");
@@ -412,5 +516,5 @@
 		if(MariusNet_IncomingPacketWrapper(Marius_Socket, incomingData, 1400, 0) == SOCKET_ERROR)
 		{
-			return 0;
+			return MSNet_Cleanup();
 		}
 		
@@ -450,5 +554,5 @@
 			if(!NetUDPSocket_Recieve(Marius_Socket, (sockaddr*)&Marius_Addr,incomingData, &incomingLength))
 			{
-				return 0;
+				return MSNet_Cleanup();
 			}
 			DDrConsole_PrintF("Password ACK!");
@@ -465,5 +569,5 @@
 				if(MariusNet_IncomingPacketWrapper(Marius_Socket, incomingData, 1400, 0) == SOCKET_ERROR)
 				{	
-					return 0;
+					return MSNet_Cleanup();
 				}
 			}
@@ -482,10 +586,9 @@
 			//DDrConsole_PrintF("Login failed: %s", incomingPacket->login_denied.DenialMessage );
 			MSNet_LoginError_Output(ntohl(incomingPacket->login_denied.code));
-			return 0;
+			return MSNet_Cleanup();
 		}
 		else 
 		{
-			DDrConsole_PrintF("Something went wrong! Disconnecting from Mariusnet");
-			return 0;
+			return MSNet_Cleanup();
 		}
 
@@ -495,5 +598,5 @@
 			if(MariusNet_IncomingPacketWrapper(Marius_Socket, incomingData, 1400, 0) == SOCKET_ERROR)
 			{	
-				return 0;
+				return MSNet_Cleanup();
 			}
 			if(ntohs(incomingPacket->header.PacketId)== pt_RoomList)
@@ -512,5 +615,5 @@
 			{
 				DDrConsole_PrintF("Invalid packet type %hi", ntohs(incomingPacket->header.PacketId));
-				return 0;
+				return MSNet_Cleanup();
 			}
 		}
Index: Daodan/MSVC/Mariusnet_Defs.h
===================================================================
--- Daodan/MSVC/Mariusnet_Defs.h	(revision 587)
+++ Daodan/MSVC/Mariusnet_Defs.h	(revision 588)
@@ -167,12 +167,64 @@
 typedef struct
 {
-
-    ColorStuff : TColorInfo;
+	m_colour	PrimaryColor;
+	m_colour	SecondaryColor;
 	int    SenderId;
     int		TargetId;
     char Message[256];
-}
-
-
+} m_message;
+
+typedef struct
+{
+	short unknown16;
+	short type;
+	int options;
+	int timelimit;
+	int checksum;
+	short difficulty;
+	short maxplayers;
+	short teamrandomseed;
+	short maxteams; //-1
+	int planningtime;
+	int unusedint;
+	int unusedint_2;
+	short unknown16_2;
+	short pluginflag;
+	char pluginlist[512];
+	int clientversion;//0xc136e436
+	int unknownint;
+	short status;
+	short numplayers;
+	char action;
+	char pad[3];
+	char Buffer[128];
+} m_gamedescription;
+
+typedef struct
+{
+	short port;
+	short zero;
+	m_gamedescription g;
+} m_announcegame;
+
+typedef struct
+{
+	unsigned int	gameID;
+	unsigned int	ipAddress;
+	unsigned short	port;
+	unsigned char	verb;
+	unsigned char	gameEnable;
+	unsigned int	timeRemaining;
+	unsigned int	hostPlayerID;
+	unsigned short	len;
+	int unused1;
+	int unused2;
+	short pad;
+	m_gamedescription g;
+} m_gameinfo;
+
+typedef struct
+{
+	m_gameinfo Games[];
+} m_gamelist;
 typedef struct
 {
@@ -190,4 +242,7 @@
 		m_player_info player_info;
 		m_motd motd;
+		m_message message;
+		m_announcegame newgame;
+		m_gamelist gamelist;
 	};
 } marius_packet;
Index: Daodan/MSVC/Mariusnet_Public.h
===================================================================
--- Daodan/MSVC/Mariusnet_Public.h	(revision 587)
+++ Daodan/MSVC/Mariusnet_Public.h	(revision 588)
@@ -1,1 +1,4 @@
+extern bool MsNet_Running;
+
 bool MSNet_Login(char* username, char* password);
+void MSNet_SendChat( char* msg );
Index: Daodan/MSVC/PortForwardWrapper.cpp
===================================================================
--- Daodan/MSVC/PortForwardWrapper.cpp	(revision 588)
+++ Daodan/MSVC/PortForwardWrapper.cpp	(revision 588)
@@ -0,0 +1,87 @@
+#include <atlbase.h>
+#include "PortForwardWrapper.h"
+#include <Natupnp.h>
+#include <UPnP.h>
+#include <stdlib.h>
+#include "Daodan_Console.h"
+extern "C" int uPnP_Forward( PortMappingContainer_C* ptr )
+{
+	bool bContinue = true;
+	IUPnPNAT* piNAT = NULL;
+	IStaticPortMappingCollection* piPortMappingCollection = NULL;	
+	CoInitialize(NULL);
+	HRESULT CoResult;
+
+	if ( !bContinue || !SUCCEEDED( CoResult  = CoCreateInstance(
+		__uuidof(UPnPNAT), 
+		NULL, 
+		CLSCTX_ALL, 
+		__uuidof(IUPnPNAT), 
+		(void **)&piNAT)
+		) )
+		bContinue = FALSE;
+
+	// Get the collection of forwarded ports 
+
+	if ( !bContinue || !SUCCEEDED( CoResult = piNAT->get_StaticPortMappingCollection(&piPortMappingCollection)) || (piPortMappingCollection==NULL ) )
+		bContinue = FALSE;
+
+	
+	
+	// add the new mapping
+
+	IStaticPortMapping* piStaticPortMapping = NULL;
+	USES_CONVERSION;  // for conversion from CString's
+
+	//VARIANT_BOOL vb = ( ( newMapping.Enabled == _T("Yes") ) ? VARIANT_TRUE : VARIANT_FALSE );
+	BSTR Protocol = SysAllocString( CT2W(ptr->Protocol) );
+	BSTR InternalClient = SysAllocString( CT2W(ptr->InternalClient) );
+	BSTR Description = SysAllocString( CT2W(ptr->Description) );
+	
+	//Remove the old binding, just in case. Probably not the best option, but it shall do for now.
+	if ( !bContinue ) piPortMappingCollection->Remove( _ttol( ptr->ExternalPort), Protocol );
+	
+	if ( !bContinue || 
+		!SUCCEEDED( CoResult = 
+		piPortMappingCollection->Add( 
+			_ttol( ptr->ExternalPort), 
+			Protocol,
+			_ttol( ptr->InternalPort), 
+			InternalClient, 
+			-1, 
+			Description,
+		&piStaticPortMapping ) ) || (piStaticPortMapping==NULL) )
+		
+		bContinue = FALSE;
+	
+	SysFreeString(Protocol);
+	SysFreeString(InternalClient);
+	SysFreeString(Description);
+	
+		
+	// clean up and de-initialize COM
+	
+	if ( piStaticPortMapping != NULL )
+	{
+		piStaticPortMapping->Release();
+		piStaticPortMapping = NULL;
+	}
+	
+	
+	if ( piPortMappingCollection != NULL )
+	{
+		piPortMappingCollection->Release();
+		piPortMappingCollection = NULL;
+	}
+	
+	if ( piNAT != NULL )
+	{
+		piNAT->Release();
+		piNAT = NULL;
+	}
+	
+	
+	CoUninitialize();
+	if(bContinue) return 0;
+	else return CoResult;
+}
Index: Daodan/MSVC/PortForwardWrapper.h
===================================================================
--- Daodan/MSVC/PortForwardWrapper.h	(revision 588)
+++ Daodan/MSVC/PortForwardWrapper.h	(revision 588)
@@ -0,0 +1,15 @@
+typedef struct
+{
+		char ExternalIPAddress[64];
+		char ExternalPort[64];
+		char InternalPort[64];
+		char Protocol[64];
+		char InternalClient[64];	
+		char Enabled[64];	
+		char Description[255];
+} PortMappingContainer_C;
+		
+#ifdef __cplusplus
+extern "C"
+#endif
+ int uPnP_Forward( PortMappingContainer_C* ptr );
