diff --git a/Content/Levels/Sergio_Level.umap b/Content/Levels/Sergio_Level.umap
index d109eae..f7ddda5 100644
--- a/Content/Levels/Sergio_Level.umap
+++ b/Content/Levels/Sergio_Level.umap
Binary files differ
diff --git a/Content/Levels/Sergio_Level_2.umap b/Content/Levels/Sergio_Level_2.umap
deleted file mode 100644
index 463b671..0000000
--- a/Content/Levels/Sergio_Level_2.umap
+++ /dev/null
Binary files differ
diff --git a/Content/Matchmaking_Widget.uasset b/Content/Matchmaking_Widget.uasset
new file mode 100644
index 0000000..7680607
--- /dev/null
+++ b/Content/Matchmaking_Widget.uasset
Binary files differ
diff --git a/SkyFrontier.uproject b/SkyFrontier.uproject
index f1d9588..de53b0e 100644
--- a/SkyFrontier.uproject
+++ b/SkyFrontier.uproject
@@ -9,7 +9,8 @@
 			"Type": "Runtime",
 			"LoadingPhase": "Default",
 			"AdditionalDependencies": [
-				"Engine"
+				"Engine",
+				"UMG"
 			]
 		}
 	],
diff --git a/Source/SkyFrontier/Private/MyButton.cpp b/Source/SkyFrontier/Private/MyButton.cpp
new file mode 100644
index 0000000..a4ba9cc
--- /dev/null
+++ b/Source/SkyFrontier/Private/MyButton.cpp
@@ -0,0 +1,17 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+
+#include "MyButton.h"
+
+UMyButton::UMyButton()
+{
+OnClicked.AddDynamic(this, &UMyButton::OnClick);
+}
+void UMyButton::SetSessionInfo(int sID, TCPClient *tclient)
+{
+	sessionID = sID;  tcpClient = tclient;
+}
+void UMyButton::OnClick()
+{
+	tcpClient->JoinGameSession(sessionID);
+}
\ No newline at end of file
diff --git a/Source/SkyFrontier/Private/MyPlayerState.cpp b/Source/SkyFrontier/Private/MyPlayerState.cpp
new file mode 100644
index 0000000..38f2d07
--- /dev/null
+++ b/Source/SkyFrontier/Private/MyPlayerState.cpp
@@ -0,0 +1,92 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+
+#include "MyPlayerState.h"
+
+#include "MyButton.h"
+#include "TCPClient.h"
+#include "Blueprint/UserWidget.h"
+#include "Components/Button.h"
+#include "Components/ScrollBox.h"
+#include "Components/TextBlock.h"
+#include "Components/VerticalBox.h"
+#include "Components/VerticalBoxSlot.h"
+
+void AMyPlayerState::BeginPlay()
+{
+	FString levelName = GetWorld()->GetMapName();
+	levelName.RemoveFromStart(GetWorld()->StreamingLevelsPrefix);
+	if (levelName == "StartMap")
+	{
+		tcpClient = new TCPClient(this);
+		canConnectToGameServer = false;
+		if ((MatchmakingWidgetClass) && (tcpClient->IsConnected()))
+		{
+			serversList = new TArray<FSessionInfo*>();
+			GetWorld()->GetTimerManager().SetTimer(serverListTimerHandle,  this, &AMyPlayerState::OnUpdateServerList, 2, true);
+			MatchmakingWidget = CreateWidget<UUserWidget>(GetWorld(),MatchmakingWidgetClass);
+			MatchmakingWidget->AddToViewport();
+			serverListScrollBoxWidget = Cast<UScrollBox>(MatchmakingWidget->GetWidgetFromName(TEXT("MyScrollBox")));
+			UButton* newSessionButton = Cast<UButton>(MatchmakingWidget->GetWidgetFromName(TEXT("NewSession")));
+			if (newSessionButton)
+			{	
+				newSessionButton->SetIsEnabled(true);
+				newSessionButton->OnClicked.AddDynamic(this,  &AMyPlayerState::OnNewSessionClicked);
+			}
+		}
+	}
+}
+void AMyPlayerState::OnNewSessionClicked()
+{
+	tcpClient->CreateNewGameSession("My test session");
+}
+void AMyPlayerState::UpdateSessionsList(FString serverinfo)
+{
+	TArray<FString> Out;  serverinfo.ParseIntoArray(Out, TEXT("|"), true);
+	for (int i = 1; i < Out.Num() - 1; i += 2) {  FSessionInfo *tempInfo = new FSessionInfo();
+		tempInfo->id = FCString::Atoi(*Out[i]);
+		tempInfo->name = Out[i + 1];
+		tempInfo->serverip = "";
+		tempInfo->serverport = -1;
+		serversList->Add(tempInfo);  }
+}
+void AMyPlayerState::ConnectToGameServer(FSessionInfo session)
+{
+	canConnectToGameServer = true;  connectToGameServerSession = session;
+}
+void AMyPlayerState::OnUpdateServerList()  {
+	if (tcpClient) {
+		if (tcpClient->IsConnected()) {
+			if (serversList->Num() > 0) {
+				if ((MatchmakingWidget) && (serverListScrollBoxWidget)) {
+					TArray<UWidget*> allChildren = serverListScrollBoxWidget->  GetAllChildren();
+					for (int i = 0; i < allChildren.Num(); i++)
+					{
+						allChildren[i]->RemoveFromParent();
+					}
+					for (int i = 0; i < serversList->Num(); i++)
+					{
+						UVerticalBox* ItemWidgetsBox = NewObject<UVerticalBox>();
+						serverListScrollBoxWidget->AddChild(ItemWidgetsBox);
+						UMyButton* ItemWidget = NewObject<UMyButton>(this);
+						ItemWidget->SetSessionInfo((*serversList)[i]->id,  tcpClient);
+						UTextBlock* ItemWidgetText = NewObject<UTextBlock>();
+						ItemWidgetText->SetText(FText::FromString(  (*serversList)[i]->name));
+						ItemWidget->AddChild(ItemWidgetText);
+						UVerticalBoxSlot* Slot = ItemWidgetsBox->  AddChildToVerticalBox(ItemWidget);
+						static FMargin Padding(5);
+						Slot->SetPadding(Padding);
+					}
+				}
+			}
+			if (canConnectToGameServer){  APlayerController* pController = GetWorld()->  GetFirstPlayerController();
+				if (pController){  FString cmd = "open " + connectToGameServerSession.serverip + ":" + FString::FromInt(connectToGameServerSession.serverport);
+					tcpClient->Stop();
+					canConnectToGameServer = false;
+					MatchmakingWidget->RemoveFromViewport();
+					pController->ConsoleCommand(cmd);
+				}
+			}
+		}
+	}
+}
\ No newline at end of file
diff --git a/Source/SkyFrontier/Private/TCPClient.cpp b/Source/SkyFrontier/Private/TCPClient.cpp
new file mode 100644
index 0000000..82daf34
--- /dev/null
+++ b/Source/SkyFrontier/Private/TCPClient.cpp
@@ -0,0 +1,110 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+
+#include "TCPClient.h"
+
+#include "MyPlayerState.h"
+#include "Sockets.h"
+#include "SocketSubsystem.h"
+#include "Interfaces/IPv4/IPv4Address.h"
+#include "TraceServices/Model/Diagnostics.h"
+
+TCPClient::TCPClient(AMyPlayerState* pState)
+{
+	Thread = FRunnableThread::Create(this, TEXT("TCPClientThread"), 0,  TPri_Normal);  PlayerState = pState;
+}
+TCPClient::~TCPClient()
+{
+	TCPClient::Stop();  delete Thread;
+}
+void TCPClient::Stop()
+{
+	running = false;
+}
+bool TCPClient::IsConnected()
+{
+	return connected;
+}
+
+bool TCPClient::Init()
+{
+	Socket = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateSocket(NAME_Stream, TEXT("default"), false);
+	int32 NewSize = 0;
+	Socket->SetReceiveBufferSize(1024, NewSize);
+	FIPv4Address matchmakingServerIP(127, 0, 0, 1);
+	TSharedRef<FInternetAddr> matchmakingServer = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateInternetAddr();
+	matchmakingServer->SetIp(matchmakingServerIP.Value);
+	matchmakingServer->SetPort(8856);
+	
+	connected = Socket->Connect(*matchmakingServer);
+	if (connected)
+	{
+		UE_LOG(LogTemp, Log, TEXT("CONNECTED!"));
+		FString serialized = TEXT("g|#");
+		TCHAR *serializedChar = serialized.GetCharArray().GetData();
+		int32 size = FCString::Strlen(serializedChar);
+		int32 sent = 0;
+		bool successful = Socket->Send((uint8*)TCHAR_TO_UTF8(serializedChar), size, sent);
+		if (successful)
+			{UE_LOG(LogTemp, Log, TEXT("MESSAGE SENT!"));
+			return true;
+		}
+		else
+		{
+			UE_LOG(LogTemp, Log, TEXT("ERROR: NOT CONNECTED!"));return false;
+		}
+	}
+	return 0;
+}
+	uint32 TCPClient::Run()
+	{
+		running = true;
+		TArray<uint8> ReceivedData;
+		while (running)
+		{
+			uint32 Size = 0;
+			if (Socket->HasPendingData(Size))
+			{
+				ReceivedData.Init(0, Size);
+				int32 Read = 0;
+				Socket->Recv(ReceivedData.GetData(), ReceivedData.Num(), Read);
+				FString ServerMessage = FString(UTF8_TO_TCHAR(ReceivedData.GetData()));
+				UE_LOG(LogTemp, Log, TEXT("RECEIVED: %s"), *ServerMessage);
+				if ((ServerMessage[0] == 's') && (PlayerState))
+				{
+					PlayerState->UpdateSessionsList(ServerMessage);
+				}
+				else if((ServerMessage[0] == 'o') && (PlayerState))
+				{
+					TArray<FString> Out;
+					ServerMessage.ParseIntoArray(Out, TEXT("|"), true);
+					FSessionInfo session;
+					session.id = -1;
+					session.name = "";
+					session.serverip = Out[1];
+					session.serverport = FCString::Atoi(*Out[2]);
+					PlayerState->ConnectToGameServer(session);
+				}
+			}
+		}
+		return 0;
+	}
+	
+	void TCPClient::CreateNewGameSession(FString sname)
+	{
+		FString serialized = "c|" + sname + "|#";
+		TCHAR *serializedChar = serialized.GetCharArray().GetData();
+		int32 size = FCString::Strlen(serializedChar);
+		int32 sent = 0;
+		bool successful = Socket->Send((uint8*)  TCHAR_TO_UTF8(serializedChar), size, sent);
+		if (successful)  UE_LOG(LogTemp, Log, TEXT("MESSAGE SENT!!!!"));
+	}
+	void TCPClient::JoinGameSession(int sID)
+	{
+		FString serialized = "j|" + FString::FromInt(sID) + "|#";
+		TCHAR *serializedChar = serialized.GetCharArray().GetData();
+		int32 size = FCString::Strlen(serializedChar);
+		int32 sent = 0;
+		bool successful = Socket->Send((uint8*)  TCHAR_TO_UTF8(serializedChar), size, sent);
+		if (successful)  UE_LOG(LogTemp, Log, TEXT("MESSAGE SENT!!!!"));
+	}
\ No newline at end of file
diff --git a/Source/SkyFrontier/Public/MyButton.h b/Source/SkyFrontier/Public/MyButton.h
new file mode 100644
index 0000000..57e7828
--- /dev/null
+++ b/Source/SkyFrontier/Public/MyButton.h
@@ -0,0 +1,26 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+#pragma once
+
+#include "CoreMinimal.h"
+#include "TCPClient.h"
+#include "Components/Button.h"
+#include "MyButton.generated.h"
+
+/**
+ * 
+ */
+UCLASS()
+class SKYFRONTIER_API UMyButton : public UButton
+{
+	GENERATED_BODY()
+public:
+	UMyButton();
+	void SetSessionInfo(int sID, TCPClient *tclient);
+protected:  int sessionID;
+	TCPClient *tcpClient;
+	
+	UFUNCTION()
+	void OnClick();
+	
+};
diff --git a/Source/SkyFrontier/Public/MyPlayerState.h b/Source/SkyFrontier/Public/MyPlayerState.h
new file mode 100644
index 0000000..816fe70
--- /dev/null
+++ b/Source/SkyFrontier/Public/MyPlayerState.h
@@ -0,0 +1,52 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+#pragma once
+
+#include "CoreMinimal.h"
+#include "GameFramework/PlayerState.h"
+#include "MyPlayerState.generated.h"
+
+USTRUCT()
+struct FSessionInfo 
+{  
+  GENERATED_BODY()
+  UPROPERTY()
+  int id;
+  UPROPERTY()
+  FString name;
+  UPROPERTY()
+  FString serverip;
+  UPROPERTY()
+  int serverport;
+};
+
+UCLASS()
+class SKYFRONTIER_API AMyPlayerState : public APlayerState
+{
+  GENERATED_BODY()
+public:
+  void UpdateSessionsList(FString serverinfo);
+  void ConnectToGameServer(FSessionInfo session);
+  
+protected:
+  virtual void BeginPlay() override;
+  
+  class TCPClient* tcpClient;
+  
+  UPROPERTY(EditDefaultsOnly, Category = "UI")
+  TSubclassOf<class UUserWidget> MatchmakingWidgetClass;
+  class UUserWidget* MatchmakingWidget;
+  class UScrollBox* serverListScrollBoxWidget;
+  
+  TArray<FSessionInfo*> *serversList;
+  FTimerHandle serverListTimerHandle;
+  
+  bool canConnectToGameServer;
+  FSessionInfo connectToGameServerSession;
+  
+  UFUNCTION() 
+  void OnNewSessionClicked();
+  
+  UFUNCTION()
+  void OnUpdateServerList();
+};
diff --git a/Source/SkyFrontier/Public/TCPClient.h b/Source/SkyFrontier/Public/TCPClient.h
new file mode 100644
index 0000000..5e83447
--- /dev/null
+++ b/Source/SkyFrontier/Public/TCPClient.h
@@ -0,0 +1,29 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+#pragma once
+
+#include "CoreMinimal.h"
+
+/**
+ * 
+ */
+class SKYFRONTIER_API TCPClient : public FRunnable
+{
+public:
+ TCPClient(class AMyPlayerState* pState);
+ ~TCPClient();
+ virtual bool Init();
+ virtual uint32 Run();
+ virtual void Stop();
+ void CreateNewGameSession(FString sname);
+ void JoinGameSession(int sID);
+ bool IsConnected();
+ 
+private:
+ FRunnableThread* Thread;
+ FSocket* Socket;
+ FSocket* ListenerSocket;
+ bool running;
+ bool connected;
+ class AMyPlayerState* PlayerState;
+};
diff --git a/Source/SkyFrontier/SkyFrontier.Build.cs b/Source/SkyFrontier/SkyFrontier.Build.cs
index da8d9ff..f2bbd8e 100644
--- a/Source/SkyFrontier/SkyFrontier.Build.cs
+++ b/Source/SkyFrontier/SkyFrontier.Build.cs
@@ -10,7 +10,7 @@
 
 		PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "AIModule",  "Sockets", "Networking", "UMG" });
 
-		PrivateDependencyModuleNames.AddRange(new string[] {  });
+		PrivateDependencyModuleNames.AddRange(new string[] { "SessionServices", "TraceServices" });
 
 		// Uncomment if you are using Slate UI
 		// PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" });