Index: /Daodan/makefile
===================================================================
--- /Daodan/makefile	(revision 875)
+++ /Daodan/makefile	(revision 876)
@@ -8,16 +8,18 @@
 endif
 
-GCCFLAGS = -std=c99 -O0 -Wall -fomit-frame-pointer -fpack-struct -Wextra -Wno-unused-variable -Wno-unused-parameter
+DEF = NOFLATLINE
+GCCFLAGS = -std=c99 -O0 -Wall -fomit-frame-pointer -fpack-struct -Wextra -Wno-unused-variable -Wno-unused-parameter -D $(DEF)
 LINKFLAGS = -O0 -Wall -fomit-frame-pointer -fpack-struct -s -mdll
 LOCALE = LC_MESSAGES=C
 
 #LIBS = -lwinmm -lopengl32 -lgdi32
-LIBS = -lgdi32
-OBJS = src/binkw32.def
+LIBS = -lgdi32 -lwsock32
+OBJS = src/binkw32.def 
 OUT = build/binkw32.dll
 
 FOLDERS = patches
-SRC = src/Daodan.c src/Daodan_BSL.c src/Daodan_Character.c src/Daodan_Cheater.c src/Daodan_Config.c src/Daodan_Console.c src/Daodan_GL.c src/Daodan_Patch.c src/Daodan_Persistence.c src/Daodan_Utility.c src/Daodan_Win32.c src/Inifile_Reader.c src/_DLLInfo.rc src/patches/Patches.c
+SRC = src/Daodan.c src/Daodan_BSL.c src/Daodan_Character.c src/Daodan_Cheater.c src/Daodan_Config.c src/Daodan_Console.c src/Daodan_GL.c src/Daodan_Patch.c src/Daodan_Persistence.c src/Daodan_Utility.c src/Daodan_Win32.c src/Inifile_Reader.c src/_DLLInfo.rc src/patches/Patches.c src/Flatline.c src/Flatline_BSL.c src/Flatline_Client.c src/Flatline_Hooks.c src/Flatline_Net.c src/Flatline_Packet.c src/Flatline_PacketReader.c src/Flatline_PacketBuilder.c src/Flatline_Server.c src/Flatline_Win32.c src/Mariusnet.c  src/Flatline_Events.c
 DEST = $(patsubst src/%.rc,build/%.o,$(patsubst src/%.c,build/%.o,$(SRC)))
+
 
 ALL: $(FOLDERS) $(DEST) $(OBJS)
Index: /Daodan/src/Daodan_BSL.c
===================================================================
--- /Daodan/src/Daodan_BSL.c	(revision 875)
+++ /Daodan/src/Daodan_BSL.c	(revision 876)
@@ -821,4 +821,6 @@
 }
 
+extern void SLrFlatline_Initialize();
+
 void SLrDaodan_Initialize()
 {
@@ -857,4 +859,8 @@
 	SLrScript_Command_Register_ReturnType("st", "Prints to console in color", "", sl_void, bsl_dprintcolored);
 	SLrScript_Command_Register_ReturnType("d_dprint", "Prints to console in color", "", sl_void, bsl_dprintcolored);
+
+#ifdef FLATLINE
+	SLrFlatline_Initialize();
+#endif
 }
 
Index: /Daodan/src/Flatline.c
===================================================================
--- /Daodan/src/Flatline.c	(revision 876)
+++ /Daodan/src/Flatline.c	(revision 876)
@@ -0,0 +1,589 @@
+#include "Flatline.h"
+#include "Oni_Character.h"
+#include "Oni_Gamestate.h"
+#include "Oni_Symbols.h"
+#include "Flatline_Client.h"
+#include "Flatline_Server.h"
+#include "Flatline_Events.h"
+#include "Daodan_Utility.h"
+#include <Windows.h>
+//#include <sys/time.h>
+#include <time.h>
+#include <float.h>
+#define isnan(x) ((x) != (x))
+uint32_t last1 = 0; uint32_t last2 = 0;
+player_info Players[MAX_PLAYERS] = {{0}, {0}, {0}, {0}};
+player_info * PlayerList[MAX_CONNECTIONS] = {0};
+multiplayer_status MultiplayerStatus;
+unsigned int lastPingTime;
+
+const char * Rejection_Messages[][255] = {
+	{"Server is full"},
+	{"-2"},
+	{"-3"},
+	{"-4"},
+	{"-5"},
+};
+
+#define BETTER_SYNC
+
+
+
+
+short TRrAnimation_GetType(char* anim)
+{
+	return *(short*)(anim + 0x15A);
+}
+
+void ONrCharacter_SetAnimationInternal(Character* Char, ActiveCharacter* AChar,
+	short inFromState, short inNextAnimType, const void *TRAM)
+{
+	ONCC		*ONCC	= Char->ONCC;
+	void		*TRAC	= ONCC->TRAC;
+	short	index = Char->Number;
+	short animType;
+
+	if (TRAM == 0) return;
+
+	animType = TRrAnimation_GetType(TRAM);
+
+	AChar->Animation = TRAM;
+	AChar->Frame = 0;
+	AChar->AnimationFromState = inFromState;
+	AChar->AnimationType = animType;
+
+	AChar->NextAnimationType= inNextAnimType;
+	AChar->AnimationToState = TRrAnimation_GetTo(TRAM);
+
+	return;
+}
+
+
+
+
+
+
+//wtf, this needs cleaned up...
+player_info *FLr_FindEmptySlot() {
+	int j;
+	for(j = 0; j < MAX_PLAYERS; j++) {
+		if (Players[j].ip == 0) {
+			return &Players[j];
+		}
+	}
+	return 0;
+}
+
+extern uint16_t max_connections;
+uint16_t FLr_FindEmptyListSlot() {
+	int j;
+	for(j = 0; j < max_connections; j++) {
+		if (PlayerList[j] == 0) {
+			return j;
+		}
+	}
+	return -1;
+}
+typedef struct
+{
+	uint16_t x;
+	uint16_t y;
+} IMtPoint2D;
+static flatline_packet cache_input = {0};
+
+
+void * ONICALL FLrInput_Update_Keys(void) 
+{
+	uint32_t i;
+	flatline_packet all_input = {0};
+	int16_t InputIndex = 0;
+	
+	if(client_connected) 
+	{
+		int sent_bytes;
+		flatline_packet input_packet = {0};
+
+		FLrClient_GetPackets();
+
+		input_packet.id = PLAYER_INPUT;
+//		input_packet.input_struct.Time = ONgGameState->GameTime;
+		input_packet.input_struct.Actions1 = ONgGameState->Input.Current.Actions1;
+		input_packet.input_struct.Actions2 = ONgGameState->Input.Current.Actions2;
+		input_packet.input_struct.MouseDeltaX = ONgGameState->Input.MouseDeltaX;
+		input_packet.input_struct.MouseDeltaY = ONgGameState->Input.MouseDeltaY;
+		input_packet.input_struct.DesiredFacing = ONgGameState->PlayerCharacter->DesiredFacing;
+
+		sent_bytes = NetUDPSocket_Send(client_sock,(sockaddr *) &address, (char*)&input_packet, sizeof(input_struct) + FLATLINE_HEADER);
+
+		//return ONgGameState;
+	}
+
+
+	if(!(server_started || client_connected)) return ONgGameState;
+
+
+
+	for(i = 0; i < max_connections; i++) {
+		ActiveCharacter * Active_Player;
+		Character* Player;
+		GameInput * Active_Input;
+		if(PlayerList[i] == 0) continue;
+		
+
+
+		Player = PlayerList[i]->Chr;
+		Active_Player = ONrGetActiveCharacter( PlayerList[i]->Chr);
+
+		if(!Player)
+		{
+			DDrConsole_Print("Warning, missing Character!");
+			continue;
+		}
+
+		if( server_started && i != 0 )
+		{
+			PlayerList[i]->Chr->DesiredFacing = PlayerList[i]->FacingFromClient;
+		}
+
+
+		
+		//Set the health properly first.
+		//Always overridden by the server because of the chance of random damage and such
+		if( client_connected && DoWeUpdateThis( PlayerList[i]->UpdateFlags, PFlag_Health) )
+		{
+			PlayerList[i]->Chr->MaxHealth = PlayerList[i]->Health.MaxHealth;
+			ONrCharacter_SetHitPoints(  PlayerList[i]->Chr, PlayerList[i]->Health.Health);
+			//PlayerList[i]->UpdateFlags &= ~( 1 << PFlag_Health );
+		}
+
+		//If the player is dead
+		if( PlayerList[i]->Chr->Health == 0 )
+			
+		{
+			const short TicksToRespawn = 3 * 60;
+			
+			//Permanently kill off dumb AI
+			if(PlayerList[i]->flags & PF_SCRIPTEDAI)
+			{
+				FLrPlayerDisconnect( i );
+				continue;
+			}
+
+			//Just to know if we have started counting off the respawn
+			if(PlayerList[i]->state != STATE_DEAD)
+			{
+				PlayerList[i]->state = STATE_DEAD;
+				PlayerList[i]->DeathTime = ONgGameState->GameTime;
+				if(i == client_slot)
+				{
+					ONrGameState_Timer_Start( "", TicksToRespawn  );
+				}
+
+				if(server_started)
+				{
+					FLsPublic_Event( EV_KILLED, &i );	
+				}
+				
+			}
+
+			//Server respawning
+			if(server_started)
+			{
+				int Actions;
+				if(i == 0)
+				{
+					Actions =  ONgGameState->Input.Current.Actions1;
+				}
+				else
+				{
+					Actions = PlayerList[i]->InputFromClient.Actions1;
+				}
+
+				if(ONgGameState->GameTime - PlayerList[i]->DeathTime > TicksToRespawn && 
+					(Actions & (Action_Punch | Action_Kick)) )
+				{
+					FLrPlayerRespawn( i );
+					
+					FLsPublic_Event( EV_RESPAWN, &i );
+				}
+				else
+				{
+					continue;
+				}
+			}
+			else //clients?!
+			{
+				continue;
+			}
+		}
+
+		PlayerList[i]->state = STATE_ALIVE;
+
+		if( client_connected && DoWeUpdateThis( PlayerList[i]->UpdateFlags, PFlag_Class ) )
+		{
+			if(PlayerList[i]->Class)
+			{
+				ONrCharacter_SetCharacterClass( PlayerList[i]->Chr, PlayerList[i]->Class );
+			}
+			PlayerList[i]->UpdateFlags &= ~( 1 << PFlag_Class );
+		}
+
+		if( client_connected &&  DoWeUpdateThis( PlayerList[i]->UpdateFlags, PFlag_Facing ) )
+		{
+			PlayerList[i]->Chr->Facing = PlayerList[i]->Facings.Facing;					
+			if(i != client_slot)
+			{
+				PlayerList[i]->Chr->DesiredFacing = PlayerList[i]->Facings.DesiredFacing;
+			}
+			PlayerList[i]->UpdateFlags &= ~( 1 << PFlag_Facing );
+		}
+
+		if(Active_Player == 0) continue;
+
+		
+		
+			//		Active_Player->PlayingFilm.Flags = 1;
+
+					Active_Input = &(Active_Player->Input);
+
+		
+		if( (server_started && i !=0)  || !server_started ) 
+		{
+			Active_Input->Stop.Actions1 = ~PlayerList[i]->Input.Actions1 & Active_Input->Current.Actions1;
+			Active_Input->Stop.Actions2 = ~PlayerList[i]->Input.Actions2 & Active_Input->Current.Actions2;
+			Active_Input->Start.Actions1 = ~Active_Input->Current.Actions1 & PlayerList[i]->Input.Actions1;
+			Active_Input->Start.Actions2 = ~Active_Input->Current.Actions2 & PlayerList[i]->Input.Actions2;
+
+			Active_Input->Current.Actions1 = PlayerList[i]->Input.Actions1;
+			Active_Input->Current.Actions2 = PlayerList[i]->Input.Actions2;
+			Active_Input->Stopped.Actions1 = ~Active_Input->Current.Actions1;
+			Active_Input->Stopped.Actions2 = ~Active_Input->Current.Actions2;
+			if(client_connected && i == client_slot)
+			{
+				Active_Input->MouseDeltaX = ONgGameState->Input.MouseDeltaX;
+				Active_Input->MouseDeltaY = ONgGameState->Input.MouseDeltaY;
+			}
+			else
+			{
+				Active_Input->MouseDeltaX = PlayerList[i]->Input.MouseDeltaX;
+				Active_Input->MouseDeltaY = PlayerList[i]->Input.MouseDeltaY;
+			}
+		} 
+		
+		{
+		void* ConsoleAnimation = 0; 
+		TMrInstance_GetDataPtr( 'TRAM', "KONOKOwatch_idle", &ConsoleAnimation);
+
+		if(!Active_Player->IsInAir && Active_Input->Current.Actions1 & (Action_Console | Action_PauseScreen) 
+			&& !(PlayerList[i]->Chr->Flags & ONcCharacterFlag_BeingThrown)
+			&& Active_Player->ThrowTargetCharacter != -1)
+		{
+			if(ConsoleAnimation && ConsoleAnimation != Active_Player->Animation)
+			{
+				ONrCharacter_SetAnimationExternal(PlayerList[i]->Chr, Active_Player->AnimationFromState, ConsoleAnimation, 10);
+				Player->Flags |= 0x00200000;
+				Active_Player->ForcedAnimationFrames = -1;// TRrAnimation_GetDuration(ConsoleAnimation);
+			}
+		}
+		else if(Active_Input->Stopped.Actions1 & (Action_Console | Action_PauseScreen) )
+		{
+			Active_Player->ForcedAnimationFrames = 0;
+		}
+
+		}
+
+		//Check for character switching requests
+		if(server_started && PlayerList[i]->Chr->Health != 0 
+			&& PlayerList[i]->InputFromClient.Actions1 & Action_Block)
+		{
+			if( PlayerList[i]->ShapeshiftCooldown < ONgGameState->GameTime)
+			{
+				int error;
+
+
+
+				ONCC *newClass;
+				short numClasses = (short)TMrInstance_GetTagCount('ONCC');
+				/*
+				if(Active_Player->Input.Start.Actions1 & Action_Block)
+				{
+				//This might not be getting hit. Find out why, eh?
+				PlayerList[i]->ShapeshiftCooldown = ONgGameState->GameTime + 15;
+				}
+				else
+				{
+				PlayerList[i]->ShapeshiftCooldown = ONgGameState->GameTime + 5;
+				}
+				*/
+
+				PlayerList[i]->ShapeshiftCooldown = ONgGameState->GameTime + 15;
+
+				if (PlayerList[i]->InputFromClient.Actions1 & Action_Crouch) {
+					Player->ONCCnumber += numClasses - 1;
+				}
+				else {
+					Player->ONCCnumber += 1;
+				}
+
+				if (numClasses > 0) {
+					Player->ONCCnumber = Player->ONCCnumber % numClasses;
+
+					error = TMrInstance_GetDataPtr_ByNumber('ONCC', Player->ONCCnumber, &newClass); 
+
+					if ((newClass != NULL) && (!error)) {
+						ONrCharacter_SetCharacterClass(Player, newClass);
+					}
+				}
+
+			}
+		}
+		else
+		{
+			PlayerList[i]->ShapeshiftCooldown = 0;
+		}
+		if(client_connected) {
+
+			if( DoWeUpdateThis( PlayerList[i]->UpdateFlags, PFlag_Position) )
+			{
+				//Active_Player->PhyContext->Position = PlayerList[i]->Position;
+
+				Active_Player->PhyContext->Position.X = 
+					(PlayerList[i]->Position.X + Active_Player->PhyContext->Position.X) / 2;
+
+				Active_Player->PhyContext->Position.Y = 
+					(PlayerList[i]->Position.Y + Active_Player->PhyContext->Position.Y) / 2;
+
+				Active_Player->PhyContext->Position.Z = 
+					(PlayerList[i]->Position.Z + Active_Player->PhyContext->Position.Z) / 2;
+
+				PlayerList[i]->UpdateFlags &= ~( 1 << PFlag_Position );
+			}
+
+
+
+
+			if (!(Player->Flags & ONcCharacterFlag_BeingThrown) &&
+				DoWeUpdateThis( PlayerList[i]->UpdateFlags, PFlag_Animation) && (PlayerList[i]->Animation))
+			{
+				// get a pointer to the animation
+
+
+				if (PlayerList[i]->Animation != Active_Player->Animation)
+				{
+
+					///////////////////////////////////
+					//TODO: Check age of animation
+					///////////////////////////////////
+					// set the characters animation
+					/*ONrCharacter_SetAnimationInternal(Player,
+					Active_Player,
+					Active_Player->AnimationToState,
+					0,
+					PlayerList[i]->Animation);*/
+					//ONrCharacter_NewAnimationHook(Player, Active_Player);
+					ONrCharacter_SetAnimationExternal(Player, TRrAnimation_GetFrom(PlayerList[i]->Animation), PlayerList[i]->Animation, 1);
+					//ONrCharacter_NewAnimationHook(Player, Active_Player);
+				}
+
+
+			}
+			PlayerList[i]->UpdateFlags &= ~( 1 << PFlag_Animation );
+
+			//Disabled Frame syncing for now. In most cases it won't be useful.
+			if(0 && DoWeUpdateThis( PlayerList[i]->UpdateFlags, PFlag_FramePing) && PlayerList[i]->Frame != -1 
+				//&& !DoWeUpdateThis( PlayerList[i]->UpdateFlags, PFlag_Animation) 
+				)
+			{
+				if( abs(PlayerList[i]->Frame - Active_Player->Frame) > 2 )
+				{
+					short AnimationLength;
+					AnimationLength = TRrAnimation_GetDuration(Active_Player->Animation);
+					if (PlayerList[i]->Frame >= AnimationLength)
+					{
+						Active_Player->Frame = AnimationLength - 1;
+						//Active_Player->Frame = 0;
+					}
+					else
+					{
+						Active_Player->Frame = PlayerList[i]->Frame;
+					}
+				}
+
+			}
+			PlayerList[i]->UpdateFlags &= ~( 1 << PFlag_FramePing );
+
+			//Increment frame in case we were waiting
+			PlayerList[i]->Frame++;
+
+			if (DoWeUpdateThis( PlayerList[i]->UpdateFlags, PFlag_Throws) 
+				&& PlayerList[i]->ThrowData.throwName[0] != 0)
+			{
+				if(PlayerList[PlayerList[i]->ThrowData.throwing])
+				{
+					short throwTarget = PlayerList[PlayerList[i]->ThrowData.throwing]->spawnnumber;
+					/*if ((throwTarget != Active_Player->throwing) &&
+					(PlayerList[i]->ThrowData.throwFrame < 10))*/
+					{
+						void	*throw_animation;
+						ActiveCharacter* Target;
+						// get the animation
+
+						TMrInstance_GetDataPtr(
+							'TRAM',
+							PlayerList[i]->ThrowData.throwName,
+							&throw_animation);
+						//if (error) return;
+
+						// set the throw target
+						Active_Player->ThrowTargetCharacter = &ONgGameState->CharacterStorage[throwTarget];
+						Target = ONrGetActiveCharacter(Active_Player->ThrowTargetCharacter);
+						//if (/*(Target->Animation != throw_animation) &&*/
+						//	(OldAnimation != Animation) &&
+						//	!(Active_Player->ThrowTargetCharacter->Flags & ONcCharacterFlag_BeingThrown))
+						//	Target->thrownBy == -
+						{
+							// set the throw variables
+							Active_Player->targetThrow	= throw_animation;
+							Active_Player->throwing		= throwTarget;
+
+							// run the throw
+							ONrCharacter_NewAnimationHook(Player, Active_Player);
+
+							//if (Active_Player->ThrowTargetCharacter)
+							{
+								//		Target->Frame += 2;
+								//DDrConsole_PrintF("Thrown by player %hi", Player->Number );
+								//DDrStartupMessage("Thrown by player %hi", Player->Number );
+								Target->thrownBy = Player->Number & 0x00ff;
+							}
+						}
+					}
+				}
+				else
+				{
+					DDrConsole_PrintF("Warning, tried to throw nonexistant player %hi", 
+						PlayerList[i]->ThrowData.throwing );
+				}
+			} 
+
+			//Always discard old throw data, even if it isnt applied
+			PlayerList[i]->UpdateFlags &= ~( 1 << PFlag_Throws );
+		}
+
+
+	}
+	
+	if(server_started)
+	{
+		if(ONgGameState->GameTime % 120 == 0)
+		{
+			FLsPingAll();
+		}
+
+		if(PlayerList[0])
+		{
+			PlayerList[0]->InputFromClient.Actions1 = ONgGameState->Input.Current.Actions1;
+			PlayerList[0]->InputFromClient.Actions2 = ONgGameState->Input.Current.Actions2;
+			PlayerList[0]->InputFromClient.MouseDeltaX = ONgGameState->Input.MouseDeltaX;
+			PlayerList[0]->InputFromClient.MouseDeltaY = ONgGameState->Input.MouseDeltaY;
+		}
+		FLsSendPlayerData();
+	}
+	MultiplayerStatus.PleaseUpdateAllPlayers = 0;
+	return ONgGameState;
+}
+
+void FLrPlayerDisconnect( int Player )
+{
+	if(server_started)
+	{
+		//FLsPublic_Event(EV_DISCONNECT, &Player );
+		MultiplayerStatus.PleaseUpdateAllPlayers = 1;
+	}
+	//Kill off the character in another function, please
+	//ONrCharacter_SetHitPoints(  PlayerList[Player]->Chr, 0);
+
+	memset(PlayerList[Player], 0, sizeof(player_info));
+	PlayerList[Player] = 0;
+
+
+
+	return;
+}
+
+void FLrPlayerRespawn( int Player )
+{
+	PlayerList[Player]->state = STATE_ALIVE;
+	ONrCorpse_Create(PlayerList[Player]->Chr);
+	ONrCharacter_SetHitPoints(  PlayerList[Player]->Chr, PlayerList[Player]->Chr->MaxHealth );
+}
+
+
+void* ScoreboardInstance = 0;
+void FLrRun_Scores()
+{
+	if(client_connected || server_started)
+	{
+		if(!ScoreboardInstance){
+			void* TSFFTahoma;
+			TMrInstance_GetDataPtr( 'TSFF', "Tahoma", &TSFFTahoma);
+			TSrContext_New( TSFFTahoma, 7, 1, 1,  0, &ScoreboardInstance);
+		}
+		if(ScoreboardInstance){
+			const int white =	0x00FFFFFF;
+			const int green =	0x0000FF00;
+			const int red =		0x00FF0000;
+			const int blue =	0x000000FF;
+			int i;
+			char DrawString[255];
+			const int LineHeight = 15;
+			IMtPoint2D DrawLocation = {25, 20};
+			TSrContext_SetShade(ScoreboardInstance, white);
+			TSrContext_DrawText(ScoreboardInstance, "Oni Flatline build " __DATE__ " " __TIME__, 255, 0, &DrawLocation);
+			TSrContext_SetShade(ScoreboardInstance, white);
+			DrawLocation.y += LineHeight;
+			DrawLocation.x = 25;
+			TSrContext_DrawText(ScoreboardInstance, "Name", 255, 0, &DrawLocation);
+			DrawLocation.x += 150;
+			TSrContext_DrawText(ScoreboardInstance, "Score", 255, 0, &DrawLocation);
+			DrawLocation.x += 50;
+			TSrContext_DrawText(ScoreboardInstance, "Ping", 255, 0, &DrawLocation);
+			for(i = 0; i <MAX_PLAYERS; i++)
+			{
+				if(PlayerList[i] == 0 || PlayerList[i]->Chr == 0) continue;
+
+				DrawLocation.x = 10;
+				DrawLocation.y += LineHeight;
+
+				sprintf(DrawString, "%i.", i );
+				TSrContext_DrawText(ScoreboardInstance, DrawString, 255, 0, &DrawLocation);
+				DrawLocation.x += 15;
+
+				if(PlayerList[i]->Chr && PlayerList[i]->Chr->Health == 0) 
+				{
+					TSrContext_SetShade(ScoreboardInstance, red);
+				}
+				else if (i == client_slot)
+				{
+					TSrContext_SetShade(ScoreboardInstance, green);
+				}
+				TSrContext_DrawText(ScoreboardInstance, PlayerList[i]->name, 255, 0, &DrawLocation);
+				TSrContext_SetShade(ScoreboardInstance, white);
+				DrawLocation.x += 150;
+				sprintf(DrawString, "%i", PlayerList[i]->Chr->Damage);
+				TSrContext_DrawText(ScoreboardInstance, DrawString, 255, 0, &DrawLocation);
+				DrawLocation.x += 50;
+				sprintf(DrawString, "%i", PlayerList[i]->Ping);
+				TSrContext_DrawText(ScoreboardInstance, DrawString, 255, 0, &DrawLocation);
+			}
+		}
+	}
+}
+
+bool FlatlineInitialize()
+{
+	memset( Players, 0, sizeof( player_info ) * MAX_PLAYERS );
+	memset( PlayerList, 0, 4 * MAX_PLAYERS );
+	memset( &MultiplayerStatus, 0, sizeof( multiplayer_status ));
+	return 1;
+}
Index: /Daodan/src/Flatline.h
===================================================================
--- /Daodan/src/Flatline.h	(revision 876)
+++ /Daodan/src/Flatline.h	(revision 876)
@@ -0,0 +1,308 @@
+#pragma once
+#ifndef FLATLINE_H
+#define FLATLINE_H
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+//#define DDrStartupMessage printf
+
+#include <string.h>
+////#include <stdint.h>
+
+#define thread __thread
+
+#include "Flatline_Public.h"
+
+#include <winsock2.h>
+#include "Flatline_Win32.h"
+#else
+#include <sys/ioctl.h> 
+#include <sys/types.h>
+#include <sys/socket.h> 
+#include <unistd.h> 
+#include <stropts.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+
+#define NetPlatform_Initalize() /* */
+#define NetPlatform_Shutdown() /* */
+#define closesocket close
+#define ioctlsocket ioctl
+#endif
+
+#include "Daodan.h"
+#include "BFW_Utility.h"
+#include "Daodan_Console.h"
+#include "Oni_Character.h"
+#include "Oni_Gamestate.h"
+#include "Flatline_Packet.h"
+
+#include "Oni_Symbols.h"
+//#define breakpoint asm("int3")
+
+
+#include "Flatline_Net.h"
+
+DWORD WINAPI StartServer(void* lol);
+DWORD WINAPI StartClient(void* lol);
+
+
+//initial connection
+typedef struct {
+	char country[2];
+	char name[256];
+} connect_send; //signature="CONNECT\0"
+
+//reply to connection.
+//goodtogo is if it is going to let you in
+//message is optional, only used for denial message
+typedef struct {
+	bool goodtogo;
+	int player_slot;
+	char message[256];
+} connect_reply;
+
+//um, status of the server? :/
+//probably obsolete. revive again once i do something crazy
+//like make a master server
+typedef struct {
+	char name[256];
+	uint32_t numplayers; //signature="STATUS\0\0"
+} server_status;
+
+typedef struct {
+	uint16_t	 Playernumber;
+	CharacterObject Character;
+} new_player;
+
+//extern int update_rate;
+
+typedef struct {
+	float MouseDeltaX;
+	float MouseDeltaY;
+	uint32_t Actions1;
+	uint32_t Actions2;
+	float DesiredFacing;
+	//unsigned int Time;
+} input_struct;
+
+//TODO:
+//Varient
+//Figure out + fix overlays
+//AC->HeadFacing
+//AC->HeadPitch
+typedef struct {
+	uint16_t				throwing;
+	uint16_t				throwFrame;
+	char					throwName[32];
+} td;
+/*
+typedef struct {
+	uint16_t PlayerNum;
+	//Vector3 Position;
+	
+	//float Facing;
+	//float DesiredFacing;
+
+	float UD;
+	float LR;
+
+	uint32_t Health;
+	uint32_t MaxHealth;
+	//input_struct Inputs;
+	int rare_sync_index;
+	char Animation[32];
+	uint16_t Frame;
+	td throw_data;
+	int Kills;
+	int Damage;
+	int Deaths;
+	uint16_t Ping;
+
+} player_data;
+*/
+//todo, move health in...
+/*typedef struct {
+	short unsigned int PlayerNum;
+	unsigned int index;
+	Inventory Inventory;
+	char Class[32];
+} rare_sync_data;
+*/
+typedef struct {
+	unsigned int event_index;
+	int intArray[];
+} flatline_event;
+/*
+typedef struct {
+	int16_t PlayerNum;
+	float MouseDeltaX;
+	float MouseDeltaY;
+	uint32_t Actions1;
+	uint32_t Actions2;
+	float Facing;
+	float DesiredFacing;
+	Vector3 Position;
+} player_input;
+*/
+//used for storing data about each player
+typedef struct {
+	//int	FLATLINE;
+	short	signature;
+	short	id;
+	int		size;
+	//int		packet_index;
+	union	
+	{
+		char			data[1080];
+		connect_reply	connect_reply;
+		connect_send	connect_send;
+		input_struct	input_struct;
+		new_player		new_player;
+		server_status	server_status;
+		//player_data		player_data;
+		//rare_sync_data  rare_sync_data;
+		uint16_t		sync_request;
+		flatline_event	flatline_event;
+		uint32_t		ping;
+		//player_input	all_input[33];
+		uint32_t		integer; //generic integer ;)
+	};
+} flatline_packet;
+#define FLATLINE_HEADER (sizeof(flatline_packet)-sizeof(char)*1080)
+//#define FLATLINE_PACKET_SIZE sizeof(flatline_packet) 
+
+
+bool FLrServer_PacketCallback(char* data, int datalen, int from);
+bool FLrServer_Run();
+bool FLrClient_Run(flatline_packet* packet);
+extern int sock;
+
+enum {
+	NULL_PACKET, //Don't use. ;)
+	CONNECT_SEND,
+	CONNECT_REPLY,
+	STATUS,
+	MESSAGE,
+	CHANGE_NAME,
+	ECHO,
+	NEW_PLAYER,
+	PLAYER_INPUT,
+	//PLAYER_DATA,
+	//RARE_SYNC_DATA,
+	//RARE_SYNC_DATA_REQUEST,
+	FLATLINE_EVENT,
+	PK_PING,
+	PK_PONG,
+	//PK_ALL_INPUT,
+	PK_PLAYER_DATA,
+	PK_MISSING_PLAYER,
+};
+
+enum FlatlineEvent {
+	EV_RESPAWN,
+	EV_KILLED,
+	EV_DISCONNECT,
+	EV_DOOR_OPEN,
+	EV_CONSOLE_USE,
+	EV_MAX,
+};
+
+
+typedef struct {
+	//Server Only
+	bool PleaseUpdateAllPlayers;
+	//Client stuff (can be used by server "client")
+
+	//Move from random scattered bools to these, please.
+	bool ClientConnected;
+	unsigned int ClientSlot;
+	bool ServerStatus;
+} multiplayer_status;
+
+enum {
+	STATE_ALIVE,
+	STATE_DEAD,
+};
+enum {
+	PF_HOST,
+	PF_BOT,
+	PF_SCRIPTEDAI,
+};
+typedef struct {
+	int	 ip;
+	char name[32]; 
+	char country[2];
+	Character* Chr;
+	uint16_t spawnnumber;
+	uint16_t list_slot;
+
+	PlayerInput InputFromClient;
+	float FacingFromClient;
+
+	////////////////////////////
+	//Sync stuff
+	////////////////////////////
+	uint16_t UpdateFlags;
+
+	PlayerInput Input;
+	PlayerHealth Health;
+	PlayerFacing Facings;
+	PlayerScore Score;
+	void* Animation;
+	char AnimationString[32];
+	uint16_t Frame;
+	PlayerThrowData ThrowData;
+	void* Class;
+	char ClassString[32];
+	PlayerInventory Inventory;
+	Vector3 Position;
+	////////////////////////////
+	bool HasAppliedThrow;
+
+	unsigned int LastInputTime;
+
+
+	uint16_t state;
+	int flags;
+	int DeathTime;
+	uint32_t Ping;
+	bool DataApplied;
+	bool NeedToSetFP;
+	uint32_t ShapeshiftCooldown;
+} player_info;
+
+player_info * FLr_FindEmptySlot();
+uint16_t FLr_FindEmptyListSlot();
+void * ONICALL FLrInput_Update_Keys(void);
+
+void NetCatchError();
+#define MAX_PLAYERS 32
+#define CONNECTION_TIMEOUT 15
+#define MAX_CONNECTIONS 32
+#define NetTCPSocket_Send NetUDPSocket_Send
+#define NetTCPServer_Send NetUDPServer_Send
+extern int client_sock;
+//these two could probably be combined
+extern sockaddr_in client_address;
+extern sockaddr_in address;
+extern player_info Players[];
+extern player_info * PlayerList[];
+extern multiplayer_status MultiplayerStatus;
+int UDPServer_SendToAll(void* packet, int size);
+
+
+void FLrRun_Scores();
+void FLrPlayerDisconnect( int Player );
+void FLrPlayerRespawn( int Player );
+int FLrEvent_GetNumArgs( int eventIndex );
+bool FlatlineInitialize();
+
+bool DoWeUpdateThis( uint16_t BitSet, uint16_t Flag );
+
+extern unsigned int lastPingTime;
+
+extern char player_name[32];
+
+#define FLATLINE_PORT 27778
Index: /Daodan/src/Flatline_BSL.c
===================================================================
--- /Daodan/src/Flatline_BSL.c	(revision 876)
+++ /Daodan/src/Flatline_BSL.c	(revision 876)
@@ -0,0 +1,248 @@
+#include <winsock2.h>
+#include "BFW_ScriptLang.h"
+
+#include "Daodan_Patch.h"
+#include "Daodan_BSL.h"
+#include "Flatline_BSL.h"
+#include "Flatline.h"
+#include "Flatline_Server.h"
+#include "Mariusnet_Public.h"
+#include "Flatline_Client.h"
+unsigned char server_started = 0;
+unsigned char client_connected = 0;
+int sock = 0;
+sockaddr_in address;
+char player_name[32] = "Striker";
+char player_country[256] = {0};
+int update_rate = 5;
+#include "Oni.h"
+#include "Daodan_Cheater.h"
+uint16_t ONICALL start_server(sl_callinfo* callinfo, uint32_t numargs, sl_arg args[], int* dontuse1, int* dontuse2, sl_arg* ret)
+{
+	CreateThread(NULL, 0, StartServer, NULL, 0, 0);
+	server_started = 1;
+	return 0;
+}
+
+uint16_t ONICALL control_update_rate(sl_callinfo* callinfo, uint32_t numargs, sl_arg args[], int* dontuse1, int* dontuse2, sl_arg* ret)
+{
+	update_rate = args[0].val.value_int32;
+	server_started = 1;
+	return 0;
+}
+
+uint16_t ONICALL change_name(sl_callinfo* callinfo, uint32_t numargs, sl_arg args[], int* dontuse1, int* dontuse2, sl_arg* ret)
+{
+
+	//should also return your name...
+	sprintf(player_name, "%.31s", args[0].val.value_str32);
+	if(client_connected) {
+		flatline_packet packet;	
+		packet.id = CHANGE_NAME;
+		memcpy(packet.data, args[0].val.value_str32, 256);
+		NetUDPSocket_Send(client_sock, (sockaddr*)&address, (char*)&packet, 257);
+	}
+	if(server_started)
+	{
+		FLsUpdateName( 0, args[0].val.value_str32 );
+	}
+	return 0;
+}
+
+uint16_t ONICALL send_message(sl_callinfo* callinfo, uint32_t numargs, sl_arg args[], int* dontuse1, int* dontuse2, sl_arg* ret)
+{
+
+	flatline_packet message;
+	message.id = MESSAGE;
+
+	if(server_started) {
+		int message_size = sprintf(message.data, "%s: %s", player_name, args[0].val.value_str32);
+		COrMessage_Print(message.data, "chat", 0);
+		UDPServer_SendToAll(&message, message_size + 1 + FLATLINE_HEADER );
+	}
+	else if(client_connected) {
+		sprintf(message.data, "%s", args[0].val.value_str32);
+		NetUDPSocket_Send(client_sock, (sockaddr*)&address, (char*)&message, 257);
+	}
+	else if(MsNet_Running) {
+		MSNet_SendChat( args[0].val.value_str32 );
+	}
+	else {
+		DDrConsole_PrintF("You aren't connected to a server!");
+	}
+	return 0;
+}
+
+
+uint16_t ONICALL connect_to_server(sl_callinfo* callinfo, uint32_t numargs, sl_arg args[], int* dontuse1, int* dontuse2, sl_arg* ret)
+{
+	//TODO: Move this into the client initialization. Doing it like this is silly.
+	FLcConnect(inet_addr(args[0].val.value_str32), htons(FLATLINE_PORT));
+	return 0;
+}
+uint16_t ONICALL status(sl_callinfo* callinfo, uint32_t numargs, sl_arg args[], int* dontuse1, int* dontuse2, sl_arg* ret)
+{
+	int j;
+	if(server_started) {
+		for(j = 0; j < max_connections; j++) {
+
+			if (PlayerList[j] != 0) {
+				DDrConsole_PrintF("Client %i: %s from %s", 
+					j,
+					PlayerList[j]->name,
+					inet_ntoa(*( (struct in_addr*)(int*)&(PlayerList[j]->ip )   )));
+			}
+		}
+	}
+	else if(client_connected) {
+		DDrConsole_PrintF("Connected to %s, port %i, socket %i", inet_ntoa(address.sin_addr), ntohs(address.sin_port), sock);
+		for(j = 0; j < max_connections; j++) {
+
+			if (PlayerList[j] != 0) {
+				DDrConsole_PrintF("Client %i: %s %x", 
+					j,
+					PlayerList[j]->name,
+					PlayerList[j]->Chr
+					);
+			}
+		}
+	}
+	else{}
+	return 0;
+}
+
+uint16_t ONICALL addfake(sl_callinfo* callinfo, uint32_t numargs, sl_arg args[], int* dontuse1, int* dontuse2, sl_arg* ret)
+{
+	player_info * info;
+	info = FLrServer_AddPlayer( 0, "shinny", 0 , 1);
+	return 0;
+}
+
+uint16_t ONICALL kick(sl_callinfo* callinfo, uint32_t numargs, sl_arg args[], int* dontuse1, int* dontuse2, sl_arg* ret)
+{
+	if(server_started && PlayerList[args[0].val.value_int32])
+	{
+	ONrCharacter_SetHitPoints(PlayerList[args[0].val.value_int32]->Chr, 0);
+	FLrPlayerDisconnect(args[0].val.value_int32);
+	FLsPublic_Event(EV_DISCONNECT, &args[0].val.value_int32);
+	}
+	return 0;
+}
+
+uint16_t ONICALL ping(sl_callinfo* callinfo, uint32_t numargs, sl_arg args[], int* dontuse1, int* dontuse2, sl_arg* ret)
+{
+	if(server_started)
+	{
+		FLsPingAll();
+	}
+	return 0;
+}
+
+CharacterObject* spawnObject = 0;
+char BINACHARCallback(CharacterObject* inObj, char* userdata)
+{
+	if(strcmp(userdata, inObj->OSD.Name))
+	{
+		return 1;
+	}
+	spawnObject = inObj;
+	return 0;
+}
+uint16_t ONICALL FLrSpawnHack(sl_callinfo* callinfo, uint32_t numargs, sl_arg args[], int* dontuse1, int* dontuse2, sl_arg* ret)
+{
+	flatline_packet new_char = {0};
+	int i;
+	if(client_connected) return 0;
+	AI2iScript_Spawn(callinfo, numargs, args, dontuse1, dontuse2, ret);
+	if(!server_started) return 0;
+	for(i = 0; i < 64; i++)
+	{
+		if(!strcmp(ONgGameState->CharacterStorage[i].Name, args[0].val.value_str32))
+		{
+			//DDrConsole_PrintF("%s spawned, slot %i", args[0].value_str32, i);
+			int		playerlist_slot = FLr_FindEmptyListSlot();
+			int player_slot = i;
+			new_char.new_player.Playernumber = playerlist_slot; 
+			new_char.id = NEW_PLAYER;
+			OBJrObjectType_EnumerateObjects('CHAR',BINACHARCallback, (int)args[0].val.value_str32);
+			//	while(!spawnObject);
+			if(spawnObject)
+			{
+				memcpy(&new_char.new_player.Character, spawnObject, sizeof(CharacterObject) );
+			}
+			else return 1;
+			//new_char.new_player.Character;
+			PlayerList[playerlist_slot] = Players+player_slot;
+			PlayerList[playerlist_slot]->spawnnumber = player_slot;
+			PlayerList[playerlist_slot]->Chr = &((Character *)(((GameState * )(ONgGameState))->CharacterStorage))[player_slot];
+			/*THIS MIGHT BE BAD*/ snprintf(PlayerList[playerlist_slot]->name, 32, "%s", PlayerList[playerlist_slot]->Chr->Name);
+			//			PlayerList[playerlist_slot]->Chr->Flags = chr_dontaim | chr_unkillable; //&= 0xFFBFFFFF; //WTF
+			//			if(!is_bot) PlayerList[playerlist_slot]->Chr->Flags &= 0xFFBFFFFF; //WTF
+			//			sprintf(PlayerList[playerlist_slot]->Chr->Name, "%.31s", name);		
+			UDPServer_SendToAll( (char*)&new_char, sizeof(new_player) + FLATLINE_HEADER );
+			PlayerList[playerlist_slot]->flags = PF_SCRIPTEDAI;
+			PlayerList[playerlist_slot]->list_slot = playerlist_slot;
+			return 0;
+		}
+	}
+
+	return 0;
+}
+
+uint16_t ONICALL list_players(sl_callinfo* callinfo, uint32_t numargs, sl_arg args[], int* dontuse1, int* dontuse2, sl_arg* ret)
+{
+	int i;
+	for(i = 0; i++; i < MAX_PLAYERS)
+	{
+		if(PlayerList[i])
+		{
+			DDrConsole_PrintF("%i %i | %s", i, PlayerList[i]->spawnnumber, PlayerList[i]->name);
+		}
+	}
+	return 0;
+}
+uint16_t ONICALL con(sl_callinfo* callinfo, uint32_t numargs, sl_arg args[], int* dontuse1, int* dontuse2, sl_arg* ret)
+{
+	OBJrConsole_OnActivate( OBJrConsole_GetByID(args[0].val.value_int32), PlayerList[0]->Chr );
+	return 0;
+}
+
+uint16_t tele(sl_callinfo* callinfo, uint32_t numargs, sl_arg args[], int* dontuse1, int* dontuse2, sl_arg* ret)
+{
+	ActiveCharacter *AC = ONrGetActiveCharacter(ONgGameState->PlayerCharacter);
+//	AC->PhyContext->Position = AC->AimTarget;
+	AC->PhyContext->Position.X += AC->AimVector.X;
+	AC->PhyContext->Position.Y += AC->AimVector.Y;
+	AC->PhyContext->Position.Z += AC->AimVector.Z;
+	return 0;
+}
+
+uint16_t ONICALL mnet_login(sl_callinfo* callinfo, uint32_t numargs, sl_arg args[], int* dontuse1, int* dontuse2, sl_arg* ret)
+{
+	MSNet_Login(args[0].val.value_str32, args[1].val.value_str32);
+	return 0;
+}
+
+extern uint16_t ONICALL mnet_joingame(sl_callinfo* callinfo, uint32_t numargs, sl_arg args[], int* dontuse1, int* dontuse2, sl_arg* ret);
+
+void SLrFlatline_Initialize() 
+{
+
+	DDrPatch_MakeCall(0x004FA88B, FLrInput_Update_Keys);
+	FLrInput_Update_Keys();
+	SLrGlobalVariable_Register_Int32("skip", "skips", &(((GameState*)ONgGameState)->field_40) );
+	SLrScript_Command_Register_Void("tele","teleports", "", tele);
+	SLrScript_Command_Register_ReturnType("connect","Connects to a server", "ip:string", sl_void, connect_to_server);
+	SLrScript_Command_Register_Void("host","Starts a server", "", start_server);
+	SLrScript_Command_Register_Void("msg","Sends a message", "", send_message);
+	SLrScript_Command_Register_ReturnType("name","changes your name", "name:string", sl_void, change_name);
+	SLrScript_Command_Register_Void("status","shows the connection status", "", status);
+	//SLrGlobalVariable_Register_String("country", "Your Multiplayer country", player_name);
+	SLrScript_Command_Register_ReturnType("addbot","adds a fake client", "", sl_void, addfake);
+	SLrScript_Command_Register_Void("kick", "Kicks a client from the server", "clientnum:int", kick);
+	SLrScript_Command_Register_Void("con", "Activates a console", "con:int", con);
+	SLrScript_Command_Register_Void("ping", "pong!", "", ping);
+
+	SLrScript_Command_Register_Void("login", "logs into mariusnet", "username:string password:string", mnet_login);
+	SLrScript_Command_Register_Void("join", "joins a mariusnet game", "index:int", mnet_joingame);
+}
Index: /Daodan/src/Flatline_BSL.h
===================================================================
--- /Daodan/src/Flatline_BSL.h	(revision 876)
+++ /Daodan/src/Flatline_BSL.h	(revision 876)
@@ -0,0 +1,6 @@
+#ifndef FLATLINE_BSL_H
+#define FLATLINE_BSL_H
+#include "Daodan.h"
+void SLrFlatline_Initialize();
+uint16_t ONICALL FLrSpawnHack(sl_callinfo* callinfo, uint32_t numargs, sl_arg args[], int* dontuse1, int* dontuse2, sl_arg* ret);
+#endif
Index: /Daodan/src/Flatline_Client.c
===================================================================
--- /Daodan/src/Flatline_Client.c	(revision 876)
+++ /Daodan/src/Flatline_Client.c	(revision 876)
@@ -0,0 +1,223 @@
+#include "Flatline.h"
+#include "Flatline_Client.h"
+#include "Mariusnet_Public.h"
+//#include "PortForwardWrapper.h"
+
+int client_slot = 0;
+RGBA green = {0, 0xFF, 0, 0};
+RGBA red = {0, 0, 0xFF, 0};
+RGBA grey = {0x80,0x80,0x80,0x80};
+
+
+int FLcEventHandler( int eventIndex, int args[] )
+{
+	switch(eventIndex)
+	{
+	case(EV_DISCONNECT):
+		FLrPlayerDisconnect( args[0] );
+		break;
+	case(EV_KILLED):
+		ONrCharacter_SetHitPoints( PlayerList[args[0]]->Chr, 0);
+	case(EV_DOOR_OPEN):
+		OBJrDoor_ForceOpen( args[0] );
+		break;
+	case(EV_CONSOLE_USE):
+		OBJrConsole_OnActivate( OBJrConsole_GetByID(args[0]), PlayerList[args[1]]->Chr );
+		break;
+	case(EV_RESPAWN):
+		ONrCorpse_Create(PlayerList[args[0]]->Chr);
+		break;
+	default:
+		break;
+	}
+	return 0;
+}
+
+void FLcConnect( int ip, short port )
+{
+	if(	NetPlatform_Initalize()) {
+		static flatline_packet packet;
+		memset(&client_address, 0, sizeof(sockaddr_in));
+		sock = NetUDPSocket_Create(ntohs(port), &client_address);
+		address.sin_family = AF_INET; address.sin_port = port; address.sin_addr.S_un.S_addr = ip;
+		//address.sin_family = AF_INET; address.sin_port = htons(27777); address.sin_addr.S_un.S_addr = inet_addr("192.168.0.1");	
+
+		packet.id = CONNECT_SEND;
+		memcpy(((connect_send*)(packet.data))->country ,  "XD", 2);
+		memcpy(((connect_send*)(packet.data))->name, player_name, 256);
+		DDrConsole_PrintF("%s", ((connect_send*)(packet.data))->name);
+		CreateThread(NULL, 0, StartClient, &packet, 0, 0);
+
+	}
+}
+
+bool FLrClient_Run(flatline_packet* packet)
+{
+
+	char data[1400];
+	uint16_t len;
+	int j;
+	int sent_bytes;
+
+/*	PortMappingContainer_C PMC = 
+	{
+		"", 
+		"27777",
+		"27777",
+		"UDP",
+		"",
+		"",
+		"Flatline!"
+	};
+
+	uPnP_Remove( &PMC );*/
+	client_connected = 0;
+
+	
+	//starts the connection
+	DDrConsole_PrintF("Connecting to server %s on socket %i",  inet_ntoa(address.sin_addr), client_sock);
+	sent_bytes = NetUDPSocket_Send(client_sock, (sockaddr*)&address, (char*)packet, FLATLINE_HEADER + sizeof(connect_send) );
+	if(sent_bytes == SOCKET_ERROR) {
+		NetCatchError();
+	}
+	//loops once per second waiting for a reply.
+	for(j = 0; j < CONNECTION_TIMEOUT; j++) {
+		while(NetUDPSocket_Recieve(client_sock, (sockaddr_storage *) &client_address, data, &len)){		
+			packet = (flatline_packet*)data;
+			if(packet->id == CONNECT_REPLY) {
+				if(packet->connect_reply.goodtogo){
+
+					client_connected = 1;
+
+					client_slot = ((connect_reply*)packet->data)->player_slot;
+
+					PlayerList[client_slot] = Players+client_slot;
+					PlayerList[client_slot]->Chr = ONgGameState->PlayerCharacter;
+
+					DDrConsole_PrintColored("Connection successful!",0,green, grey);
+
+					/*THIS MIGHT BE BAD*/ snprintf( PlayerList[client_slot]->name, 32, "%s", player_name );
+
+					//disable local input.
+					DDrPatch_NOOP(0x004FA929, 5 + 6 + 5);
+					
+					//Disable local turning
+					//DDrPatch_NOOP(0x004F7EA8, 2);
+					//DDrPatch_Byte( 0x004F7EB1 , 0xE9);
+					//DDrPatch_MakeJump( 0x004F7EB1, 0x004F8030 );
+
+
+					//DDrPatch_Byte(0x04ED6FB, 0xEB);
+
+					//DDrConsole_PrintF("Slot %i",  ((connect_reply*)packet)->player_slot);
+					//DDrPatch_NOOP(0x43B23,0x10);
+					//DDrPatch_NOOP(0x4EC248,(0x5A-0x48));
+					//DDrPatch_NOOP(0x4EC861, 6);
+
+					//Close Mariusnet collection because it hurts latency
+					MSNet_RoomExit();
+					break;
+				}
+				else {
+					DDrConsole_PrintF("Connection rejected: %s", ((connect_reply*)packet->data)->message);
+					return false;
+					break;
+				}
+			}
+		}
+		if(client_connected) break;
+		DDrConsole_PrintF("Connection timing out in %i seconds...", CONNECTION_TIMEOUT - j);
+		Sleep(1000);
+	}
+	//the client timed out without recieving an error message.
+	if(!client_connected) {
+		DDrConsole_PrintColored("Connection timed out.",0,red, grey);
+		return false;
+	}
+
+	return true;
+}
+
+
+void FLrClient_GetPackets()
+{
+	flatline_packet packet;
+	uint16_t len;
+	//#define SPAM_INPUT
+#ifdef SPAM_INPUT
+	struct timeval lasttime;
+	struct timeval thistime;
+	gettimeofday(&lasttime, 0);
+#endif
+	
+
+		while(NetUDPSocket_Recieve(client_sock, (sockaddr_storage *) &client_address, &packet, &len)) {
+			//packet = (flatline_packet*)data;
+			//DDrConsole_PrintF("Data recieved, length %i, type %i", len, ((flatline_packet*)data)->id);
+			switch(packet.id) {
+			case MESSAGE:
+				COrMessage_Print(packet.data, "chat", 0);
+				break;
+			case CHANGE_NAME:
+				if(PlayerList[(char)packet.data[0]])
+				{
+					char message_buffer[1024];
+					sprintf(message_buffer,"%s changed their name to %s", PlayerList[(char)packet.data[0]]->name, packet.data + 1);
+					COrMessage_Print(message_buffer, "name_change", 0);
+
+					/*THIS MIGHT BE BAD*/ snprintf(PlayerList[packet.data[0]]->name, 32, "%s", packet.data + 1);
+
+				}
+				break;
+			case CONNECT_SEND:
+				;if(1) {
+					flatline_packet connect_recv;
+					memcpy(&connect_recv.connect_reply.message,"This isn't a server!", sizeof("This isn't a server!"));
+					NetUDPSocket_Send(client_sock, (sockaddr *) &address, (char*)&connect_recv, sizeof(bool) + FLATLINE_HEADER + sizeof("This isn't a server!"));			
+				}
+			case CONNECT_REPLY:
+				break; //extra packet or something.
+			case NEW_PLAYER:
+				;if(1) { //haxhaxhax
+					CharacterObject* Char = &(packet.new_player.Character);
+					uint32_t chr_index = 0;
+					Character* PC;
+					DDrConsole_PrintF("%i |  %i", packet.new_player.Playernumber ,client_slot);
+					//Char->OSD.Options = 0;
+					if(packet.new_player.Playernumber == client_slot) {
+						PlayerList[packet.new_player.Playernumber] = &Players[0];
+						PC = (ONgGameState->PlayerCharacter);
+						Players[0].Chr = PC;
+
+					}
+					else {
+						ONrGameState_NewCharacter(Char, NULL, NULL, &chr_index);
+						ONgGameState->CharacterStorage[chr_index].charType = 0;
+						PlayerList[packet.new_player.Playernumber] = &Players[chr_index];
+						Players[chr_index].Chr = &(ONgGameState->CharacterStorage[chr_index]);
+						Players[chr_index].Chr->Flags &= 0xFFBFFFFF;
+						Players[chr_index].spawnnumber = chr_index;
+						DDrConsole_PrintF("Spawning player %s, class %s, slot  %i", ((new_player*)(packet.data))->Character.OSD.Name, ((new_player*)(packet.data))->Character.OSD.Class,chr_index) ;
+						/*THIS MIGHT BE BAD*/ snprintf(Players[chr_index].name, 32, "%s", ((new_player*)(packet.data))->Character.OSD.Name);
+					}
+					//Players[((new_player*)(packet.data))->Playernumber].spawnnumber = ONrGameState_NewCharacter(&(((new_player*)(packet.data))->Character), NULL, NULL, 0);
+					break;
+				}
+		
+			case FLATLINE_EVENT:
+				FLcEventHandler( packet.flatline_event.event_index, packet.flatline_event.intArray );
+				break;
+			case PK_PING:
+				packet.id = PK_PONG;
+				NetUDPSocket_Send(client_sock, (sockaddr *) &address, (char*)&packet, FLATLINE_HEADER + 4);		
+				break;
+			case PK_PLAYER_DATA:
+				FLcReadPlayerData( &packet, len );
+				break;
+			default:
+				DDrConsole_PrintF("Warning, recieved badly formed packet!");
+				break;
+			}
+	}
+}
+
Index: /Daodan/src/Flatline_Client.h
===================================================================
--- /Daodan/src/Flatline_Client.h	(revision 876)
+++ /Daodan/src/Flatline_Client.h	(revision 876)
@@ -0,0 +1,11 @@
+#ifndef FLATLINE_CLIENT_H
+#define FLATLINE_CLIENT_H
+#include "Flatline.h"
+
+int FLcEventHandler( int eventIndex, int Args[] );
+bool FLrClient_Run(flatline_packet* packet);
+void FLrClient_GetPackets();
+void FLcConnect( int ip, short port );
+extern int client_slot;
+
+#endif
Index: /Daodan/src/Flatline_Events.c
===================================================================
--- /Daodan/src/Flatline_Events.c	(revision 876)
+++ /Daodan/src/Flatline_Events.c	(revision 876)
@@ -0,0 +1,16 @@
+#include "Flatline.h"
+#include "Flatline_Hooks.h"
+
+const int EventArgs[EV_MAX] =
+{
+	1,//EV_RESPAWN,
+	1,//EV_KILLED,
+	1,//EV_DISCONNECT,
+	2,//EV_DOOR_OPEN,
+	2//EV_CONSOLE_USE,
+};
+
+int FLrEvent_GetNumArgs( int eventIndex )
+{
+	return EventArgs[eventIndex];
+}
Index: /Daodan/src/Flatline_Hooks.c
===================================================================
--- /Daodan/src/Flatline_Hooks.c	(revision 876)
+++ /Daodan/src/Flatline_Hooks.c	(revision 876)
@@ -0,0 +1,75 @@
+#include "Flatline.h"
+#include "Flatline_Hooks.h"
+#include "Flatline_Server.h"
+
+//Don't modify this.
+char * FLrHook_DoorOpen( DoorObject *Door, Character *Char)
+{
+	int crashStop;		
+	int Args[2] = {Door->Door.ID, 0};
+	if(server_started)
+	{
+		if(Char)
+		{
+			Args[1] = Char->Number;
+		}
+		else
+		{
+			Args[1] = -1;
+		}
+	}
+	crashStop = !server_started || FLsPublic_Event(EV_DOOR_OPEN, Args);
+	return (char*)(Door->Door.class);
+}
+short FLrHook_ConsoleActivate( void *inObject, Character *inCharacter )
+{
+	if(server_started)
+	{
+		int Args[2] = {*((char*)inObject + 0x2C), inCharacter->Number};
+		FLsPublic_Event(EV_CONSOLE_USE, Args);
+	}
+	return OBJrConsole_OnActivate( inObject, inCharacter );
+}
+
+int FLrHook_DebugNameTextureInit(short width, short height, int type, int allocated, int flags, char* name, void** output)
+{
+	//flags = (1 << 10);
+	type = 1;
+	//DDrPatch_Byte( 0x005EB83C + 3, 0xff );
+	DDrPatch_Int32( 0x005EB83C, 0xFF000000 );
+	return M3rTextureMap_New(width, height, type, allocated, flags, name, output);
+}
+
+short FLrHook_DebugNameShadeHack( Character* Char )
+{
+	
+	return TSrContext_SetShade(*(void**)0x005EB844, ONrCharacter_GetHealthShade( Char->Health, Char->MaxHealth ));
+	//return TSrContext_SetShade(*(void**)0x005EB844, 0xFFFFFFFF);
+}
+/*
+void FLrHook_Lasers( Character* PlayerChar )
+{
+	if(server_started || client_connected)
+	{
+		int i;
+		for(i = 0; i < MAX_PLAYERS; i++)
+		{
+			if(PlayerList[i] && PlayerList[i]->Chr && PlayerList[i]->Chr->Inventory.Weapons[0])
+			{
+				ONiDrawWeaponSight( PlayerList[i]->Chr );
+			}
+		}
+	}
+	else
+	{
+		if(
+		ONiDrawWeaponSight( ONgGameState->PlayerCharacter );
+	}
+}
+*/
+
+void FLrHook_Lasers( Character* Char )
+{
+	ONiDrawWeaponSight( Char );
+	AI2rDisplayDebuggingInfo( Char );
+}
Index: /Daodan/src/Flatline_Hooks.h
===================================================================
--- /Daodan/src/Flatline_Hooks.h	(revision 876)
+++ /Daodan/src/Flatline_Hooks.h	(revision 876)
@@ -0,0 +1,6 @@
+#include "Oni.h"
+char * FLrHook_DoorOpen( DoorObject *Door, Character *Char);
+short FLrHook_ConsoleActivate( void *inObject, Character *inCharacter );
+int FLrHook_DebugNameTextureInit(short width, short height, int type, int allocated, int flags, char* name, void** output);
+short FLrHook_DebugNameShadeHack( Character* Char );
+void FLrHook_Lasers( Character* PlayerChar );
Index: /Daodan/src/Flatline_Net.c
===================================================================
--- /Daodan/src/Flatline_Net.c	(revision 876)
+++ /Daodan/src/Flatline_Net.c	(revision 876)
@@ -0,0 +1,224 @@
+#include "Flatline.h"
+#include "Flatline_Server.h"
+
+
+#define TRACK_PACKETS
+
+/*thread */int UDPServer_Socket = 0;
+
+
+
+
+unsigned char NetUDPServer_Listen(uint16_t port, unsigned char (*packet_callback)(char* data, int datalen, int from))
+{
+	sockaddr_in address;	
+	UDPServer_Socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+	
+	if (UDPServer_Socket < 0)
+	{
+		DDrConsole_PrintF("could not create socket");
+		return false;
+	}
+	
+
+	memset(&address, 0, sizeof(sockaddr_in));
+	address.sin_family = AF_INET;
+	address.sin_addr.s_addr = htonl(INADDR_ANY);
+	address.sin_port = htons(port);
+	
+	if (bind(UDPServer_Socket, (sockaddr*)&address, sizeof(sockaddr_in)) < 0)
+	{
+		DDrConsole_PrintF("could not bind port %d", port);
+		closesocket(UDPServer_Socket);
+		return false;
+	}
+	else {
+
+
+		char data[65537] = {0};
+	
+		sockaddr_in from;
+		int recvlen;
+		FLrServer_Initialize();
+		for (;;)
+		{
+			int fromlen = sizeof(sockaddr_in);
+			memset(&from, 0, sizeof(sockaddr_in));
+			recvlen = recvfrom(UDPServer_Socket, data, 65537 - 1, 0, (sockaddr*)&from, (void*)&fromlen);
+
+			if (!packet_callback(data, recvlen, ntohl(from.sin_addr.s_addr)))
+				break; 
+		}
+		closesocket(UDPServer_Socket);
+		return true;
+	}
+}
+
+unsigned char NetUDPServer_Send(sockaddr* address, char* data, int datalen)
+{
+	//DDrConsole_PrintF("Sending data size %u to %s on socket %i", datalen, inet_ntoa( ((sockaddr_in*)address)->sin_addr ), UDPServer_Socket);
+	//data->FLATLINE = *(int*)"FLATLINE";
+	return NetUDPSocket_Send(UDPServer_Socket, address, data, datalen);
+}
+
+int client_sock = 0;
+sockaddr_in client_address;
+
+int NetUDPSocket_Create(uint16_t port, sockaddr_in* address)
+{
+	int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+
+		unsigned long nonBlocking = 1;
+	if (sock < 0)
+	{
+		DDrConsole_PrintF("could not create socket");
+		return -1;
+	}
+	
+
+//	memset(&client_address, 0, sizeof(sockaddr_in));
+	address->sin_family = AF_INET;
+	address->sin_addr.s_addr = htonl(INADDR_ANY);
+	address->sin_port =  htons(port);
+	
+	if (bind(sock, (sockaddr*)address, sizeof(sockaddr_in)) < 0)
+	{
+		DDrConsole_PrintF("could not bind port %d", port);
+		return false;
+	}
+	
+
+	if (ioctlsocket(sock, FIONBIO, &nonBlocking))
+	{
+		DDrConsole_PrintF("failed to set non-blocking socket");
+		return false;
+	}
+	client_sock = sock;
+	return sock;
+}
+
+int NetTCPSocket_Create(uint16_t port, sockaddr_in* address)
+{
+	int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+
+		unsigned long nonBlocking = 0;
+	if (sock < 0)
+	{
+		DDrConsole_PrintF("could not create socket");
+		return -1;
+	}
+	
+
+//	memset(&client_address, 0, sizeof(sockaddr_in));
+	//address->sin_family = AF_INET;
+	//address->sin_addr.s_addr = INADDR_ANY;
+	//address->sin_port =  htons(port);
+	/*
+	if (bind(sock, (sockaddr*)address, sizeof(sockaddr_in)) < 0)
+	{
+		DDrConsole_PrintF("could not bind port %d", port);
+		return false;
+	}
+	*/
+	/*
+	if (ioctlsocket(sock, FIONBIO, &nonBlocking))
+	{
+		DDrConsole_PrintF("failed to set non-blocking socket");
+		return false;
+	}*/
+	//client_sock = sock;
+	return sock;
+}
+
+void NetUDPSocket_Close(int socket)
+{
+	closesocket(socket);
+}
+
+int NetUDPSocket_Send(int socket, const sockaddr* address, char* data, int datalen)
+{
+	//currently only protects against duplicate packets.
+	int addr_size;
+	int sent_bytes;
+#if 0 //#ifdef TRACK_PACKETS
+	static uint32_t packet_index = 0;
+	packet_index = (packet_index + 1);
+	data->packet_index = packet_index;
+#endif
+	//data->FLATLINE = *(int*)"FLATLINE";
+	switch (address->sa_family)
+	{
+		case AF_INET:
+			addr_size = sizeof(sockaddr_in);
+			break;
+		case AF_INET6:
+			addr_size = sizeof(sockaddr_in6);
+			break;
+		default:
+			addr_size = sizeof(sockaddr_storage);
+	}
+	sent_bytes = sendto(socket, data, datalen, 0, address, addr_size);
+
+	if(sent_bytes == SOCKET_ERROR) {
+		NetCatchError();
+	}
+
+	return sent_bytes;
+}
+
+#ifdef TRACK_PACKETS
+uint32_t last_packet = -1;
+#endif
+
+unsigned char NetUDPSocket_Recieve(int socket, sockaddr_storage* address, char* data, uint16_t* datalen)
+{
+	int address_size = sizeof(sockaddr_storage);
+	uint32_t msg_size = recvfrom(socket, data, 1400, 0, (SOCKADDR *)address, &address_size);
+	if (msg_size == 0)
+		return false;
+	else if (msg_size == SOCKET_ERROR) {
+		int errorno = WSAGetLastError();
+		if (errorno == WSAEWOULDBLOCK) return false; //no packets.
+		else {
+			DDrConsole_PrintF("Packet type %i", ((flatline_packet*)data)->id);
+			NetCatchError();
+			return false;
+		}
+	}
+	*datalen = msg_size;				
+	return true;
+	
+}
+
+DWORD WINAPI StartServer(void* lol){
+	if(NetPlatform_Initalize() && FlatlineInitialize())
+	{
+		FLrServer_Run();
+	}
+	return 0;
+} 
+
+DWORD WINAPI StartClient(void* lol){
+	//NetPlatform_Initalize();
+	if(FlatlineInitialize())
+	{
+		FLrClient_Run((flatline_packet*)lol);
+	}
+	return 0;
+} 
+void NetCatchError(){
+	char Message[1024];
+	int errorno = WSAGetLastError();
+	if(errno == WSAEWOULDBLOCK) {
+		return;
+	}
+#ifdef WIN32
+
+	FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS |
+		FORMAT_MESSAGE_MAX_WIDTH_MASK, NULL, errorno,
+		MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+		(LPSTR) Message, 1024, NULL);
+	DDrConsole_Print(Message);
+#endif
+
+}
Index: /Daodan/src/Flatline_Net.h
===================================================================
--- /Daodan/src/Flatline_Net.h	(revision 876)
+++ /Daodan/src/Flatline_Net.h	(revision 876)
@@ -0,0 +1,33 @@
+#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 hostent hostent ;
+typedef struct in_addr in_addr;
+
+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();
+
+unsigned char NetUDPServer_Listen(uint16_t port, unsigned char (*packet_callback)(char* data, int datalen, int from));
+unsigned char 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, char* data, int datalen);
+void NetUDPSocket_Close(int sock);
+unsigned char NetUDPSocket_Recieve(int socket, sockaddr_storage* address, char* data, uint16_t* datalen);
+
+#endif
Index: /Daodan/src/Flatline_Packet.c
===================================================================
--- /Daodan/src/Flatline_Packet.c	(revision 876)
+++ /Daodan/src/Flatline_Packet.c	(revision 876)
@@ -0,0 +1,25 @@
+#include "Flatline_Packet.h"
+
+
+//Always keep this mirrored with the PFlags
+uint8_t sizes[] = 
+{
+	0,
+	sizeof(PlayerInput),	//PFlag_Input,
+	sizeof(PlayerFacing),	//PFlag_Facing,	
+	sizeof(PlayerHealth),	//PFlag_Health,		
+	sizeof(PlayerScore),	//PFlag_Score,		
+	sizeof(PlayerFP),		//PFlag_FramePing,
+	sizeof(PlayerInventory),//PFlag_Inventory,
+	32,						//PFlag_Class,	
+	12,						//PFlag_Position
+	32,						//PFlag_Animation,	
+	sizeof(PlayerThrowData),//PFlag_Throws,
+};
+
+//please oh please name this better
+uint16_t FLpData_PartSize( uint8_t e)
+{
+	if( e >= PFlag_Max ) return 0;
+	return sizes[e];
+}
Index: /Daodan/src/Flatline_Packet.h
===================================================================
--- /Daodan/src/Flatline_Packet.h	(revision 876)
+++ /Daodan/src/Flatline_Packet.h	(revision 876)
@@ -0,0 +1,81 @@
+#ifndef FLATLINE_PACKET_H
+#define FLATLINE_PACKET_H
+#include "stdint.h"
+
+
+uint16_t FLpData_PartSize( uint8_t e);
+void FLsSendPlayerData();
+//void FLcReadPlayerData( flatline_packet* Packet, int16_t Size );
+
+typedef struct
+{
+	uint16_t ID;
+	uint16_t Size;
+	uint16_t UpdateFlags;
+	uint8_t  data[255];
+} PlayerData;
+
+
+typedef struct {
+	uint32_t Actions1;
+	uint32_t Actions2;
+	float MouseDeltaX;
+	float MouseDeltaY;	
+} PlayerInput;
+
+typedef struct {
+	float Facing;
+	float DesiredFacing;
+} PlayerFacing;
+
+typedef struct {
+	uint16_t Health;
+	uint16_t MaxHealth;
+} PlayerHealth;
+
+typedef struct {
+	uint16_t Score;
+	uint16_t Deaths;
+} PlayerScore;
+
+//Change this later to be misc info
+typedef struct {
+	uint16_t Frame;
+	uint16_t Ping;
+} PlayerFP;
+
+typedef struct {
+	uint8_t Ammo;
+	uint8_t Cells;
+	uint8_t Hypo;
+	uint8_t pad;
+	uint16_t Invis;
+	uint16_t Shield;
+} PlayerInventory;
+
+typedef struct {
+	uint16_t				throwing;
+	uint16_t				throwFrame;
+	char					throwName[32];
+} PlayerThrowData;
+
+enum
+{
+	PFlag_None,
+	PFlag_Input,
+	PFlag_Facing,	
+	PFlag_Health,		
+	PFlag_Score,		//TODO
+	PFlag_FramePing,
+	PFlag_Inventory, //TODO
+	PFlag_Class,	
+	PFlag_Position,
+	PFlag_Animation,	
+	PFlag_Throws,
+	PFlag_Max,
+	PFlag_AnimationWait,//Clients only!
+};
+
+
+
+#endif
Index: /Daodan/src/Flatline_PacketBuilder.c
===================================================================
--- /Daodan/src/Flatline_PacketBuilder.c	(revision 876)
+++ /Daodan/src/Flatline_PacketBuilder.c	(revision 876)
@@ -0,0 +1,200 @@
+#include "Flatline.h"
+#include "Oni_Symbols.h"
+#include <assert.h>
+
+#define FLAG_AND_INCREMENT( FLAG )	PD->UpdateFlags |= (1 << FLAG ); DataPointer += FLpData_PartSize( FLAG );
+
+void FLsPacketBuild( uint8_t p, PlayerData* PD, bool UpdateAll )
+{
+	Character* Player = PlayerList[p]->Chr;
+	ActiveCharacter* APlayer = ONrGetActiveCharacter(Player);
+	player_info * PI = PlayerList[p];
+	uint8_t * DataPointer = PD->data;
+	PD->ID = p;
+	
+	//if ( data has changed )
+	//{
+	//	copy it to the buffer
+	//  copy it to the player info
+	//  set the changed flag
+	//  increment the buffer pointer
+	//}
+
+	/* 
+	//Could probably send this every frame, but afk players can save a few bytes, eh?
+	if( PI->Input.Actions1 != PI->InputFromClient.Actions1 ||
+		PI->Input.Actions2 != PI->InputFromClient.Actions2 ||
+		PI->Input.MouseDeltaX != PI->InputFromClient.MouseDeltaX ||
+		PI->Input.MouseDeltaY != PI->InputFromClient.MouseDeltaY )
+	{*/
+
+	//Better in case of dropped packets to send input every frame
+	if(1)
+	{
+		memcpy( DataPointer, &PI->InputFromClient, sizeof(PlayerInput));
+		PI->Input = PI->InputFromClient;
+
+		FLAG_AND_INCREMENT( PFlag_Input );
+	}
+
+	if( PI->Facings.Facing != Player->Facing ||
+		PI->Facings.DesiredFacing != Player->DesiredFacing || UpdateAll )
+	{
+		PlayerFacing* ptr = (void*)DataPointer;
+		ptr->Facing = Player->Facing;
+		ptr->DesiredFacing = Player->DesiredFacing;
+
+		PI->Facings = *ptr;
+
+		FLAG_AND_INCREMENT( PFlag_Facing );
+	}
+
+	if(PI->Health.Health != Player->Health ||
+		PI->Health.MaxHealth != Player->MaxHealth || UpdateAll )
+	{
+		PlayerHealth* ptr = (void*)DataPointer;
+		ptr->Health = Player->Health;
+		ptr->MaxHealth = Player->MaxHealth;
+
+		PI->Health = *ptr;
+
+		FLAG_AND_INCREMENT( PFlag_Health );
+	}
+
+	//Score
+	//skipping for now
+
+	//Frame and ping can be sent every frame, i guess. Improve this later,
+	if( 1 )
+	{
+		PlayerFP* ptr = (void*)DataPointer;
+		if(APlayer)
+		{
+			ptr->Frame = APlayer->Frame;
+		}
+		else
+		{
+			ptr->Frame = -1;
+		}
+		ptr->Ping = PI->Ping;
+
+		PI->Frame = ptr->Frame;
+
+		FLAG_AND_INCREMENT( PFlag_FramePing );
+	}
+	
+	//Skipping inventory because we dont need it right now
+	if( 0 )
+	{
+		//Do inventory
+	}
+
+	if( PI->Class != Player->ONCC || UpdateAll )
+	{
+		snprintf( DataPointer, 32, "%s", TMrInstance_GetInstanceName( Player->ONCC ) );
+		snprintf( PI->ClassString, 32, "%s", DataPointer );
+		PI->Class = Player->ONCC;
+
+		FLAG_AND_INCREMENT( PFlag_Class );
+	}
+
+	if(APlayer)
+	{
+		if( (APlayer->PhyContext) && (memcmp(&PI->Position, &APlayer->PhyContext->Position, sizeof(Vector3)) || UpdateAll ))
+		{
+			Vector3* ptr = (Vector3*)DataPointer;
+			*ptr = PI->Position = APlayer->PhyContext->Position;
+		
+			FLAG_AND_INCREMENT( PFlag_Position );
+		}
+
+		if(APlayer->Animation != PI->Animation || !APlayer->Frame || UpdateAll )
+		{
+			snprintf( DataPointer, 32, "%s", TMrInstance_GetInstanceName( APlayer->Animation ) );
+			snprintf( PI->AnimationString, 32, "%s", DataPointer );
+			PI->Animation = APlayer->Animation;
+
+			
+			FLAG_AND_INCREMENT( PFlag_Animation );
+		}
+
+		if(APlayer->targetThrow)
+		{
+			if(!PI->HasAppliedThrow || UpdateAll )
+			{
+				PlayerThrowData* ptr = (void*)DataPointer;
+				ptr->throwing = Players[APlayer->throwing].list_slot;
+				memcpy(ptr->throwName, TMrInstance_GetInstanceName(APlayer->targetThrow), 31);
+				ptr->throwFrame = ONrGetActiveCharacter(APlayer->targetThrow)->Frame;
+
+				PI->ThrowData = *ptr;
+
+				PI->HasAppliedThrow = 1;
+
+				FLAG_AND_INCREMENT( PFlag_Throws );
+			}
+		}
+		else
+		{
+			PI->HasAppliedThrow = 0;
+		}
+	}
+	
+	PD->Size = (uint32_t)DataPointer - (uint32_t)PD;
+
+	PI->UpdateFlags = PD->UpdateFlags;	
+	
+}
+
+
+
+void FLsSendPlayerData()
+{
+	PlayerData BuildData[32] = {0};
+	uint8_t p = 0;
+	uint32_t PacketSize = 0;
+	flatline_packet OutputPacket = {0};
+	uint8_t* OutputPointer = OutputPacket.data;
+	//Most of the time we won't even hit this. Could probably be bumped up a few hundred bytes
+	const uint32_t max_packet_size = 1000;
+
+	//Prepare buffers
+	OutputPacket.id = PK_PLAYER_DATA;
+	memset( BuildData, 0, sizeof(PlayerData) * 32 );
+
+	//Build data
+	for(p = 0; p < MAX_PLAYERS; p++)
+	{
+		if(PlayerList[p] && PlayerList[p]->Chr)
+		{
+			FLsPacketBuild(p, &BuildData[p], 0);
+			
+			assert( BuildData[p].Size < 255 );
+			
+			if( BuildData[p].Size > 0 )
+			{
+
+				//If we hit maximum size, send the packet and reset the buffer for a new one
+				if( BuildData[p].Size + PacketSize > max_packet_size )
+				{
+					UDPServer_SendToAll(&OutputPacket, PacketSize + FLATLINE_HEADER);
+
+					memset( OutputPacket.data, 0, PacketSize );
+					OutputPointer = OutputPacket.data;
+					PacketSize = 0;
+				}
+
+				//add to the packet
+				memcpy( OutputPointer, &BuildData[p], BuildData[p].Size );
+
+				OutputPointer += BuildData[p].Size;
+				PacketSize += BuildData[p].Size;
+			}
+		}
+	}
+	//Send data
+	if( PacketSize > 0 )
+	{
+		UDPServer_SendToAll(&OutputPacket, PacketSize + FLATLINE_HEADER);
+	}
+}
Index: /Daodan/src/Flatline_PacketReader.c
===================================================================
--- /Daodan/src/Flatline_PacketReader.c	(revision 876)
+++ /Daodan/src/Flatline_PacketReader.c	(revision 876)
@@ -0,0 +1,160 @@
+#include "Flatline.h"
+
+bool DoWeUpdateThis( uint16_t BitSet, uint16_t Flag )
+{
+	if( BitSet & (1 << Flag) ) return true;
+	return false;
+}
+
+//Long winded?
+
+
+
+void FLcPacketBufferToPlayerData( PlayerData* PD)
+{
+	player_info* PI = PlayerList[PD->ID];
+	uint8_t * DataPointer = PD->data;
+
+	static player_info BufferData[MAX_PLAYERS] = {0};
+	static bool IsBuffered[32];
+	
+
+	if(!PI)
+	{
+		//TODO: Store this data and then apply it once we have a character that matches!
+		flatline_packet pk;
+		pk.id = PK_MISSING_PLAYER;
+		pk.integer = PD->ID;
+		DDrConsole_Print("input");
+		NetUDPSocket_Send(client_sock, (sockaddr*)&address, (char*)&pk, FLATLINE_HEADER + 4 );
+		
+		IsBuffered[PD->ID] = 1;
+		PI = &BufferData[PD->ID];
+		
+		//return;
+	}
+	else if(IsBuffered[PD->ID])
+	{
+		player_info* Buffer = BufferData + PD->ID;
+		if( DoWeUpdateThis( Buffer->UpdateFlags, PFlag_Input) )	PI->Input = Buffer->Input;
+		if( DoWeUpdateThis( Buffer->UpdateFlags, PFlag_Facing) )	PI->Facings = Buffer->Facings;
+		if( DoWeUpdateThis( Buffer->UpdateFlags, PFlag_Health) )	PI->Health = Buffer->Health;
+		if( DoWeUpdateThis( Buffer->UpdateFlags, PFlag_FramePing) )	{
+			PI->Frame = Buffer->Frame;
+			PI->Ping = Buffer->Ping;
+		}
+		//if( DoWeUpdateThis( Buffer->UpdateFlags, PFlag_Inventory) )	PI->invi= Buffer->Input;
+		if( DoWeUpdateThis( Buffer->UpdateFlags, PFlag_Class) )	
+		{
+			PI->Class = Buffer->Class;
+			/*THIS MIGHT BE BAD*/ snprintf( PI->ClassString, 32, "%s", Buffer->ClassString );
+		}
+
+		if( DoWeUpdateThis( Buffer->UpdateFlags, PFlag_Position) )	PI->Position = Buffer->Position;
+		if( DoWeUpdateThis( Buffer->UpdateFlags, PFlag_Animation) )	
+		{
+			PI->Animation = Buffer->Animation;
+			/*THIS MIGHT BE BAD*/ snprintf( PI->AnimationString, 32, "%s", Buffer->AnimationString);
+		}
+		if( DoWeUpdateThis( Buffer->UpdateFlags, PFlag_Throws) )	PI->ThrowData = Buffer->ThrowData;
+		
+		PI->UpdateFlags |= Buffer->UpdateFlags;
+		IsBuffered[PD->ID] = 0;
+	}
+
+	if( DoWeUpdateThis( PD->UpdateFlags, PFlag_Input) )
+	{
+		PI->Input = *(PlayerInput*)DataPointer;
+		DataPointer += FLpData_PartSize( PFlag_Input);
+	}
+
+	if( DoWeUpdateThis( PD->UpdateFlags, PFlag_Facing) )
+	{
+		PI->Facings = *(PlayerFacing*)DataPointer;
+		DataPointer += FLpData_PartSize( PFlag_Facing);
+	}
+
+	if( DoWeUpdateThis( PD->UpdateFlags, PFlag_Health) )
+	{
+		PI->Health = *(PlayerHealth*)DataPointer;
+		DataPointer += FLpData_PartSize( PFlag_Health);
+	}
+
+	//Not done
+	if( DoWeUpdateThis( PD->UpdateFlags, PFlag_Score) )
+	{
+		PI->Score = *(PlayerScore*)DataPointer;
+		DataPointer += FLpData_PartSize( PFlag_Score);
+	}
+	
+	if( DoWeUpdateThis( PD->UpdateFlags, PFlag_FramePing) )
+	{
+		PlayerFP* FP = (PlayerFP*)DataPointer;
+		PI->Ping = FP->Ping;
+		
+		if(FP->Frame != -1)
+		{
+			PI->Frame = FP->Frame;
+		}
+		else
+		{
+			PD->UpdateFlags &= ~( 1 << PFlag_FramePing );
+		}
+		DataPointer += FLpData_PartSize( PFlag_FramePing);
+	}
+	
+	//Not done
+	if( DoWeUpdateThis( PD->UpdateFlags, PFlag_Inventory) )
+	{
+		PI->Inventory = *(PlayerInventory*)DataPointer;
+		DataPointer += FLpData_PartSize( PFlag_Inventory );
+	}
+		
+	if( DoWeUpdateThis( PD->UpdateFlags, PFlag_Class ) )
+	{
+		/*THIS MIGHT BE BAD*/ snprintf( PI->ClassString, 32, "%s", DataPointer );
+		TMrInstance_GetDataPtr( 'ONCC', (char*)DataPointer, &PI->Class ); 
+		DataPointer += FLpData_PartSize( PFlag_Class );
+	}
+		
+	if( DoWeUpdateThis( PD->UpdateFlags, PFlag_Position ) )
+	{
+		PI->Position = *(Vector3*)DataPointer;
+		DataPointer += FLpData_PartSize( PFlag_Position );
+	}
+		
+	if( DoWeUpdateThis( PD->UpdateFlags, PFlag_Animation ) )
+	{
+		/*THIS MIGHT BE BAD*/ snprintf( PI->AnimationString, 32, "%s", DataPointer );
+		TMrInstance_GetDataPtr( 'TRAM', PI->AnimationString, &PI->Animation );
+		DataPointer += FLpData_PartSize( PFlag_Animation );
+	}
+		
+	if( DoWeUpdateThis( PD->UpdateFlags, PFlag_Throws ) )
+	{
+		PI->ThrowData = *(PlayerThrowData*)DataPointer;
+		DataPointer += FLpData_PartSize( PFlag_Throws );
+	}
+
+
+	PI->UpdateFlags |= PD->UpdateFlags;
+}
+
+void FLcReadPlayerData( flatline_packet* Packet, int16_t Size )
+{
+	PlayerData* PDCast = (PlayerData*)Packet->data;
+	Size -= FLATLINE_HEADER;
+	while(Size > 0)
+	{
+		if(PDCast->Size > Size)
+		{
+			DDrConsole_PrintF( "Warning, (almost) read %hi bytes too much of player data buffer", -Size );
+			break;
+		}
+		FLcPacketBufferToPlayerData( PDCast );
+		Size -= PDCast->Size;
+		PDCast = (PlayerData*)((char*)PDCast + PDCast->Size);
+	}
+
+	//Packet
+}
Index: /Daodan/src/Flatline_Public.h
===================================================================
--- /Daodan/src/Flatline_Public.h	(revision 876)
+++ /Daodan/src/Flatline_Public.h	(revision 876)
@@ -0,0 +1,8 @@
+#ifndef FLATLINE_PUBLIC_H
+#define FLATLINE_PUBLIC_H
+
+extern unsigned char client_connected;
+extern unsigned char server_started;
+
+
+#endif
Index: /Daodan/src/Flatline_Server.c
===================================================================
--- /Daodan/src/Flatline_Server.c	(revision 876)
+++ /Daodan/src/Flatline_Server.c	(revision 876)
@@ -0,0 +1,425 @@
+#include "Flatline.h"
+#include "Flatline_Server.h"
+#include <Windows.h>
+//#include "PortForwardWrapper.h"
+#include "Mariusnet_Public.h"
+//I hereby apologize for the uglyness of the below code. 
+//It was never intended to be "final" code, much less shared with anyone
+
+int total_players = 0;
+uint16_t max_connections = MAX_CONNECTIONS;
+
+player_info* FLrServer_AddPlayer(int ip, char* name, bool is_server, bool is_bot) {
+	flatline_packet new_char = {0};
+	CharacterObject* Char;
+	uint32_t player_slot = 0;
+	int playerlist_slot = 0;
+	
+	if(is_server || total_players < max_connections) {
+		
+		int i = 0;
+		int k = 0;
+
+		//Skip for the host
+		if(!is_server)
+		{
+			char* zero = strchr(name, 0);
+			playerlist_slot = FLr_FindEmptyListSlot();
+
+			total_players++;
+
+			//checks to see if a name exists or not
+			//then appends [#] on the end of it if it does
+			//May be buggy, come back to this.
+			if(zero - name > 28) zero = name + 28; 
+			for(i = 0; i < max_connections; i++) {
+				if(PlayerList[i] != 0 && !strcmp(name, PlayerList[i]->name)) {
+					k++;				
+					sprintf(zero, "[%i]", k);
+					i = 0;
+				}
+			}
+		}
+		
+		new_char.new_player.Playernumber = playerlist_slot; 
+
+		//Set up a new Character structure to be spawned as the new player.
+		//Can this code be surrounded with if(!is_server){}?
+		Char = &new_char.new_player.Character;
+		memset(Char, 0, sizeof(CharacterObject));
+		Char->Header.Type = 'CHAR';
+		sprintf(Char->OSD.Name,"%s",name);
+		sprintf(Char->OSD.Class, "%s", "konoko_generic");
+		if(is_bot) {
+			Char->OSD.MeleeID = 22;
+			Char->OSD.JobID = 1;
+			Char->OSD.MinimalAlertLevel = 4;
+			Char->OSD.InvestigatingAlertLevel = 4;
+			Char->OSD.InitialAlertLevel = 4;
+			Char->OSD.StartJobAlertLevel = 4;
+		}
+		else if( !is_server )
+		{
+			Char->Header.Position.X = PlayerList[0]->Chr->Position.X;
+			Char->Header.Position.Y = PlayerList[0]->Chr->Position.Y;
+			Char->Header.Position.Z = PlayerList[0]->Chr->Position.Z;
+		}
+		
+		//TMrInstance_GetDataPtr('ONCC', "striker_easy_1", PlayerList[playerlist_slot]->Chr->ONCC);
+
+		new_char.id = NEW_PLAYER;
+		if(!is_server) { 
+			ONrGameState_NewCharacter(Char, NULL, NULL, &(player_slot));
+			//move this to a set up characters function...
+			if(!is_bot) ONgGameState->CharacterStorage[player_slot].charType = 0;
+
+			PlayerList[playerlist_slot] = Players+player_slot;
+			PlayerList[playerlist_slot]->spawnnumber = player_slot;
+			PlayerList[playerlist_slot]->Chr = &(ONgGameState->CharacterStorage)[player_slot];
+			//PlayerList[playerlist_slot]->Chr->Flags = chr_dontaim | chr_unkillable; //&= 0xFFBFFFFF; //WTF
+			if(!is_bot) PlayerList[playerlist_slot]->Chr->Flags &= 0xFFBFFFFF; //WTF, magic number. 
+			/*THIS MIGHT BE BAD*/ snprintf(PlayerList[playerlist_slot]->Chr->Name, 32, "%s", name);		
+			/*THIS MIGHT BE BAD*/ snprintf(PlayerList[playerlist_slot]->name, 32, "%s", name);		
+			UDPServer_SendToAll( (char*)&new_char, sizeof(new_player) + FLATLINE_HEADER );
+			
+		}
+		else {
+			PlayerList[0] = Players;
+			PlayerList[0]->Chr = (Character *)(((GameState * )(ONgGameState))->CharacterStorage);
+		}
+
+		//add player to list
+		
+		PlayerList[playerlist_slot]->ip = ip;
+		PlayerList[playerlist_slot]->list_slot = playerlist_slot;
+		/*THIS MIGHT BE BAD*/ snprintf(PlayerList[playerlist_slot]->name, 32, "%s", name);		
+		
+		MultiplayerStatus.PleaseUpdateAllPlayers = 1;
+
+		return &Players[player_slot];
+	}
+	return (player_info*)(-1);
+}
+
+void FLrServer_Initialize(){
+	FLrServer_AddPlayer(inet_addr("127.0.0.1"), "host", 1, 0);
+}
+
+//UDPServer_SendToAll
+//Sends a packet to all the clients currently connected.
+//Returns the number of players sent to.
+int UDPServer_SendToAll(void* packet, int size) {
+	int j;
+	int players = 0;
+	sockaddr_in address;
+	memset(&address, 0, sizeof(sockaddr_in)); 
+	address.sin_family = AF_INET;
+	address.sin_addr.s_addr = htonl(INADDR_ANY);
+	address.sin_port = htons(FLATLINE_PORT);
+	for(j = 0; j < max_connections; j++) {
+		if (PlayerList[j] != 0 && PlayerList[j]->ip && (PlayerList[j]->ip != inet_addr("127.0.0.1"))) {
+			int sent_bytes;
+			address.sin_addr.s_addr = htonl(PlayerList[j]->ip);//*((struct in_addr*)(int*)&(Players[j].ip));		
+			DDrConsole_PrintF("Sending packet to %i", PlayerList[j]->ip);
+			sent_bytes = NetUDPServer_Send((sockaddr *) &address, (char*)packet, size);
+			if(sent_bytes == SOCKET_ERROR) NetCatchError();
+			else players++;
+		}
+	}
+	return players;
+}
+
+//FLsPublic_Event
+//Sends an event (door opening, player disconnecting, etc) to all players
+//Always make sure you send a pointer to this, even if it is just one arg. ;).
+//If it is void the double door in State crashes. Probably stack corruption,
+//I'm not sure exactly why.
+//So we return 0 to stop that.
+int FLsPublic_Event( const unsigned int eventIndex, const int * args )
+{
+	int numArgs = FLrEvent_GetNumArgs( eventIndex );
+	int ret;
+	flatline_packet eventPacket = {0};
+	eventPacket.id = FLATLINE_EVENT;
+	eventPacket.flatline_event.event_index = eventIndex;
+	ret = memcpy( eventPacket.flatline_event.intArray, args, sizeof(int) * numArgs );
+	ret = UDPServer_SendToAll( &eventPacket, sizeof(int) * (numArgs + 1) + FLATLINE_HEADER );
+	return 0;
+}
+
+void FLsPingAll()
+{
+	flatline_packet ping;
+	ping.id = PK_PING;
+	lastPingTime = ping.ping = GetTickCount();
+	UDPServer_SendToAll(&ping, FLATLINE_HEADER + 4);
+}
+
+void FLsUpdateName( int index, char* name )
+{
+	flatline_packet message;
+	int message_size;	
+
+	char message_buffer[1024];
+	sprintf(message_buffer,"%s changed their name to %s", PlayerList[index]->name, name);
+	COrMessage_Print(message_buffer, "name_change", 0);
+	
+	/*THIS MIGHT BE BAD*/ snprintf(PlayerList[index]->name, 32, "%s", name);
+	/*THIS MIGHT BE BAD*/ snprintf(PlayerList[index]->Chr->Name, 32, "%s", name);
+
+	message.id = CHANGE_NAME;
+	message.data[0] = index;
+	message_size = sprintf(message.data + 1, "%s", name);
+
+	UDPServer_SendToAll(&message, message_size + 2 + FLATLINE_HEADER);
+}
+void FLsSend_BINACHAR( short j, sockaddr* socket )
+{
+
+	ActiveCharacter* AC = ONrGetActiveCharacter( PlayerList[j]->Chr);
+	flatline_packet new_char = {0};
+	CharacterObject* Char = &new_char.new_player.Character; 
+
+	new_char.id = NEW_PLAYER;
+	new_char.new_player.Playernumber = j;
+
+//	memset(Char, 0, sizeof(CharacterObject));
+	Char->Header.Type = 'CHAR';
+	Char->OSD.Options = chr_dontaim;
+
+	sprintf(Char->OSD.Name,"%s",PlayerList[j]->name);
+
+	sprintf(Char->OSD.Class, "%s", TMrInstance_GetInstanceName(PlayerList[j]->Chr->ONCC));
+		
+	if(AC && AC->PhyContext)
+	{
+		Char->Header.Position = AC->PhyContext->Position;
+	}
+	else
+	{
+		Char->Header.Position.X = 0;
+		Char->Header.Position.Y = 0;
+		Char->Header.Position.Z = 0;
+	}
+	
+	NetTCPServer_Send(socket, (char*)&new_char, sizeof(new_player) + FLATLINE_HEADER );
+}
+bool FLrServer_PacketCallback(char* data, int datalen, int from)
+{
+	int i, j;
+	bool found_player = 0;
+	flatline_packet * packet = (flatline_packet*)data;
+	static int recieved = 0;
+	sockaddr_in sender;
+	sender.sin_family = AF_INET;
+	sender.sin_port = htons(FLATLINE_PORT);
+	sender.sin_addr = *((struct in_addr*)(int*)&from);
+
+
+	//packet->data[datalen] = '\0';
+
+	//DDrConsole_PrintF("Packet \r%d recieved from %i",  ++recieved, from);
+
+
+
+	//if data[0] != CONNECT_SEND, search in playerlist for ip address
+
+
+
+
+	switch(packet->id) {
+		flatline_packet connect_recv;
+		player_info * playah;
+		//rewrite this when we get TCP support.
+		//rewrite this before we get TCP support*
+		//the way of seeing if there is room for players sucks.
+	case CONNECT_SEND:
+		;
+
+		connect_recv.id = CONNECT_REPLY;
+
+		//if(Players[i].ip == sender.sin_addr.S_un.S_addr) break; //needs to send an error message
+		sender.sin_addr.S_un.S_addr = htonl(sender.sin_addr.S_un.S_addr);
+		playah = FLrServer_AddPlayer(from,packet->connect_send.name, 0, 0);
+		DDrConsole_PrintF("%s connected from %s", packet->connect_send.name, inet_ntoa(sender.sin_addr ) );
+		if(!((int)playah > -5 && (int)playah <= 0)) {
+			
+			connect_recv.connect_reply.goodtogo = 1;
+			connect_recv.connect_reply.player_slot = playah->list_slot;
+			//DDrConsole_PrintF("Slot: %i", playah->list_slot);
+
+			//sending this several times to make sure it gets through. Really need to make up some form of packet tracking.
+			NetUDPServer_Send((sockaddr *) &sender, (char*)&connect_recv, sizeof(connect_reply) + FLATLINE_HEADER);
+			NetUDPServer_Send((sockaddr *) &sender, (char*)&connect_recv, sizeof(connect_reply) + FLATLINE_HEADER);
+			NetUDPServer_Send((sockaddr *) &sender, (char*)&connect_recv, sizeof(connect_reply) + FLATLINE_HEADER);
+			NetUDPServer_Send((sockaddr *) &sender, (char*)&connect_recv, sizeof(connect_reply) + FLATLINE_HEADER);
+			NetUDPServer_Send((sockaddr *) &sender, (char*)&connect_recv, sizeof(connect_reply) + FLATLINE_HEADER);
+			Sleep(100);
+
+			
+			
+			for(j = 0; j < max_connections; j++) {
+				if(PlayerList[j] != 0) {
+					FLsSend_BINACHAR( j, (sockaddr *)&sender);
+				}
+
+			}
+		}
+		else {
+			//fix the error messages...
+			DDrConsole_PrintF("Server is full. :(");
+			connect_recv.connect_reply.goodtogo = 0;
+			sender.sin_addr.S_un.S_addr = htonl(sender.sin_addr.S_un.S_addr);
+			memcpy(&connect_recv.connect_reply.message,"Server is full.", sizeof("Server is full."));
+			NetTCPServer_Send((sockaddr *) &sender, (char*)&connect_recv, sizeof(bool)*2 + FLATLINE_HEADER + sizeof("Server is full."));	
+
+		} 
+
+
+		break;
+	case CONNECT_REPLY:
+		break;	//do nothing...a server shouldn't recieve this type of packet.
+	case MESSAGE:
+		for(i = 0; i < MAX_PLAYERS; i++) {
+			//DDrConsole_PrintF("%i : %i | %s : %s", from, Players[i].ip, inet_ntoa(*(struct in_addr*)&from), inet_ntoa(*(struct in_addr*)&(Players[i].ip)));
+			if(Players[i].ip == sender.sin_addr.S_un.S_addr) {
+				found_player = 1;
+				break;
+			}	
+		}
+		if(found_player == 0) break;
+		else {
+			char message_buffer[512] = {0};
+			flatline_packet message;
+			int message_size;
+			data[datalen] = 0;
+
+			DDrConsole_PrintF("%s: %s", Players[i].name, packet->data);
+			sprintf(message_buffer, "%s: %s", Players[i].name, packet->data);
+
+			message.id = MESSAGE;
+			message_size = sprintf(message.data, "%s", message_buffer);
+			COrMessage_Print(message_buffer, "chat", 0);
+			UDPServer_SendToAll(&message, message_size + 1 + FLATLINE_HEADER);
+			break;
+		}
+	case CHANGE_NAME:
+		for(i = 0; i < MAX_PLAYERS; i++) {
+			if(PlayerList[i] && PlayerList[i]->ip == sender.sin_addr.S_un.S_addr) {
+				found_player = 1;
+				break;
+			}	
+		}
+		if(found_player == 0) break;
+		else {
+			bool name_exists = 0;
+			for(j = 0; j < MAX_PLAYERS; j++) {
+				if(PlayerList[j] && !strcmp(packet->data, PlayerList[j]->name)) {
+					name_exists = 1;
+					break;
+				}
+			}
+			if(!name_exists) {
+				FLsUpdateName( i, packet->data );
+			}
+			break;
+		}
+	case PLAYER_INPUT:
+
+		for(i = 0; i < max_connections; i++) {
+			if(PlayerList[i] != 0 && PlayerList[i]->ip == sender.sin_addr.S_un.S_addr) {
+				found_player = 1;
+				break;
+			}	
+		}
+
+		if(found_player == 0) break;
+		else {
+			input_struct * packet_input = &packet->input_struct;
+
+
+			PlayerList[i]->InputFromClient.Actions1 = packet_input->Actions1;
+			PlayerList[i]->InputFromClient.Actions2 = packet_input->Actions2;
+			PlayerList[i]->InputFromClient.MouseDeltaX = packet_input->MouseDeltaX;
+			PlayerList[i]->InputFromClient.MouseDeltaY = packet_input->MouseDeltaY;
+			PlayerList[i]->FacingFromClient = packet_input->DesiredFacing;
+			//PlayerList[i]->LastInputTime = packet_input->Time;
+
+			break;
+		}
+	case PK_PONG:
+		for(i = 0; i < max_connections; i++) {
+			if(PlayerList[i] != 0 && PlayerList[i]->ip == sender.sin_addr.S_un.S_addr) {
+				found_player = 1;
+				break;
+			}	
+		}
+
+		if(found_player == 0) break;
+		if(packet->ping != lastPingTime)
+		{
+			PlayerList[i]->Ping = 999;
+		}
+		else
+		{
+			PlayerList[i]->Ping = GetTickCount() - packet->ping;
+		}
+		break;
+	case PK_MISSING_PLAYER:
+		if(packet->integer < MAX_PLAYERS)
+		{
+			FLsSend_BINACHAR( packet->integer, &sender);
+		}
+		break;
+	default:
+		DDrConsole_PrintF("Warning, recieved badly formed packet!");
+		break;
+	}
+	return true;
+}
+
+
+
+bool FLrServer_Run()
+{
+	m_announcegame Game;
+	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));
+
+	Game.port = htons(FLATLINE_PORT);
+	/*THIS MIGHT BE BAD*/ snprintf(Game.g.Buffer, 128, "%s's Game", MariusLogin);
+
+	MSNet_CreateGame( &Game );
+
+	return NetUDPServer_Listen(27777, FLrServer_PacketCallback);
+}
Index: /Daodan/src/Flatline_Server.h
===================================================================
--- /Daodan/src/Flatline_Server.h	(revision 876)
+++ /Daodan/src/Flatline_Server.h	(revision 876)
@@ -0,0 +1,16 @@
+#ifndef FLATLINE_SERVER_H
+#define FLATLINE_SERVER_H
+
+#define TOO_MANY_CONNECTIONS -1
+#include "Flatline.h"
+#include "winsock.h"
+
+
+extern uint16_t max_connections;
+player_info* FLrServer_AddPlayer(int ip, char* name, bool is_server, bool is_bot);
+int FLsPublic_Event( const unsigned int eventIndex, const int * args);
+
+void FLrServer_Initialize();
+void FLsPingAll();
+void FLsUpdateName( int index, char* name );
+#endif
Index: /Daodan/src/Flatline_Win32.c
===================================================================
--- /Daodan/src/Flatline_Win32.c	(revision 876)
+++ /Daodan/src/Flatline_Win32.c	(revision 876)
@@ -0,0 +1,22 @@
+#include "Flatline.h"
+unsigned char WSAStarted = 0;
+unsigned char NetPlatform_Initalize()
+{
+	WSADATA wsaData;
+	if(!WSAStarted)
+	{
+		if (WSAStartup(MAKEWORD(2, 2), &wsaData))
+		{
+			DDrConsole_PrintF("WSA initalization failed");
+			return false;
+		}
+		DDrConsole_PrintF("net started using WSA version %d.%d", LOBYTE(wsaData.wVersion), HIBYTE(wsaData.wVersion));
+	}
+	return true;
+}
+
+unsigned char NetPlatform_Shutdown()
+{
+	WSACleanup();
+	return true;
+}
Index: /Daodan/src/Flatline_Win32.h
===================================================================
--- /Daodan/src/Flatline_Win32.h	(revision 876)
+++ /Daodan/src/Flatline_Win32.h	(revision 876)
@@ -0,0 +1,4 @@
+#pragma once
+
+unsigned char NetPlatform_Initalize();
+unsigned char NetPlatform_Shutdown();
Index: /Daodan/src/Mariusnet.c
===================================================================
--- /Daodan/src/Mariusnet.c	(revision 876)
+++ /Daodan/src/Mariusnet.c	(revision 876)
@@ -0,0 +1,789 @@
+
+#include <winsock2.h>
+#include "stdint.h"
+#include "Flatline_Net.h"
+#include "Flatline_Win32.h"
+#include "Flatline_Client.h"
+#include "Mariusnet_Defs.h"
+#include "Daodan_Console.h"
+#include "Oni_Symbols.h"
+#include <stdio.h>
+
+#pragma comment(lib, "wininet.lib")
+
+
+char MariusLogin[32]={0};
+unsigned char MariusPassword[16]={0};
+
+m_room RoomList[64] = {0};
+unsigned char RoomListGotten = 0;
+
+unsigned char MariusNet_LoggedIn = 0;
+
+unsigned char MsNet_Running = 0;
+int Marius_Socket = -1;
+int Room_Socket = -1;
+sockaddr_in RoomAddr = {0};
+int PlayerID = 0;
+
+m_gameinfo StaticGameList[64] = {0};
+enum
+{
+	glAddGame,
+	glRemoveGame,
+	glUpdateGame,
+};
+
+/*
+
+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;
+
+typedef struct
+{
+	uint16_t x;
+	uint16_t y;
+
+} IMtPoint2D;
+void* DrawInstance = 0;
+void MSNet_DrawGames()
+{
+	
+		if(!DrawInstance){
+			void* TSFFTahoma;
+			TMrInstance_GetDataPtr( 'TSFF', "Tahoma", &TSFFTahoma);
+			TSrContext_New( TSFFTahoma, 7, 1, 1,  0, &DrawInstance);
+		}
+		if(DrawInstance){
+			const int white =	0x00FFFFFF;
+			const int green =	0x0000FF00;
+			const int red =		0x00FF0000;
+			const int blue =	0x000000FF;
+			int i;
+			char DrawString[255];
+			const int LineHeight = 15;
+			IMtPoint2D StartLocation = {500, 20}; 
+			IMtPoint2D DrawLocation = StartLocation; 
+			TSrContext_SetShade(DrawInstance, white);
+			TSrContext_DrawText(DrawInstance, "Mariusnet Games:", 255, 0, &DrawLocation);
+			TSrContext_SetShade(DrawInstance, white);
+			DrawLocation.y += LineHeight;
+			
+			for(i = 0; i < 64; i++)
+			{
+				
+				if(StaticGameList[i].gameID)
+				{
+					DrawLocation.x = StartLocation.x - 10;
+					sprintf(DrawString, "%i.", i );
+					TSrContext_DrawText(DrawInstance, DrawString, 255, 0, &DrawLocation);
+					DrawLocation.x += 20;
+					TSrContext_DrawText(DrawInstance, StaticGameList[i].g.Buffer, 255, 0, &DrawLocation);
+					DrawLocation.y += LineHeight;
+				}
+			}
+
+	}
+}
+
+
+int MariusNet_OutgoingPacketWrapper(int socket, const sockaddr* address, marius_packet* data, short datalen)
+{
+	data->header.PacketSize = htonl(datalen);
+	//NetUDPSocket_Send( socket, address, (char*)data, sizeof(marius_header) );
+	//datalen -= sizeof(marius_header);
+	//(char*)data += sizeof(marius_header);
+	return NetUDPSocket_Send( socket, address, (char*)data, datalen);
+}
+
+int PacketCached = 0;
+int MariusNet_IncomingPacketWrapper(int socket, char buffer[], int bufferlength, int flags)
+{
+	int inSize = 0;
+	unsigned fullSize = -1;
+	static char cacheBuffer[1440] = {0};
+	unsigned char NeedMoreData = 0;
+	if(PacketCached)
+	{
+		unsigned int PacketSize = ntohl(((marius_packet*)cacheBuffer)->header.PacketSize);
+	/*
+		if(ntohs(((marius_packet*)cacheBuffer)->header.PacketSignature) != 0xDEAD)
+		{
+			PacketCached = PacketSize = 0;
+			NeedMoreData = 1;
+		}
+		*/
+
+		
+		
+		if(PacketCached >= PacketSize)
+		{
+			memcpy( buffer, cacheBuffer, PacketSize );
+			PacketCached -= PacketSize;
+		}
+		else
+		{
+			memcpy( buffer, cacheBuffer, PacketCached );
+			inSize += PacketCached;
+			NeedMoreData = 1;
+			PacketCached = 0;
+		}
+		if(PacketCached < 0)
+		{
+			DDrConsole_PrintF("Warning, took too much from cache");
+			PacketCached = 0;
+		}
+		else if (PacketCached > 0)// && ntohs((short*)(cacheBuffer + PacketSize)) == 0xDEAD)
+		{
+			memcpy( cacheBuffer, cacheBuffer + PacketSize, PacketCached );
+		}
+		else
+		{
+			memset(cacheBuffer, 0, 1440);
+		}
+		
+		if(!NeedMoreData) return PacketSize;
+
+	}
+	do
+	{
+		int tempSize = recv(socket, buffer + inSize, bufferlength, flags);
+		if(tempSize == SOCKET_ERROR)
+		{
+			NetCatchError();
+			return SOCKET_ERROR;
+		}
+		
+		if(fullSize == -1)
+		{
+			if(ntohs(((marius_packet*)buffer)->header.PacketSignature) != 0xDEAD)
+			{
+				DDrConsole_PrintF("Bad header signature...closing Mariusnet connection");
+				return SOCKET_ERROR;
+			}
+			fullSize = ntohl(((marius_packet*)buffer)->header.PacketSize);
+		}
+		inSize += tempSize;
+		
+	}
+	while(inSize < fullSize);
+	
+	//double packet madness
+	if(inSize > fullSize 
+		&& ntohs(*(short*)(buffer + fullSize)) == 0xDEAD 
+		&& ntohl(((marius_packet*)(buffer + fullSize))->header.PacketSize) > 0
+		&& inSize - fullSize > sizeof(marius_header)
+		)
+	{
+		memcpy(cacheBuffer, buffer + fullSize, inSize - fullSize);
+		
+		PacketCached = inSize - fullSize;
+	}
+	else PacketCached = 0;
+	return inSize;
+}
+
+
+sockaddr_in Marius_Server;
+
+
+unsigned char MariusNet_Initialize()
+{
+	hostent* host_info = 0;
+	//host_info = gethostbyname("myth.mariusnet.com");
+	
+	host_info = gethostbyname("metaserver.lhowon.org");
+	if(!host_info)
+	{
+		DDrConsole_PrintF("Error, could not resolve myth.mariusnet.com");
+		return 1;
+	}
+	Marius_Server.sin_port = htons(6321);
+	Marius_Server.sin_family = AF_INET;
+	Marius_Server.sin_addr.S_un.S_addr = *(ULONG*)host_info->h_addr_list[0];
+	return 0;
+}
+
+void Initialize_MPacket( marius_packet* packet, short ID )
+{
+	memset( packet, 0, sizeof(marius_packet) );
+	packet->header.PacketSignature = htons(0xDEAD);
+	packet->header.PacketId = htons(ID);
+	
+}
+
+void Initialize_LoginPacket( marius_packet* packet)
+{
+	int NameSize = 0;
+	int TeamSize = 0;
+	char (*test)[] = packet;
+	Initialize_MPacket(packet, pt_PlayerLogin);
+	
+	packet->login.UpdateAppearance = 1;
+	packet->login.Platform = htons(1);
+	strncpy(packet->login.LoginId, MariusLogin, 32);
+	packet->login.EncryptionType = htons(1);
+	strcpy(packet->login.AppName, "MARATHON" ); //ONI ;)
+	strncpy(packet->login.BuildDate, __DATE__, 32 );
+	strncpy(packet->login.BuildTime, __TIME__, 32 );
+
+	
+	packet->login.PlayerInfo.clientVersion = htons(5000);
+	NameSize = sprintf(packet->login.PlayerInfo.Name, MariusLogin);
+	//TeamSize = sprintf(packet->login.PlayerInfo.Name + NameSize, "TCTF") + 1;
+	
+	packet->login.PlayerInfoSize = htons(40 + NameSize + TeamSize);
+}
+
+char EncryptionTypes[][32] = 
+{
+	"Plaintext",
+	"Braindead Simple",
+};
+
+enum {
+	SyntaxError,
+	GamesNotAllowed,
+	InvalidVersion,
+	BadUserOrPassword,
+	UserNotLoggedIn,
+	BadMetaserverVersion,
+	UserAlreadyLoggedIn,
+	UnknownGameType,
+	LoginSuccessful,
+	LogoutSuccessful,
+	PlayerNotInRoom,
+	GameAlreadyExists,
+	AccountAlreadyLoggedIn,
+	RoomFull,
+	AccountLocked,
+	NotSupported
+};
+
+static const char* sRoomNames[] = {
+	"Crows Bridge",
+	"Otter Ferry",
+	"White Falls",
+	"Silvermines",
+	"Shoal",
+	"Madrigal",
+	"Tyr",
+	"Ash",
+	"Scales",
+	"Covenant",
+	"Muirthemne",
+	"Seven Gates",
+	"Bagrada",
+	"The Barrier",
+	"Forest Heart",
+	"The Ermine",
+	"The Dire Marsh",
+	"The Highlands",
+	"The Drowned Kingdom",
+	"The Great Devoid",
+	"Shiver",
+	"The Caterthuns",
+	"Soulblighter",
+	"Balor",
+	"Sons of Myrgard",
+	"Heart of the Stone",
+	"Arrival",
+	"Ingue Ferroque",
+	"Vimy Ridge",
+	"Stilwell Road"
+};
+void MSNet_LoginError_Output( int code )
+{
+	switch(code)
+	{
+	case(BadUserOrPassword):
+		DDrConsole_PrintF( "Login denied: bad username or password." );
+		break;
+	case(UserAlreadyLoggedIn):
+		DDrConsole_PrintF( "Login denied: that user is already logged in.");
+		break;
+	case(AccountAlreadyLoggedIn):
+		DDrConsole_PrintF( "Login denied: that account is already logged in.");
+		break;
+	case(RoomFull):
+		DDrConsole_PrintF( "Login denied: room is full!?");
+		break;
+	case(AccountLocked):
+		DDrConsole_PrintF( "Login denied: your account is locked.");
+		break;
+	default:
+		DDrConsole_PrintF("There was a problem connecting to the server"
+			"that tracks Internet games. Please try again later.");
+		break;
+	}
+
+}
+
+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 = /*THIS MIGHT BE BAD*/ snprintf( Message, 1024, "%s", msg->Message ) + 1;
+	/*THIS MIGHT BE BAD*/ snprintf( 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) );
+
+
+}
+
+void MSNet_RoomExit()
+{
+	if(MariusNet_LoggedIn)
+	{
+		if( Room_Socket != -1) closesocket(Room_Socket);
+		memset(StaticGameList, 0, sizeof(m_gameinfo) * 64);
+		MsNet_Running = 0;
+		MariusNet_LoggedIn = 0;
+
+	}
+	return;
+}
+
+
+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 );
+	memset(StaticGameList, 0, sizeof(m_gameinfo) * 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, k;
+	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);
+
+		/*THIS MIGHT BE BAD*/ snprintf( TempGameList[i].g.Buffer, 128, "%s", PacketGames->g.Buffer);
+		PacketSize -= ThisSize;
+		PacketGames = (m_gameinfo*)((char*)PacketGames + ThisSize);
+		
+	}
+	for( i = 0; TempGameList[i].gameID; i++)
+	{
+		int DesiredID = 0;
+		switch(TempGameList[i].verb)
+		{
+		case(glRemoveGame):
+			//Remove game from list
+			DDrConsole_PrintF("%s has ended", TempGameList[i].g.Buffer);
+			for(k = 0; k < 64; k++)
+			{
+				if(TempGameList[i].gameID == StaticGameList[k].gameID)
+				{
+					memset(StaticGameList + k, 0, sizeof(m_gameinfo) );
+					break;
+				}
+				
+			}
+			break;
+			
+		case(glAddGame):
+			//Add game to list
+			DDrConsole_PrintF("%s has started", TempGameList[i].g.Buffer);
+		case(glUpdateGame):
+			//Update list
+
+			//If updating, look for the game to update, otherwise look for empty
+			if(TempGameList[i].verb) DesiredID = TempGameList[i].gameID;
+			for(k = 0; k < 64; k++)
+			{
+				if(DesiredID == StaticGameList[k].gameID)
+				{
+					memcpy(StaticGameList + k, TempGameList + i, sizeof(m_gameinfo) );
+					break;
+				}
+				
+			}
+			break;
+			break;
+		}
+		//TempGame
+	}
+	//Do stuff with the games.
+}
+
+int MSNet_CreateGame( m_announcegame* Game )
+{
+	marius_packet mPacket;
+	Initialize_MPacket(&mPacket, 104);
+	mPacket.newgame = *Game;
+	MariusNet_OutgoingPacketWrapper(Room_Socket, (sockaddr*)&RoomAddr, (char*)&mPacket, 
+		sizeof(marius_header) + sizeof(m_announcegame));
+}
+
+	/*
+	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);
+	*/
+
+int MSNet_Room_Join( short Room, char* Key)
+{
+	marius_packet mPacket = {0};
+
+	char incomingData[1400] = {0};
+	marius_packet* incomingPacket = (marius_packet*)incomingData;
+	int sent_bytes = 0;	
+
+	sockaddr_in SockAddr;
+	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);
+
+	if(Room_Socket == -1)
+	{
+		DDrConsole_PrintF("Failed to initialize room socket!");
+		return MSNet_Cleanup();
+	}
+	
+	if(connect( Room_Socket, (sockaddr *)&RoomAddr, sizeof(sockaddr_in)))
+	{
+		NetCatchError();
+		MariusNet_LoggedIn = 0;
+		return MSNet_Cleanup();
+	}
+	
+	Initialize_MPacket(&mPacket, pt_ChatRoomLogin);
+	memcpy(mPacket.chatroom_join.RoomKey, Key, 32);
+	strcpy(mPacket.chatroom_join.Name, MariusLogin);
+	sent_bytes = MariusNet_OutgoingPacketWrapper(Room_Socket, (sockaddr*)&RoomAddr, (char*)&mPacket, 
+		sizeof(marius_header) + 33 + strlen(MariusLogin));
+	
+	
+
+	Initialize_MPacket(&mPacket, pt_RoomPlayerInfo);
+	mPacket.player_info.clientVersion = htons(5000);
+	sprintf(mPacket.player_info.Name, MariusLogin);
+	sent_bytes = MariusNet_OutgoingPacketWrapper(Room_Socket, (sockaddr*)&RoomAddr, (char*)&mPacket, 
+		sizeof(marius_header) + 40 + strlen(MariusLogin));
+
+	if(MariusNet_IncomingPacketWrapper(Room_Socket, incomingData, 1400, 0) == SOCKET_ERROR)
+	{
+		return MSNet_Cleanup();
+	}
+
+	if(ntohs(incomingPacket->header.PacketId)== pt_LoginInfo)
+	{
+		//DDrConsole_PrintF("Login failed: %s", incomingPacket->login_denied.DenialMessage );
+		MSNet_LoginError_Output(ntohl(incomingPacket->login_denied.code));
+		return MSNet_Cleanup();
+	}
+
+	MariusNet_LoggedIn = 1;
+
+
+	while(1)
+	{
+		if(MariusNet_IncomingPacketWrapper(Room_Socket, incomingData, 1400, 0) == SOCKET_ERROR)
+		{
+			return 0;
+		}
+		switch(ntohs(incomingPacket->header.PacketId))
+		{
+		case pt_RoomList:
+		case pt_PlayerInfo:
+		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, cyan, grey );
+			break;
+		case pt_ChatMessage:
+			MSNet_HandleChat(&incomingPacket->message);
+			break;
+		case pt_KeepAlive:
+			MariusNet_OutgoingPacketWrapper(Room_Socket, (sockaddr*)&RoomAddr, incomingData, 
+				sizeof(marius_header));
+			break;
+		default:
+			DDrConsole_PrintF("Got packet of type %hi", ntohs(incomingPacket->header.PacketId));
+			break;
+		}
+	}
+	
+	return 0;
+}
+
+DWORD WINAPI MSNet_Handler(void* unused)
+{
+	int Port = 4156;
+	
+	
+	char RoomToken[33] = {0};
+	int i = 0;
+	
+	
+	
+	sockaddr_in Marius_Addr = {0};
+	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 MSNet_Cleanup();
+	}
+
+	NetPlatform_Initalize();
+
+
+	if(MariusNet_Initialize())
+	{
+		return MSNet_Cleanup();
+	}
+
+	//Horribly set up.
+	while( (Marius_Socket == -1 || Marius_Socket == 0 )&& Port < 6641)
+	{
+	
+		//Marius_Socket = NetTCPSocket_Create(Port, &Marius_Addr);
+		//NetUDPSocket_Close( Marius_Socket );
+		Marius_Socket = NetTCPSocket_Create(Port, &Marius_Addr);
+		//Port++;
+	}
+	
+	if(Marius_Socket != -1)
+	{
+		unsigned char incomingData[1400] = {0};
+		short incomingLength = 0;
+		marius_packet* incomingPacket = &incomingData;
+		//Initialize 
+		marius_packet mPacket;
+		int sent_bytes;
+		Initialize_LoginPacket(&mPacket);
+		
+		DDrConsole_PrintF("Logging into Mariusnet <%s>...",  inet_ntoa(Marius_Server.sin_addr));
+		if(connect( Marius_Socket, &Marius_Server, sizeof(sockaddr_in)))
+		{
+			NetCatchError();
+			return MSNet_Cleanup();
+		}
+		DDrConsole_PrintF("Sending Player Info...");
+		sent_bytes = MariusNet_OutgoingPacketWrapper(Marius_Socket, (sockaddr*)&Marius_Server, (char*)&mPacket, 
+			sizeof(marius_header) + sizeof(m_player_login) - (sizeof(m_player_info) - ntohs(mPacket.login.PlayerInfoSize) ) );
+		/*
+		if(!NetUDPSocket_Recieve(Marius_Socket, (sockaddr*)&Marius_Addr,incomingData, &incomingLength))
+		{
+			DDrConsole_PrintF("Data: %s Length %i", incomingData, incomingLength);
+			return 0;
+		}
+		*/
+		if(MariusNet_IncomingPacketWrapper(Marius_Socket, incomingData, 1400, 0) == SOCKET_ERROR)
+		{
+			return MSNet_Cleanup();
+		}
+		
+		if(ntohs(incomingPacket->header.PacketId)== pt_EncryptionKey)
+		{
+			//recv( Marius_Socket, incomingData, 1440, 0);
+			DDrConsole_PrintF("Encryption Type %s", EncryptionTypes[ntohs(incomingPacket->salt.EncryptionType)] );
+
+			Initialize_MPacket(&mPacket, pt_Password);
+			if(incomingPacket->salt.EncryptionType)
+			{
+				
+				unsigned char* Hash = mPacket.password.passHash;
+				unsigned char* Salt = incomingPacket->salt.salt;
+				unsigned char Pass[16] = {0};
+
+				memset(Pass, 0x23, 16);
+				strcpy(Pass, MariusPassword );
+
+				for( i = 0; i < 16; i++ ) Hash[i] = Pass[i]^Salt[i];
+				for( i = 1; i < 16; i++ ) Hash[i] = Hash[i]^Hash[i-1];
+				for( i = 1; i < 16; i++ ) 
+				{
+					short value = ~( Hash[i]*Hash[i-1] );
+					Hash[i] = (unsigned char) value;
+
+				}
+			}
+			else
+			{
+				strncpy(mPacket.password.passHash, MariusPassword, 16);
+			}
+
+			DDrConsole_PrintF("Sending Password...");
+			sent_bytes = MariusNet_OutgoingPacketWrapper(Marius_Socket, (sockaddr*)&Marius_Server, (char*)&mPacket, sizeof(marius_header) + sizeof(m_password) );
+
+			if(!NetUDPSocket_Recieve(Marius_Socket, (sockaddr*)&Marius_Addr,incomingData, &incomingLength))
+			{
+				return MSNet_Cleanup();
+			}
+			DDrConsole_PrintF("Password ACK!");
+			if(ntohs(incomingPacket->header.PacketId)== pt_PasswordAck)
+			{
+
+				Initialize_MPacket(&mPacket, pt_Localization);
+				mPacket.localization.one = htonl(1);
+				mPacket.localization.two = htonl(2);
+				mPacket.localization.three = htonl(3);
+				mPacket.localization.zero = 0;
+				sent_bytes = MariusNet_OutgoingPacketWrapper(Marius_Socket, (sockaddr*)&Marius_Server, (char*)&mPacket, sizeof(marius_header) + sizeof(m_localization) );
+
+				if(MariusNet_IncomingPacketWrapper(Marius_Socket, incomingData, 1400, 0) == SOCKET_ERROR)
+				{	
+					return MSNet_Cleanup();
+				}
+			}
+		}
+
+		if(ntohs(incomingPacket->header.PacketId)== pt_UserLoggedIn)
+		{
+			PlayerID = ntohl(incomingPacket->login_success.userID);
+			//Not sure if this is a string or byte array, so I allocated 33 bytes,
+			//so it always zero terminates.
+			memcpy(RoomToken, incomingPacket->login_success.Token, 32);
+			DDrConsole_PrintF("Logged into Mariusnet!");
+			//strcpy_s( player_name, 32, MariusLogin );
+			strncpy(player_name,MariusLogin,32);
+		}
+		else if(ntohs(incomingPacket->header.PacketId)== pt_LoginInfo)
+		{
+			//DDrConsole_PrintF("Login failed: %s", incomingPacket->login_denied.DenialMessage );
+			MSNet_LoginError_Output(ntohl(incomingPacket->login_denied.code));
+			return MSNet_Cleanup();
+		}
+		else 
+		{
+			return MSNet_Cleanup();
+		}
+
+
+		do
+		{
+			if(MariusNet_IncomingPacketWrapper(Marius_Socket, incomingData, 1400, 0) == SOCKET_ERROR)
+			{	
+				return MSNet_Cleanup();
+			}
+			if(ntohs(incomingPacket->header.PacketId)== pt_RoomList)
+			{
+				DDrConsole_PrintF("Got room list!");
+				RoomListGotten = 1;
+				memcpy(RoomList, incomingPacket->roomlist.Rooms, 
+					ntohl(incomingPacket->header.PacketSize) - sizeof(marius_header));
+			}
+			else if(ntohs(incomingPacket->header.PacketId)== pt_PlayerInfo)
+			{
+				//What do we do with this?!
+				DDrConsole_PrintF("Got player info!");
+			}
+			else
+			{
+				DDrConsole_PrintF("Invalid packet type %hi", ntohs(incomingPacket->header.PacketId));
+				return MSNet_Cleanup();
+			}
+		}
+		while(PacketCached || !RoomListGotten);
+
+		for(i = 0; i < 64, RoomList[i].IPAddress != 0 ; i++)
+		{
+			int IP = ntohl(RoomList[i].IPAddress);
+			DDrConsole_PrintF("Room %i %s IP %s Port %hi Players %hi", 
+				i, 
+				sRoomNames[ntohs(RoomList[i].RoomIndex)],
+				inet_ntoa(*(in_addr*)&IP),
+				ntohs(RoomList[i].Port),
+				ntohs(RoomList[i].PlayerCount)				
+				);
+			}
+		
+		closesocket(Marius_Socket);
+
+		MSNet_Room_Join( 0, RoomToken );
+
+		
+	}
+	return 0;
+}
+
+uint16_t ONICALL mnet_joingame(sl_callinfo* callinfo, uint32_t numargs, sl_arg args[], int* dontuse1, int* dontuse2, sl_arg* ret)
+{
+	int index = args[0].val.value_int32;
+	if(index >= 0)
+	{
+		FLcConnect(StaticGameList[index].ipAddress, StaticGameList[index].port);
+	}
+	return 0;
+}
+
+unsigned char MSNet_Login(char* username, char* password)
+{
+	/*THIS MIGHT BE BAD*/ snprintf(MariusLogin, 32, "%s", username);
+	/*THIS MIGHT BE BAD*/ snprintf(MariusPassword, 16, "%s", password);
+	CreateThread(NULL, 0, MSNet_Handler, NULL, 0, 0);
+
+	return 0;
+}
+
Index: /Daodan/src/Mariusnet_Defs.h
===================================================================
--- /Daodan/src/Mariusnet_Defs.h	(revision 876)
+++ /Daodan/src/Mariusnet_Defs.h	(revision 876)
@@ -0,0 +1,216 @@
+//to client
+#include "Mariusnet_Public.h"
+enum
+{
+pt_RoomList = 0x0000,
+pt_PlayerList = 0x0001,
+pt_GameList = 0x0002,
+pt_UserLoggedIn = 0x7,//0x0003,
+pt_EncryptionKey = 0x0006,
+pt_LoginInfo = 0x3,//0x0007,
+pt_PlayerInfo = 0x0008,
+pt_PlayerId = 0x0009,
+pt_BlueBarMsg = 0x000A,
+pt_PasswordAck = 0x000C,
+pt_FindResponse = 0x000E,
+pt_BuddyList = 0x000F, // the actual buddy list - i.e. names and such
+pt_OrderList = 0x0010,
+pt_PlayerInfoResponse = 0x0011,
+pt_UpdatePlayerStats = 0x0012,
+pt_UpdateBuddyList = 0x0013, // buddy status - i.e. online/offline
+pt_UpdateOrderList = 0x0014,
+};
+
+//from client
+enum
+{
+pt_PlayerLogin = 0x0064,
+pt_ChatRoomLogin = 0x0065,
+pt_RoomPlayerInfo = 0x0067,
+pt_GameInfo = 0x0068,
+pt_RemoveGame = 0x0069,
+pt_SetPlayerState = 0x006B,
+pt_Password = 0x006D,
+pt_RequestRefresh = 0x006E,
+pt_GamePlayerList = 0x006F, // game start player list
+pt_PlayerScores = 0x0070, // game over player scores
+pt_ResetScoring = 0x0071, // reset metaserver game scoring
+pt_StartGame = 0x0072,
+pt_Localization = 0x0073,
+pt_GameSearchQuery = 0x0074,
+pt_FindPlayer = 0x0075,
+pt_BuddyListQuery = 0x0076, // request a buddy list update
+pt_OrderListQuery = 0x0077,
+pt_UpdateBuddy = 0x0078, // add/remove buddy
+pt_PlayerInfoQuery = 0x0079,
+pt_SetPlayerStats = 0x007A, // change player stats (city/state/profile)
+pt_ChatMessage = 0x00C8,
+pt_WhisperMessage = 0x00C9,
+pt_KeepAlive = 0x00CA,
+pt_SessionKey = 0x00CB,
+};
+
+enum
+{
+ctMyth1 = 0,
+ctMyth2 = 1,
+// ctMyth3 = 2;
+ctMarathon = 3,
+ctMyth1Unified = 4,
+ctMyth2Unified = 5,
+ctMyth3Unified = 6,
+};
+
+
+typedef struct
+{
+	short PacketSignature;// = 0xDEAD;
+    short PacketId;
+    unsigned int PacketSize;
+} marius_header;
+
+typedef struct
+{
+	short Red;
+    short Green;
+    short Blue;
+    short Flags;
+} m_colour;
+
+typedef struct
+{
+	char Icon;
+	char pad;
+	short Flags; // 0=active, 1=inactive, in a game, grayed out, can't see chat
+	m_colour Colors[2];
+	short orderIndex;
+	short clientVersion;
+	char stupid_14byte_pad[14];
+	char Name[112];     // 2 #0 terminated fields - Name, Team Name
+} m_player_info;
+
+typedef struct
+{
+	short Platform; //Windows - 1
+	short MetaVersion; //0
+	char pad[3]; 
+    char UpdateAppearance;                      // save player settings on server,     change to bits, bit 0=update, bit 1=demo
+    int PlayerId; //0
+    short EncryptionType;  //0 - kCRYPT_PLAINTEXT, screw encryption for now
+    short PlayerInfoSize;  //40 + strlen(playername) + strlen(plaerteam(
+    char AppName[32];		//MARATHON...later ONI ;)
+    char BuildDate[32];		//_DATE_
+    char BuildTime[32];		//_TIME_
+    char LoginId[32];		//username
+    m_player_info PlayerInfo;       
+} m_player_login;
+
+typedef struct
+{
+	short EncryptionType;
+	unsigned char salt[16];
+} m_salt;
+
+typedef struct
+{
+	int one;
+	int two;
+	int three;
+	int zero;
+} m_localization;
+
+typedef struct
+{
+	unsigned char passHash[16];
+} m_password;
+
+typedef struct
+{
+	int userID;
+	short order;
+	short unused;
+	char Token[32];
+		
+} m_login_success;
+
+typedef struct
+{
+	int code;
+	char DenialMessage[];
+} m_login_denied;
+
+typedef struct
+{
+	short RoomIndex;
+	short PlayerCount;
+	int IPAddress;
+	short Port;
+	short GameCount;
+	int pad[3];
+} m_room;
+
+typedef struct
+{
+	m_room Rooms[64];
+} m_roomlist;
+
+typedef struct
+{
+	char RoomKey[32];
+	char Name[32];
+} m_chatroom_join;
+
+typedef struct
+{
+	char Message[512];
+} m_motd;
+
+typedef struct
+{
+	m_colour	PrimaryColor;
+	m_colour	SecondaryColor;
+	int    SenderId;
+    int		TargetId;
+    char Message[256];
+} m_message;
+
+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
+{
+	marius_header header;
+	union
+	{
+		m_player_login login;
+		m_password password;
+		m_localization localization;
+		m_salt salt;
+		m_login_success login_success;
+		m_login_denied login_denied;
+		m_roomlist roomlist;
+		m_chatroom_join chatroom_join;
+		m_player_info player_info;
+		m_motd motd;
+		m_message message;
+		m_announcegame newgame;
+		m_gamelist gamelist;
+	};
+} marius_packet;
Index: /Daodan/src/Mariusnet_Public.h
===================================================================
--- /Daodan/src/Mariusnet_Public.h	(revision 876)
+++ /Daodan/src/Mariusnet_Public.h	(revision 876)
@@ -0,0 +1,41 @@
+extern unsigned char MsNet_Running;
+
+unsigned char MSNet_Login(char* username, char* password);
+void MSNet_SendChat( char* msg );
+void MSNet_RoomExit();
+void MSNet_DrawGames();
+extern char MariusLogin[32];
+
+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;
+
Index: /Daodan/src/Oni_Symbols.h
===================================================================
--- /Daodan/src/Oni_Symbols.h	(revision 875)
+++ /Daodan/src/Oni_Symbols.h	(revision 876)
@@ -1,3 +1,3 @@
-#ifndef ONI_SYMBOLS_H 
+#ifndef ONI_SYMBOLS_H
 #define ONI_SYMBOLS_H
 #include "stdint.h"
@@ -34,12 +34,12 @@
 // Game termination flag (ONiRunGame loops on it).
 #define ONgTerminateGame	(*((UUtBool*)0x00630ffd))
- 
+
 // Window manager is running (drawing and updating windows).
 #define WMgActive			(*((UUtBool*)0x005e99a0))
- 
+
 // Set by WinMain, used by UUrPlatform_Initialize and ONrPlatform_Initialize,
 // which copies it into ONgPlatformData.
 #define ONgInstance			(*((HINSTANCE*)0x0061f9e4))
- 
+
 // Keeps initial gamma ramp value (before any change).
 #define GLgInitialGammaRamp	(((M3tWin32GammaRamp*)0x0055fdfc))
Index: /Daodan/src/patches/Patches.c
===================================================================
--- /Daodan/src/patches/Patches.c	(revision 875)
+++ /Daodan/src/patches/Patches.c	(revision 876)
@@ -10,5 +10,8 @@
 #include "../Daodan_Utility.h"
 #include "../Daodan_Win32.h"
-
+#ifdef FLATLINE
+#include "../Flatline_BSL.h"
+#include "../Flatline_Hooks.h"
+#endif
 #include "../Oni.h"
 
@@ -561,23 +564,23 @@
 	DD_Patch_PrintWarning();
 
+
 	DD_Patch_ShowNames();
 
-	if(1)
-	{
-		//DDrPatch_NOOP((char*)(OniExe + 0x000E1957), 6 );
-		//DDrPatch_MakeCall((void*)(OniExe + 0x000E17F6), FLrHook_Lasers );
-	}
+#ifdef FLATLINE
+	DDrPatch_NOOP((char*)(OniExe + 0x000E1957), 6 );
+	DDrPatch_MakeCall((void*)(OniExe + 0x000E17F6), FLrHook_Lasers );
+	
 
 
 	//Flatline related stuff
-//	DDrPatch_MakeCall((void*)(OniExe + 0x000FBCEA), DDrText_Hook);
-	
-//FLATLINE?	DDrPatch_Int32((int*)(OniExe + 0x000B24D2), FLrSpawnHack);
-
-//FLATLINE?	DDrPatch_NOOP((char*)(OniExe + 0x000C26CB), 6);
-
-//FLATLINE?	DDrPatch_MakeCall((void*)(OniExe + 0x000C26CB), FLrHook_DoorOpen); 
-//FLATLINE?	DDrPatch_MakeCall((void*)(OniExe + 0x000EE3CF), FLrHook_ConsoleActivate);
-
+	DDrPatch_MakeCall((void*)(OniExe + 0x000FBCEA), DDrText_Hook);
+	
+	DDrPatch_Int32((int*)(OniExe + 0x000B24D2), FLrSpawnHack);
+
+	DDrPatch_NOOP((char*)(OniExe + 0x000C26CB), 6);
+
+	DDrPatch_MakeCall((void*)(OniExe + 0x000C26CB), FLrHook_DoorOpen); 
+	DDrPatch_MakeCall((void*)(OniExe + 0x000EE3CF), FLrHook_ConsoleActivate);
+#endif
 
 	return true;
