SCUE4 Plugin fails to Package

Hello, we’re currently using SCUE4 SafeInstance children class. But when I tried to package, I got an error.
I tried adding #pragma to SCLibrary.h in SCUE4 plug-in, but it didn’t work.
I’d appreciate your help.
Please understand that I am not good at English, not English-speaking countries.

log

  Building 20 actions with 6 processes...
    [1/20] Module.NativizedAssets.7_of_20.cpp
C:\Program Files\Epic Games\UE_4.21\Engine\Plugins\Marketplace\SCUE4\Intermediate\Build\Win64\UE4\Inc\SCUE4\SCLibrary.generated.h(31): fatal error C1189: #error:  "SCLibrary.generated.h already included, missing '#pragma once' in SCLibrary.h"
    [2/20] Module.NativizedAssets.2_of_20.cpp
C:\Program Files\Epic Games\UE_4.21\Engine\Plugins\Marketplace\SCUE4\Intermediate\Build\Win64\UE4\Inc\SCUE4\SCLibrary.generated.h(31): fatal error C1189: #error:  "SCLibrary.generated.h already included, missing '#pragma once' in SCLibrary.h"
    [3/20] Module.NativizedAssets.3_of_20.cpp
C:\Program Files\Epic Games\UE_4.21\Engine\Plugins\Marketplace\SCUE4\Intermediate\Build\Win64\UE4\Inc\SCUE4\SCLibrary.generated.h(31): fatal error C1189: #error:  "SCLibrary.generated.h already included, missing '#pragma once' in SCLibrary.h"
    [4/20] Module.NativizedAssets.6_of_20.cpp
C:\Program Files\Epic Games\UE_4.21\Engine\Plugins\Marketplace\SCUE4\Intermediate\Build\Win64\UE4\Inc\SCUE4\SCLibrary.generated.h(31): fatal error C1189: #error:  "SCLibrary.generated.h already included, missing '#pragma once' in SCLibrary.h"
    [5/20] Module.NativizedAssets.5_of_20.cpp
C:\Program Files\Epic Games\UE_4.21\Engine\Plugins\Marketplace\SCUE4\Intermediate\Build\Win64\UE4\Inc\SCUE4\SCLibrary.generated.h(31): fatal error C1189: #error:  "SCLibrary.generated.h already included, missing '#pragma once' in SCLibrary.h"
    [6/20] Module.NativizedAssets.1_of_20.cpp
    [7/20] Module.NativizedAssets.9_of_20.cpp
C:\Program Files\Epic Games\UE_4.21\Engine\Plugins\Marketplace\SCUE4\Intermediate\Build\Win64\UE4\Inc\SCUE4\SCLibrary.generated.h(31): fatal error C1189: #error:  "SCLibrary.generated.h already included, missing '#pragma once' in SCLibrary.h"
    [8/20] Module.NativizedAssets.10_of_20.cpp
C:\Program Files\Epic Games\UE_4.21\Engine\Plugins\Marketplace\SCUE4\Intermediate\Build\Win64\UE4\Inc\SCUE4\SCLibrary.generated.h(31): fatal error C1189: #error:  "SCLibrary.generated.h already included, missing '#pragma once' in SCLibrary.h"
    [9/20] Module.NativizedAssets.12_of_20.cpp
C:\Program Files\Epic Games\UE_4.21\Engine\Plugins\Marketplace\SCUE4\Intermediate\Build\Win64\UE4\Inc\SCUE4\SCLibrary.generated.h(31): fatal error C1189: #error:  "SCLibrary.generated.h already included, missing '#pragma once' in SCLibrary.h"
    [10/20] Module.NativizedAssets.8_of_20.cpp
C:\Program Files\Epic Games\UE_4.21\Engine\Plugins\Marketplace\SCUE4\Intermediate\Build\Win64\UE4\Inc\SCUE4\SCLibrary.generated.h(31): fatal error C1189: #error:  "SCLibrary.generated.h already included, missing '#pragma once' in SCLibrary.h"
    [11/20] Module.NativizedAssets.11_of_20.cpp
C:\Program Files\Epic Games\UE_4.21\Engine\Plugins\Marketplace\SCUE4\Intermediate\Build\Win64\UE4\Inc\SCUE4\SCLibrary.generated.h(31): fatal error C1189: #error:  "SCLibrary.generated.h already included, missing '#pragma once' in SCLibrary.h"
    [12/20] Module.NativizedAssets.13_of_20.cpp
C:\Program Files\Epic Games\UE_4.21\Engine\Plugins\Marketplace\SCUE4\Intermediate\Build\Win64\UE4\Inc\SCUE4\SCLibrary.generated.h(31): fatal error C1189: #error:  "SCLibrary.generated.h already included, missing '#pragma once' in SCLibrary.h"
    [13/20] Module.NativizedAssets.14_of_20.cpp
C:\Program Files\Epic Games\UE_4.21\Engine\Plugins\Marketplace\SCUE4\Intermediate\Build\Win64\UE4\Inc\SCUE4\SCLibrary.generated.h(31): fatal error C1189: #error:  "SCLibrary.generated.h already included, missing '#pragma once' in SCLibrary.h"
    [14/20] Module.NativizedAssets.16_of_20.cpp
C:\Program Files\Epic Games\UE_4.21\Engine\Plugins\Marketplace\SCUE4\Intermediate\Build\Win64\UE4\Inc\SCUE4\SCLibrary.generated.h(31): fatal error C1189: #error:  "SCLibrary.generated.h already included, missing '#pragma once' in SCLibrary.h"
    [15/20] Module.NativizedAssets.15_of_20.cpp
C:\Program Files\Epic Games\UE_4.21\Engine\Plugins\Marketplace\SCUE4\Intermediate\Build\Win64\UE4\Inc\SCUE4\SCLibrary.generated.h(31): fatal error C1189: #error:  "SCLibrary.generated.h already included, missing '#pragma once' in SCLibrary.h"
    [16/20] Module.NativizedAssets.17_of_20.cpp
C:\Program Files\Epic Games\UE_4.21\Engine\Plugins\Marketplace\SCUE4\Intermediate\Build\Win64\UE4\Inc\SCUE4\SCLibrary.generated.h(31): fatal error C1189: #error:  "SCLibrary.generated.h already included, missing '#pragma once' in SCLibrary.h"
    [17/20] Module.NativizedAssets.18_of_20.cpp
C:\Program Files\Epic Games\UE_4.21\Engine\Plugins\Marketplace\SCUE4\Intermediate\Build\Win64\UE4\Inc\SCUE4\SCLibrary.generated.h(31): fatal error C1189: #error:  "SCLibrary.generated.h already included, missing '#pragma once' in SCLibrary.h"
    [18/20] Module.NativizedAssets.19_of_20.cpp
    [19/20] Module.NativizedAssets.20_of_20.cpp
UnrealBuildTool : error : UBT ERROR: Failed to produce item: C:\Robogang\Robogang\Binaries\Win64\Robogang.exe
                          (see ../Programs/UnrealBuildTool/Log.txt for full exception trace)
  Total build time: 150.72 seconds (Parallel executor: 0.00 seconds)
C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\IDE\VC\VCTargets\Microsoft.MakeFile.Targets(44,5): error MSB3075: ""C:\Program Files\Epic Games\UE_4.21\Engine\Build\BatchFiles\Build.bat" Robogang Win64 Development "C:\Robogang\Robogang\Robogang.uproject" -WaitMutex -FromMsBuild" 명령이 종료되었습니다(코드: 5). 이 명령을 실행할 권한이 있는지 확인하세요.

instance .h

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include "Windows/AllowWindowsPlatformTypes.h"
#pragma comment(lib, "ws2_32.lib")
#include <winsock2.h>
#include "Windows/HideWindowsPlatformTypes.h"
#include "Runtime/Online/HTTP/Public/Interfaces/IHttpRequest.h"
#include "Engine/GameInstance.h"
#include "SCUE4.h"
#include "SafeGameInstance_Robogang.generated.h"

using namespace std;

USTRUCT(BlueprintType)
struct FRobogang_Player_State
{
	GENERATED_BODY()

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
		int player_index_;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
		int max_life_;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
		int remained_life_;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
		int current_soul_;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
		float max_health_;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
		float remained_health_;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
		float max_shield_;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
		float remained_shield_;
};

/**
 * 
 */
UCLASS()
class ROBOGANG_API USafeGameInstance_Robogang : public USafeGameInstance
{
	GENERATED_BODY()
	
public:
	USafeGameInstance_Robogang();
	~USafeGameInstance_Robogang();

	//-------------------------------for loading screen--------------------------------------------
	virtual void Init() override;

	UFUNCTION()
		virtual void BeginLoadingScreen(const FString& MapName);
	UFUNCTION()
		virtual void EndLoadingScreen(UWorld* InLoadingWorld);
	//-------------------------------end loading screen---------------------------------------------
	
	UFUNCTION(BlueprintCallable)
		void PlayersInfoUpdate();
	UFUNCTION(BlueprintCallable)
		void GameEnd();

	UFUNCTION(BlueprintCallable)
		void CS_Connect(FString HostIP);
	UFUNCTION(BlueprintCallable)
		void CS_send_fire();
	UFUNCTION(BlueprintCallable)
		void CS_send_nonefire();
	UFUNCTION(BlueprintCallable)
		void CS_send_yaw(float yaw);
	UFUNCTION(BlueprintCallable)
		void CS_send_dodge();
	UFUNCTION(BlueprintCallable)
		void CS_send_test();
	UFUNCTION(BlueprintCallable)
		void CS_send_hitted_loc(FVector hit_loc);
	UFUNCTION(BlueprintCallable)
		void CS_send_hp_update(float hp, float shield);
	UFUNCTION(BlueprintCallable)
		void CS_send_disconnect();

	UFUNCTION(BlueprintCallable)
		void SC_Connect();
	UFUNCTION(BlueprintCallable)
		void SC_send_Client_HP();
	UFUNCTION(BlueprintCallable)
		void SC_attack_damage();
	UFUNCTION(BlueprintCallable)
		void SC_send_player_state(int client_num);
	UFUNCTION(BlueprintCallable)
		void SC_send_player_soul(int client_num, int soul);

	//IP 받는 용도
	UFUNCTION(BlueprintCallable, Category = "GetIP")
		bool VictoryPC_GetMyIP_SendRequest();
	UFUNCTION(BlueprintImplementableEvent, Category = "GetIP", meta = (DisplayName = "GetMyIP ~ Data Received!"))
		void VictoryPC_GetMyIP_DataReceived(const FString& YourIP);

	void HTTPOnResponseReceived(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful);


	//---------------------------------------------------클라이언트------------------------------------------------------------------
	/*
	UPROPERTY(VisibleAnywhere, BlueprintReadWrite)
		TArray<float> Client_Player_HP;
	UPROPERTY(VisibleAnywhere, BlueprintReadWrite)
		TArray<int> Client_Player_Life;
	UPROPERTY(VisibleAnywhere, BlueprintReadWrite)
		TArray<float> Client_Player_UpperBodyYaw;
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
		int myClinet_ID;
	// 연결 기준은 클라이언트만 넣어주면 된다
	UPROPERTY(VisibleAnywhere, BlueprintReadWrite)
		TArray<bool> Client_Player_InUse;
	UPROPERTY(VisibleAnywhere, BlueprintReadWrite)
		int Client_Player_pPress;
	*/

	UPROPERTY(VisibleAnywhere, BlueprintReadWrite)
		float Client_Player_HP;
	UPROPERTY(VisibleAnywhere, BlueprintReadWrite)
		int Client_Player_Life;

	UPROPERTY(VisibleAnywhere, BlueprintReadWrite)
		float Client_Player_UpperBodyYaw;
	UPROPERTY(VisibleAnywhere, BlueprintReadWrite)
		bool Client_Player_Fire;
	UPROPERTY(VisibleAnywhere, BlueprintReadWrite)
		FVector Client_Player_HittedLoc;
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
		int myClinet_ID;
	
	// 연결 기준은 클라이언트만 넣어주면 된다
	UPROPERTY(VisibleAnywhere, BlueprintReadWrite)
		bool Client_Player_InUse;

	// 내 플레이어의 값을 받아서 사용할 때 넣을 변수
	UPROPERTY(VisibleAnywhere, BlueprintReadWrite)
		class AActor* my_player_actor_;
	// 다른 플레이어의 값을 받아서 사용할 때 넣을 변수
	UPROPERTY(VisibleAnywhere, BlueprintReadWrite)
		TArray<class AActor*> other_players_actor;

	UPROPERTY(VisibleAnywhere, BlueprintReadWrite)
		FRobogang_Player_State my_player_state_;


	//------------------------------------------------------서버------------------------------------------------------------------
		//호스트 플레이어 1명이므로 배열이 필요없다! 
		//-> 하지만 클라이언트라는 값에 전부 넣을 수 있을거 같긴 한데 생각해보기	
	UPROPERTY(VisibleAnywhere, BlueprintReadWrite)
		FRobogang_Player_State other_player_state_;

	// 로그인 OK일때 호출
	UFUNCTION(BlueprintImplementableEvent, Category = "LoginPlayer")
		void login_myid(const int id);
	// 새로운 플레이어가 들어왔을 때 사용, 나중에 호스트 많아지면 사용
	UFUNCTION(BlueprintImplementableEvent, Category = "PutPlayer")
		void get_put_client_id(const int id);
	UFUNCTION(BlueprintImplementableEvent, Category = "fire")
		void client_get_fire(const int id, const bool isfire);
	// 테스트용, 플레이어가 p를 눌렀을 때 작용
	UFUNCTION(BlueprintImplementableEvent, Category = "test")
		void client_recv_test(const int id);
	// 연결 실패
	UFUNCTION(BlueprintImplementableEvent, Category = "connect")
		void client_connect_fail();
	// 클라이언트에게 서버가 state를 보냈을 때
	UFUNCTION(BlueprintImplementableEvent, Category = "get state")
		void client_get_my_state();
	UFUNCTION(BlueprintImplementableEvent, Category = "get state")
		void client_get_my_soul();

	UFUNCTION(BlueprintImplementableEvent, Category = "client login")
		void server_get_client_login(const int id);
	UFUNCTION(BlueprintImplementableEvent, Category = "client fire")
		void server_get_client_fire(const int id, const bool isfire);
	UFUNCTION(BlueprintImplementableEvent, Category = "client yaw")
		void server_get_client_yaw(const int id, const float yaw);
	UFUNCTION(BlueprintImplementableEvent, Category = "client dodge")
		void server_get_client_dodge(const int id);
	UFUNCTION(BlueprintImplementableEvent, Category = "client hitted_loc")
		void server_get_client_hitted_loc(const int id, const FVector hittedLoc);
	UFUNCTION(BlueprintImplementableEvent, Category = "client network test")
		void server_get_client_test(const int id);
	UFUNCTION(BlueprintImplementableEvent, Category = "client hp update")
		void server_get_client_hp_update(const int id);

	//초기화
	void InitVal();

	UFUNCTION(BlueprintCallable)
		void Init_Host_info();
	UFUNCTION(BlueprintCallable)
		void Init_Client_info();	
	UFUNCTION(BlueprintCallable)
		void client_recv_search_for_tick();

protected:
	bool im_server_ = false;
	bool im_client_ = false;
};


// networking part
void error_display(const char *mess, int err_no);
// =======================================================================
// Thread Worker for client

void client_process_packet(char *ptr);
void client_read_packet(SOCKET sock);
bool client_send_packet();
void client_send_shot_packet(bool isFire);
void client_send_yaw_packet(float yaw);
void client_send_dodge();
void client_send_hitted_loc_packet(FVector hit_loc);
void client_send_dod_packet(bool isDodging);
void client_send_dead_packet();
void client_send_test_packet();
void client_send_request_reviver_packet();
void client_send_hp_update(float hp, float shield);
void client_send_disconnect();

void client_error();

// 소켓 초기화 후 연결하는 부분, 나중에 변수를 집어넣고 변수를 이용해서
// 호스트 IP로 들어가는 작업 필요
int client_socket_init();

int client_game_shutdown();

//================================================================
// Thread Worker for server

class ThreadServer : public FNonAbandonableTask
{
public:
	ThreadServer();
	~ThreadServer();

	void DoWork();
	void Get_b_Run(bool b);

	//쓰레드 풀에 쓰레드를 등록한다.
	FORCEINLINE TStatId GetStatId() const
	{
		RETURN_QUICK_DECLARE_CYCLE_STAT(ThreadServer, STATGROUP_ThreadPoolAsyncTasks);
	}
};

void server_do_recv(char id);
// srv_send
void server_send_login_ok_packet(char new_id);
void server_send_packet(char client, void * packet);
void server_send_remove_player_packet(char cl, char id);
// 플레이어가 들어가므로 종족 성별 외모 등이 들어감
void server_send_put_player_packet(char client, char new_id);
void server_send_shoot_pacekt(char client, char send_id, bool isShoot);
void server_send_player_state(char client, FRobogang_Player_State player_state_);
void server_send_player_soul(char client, int soul);
void server_send_test_packet(char  client, char send_id);
void server_process_packet(char client, char *packet);
void server_disconnect_client(char id);
//void server_worker_thread();
//int server_do_accept();
void server_accept_client_Init(char id, const SOCKET& sock);

instance .cpp

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "SafeGameInstance_Robogang.h"
#include "Async/AsyncWork.h"
#include "Public/Sockets.h"
#include "Public/SocketSubsystem.h"
#include "Public/Networking.h"
#include "Public/IPAddress.h"
#include "Public/SocketSubsystem.h"
#include "Public/HttpModule.h"
//#include "Public/Interfaces/IHttpRequest.h"
#include "Public/Interfaces/IHttpResponse.h"
#include "GameFramework/Actor.h"
#include "Engine/World.h"
#include "Kismet/GameplayStatics.h"
#include "Templates/SharedPointer.h"
#include "GameFramework/PlayerController.h"
#include "GameFramework/Actor.h"
#include "MoviePlayer/Public/MoviePlayer.h"
//#include "UMG/Public/Components/Widget.h"
#include "MyProtocol.h"

// 나중에 모아서 구조체 형식으로 변환하자
// 클라이언트 용
string serverIP;
int client_myid = 0;
bool client_connect_false_;

// 서버용
float host_hp = 0;
int host_life = 0;
bool host_isVisible;

// 다른 클래스에서 쉽게 접근하기 위해 만든 클래스
TSharedPtr<USafeGameInstance_Robogang, ESPMode::ThreadSafe> client_game_instance;
TSharedPtr<USafeGameInstance_Robogang, ESPMode::ThreadSafe> server_game_instance;

// dowork 쓰레드가 끝나지 않는 문제를 해결하기 위해서 사용한 변수
volatile bool srv_bRun;

// 변수 써도 안 끝나서 다시 추가한 변수
SOCKET volatile srv_listenSocket;
SOCKET volatile client_mySocket;

//dowork thread for server
TSharedPtr<FAutoDeleteAsyncTask<ThreadServer>, ESPMode::ThreadSafe> srv_dowork_thread;

DWORD client_send_test_io_byte;

// for client val
// 수정 나중에 헤더에 옮기기 지금 헤더에 옮기면 실행 오류
WSABUF client_send_wsabuf;
char client_send_buffer[MAX_BUFFER];
WSABUF client_recv_wsabuf;
char client_recv_buffer[MAX_BUFFER];
char client_packet_buffer[MAX_BUFFER];
DWORD client_in_packet_size = 0;
int client_saved_packet_size = 0;
DWORD client_falgs;
WSAEVENT m_event[WSA_MAXIMUM_WAIT_EVENTS];
WSANETWORKEVENTS m_event_networks;

USafeGameInstance_Robogang::USafeGameInstance_Robogang()
{	
	srv_bRun = false;
	myClinet_ID = -1;
	UE_LOG(LogTemp, Display, TEXT("UGI_RobogangInstance"));
}
USafeGameInstance_Robogang::~USafeGameInstance_Robogang()
{
	//꺼질 때 강종하는 문제점 수정 필요
	UE_LOG(LogTemp, Display, TEXT("~UGI_RobogangInstance"));
	//_CrtSetBreakAlloc(0x00000278489D2E90);
	//_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);	
	
	if (im_client_) {
		CS_send_disconnect();
		closesocket(client_mySocket);
		WSACleanup();
	}
	else if (im_server_) {

	}
	else {

	}

	srv_bRun = false;

	//srv_dowork_thread.Reset();
 	//client_game_instance.Reset();
 	//server_game_instance.Reset();

// 	if (srv_dowork_thread.IsValid()) {
// 		UE_LOG(LogTemp, Error, TEXT("srv_dowork_thread is IsValid true!"));
// 		srv_bRun = false;
// 		TWeakPtr<FAutoDeleteAsyncTask<ThreadServer>, ESPMode::ThreadSafe> srv_dowork_thread_weak = MoveTemp(srv_dowork_thread);
// 		srv_dowork_thread_weak.Reset();
// 		//closesocket(srv_listenSocket);
// 		//WSACleanup();
// 	}
// 	if (client_game_instance.IsValid()) {
// 		UE_LOG(LogTemp, Error, TEXT("client_game_instance is IsValid true!"));
// 		TWeakPtr<USafeGameInstance_Robogang, ESPMode::ThreadSafe> client_game_instance_weak = MoveTemp(client_game_instance);
// 		client_game_instance_weak.Reset();
// 	}
// 	if (server_game_instance.IsValid()) {
// 		UE_LOG(LogTemp, Error, TEXT("server_game_instance is IsValid true!"));
// 		TWeakPtr<USafeGameInstance_Robogang, ESPMode::ThreadSafe> server_game_instance_weak = MoveTemp(server_game_instance);
// 		server_game_instance_weak.Reset();
// 	}
}
void USafeGameInstance_Robogang::GameEnd()
{
	UE_LOG(LogTemp, Display, TEXT("Editor end so srv socket close"));

	srv_bRun = false;

	if (srv_dowork_thread.IsValid()) {
		UE_LOG(LogTemp, Error, TEXT("srv_dowork_thread is IsValid true!"));
		srv_bRun = false;
		TWeakPtr<FAutoDeleteAsyncTask<ThreadServer>, ESPMode::ThreadSafe> srv_dowork_thread_weak = MoveTemp(srv_dowork_thread);
		srv_dowork_thread_weak.Reset();
		closesocket(srv_listenSocket);
		WSACleanup();
	}
	if (client_game_instance.IsValid()) {
		UE_LOG(LogTemp, Error, TEXT("client_game_instance is IsValid true!"));
		TWeakPtr<USafeGameInstance_Robogang, ESPMode::ThreadSafe> client_game_instance_weak = MoveTemp(client_game_instance);
		client_game_instance_weak.Reset();
		CS_send_disconnect();
		closesocket(client_mySocket);
		WSACleanup();
	}
	if (server_game_instance.IsValid()) {
		UE_LOG(LogTemp, Error, TEXT("server_game_instance is IsValid true!"));
		TWeakPtr<USafeGameInstance_Robogang, ESPMode::ThreadSafe> server_game_instance_weak = MoveTemp(server_game_instance);
		server_game_instance_weak.Reset();
	}

	//client_game_instance.Reset();
	//server_game_instance.Reset();
}
void USafeGameInstance_Robogang::Init()
{
	Super::Init();

	FCoreUObjectDelegates::PreLoadMap.AddUObject(this, &USafeGameInstance_Robogang::BeginLoadingScreen);
	FCoreUObjectDelegates::PostLoadMapWithWorld.AddUObject(this, &USafeGameInstance_Robogang::EndLoadingScreen);
}
void USafeGameInstance_Robogang::BeginLoadingScreen(const FString& InMapName)
{
	// loading 관련 https://wiki.unrealengine.com/Loading_Screen 참고
	// if (IsRunningDedicatedServer) 오류 떠서 임시 제거

	FLoadingScreenAttributes LoadingScreen;	

	//테스팅용
	//LoadingScreen.MinimumLoadingScreenDisplayTime = 10000.0f;	

	LoadingScreen.bAutoCompleteWhenLoadingCompletes = true;
	LoadingScreen.bMoviesAreSkippable = true;
	LoadingScreen.bWaitForManualStop = false;
	LoadingScreen.PlaybackType = EMoviePlaybackType::MT_LoadingLoop;

	//LoadingScreen.WidgetLoadingScreen = FLoadingScreenAttributes::NewTestLoadingScreenWidget();

	LoadingScreen.MoviePaths.Add(TEXT("game_intro"));
	LoadingScreen.MoviePaths.Add(TEXT("loading"));
	GetMoviePlayer()->SetupLoadingScreen(LoadingScreen);
	GetMoviePlayer()->PlayMovie();
}
void USafeGameInstance_Robogang::EndLoadingScreen(UWorld* InLoadedWorld) 
{	

}
void USafeGameInstance_Robogang::CS_Connect(FString HostIP)
{
	client_game_instance = TSharedPtr<USafeGameInstance_Robogang, ESPMode::ThreadSafe>(this);
	serverIP = string(TCHAR_TO_UTF8(*HostIP));
	client_connect_false_ = client_socket_init();

	if (client_connect_false_)
		client_connect_fail();
	else
		im_client_ = true;
}
void USafeGameInstance_Robogang::CS_send_fire()
{
	client_send_shot_packet(true);
}
void USafeGameInstance_Robogang::CS_send_nonefire()
{
	client_send_shot_packet(false);
}
void USafeGameInstance_Robogang::CS_send_yaw(float yaw)
{
	client_send_yaw_packet(yaw);
}
void USafeGameInstance_Robogang::CS_send_dodge()
{
	client_send_dodge();
}
void USafeGameInstance_Robogang::CS_send_hitted_loc(FVector hit_loc)
{
	client_send_hitted_loc_packet(hit_loc);
}
void USafeGameInstance_Robogang::CS_send_test()
{
	client_send_test_packet();
}
void USafeGameInstance_Robogang::CS_send_hp_update(float hp, float shield)
{
	client_send_hp_update(hp, shield);
}
void USafeGameInstance_Robogang::CS_send_disconnect() {
	client_send_disconnect();
	closesocket(client_mySocket);
	WSACleanup();
}
// 연결 부분은 다시 끊어줘야 하기 때문에 이런 식으로 전역으로 선언해야한다.
void USafeGameInstance_Robogang::SC_Connect()
{
	srv_bRun = true;

	server_game_instance = TSharedPtr<USafeGameInstance_Robogang, ESPMode::ThreadSafe>(this);
	Init_Host_info();

	//(new FAutoDeleteAsyncTask<ThreadServer>())->StartBackgroundTask();

	//TSharedPtr<FAutoDeleteAsyncTask<ThreadServer>> 

// 	TSharedPtr<FAutoDeleteAsyncTask<ThreadServer>, ESPMode::ThreadSafe> srv_dowork_thread_func
// 		= TSharedPtr<FAutoDeleteAsyncTask<ThreadServer>,
// 		ESPMode::ThreadSafe>(new FAutoDeleteAsyncTask<ThreadServer>());
// 	srv_dowork_thread_func->StartBackgroundTask();
// 	srv_dowork_thread = MoveTemp(srv_dowork_thread_func);
// 	srv_dowork_thread_func.Reset();

// 	//여기서 죽음
	srv_dowork_thread = TSharedPtr<FAutoDeleteAsyncTask<ThreadServer>,
		ESPMode::ThreadSafe>(new FAutoDeleteAsyncTask<ThreadServer>());
	srv_dowork_thread->StartBackgroundTask();

}
void USafeGameInstance_Robogang::SC_send_player_state(int client_num)
{
	if (client_num - CLIENT_MIN_INDEX < 0)
		return;

	server_send_player_state(client_num - CLIENT_MIN_INDEX, other_player_state_);
}
void USafeGameInstance_Robogang::SC_send_player_soul(int client_num, int soul) {
	if (client_num - CLIENT_MIN_INDEX < 0)
		return;

	server_game_instance->other_player_state_.current_soul_ = soul;
	server_send_player_soul(client_num - CLIENT_MIN_INDEX, soul);
}
//tick 같은 곳에서 계속 불러주며 이 값을 업데이트 하게 해줘야한다!
void USafeGameInstance_Robogang::PlayersInfoUpdate()
{

}
bool USafeGameInstance_Robogang::VictoryPC_GetMyIP_SendRequest()
{
	FHttpModule* Http = &FHttpModule::Get();

	if (!Http)
	{
		return false;
	}

	if (!Http->IsHttpEnabled())
	{
		return false;
	}
	//~~~~~~~~~~~~~~~~~~~

	FString TargetHost = "http://api.ipify.org";
	TSharedRef < IHttpRequest > Request = Http->CreateRequest();
	Request->SetVerb("GET");
	Request->SetURL(TargetHost);
	Request->SetHeader("User-Agent", "VictoryBPLibrary/1.0");
	Request->SetHeader("Content-Type", "text/html");

	Request->OnProcessRequestComplete().BindUObject(this, &USafeGameInstance_Robogang::HTTPOnResponseReceived);
	if (!Request->ProcessRequest())
	{
		return false;
	}

	return true;
}
void USafeGameInstance_Robogang::HTTPOnResponseReceived(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful)
{
	FString ResponseStr = "AVictoryPC::HTTPOnResponseReceived>>> Connection Error";
	if (bWasSuccessful)
	{
		ResponseStr = Response->GetContentAsString();
	}

	this->VictoryPC_GetMyIP_DataReceived(ResponseStr);
}
// 호스트 초기화
void USafeGameInstance_Robogang::Init_Host_info()
{
	server_game_instance->my_player_state_.remained_health_ = DEFAULT_HP;
	server_game_instance->my_player_state_.remained_life_ = DEFAULT_LIFE;
	server_game_instance->my_player_state_.remained_shield_ = DEFAULT_SHIELD;
	server_game_instance->my_player_state_.current_soul_ = DEFAULT_SOULS;
	server_game_instance->my_player_state_.max_health_ = MAX_HP;
	server_game_instance->my_player_state_.max_life_ = MAX_LIFE;
	server_game_instance->my_player_state_.max_shield_ = MAX_SHIELD;
	server_game_instance->my_player_state_.player_index_ = HOST_PLAYER_INDEX;
	im_server_ = true;
}
void USafeGameInstance_Robogang::Init_Client_info()
{
	client_game_instance->my_player_state_.remained_health_ = DEFAULT_HP;
	client_game_instance->my_player_state_.remained_life_ = DEFAULT_LIFE;
	client_game_instance->my_player_state_.remained_shield_ = DEFAULT_SHIELD;
	client_game_instance->my_player_state_.current_soul_ = DEFAULT_SOULS;
	client_game_instance->my_player_state_.max_health_ = MAX_HP;
	client_game_instance->my_player_state_.max_life_ = MAX_LIFE;
	client_game_instance->my_player_state_.max_shield_ = MAX_SHIELD;	
	client_game_instance->my_player_state_.player_index_ = CLIENT_MIN_INDEX;
}
//4명 기준이나 현재는 2인 플레이만 상정하고 만들기
void USafeGameInstance_Robogang::InitVal()
{

}
void USafeGameInstance_Robogang::client_recv_search_for_tick()
{
	int val;
	int i;

	i = WSAWaitForMultipleEvents(1, m_event, false, 0, false);
	if (i == WSA_WAIT_FAILED)
		return;

	i -= WSA_WAIT_EVENT_0;

	val = WSAEnumNetworkEvents(client_mySocket, m_event[i], &m_event_networks);
	if (val == SOCKET_ERROR)
		return;

	//FD_READ
	if (m_event_networks.lNetworkEvents& FD_READ)
	{
		if (m_event_networks.iErrorCode[FD_READ_BIT] != 0) {
			UE_LOG(LogTemp, Error, TEXT("FD_READ Error!"));
		}
		else {
			client_read_packet(client_mySocket);
		}
	}

	//FD_CLOSE
	if (m_event_networks.lNetworkEvents& FD_CLOSE) {
		if (m_event_networks.iErrorCode[FD_CLOSE_BIT] != 0) {
			UE_LOG(LogTemp, Error, TEXT("FD_CLOSE Error!"));
		}
		else {
			//client shutdown
		}
	}


}
void USafeGameInstance_Robogang::SC_send_Client_HP()
{

}
void USafeGameInstance_Robogang::SC_attack_damage()
{

}
void client_send_shot_packet(bool isFire)
{
	cs_packet_shoot *my_packet = reinterpret_cast<cs_packet_shoot *>(client_send_buffer);
	my_packet->size = sizeof(cs_packet_shoot);
	my_packet->isFire = isFire;
	client_send_wsabuf.len = sizeof(cs_packet_shoot);
	my_packet->type = CS_SEND_SHOOT;

	client_send_packet();

	/*
	int error = WSASend(client_mySocket, &client_send_wsabuf, 1, &client_send_wsabuf.len, 0, NULL, NULL);
	if (0 != error)
	{
		UE_LOG(LogTemp, Display, TEXT("client_send_shot_packet // send erorr code = %d"), error);
	}
	*/
}
void client_send_dod_packet(bool isDodging)
{

}
void client_send_dead_packet()
{

}
void client_send_request_reviver_packet()
{

}
void client_send_yaw_packet(float yaw)
{
	cs_packet_yaw *my_packet = reinterpret_cast<cs_packet_yaw *>(client_send_buffer);
	my_packet->size = sizeof(cs_packet_yaw);
	my_packet->yaw = yaw;
	client_send_wsabuf.len = sizeof(cs_packet_yaw);
	my_packet->type = CS_SEND_YAW;

	client_send_packet();

	/*
	int error = WSASend(client_mySocket, &client_send_wsabuf, 1, &client_send_wsabuf.len, 0, NULL, NULL);
	if (0 != error)
	{
		UE_LOG(LogTemp, Display, TEXT("client_send_yaw_packet // send erorr code = %d"), error);
	}
	*/
}
void client_send_dodge() {
	cs_packet_dodge *my_packet = reinterpret_cast<cs_packet_dodge *>(client_send_buffer);
	my_packet->size = sizeof(cs_packet_dodge);
	client_send_wsabuf.len = sizeof(cs_packet_dodge);
	my_packet->type = CS_SEND_DODGE;

	client_send_packet();

	/*
	int error = WSASend(client_mySocket, &client_send_wsabuf, 1, &client_send_wsabuf.len, 0, NULL, NULL);
	if (0 != error)
	{
		UE_LOG(LogTemp, Display, TEXT("client_send_dodge // send erorr code = %d"), error);
	}
	*/
}
void client_send_hitted_loc_packet(FVector hit_loc)
{
	cs_packet_hitted_loc *my_packet = reinterpret_cast<cs_packet_hitted_loc *>(client_send_buffer);
	my_packet->size = sizeof(cs_packet_hitted_loc);
	my_packet->hittedLoc = hit_loc;
	client_send_wsabuf.len = sizeof(cs_packet_hitted_loc);
	my_packet->type = CS_SEND_HITTED_LOC;

	client_send_packet();

	/*
	//int error = send(client_mySocket, client_send_wsabuf.buf, client_send_wsabuf.len, 0);
	int error = WSASend(client_mySocket, &client_send_wsabuf, 1, &client_send_wsabuf.len, 0, NULL, NULL);
	if (0 != error)
	{
		UE_LOG(LogTemp, Display, TEXT("client_send_loc_packet // send erorr code = %d"), error);
	}
	*/
}
void client_send_test_packet()
{
	cs_packet_network_test *my_packet = reinterpret_cast<cs_packet_network_test *>(client_send_buffer);
	my_packet->size = sizeof(cs_packet_network_test);
	client_send_wsabuf.len = sizeof(cs_packet_network_test);
	my_packet->type = CS_SEND_TEST;

	client_send_packet();

	/*
	int error = WSASend(client_mySocket, &client_send_wsabuf, 1, &client_send_wsabuf.len, 0, NULL, NULL);
	if (0 != error)
	{
		UE_LOG(LogTemp, Display, TEXT("client_send_loc_z_packet // send erorr code = %d"), error);
	}
	*/
}
void client_send_hp_update(float hp, float shield) {
	cs_packet_hp_update *my_packet = reinterpret_cast<cs_packet_hp_update *>(client_send_buffer);
	my_packet->size = sizeof(cs_packet_hp_update);
	client_send_wsabuf.len = sizeof(cs_packet_hp_update);
	my_packet->type = CS_HP_UPDATE;
	my_packet->hp = hp;
	my_packet->shield = shield;

	client_send_packet();
}
void client_send_disconnect() {
	cs_packet_disconnect *my_packet = reinterpret_cast<cs_packet_disconnect *>(client_send_buffer);
	my_packet->size = sizeof(cs_packet_disconnect);
	client_send_wsabuf.len = sizeof(cs_packet_disconnect);
	my_packet->type = CS_DISCONNECT;

	client_send_packet();
}
bool client_send_packet()
{
	if (client_connect_false_)
		return false;

	int error = WSASend(client_mySocket, &client_send_wsabuf, 1, &client_send_wsabuf.len, 0, NULL, NULL);
	if (0 != error)
	{
		UE_LOG(LogTemp, Display, TEXT("client_send_error! // send erorr code = %d"), error);
	}
	return true;
}
void client_process_packet(char *ptr)
{
	switch (ptr[1])
	{
	case SC_LOGIN_OK:
	{
		sc_packet_login_ok *login_p =
			reinterpret_cast<sc_packet_login_ok *>(ptr);
		client_myid = login_p->login_id;
		client_game_instance->myClinet_ID = client_myid;
		client_game_instance->other_player_state_.remained_health_ = login_p->host_hp;
		client_game_instance->other_player_state_.remained_life_ = login_p->host_life;
		client_game_instance->other_player_state_.remained_shield_ = login_p->host_shield;
		client_game_instance->other_player_state_.current_soul_ = login_p->host_souls;
		client_game_instance->other_player_state_.player_index_ = HOST_PLAYER_INDEX;
		client_game_instance->login_myid(client_myid + CLIENT_MIN_INDEX);
	}
	break;
	case SC_PUT_PLAYER:
	{
		sc_packet_put_player *put_p =
			reinterpret_cast<sc_packet_put_player *>(ptr);
		int id = put_p->id;
		client_game_instance->my_player_state_.remained_health_ = put_p->hp;
		client_game_instance->my_player_state_.remained_life_ = put_p->life;
		client_game_instance->my_player_state_.remained_shield_ = put_p->shield;
		client_game_instance->my_player_state_.current_soul_ = put_p->souls;
	}
	break;
	case SC_PUT_HOST:
	{

	}
	break;
	case SC_PLAYER_HP:
	{

	}
	break;
	case SC_TEST: {
		sc_packet_test_client * test_p = 
			reinterpret_cast<sc_packet_test_client*>(ptr);
		int id = test_p->id;
		client_game_instance->client_recv_test(id);
	}
		break;
	case SC_FIRE:
	{
		sc_packet_shoot_client *shoot_p =
			reinterpret_cast<sc_packet_shoot_client *>(ptr);
		int id = shoot_p->id;
		int isShoot = shoot_p->isShoot;
		client_game_instance->Client_Player_Fire = shoot_p->isShoot;
		client_game_instance->client_get_fire(id, isShoot);
	}
	break;
	case SC_SEND_CLIENT_STATE:
	{
		sc_packet_client_state *state_p =
			reinterpret_cast<sc_packet_client_state *>(ptr);
		int id = state_p->id;
		client_game_instance->my_player_state_.player_index_ = state_p->player_index_;
		client_game_instance->my_player_state_.max_life_ = state_p->max_life_;
		client_game_instance->my_player_state_.remained_life_ = state_p->remained_life_;
		client_game_instance->my_player_state_.current_soul_ = state_p->current_soul_;
		client_game_instance->my_player_state_.max_health_ = state_p->max_health_;
		client_game_instance->my_player_state_.remained_health_ = state_p->remained_health_;
		client_game_instance->my_player_state_.max_shield_ = state_p->max_shield_;
		client_game_instance->my_player_state_.remained_shield_ = state_p->remained_shield_;
		client_game_instance->client_get_my_state();
	}
	break;
	case SC_SEND_CLIENT_SOUL:
	{
		sc_packet_client_soul *soul_p =
			reinterpret_cast<sc_packet_client_soul *>(ptr);
		int id = soul_p->id;
		client_game_instance->my_player_state_.current_soul_ = soul_p->current_soul_;
		client_game_instance->client_get_my_soul();
	}
	break;
	default:
		break;
	}
}
void client_read_packet(SOCKET sock)
{
	DWORD iobyte, ioflag = 0;

	int ret = WSARecv(sock, &client_recv_wsabuf, 1, &iobyte, &ioflag, NULL, NULL);
	if (ret) {
		int err_code = WSAGetLastError();
		UE_LOG(LogTemp, Warning, TEXT("client_read_packet // send erorr code = %d"), WSAGetLastError());
	}

	BYTE *ptr = reinterpret_cast<BYTE *>(client_recv_buffer);

	while (0 != iobyte) {
		UE_LOG(LogTemp, Display, TEXT("client_read_packet"));
		if (0 == client_in_packet_size) client_in_packet_size = ptr[0];
		if (iobyte + client_saved_packet_size >= client_in_packet_size) {
			memcpy(client_packet_buffer + client_saved_packet_size, ptr, client_in_packet_size - client_saved_packet_size);
			client_process_packet(client_packet_buffer);
			ptr += client_in_packet_size - client_saved_packet_size;
			iobyte -= client_in_packet_size - client_saved_packet_size;
			client_in_packet_size = 0;
			client_saved_packet_size = 0;
		}
		else {
			memcpy(client_packet_buffer + client_saved_packet_size, ptr, iobyte);
			client_saved_packet_size += iobyte;
			iobyte = 0;
		}
	}
}
void client_error() {}
int client_socket_init()
{
	WSADATA wsadata;
	int mResult = WSAStartup(MAKEWORD(2, 2), &wsadata);
	if (mResult == INVALID_SOCKET)
	{
		UE_LOG(LogTemp, Display, TEXT("WSAStartup ERROR"));
		WSACleanup();
	}

	client_mySocket = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, NULL);
	if (client_mySocket == INVALID_SOCKET)
	{
		UE_LOG(LogTemp, Error, TEXT("INVALID_SOCKET"));
	}


	SOCKADDR_IN ServerAddr;
	ZeroMemory(&ServerAddr, sizeof(SOCKADDR_IN));
	ServerAddr.sin_family = AF_INET;
	ServerAddr.sin_port = htons(SERVER_PORT);
	// 호스트 IP는 넘겨온 변수값을 이용
	ServerAddr.sin_addr.s_addr = inet_addr(serverIP.c_str());

	// 2. 연결요청
	if (connect(client_mySocket, (struct sockaddr *)&ServerAddr, sizeof(ServerAddr)) == SOCKET_ERROR)
	{
		int err_no = WSAGetLastError();
		UE_LOG(LogTemp, Display, TEXT("Error - Fail to connect %d"), err_no);
		// 4. 소켓종료
		closesocket(client_mySocket);
		// Winsock End
		WSACleanup();
		return 1;
	}
	else
	{
		//테스트용
		UE_LOG(LogTemp, Display, TEXT("Server Connected"));
	}

	//------------------------------------------------------------------------------------------------------------

	m_event[0] = WSACreateEvent();
	if (WSAEventSelect(client_mySocket, m_event[0], FD_READ | FD_CLOSE) == SOCKET_ERROR)
	{
		//테스트 에러
		UE_LOG(LogTemp, Error, TEXT("WSAEventSelect Error"));
	}

	//------------------------------------------------------------------------------------------------------------

	//테스트
	//UE_LOG(LogTemp, Display, TEXT("client_socket_init = %d"), client_mySocket);

	client_send_wsabuf.buf = client_send_buffer;
	client_send_wsabuf.len = MAX_BUFFER;
	client_recv_wsabuf.buf = client_recv_buffer;
	client_recv_wsabuf.len = MAX_BUFFER;

	return 0;
}
int client_game_shutdown()
{
	WSACleanup();
	return 1;
}
//================================================================
// Thread Worker for Server 서버용

// 공유 자료 구조;
HANDLE g_iocp;
//문제가 된다. 여러 쓰레드가 동시에 읽고 쓰고 한다.
SOCKETINFO clients[MAX_USER];

void error_display(const char *mess, int err_no)
{
	WCHAR *lpMsgBuf;
	FormatMessage(
		FORMAT_MESSAGE_ALLOCATE_BUFFER |
		FORMAT_MESSAGE_FROM_SYSTEM,
		NULL, err_no,
		MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
		(LPTSTR)&lpMsgBuf, 0, NULL
	);
	//cout << mess;
	//wcout << L"에러 [" << err_no << L"] " << lpMsgBuf << endl;
	UE_LOG(LogTemp, Warning, TEXT("Error! err_no = %d"), err_no);

	LocalFree(lpMsgBuf);
}
void server_do_recv(char id) {

	//UE_LOG(LogTemp, Display, TEXT("server_do_recv"));

	DWORD flags = 0;

	clients[id].over_ex.dataBuffer.buf = clients[id].over_ex.messageBuffer;
	clients[id].over_ex.is_recv = true;
	if (WSARecv(clients[id].socket, &clients[id].over_ex.dataBuffer, 1,
		NULL, &flags, &(clients[id].over_ex.over), 0))
	{
		if (WSAGetLastError() != WSA_IO_PENDING)
		{
			UE_LOG(LogTemp, Display, TEXT("Error - IO pending Failure"));
		}
	}
	else {
		UE_LOG(LogTemp, Display, TEXT("Non Overlapped Recv return."));
	}
}
void server_send_packet(char client, void * packet)
{
	char *p = reinterpret_cast<char*>(packet);
	OVER_EX *ov = new OVER_EX;
	ov->dataBuffer.len = p[0];
	ov->dataBuffer.buf = ov->messageBuffer;
	ov->is_recv = false;
	memcpy(ov->messageBuffer, p, p[0]);
	ZeroMemory(&ov->over, sizeof(ov->over));

	int error = WSASend(clients[client].socket, &ov->dataBuffer, 1, 0, 0,
		&ov->over, NULL);
	if (0 != error)
	{
		if (WSAGetLastError() != WSA_IO_PENDING)
		{
			//cout << "Error - IO pending Failure\n";
			//while (true);
		}
	}
	else {
		//cout << "Non Overlapped Send return.\n";
		//while (true);
	}
}
// 로그인을 하면 호스트의 생명력과 기본 목숨, 영혼 개수를 넘겨주게 된다.
void server_send_login_ok_packet(char new_id)
{
	sc_packet_login_ok packet;
	packet.login_id = new_id;
	packet.size = sizeof(sc_packet_login_ok);
	packet.type = SC_LOGIN_OK;
	packet.host_hp = server_game_instance->my_player_state_.remained_health_;
	packet.host_life = server_game_instance->my_player_state_.remained_life_;
	packet.host_shield = server_game_instance->my_player_state_.remained_shield_;
	packet.host_souls = server_game_instance->my_player_state_.current_soul_;

	server_send_packet(new_id, &packet);
}
void server_send_remove_player_packet(char cl, char id)
{
	sc_packet_remove_player packet;
	packet.id = id;
	packet.size = sizeof(packet);
	packet.type = SC_REMOVE_PLAYER;

	server_send_packet(cl, &packet);
}
// 호스트를 처음 알려주는 패킷
void server_send_put_host_packet(char client, char new_id)
{
	//서버 정보 업데이트를 어디에서 할 것인지 생각하기
	sc_packet_put_player packet;
	packet.id = new_id;
	packet.size = sizeof(packet);
	packet.type = SC_PUT_HOST;

	server_send_packet(client, &packet);
}
// 플레이어가 들어갔다는걸 알려주는 패킷
void server_send_put_player_packet(char client, char new_id)
{
	sc_packet_put_player packet;
	packet.id = new_id;
	packet.size = sizeof(packet);
	packet.type = SC_PUT_PLAYER;
	packet.hp = clients[new_id].client_hp;
	packet.life = clients[new_id].client_life;
	packet.souls = clients[new_id].client_souls;
	packet.shield = clients[new_id].client_shield;

	server_send_packet(client, &packet);
}
void server_send_shoot_pacekt(char client, char send_id, bool isShoot)
{
	sc_packet_shoot_client packet;
	packet.id = send_id;
	packet.size = sizeof(packet);
	packet.type = SC_FIRE;
	//쏘는 상태라고 보냈을 때
	if (isShoot)
	{
		if (clients[send_id].client_dodging == false)
		{
			packet.isShoot = true;
			server_send_packet(client, &packet);
		}
	}
	else
	{
		packet.isShoot = false;
		server_send_packet(client, &packet);
	}
}
void server_send_player_state(char client, FRobogang_Player_State player_state_) {
	sc_packet_client_state packet;
	packet.size = sizeof(packet);
	packet.type = SC_SEND_CLIENT_STATE;

	packet.player_index_ = player_state_.player_index_;
	packet.max_life_ = player_state_.max_life_;
	packet.remained_life_ = player_state_.remained_life_;
	packet.current_soul_ = player_state_.current_soul_;
	packet.max_health_ = player_state_.max_health_;
	packet.remained_health_ = player_state_.remained_health_;
	packet.max_shield_ = player_state_.max_shield_;
	packet.remained_shield_ = player_state_.remained_shield_;

	server_send_packet(client, &packet);
}
void server_send_player_soul(char client, int soul)
{
	sc_packet_client_soul packet;
	packet.size = sizeof(packet);
	packet.type = SC_SEND_CLIENT_SOUL;

	packet.player_index_ = client + CLIENT_MIN_INDEX;
	packet.current_soul_ = soul;

	server_send_packet(client, &packet);
}
void server_send_test_packet(char  client, char send_id) {
	
	sc_packet_test_client packet;
	packet.id = send_id;
	packet.size = sizeof(packet);
	packet.type = SC_TEST;

	server_send_packet(client, &packet);
}
void server_process_packet(char client, char *packet)
{
	//UE_LOG(LogTemp, Display, TEXT("server_process_packet"));

	//여기 부분 수정해야 할듯
	cs_packet_shoot *p = reinterpret_cast<cs_packet_shoot *>(packet);
	switch (p->type)
	{
	case CS_DISCONNECT:
		server_disconnect_client(client);
		break;
	case CS_CONNECT:
		UE_LOG(LogTemp, Display, TEXT("recv cs connect"));
		break;
	case CS_HP_UPDATE: 
	{
		UE_LOG(LogTemp, Display, TEXT("recv cs hp update"));
		cs_packet_hp_update * h_packet = reinterpret_cast<cs_packet_hp_update *> (packet);
		server_game_instance->other_player_state_.remained_health_ = h_packet->hp;
		server_game_instance->other_player_state_.remained_shield_ = h_packet->shield;
		server_game_instance->server_get_client_hp_update(client);
	}
		break;
	case CS_SEND_SHOOT:
	{
		cs_packet_shoot *c_shoot = reinterpret_cast<cs_packet_shoot *>(packet);
		int id = client;
		bool isShoot = c_shoot->isFire;
		//서버 자신에게도 값 전달
		server_game_instance->server_get_client_fire(id, isShoot);
		for (int i = 0; i < MAX_USER; ++i)
			if (true == clients[i].in_use)
				server_send_shoot_pacekt(i, client, isShoot);
	}
	break;
	case CS_SEND_DODGE: {
		cs_packet_dodge *c_dodge = reinterpret_cast<cs_packet_dodge *>(packet);
		int id = client;
		server_game_instance->server_get_client_dodge(id);
	}
		break;
	case CS_SEND_REQUEST_REVIVER:
		break;
	case CS_SEND_YAW:
	{
		cs_packet_yaw *c_yaw = reinterpret_cast<cs_packet_yaw *>(packet);
		int id = client;
		float yaw = c_yaw->yaw;
		//굳이 yaw을 되돌려줘야 할 필요가 있을까?
		//일단 넘겨줘야할 필요 없다 생각 보류
		server_game_instance->server_get_client_yaw(id, yaw);
	}
		break;
	case CS_SEND_TEST: {
		cs_packet_network_test *c_test = reinterpret_cast<cs_packet_network_test*>(packet);
		int id = client;
		server_game_instance->server_get_client_test(id);
		server_send_test_packet(id, id);
	}
		break;
	case CS_SEND_HITTED_LOC: {
		cs_packet_hitted_loc *c_yaw = reinterpret_cast<cs_packet_hitted_loc *>(packet);
		int id = client;
		FVector HittedLoc = c_yaw->hittedLoc;
		server_game_instance->server_get_client_hitted_loc(id, HittedLoc);
	}
		break;	
	default:
		break;
	}

}
void server_disconnect_client(char id)
{
	UE_LOG(LogTemp, Display, TEXT("disconnect ID : %d "), id);
	for (int i = 0; i < MAX_USER; ++i)
	{
		if (false == clients[i].in_use) continue;
		if (i == id) continue;
		server_send_remove_player_packet(i, id);
	}

	closesocket(clients[id].socket);
	clients[id].in_use = false;
}
void server_worker_thread() {

	while (srv_bRun)
	{
		DWORD io_byte;
		ULONGLONG l_key = NULL;
		OVER_EX *over_ex = nullptr;
		int is_error = 0;

		while (over_ex == nullptr && srv_bRun)
		{
			is_error = GetQueuedCompletionStatus(g_iocp, &io_byte, reinterpret_cast<PULONG_PTR>(&l_key),
				reinterpret_cast<LPWSAOVERLAPPED *>(&over_ex), 10000);
		}
		/*
		is_error = GetQueuedCompletionStatus(g_iocp, &io_byte, reinterpret_cast<PULONG_PTR>(&l_key),
			reinterpret_cast<LPWSAOVERLAPPED *>(&over_ex), INFINITE);
		*/
		if (false == srv_bRun) {
			UE_LOG(LogTemp, Display, TEXT("Worker_Thread Function End"));
			delete over_ex;
			return;
		}


		//테스트용
		//UE_LOG(LogTemp, Display, TEXT("recv byte = %d"), io_byte);

		char key = static_cast<char>(l_key);
		// 강종
		if (0 == is_error)
		{
			int err_no = WSAGetLastError();
			if (64 == err_no)
			{
				UE_LOG(LogTemp, Display, TEXT("%d Disconnect"), err_no);
				server_disconnect_client(key);
				continue;
			}
			UE_LOG(LogTemp, Display, TEXT("GQCS : %d"), err_no);
		}

		//제대로 끊음
		if (0 == io_byte)
		{
			UE_LOG(LogTemp, Display, TEXT("Disconnect"));
			server_disconnect_client(key);
			continue;
		}


		if (true == over_ex->is_recv) {
			// 패킷 조립
			int rest = io_byte;
			char *ptr = over_ex->messageBuffer;
			char packet_size = 0;
			if (0 < clients[key].prev_size)
				packet_size = clients[key].packet_buffer[0];
			while (0 < rest) {
				if (0 == packet_size)
					packet_size = ptr[0];
				int required = packet_size - clients[key].prev_size;
				if (required <= rest) {
					memcpy(clients[key].packet_buffer + clients[key].prev_size,
						ptr, required);
					server_process_packet(key, clients[key].packet_buffer);
					rest -= required;
					ptr += required;
					packet_size = 0;
					clients[key].prev_size = 0;
				}
				else {
					memcpy(clients[key].packet_buffer + clients[key].prev_size,
						ptr, rest);
					rest = 0;
					clients[key].prev_size += rest;
				}
			}
			server_do_recv(key);
		}
		else {
			//send 처리
			if (false == over_ex->is_recv)
				delete over_ex;
		}

	}
}
int server_do_accept()
{
	UE_LOG(LogTemp, Display, TEXT("Server_accept"));
	// Winsock Start - windock.dll 로드
	WSADATA WSAData;
	if (WSAStartup(MAKEWORD(2, 2), &WSAData) != 0)
	{
		UE_LOG(LogTemp, Display, TEXT("Error - Can not load 'winsock.dll' file"));
		return 1;
	}

	// 1. 소켓생성
	srv_listenSocket = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);
	//SOCKET listenSocket = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);
	if (srv_listenSocket == INVALID_SOCKET)
	{
		UE_LOG(LogTemp, Display, TEXT("Error - Invalid socket"));
		return 1;
	}

	// 서버정보 객체설정
	SOCKADDR_IN serverAddr;
	memset(&serverAddr, 0, sizeof(SOCKADDR_IN));
	serverAddr.sin_family = PF_INET;
	serverAddr.sin_port = htons(SERVER_PORT);
	serverAddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);

	// 2. 소켓설정
	if (::bind(srv_listenSocket, (struct sockaddr*)&serverAddr,
		sizeof(SOCKADDR_IN)) == SOCKET_ERROR)
	{
		UE_LOG(LogTemp, Display, TEXT("Error - Fail bind = %d"), WSAGetLastError());
		// 6. 소켓종료
		closesocket(srv_listenSocket);
		// Winsock End
		WSACleanup();
		return 1;
	}

	// 3. 수신대기열생성
	if (listen(srv_listenSocket, 5) == SOCKET_ERROR)
	{
		UE_LOG(LogTemp, Display, TEXT("Error - Fail listen"));
		// 6. 소켓종료
		closesocket(srv_listenSocket);
		// Winsock End
		WSACleanup();
		return 1;
	}

	SOCKADDR_IN clientAddr;
	int addrLen = sizeof(SOCKADDR_IN);
	memset(&clientAddr, 0, addrLen);
	SOCKET clientSocket;
	DWORD flags;

	//바꿔야함 계속 돌면서 쓰레드를 안끔 
	//지금은 이렇게 바꿈
	while (srv_bRun)
	{
		if (srv_bRun == false) {
			closesocket(srv_listenSocket);
			WSACleanup();
			return 1;
		}

		clientSocket = accept(srv_listenSocket, (struct sockaddr *)&clientAddr, &addrLen);
		if (clientSocket == INVALID_SOCKET)
		{
			UE_LOG(LogTemp, Display, TEXT("Error - Accept Failure"));
			return 1;
		}

		int new_id = -1;
		for (int i = 0; i < MAX_USER; ++i) {
			if (false == clients[i].in_use) {
				new_id = i;
				break;
			}
		}
		if (-1 == new_id) {
			UE_LOG(LogTemp, Warning, TEXT("MAX USER overflow"));
			continue;
		}

		//초기화를 하고
		server_accept_client_Init(new_id, clientSocket);

		ZeroMemory(&clients[new_id].over_ex.over,
			sizeof(clients[new_id].over_ex.over));
		flags = 0;

		CreateIoCompletionPort(
			reinterpret_cast<HANDLE>(clientSocket), g_iocp, new_id, 0);

		//IOCP에 등록한 이후에 값을 바꾸어야 한다!
		clients[new_id].in_use = true;

		UE_LOG(LogTemp, Warning, TEXT("im server client new_id = %d"), new_id);

		//들어온 친구에게 호스트의 정보를 알려준다.
		server_send_login_ok_packet(new_id);

		// 호스트에게 접속을 알려줄 필요가 있는가?
		//플레이어들에게 접속을 알려준다.
		for (int i = 0; i < MAX_USER; ++i)
			if (true == clients[i].in_use)
				server_send_put_player_packet(i, new_id);

		//새로운 친구에게도 나머지 인원들이 들어와 있다는걸 알려준다.
		for (int i = 0; i < MAX_USER; ++i)
		{
			if (false == clients[i].in_use) continue;
			if (i == new_id) continue;
			server_send_put_player_packet(new_id, i);
		}

		server_do_recv(new_id);
	}

	// 6-2. 리슨 소켓종료
	closesocket(srv_listenSocket);

	// Winsock End
	WSACleanup();

	UE_LOG(LogTemp, Display, TEXT("server_do_accept end"));

	return 0;
}
void server_accept_client_Init(char id, const SOCKET& sock)
{
	clients[id].socket = sock;
	clients[id].prev_size = 0;
	clients[id].client_hp = DEFAULT_HP;
	clients[id].client_life = DEFAULT_LIFE;
	clients[id].client_upperBodyYaw = DEFAULT_UPPER_BODY_YAW;
	clients[id].client_souls = DEFAULT_SOULS;
	clients[id].client_shield = DEFAULT_SHIELD;

	server_game_instance->other_player_state_.player_index_ = id + CLIENT_MIN_INDEX;
	server_game_instance->other_player_state_.current_soul_ = DEFAULT_SOULS;
	server_game_instance->other_player_state_.max_health_ = MAX_HP;
	server_game_instance->other_player_state_.remained_health_ = DEFAULT_HP;
	server_game_instance->other_player_state_.max_shield_ = MAX_SHIELD;
	server_game_instance->other_player_state_.remained_shield_ = DEFAULT_SHIELD;
	server_game_instance->other_player_state_.max_life_ = MAX_LIFE;
	server_game_instance->other_player_state_.remained_life_ = DEFAULT_LIFE;
	server_game_instance->server_get_client_login(id + CLIENT_MIN_INDEX);
}
ThreadServer::ThreadServer()
{
	UE_LOG(LogTemp, Display, TEXT("Server Task Started"));
}
ThreadServer::~ThreadServer()
{
	UE_LOG(LogTemp, Display, TEXT("Server Task Finished"));
}
void ThreadServer::Get_b_Run(bool b)
{
	srv_bRun = b;
}
void ThreadServer::DoWork()
{	
	wcout.imbue(locale("korean"));

	vector <thread> worker_threads;

	thread accept_thread{ server_do_accept };

	g_iocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0, 0);
	for (int i = 0; i < 4; ++i) {
		worker_threads.emplace_back(thread{ server_worker_thread });
	}

	for (auto &th : worker_threads) th.join();
	UE_LOG(LogTemp, Display, TEXT("Worker_Threads End DoWork End"));

	//volatile로 선언한 값도 넘어가지 않고 있다. 이를 해결하기 위해서 여기서 다시 값을 변경해준다.
	srv_bRun = false;
	closesocket(srv_listenSocket);
	WSACleanup();

	accept_thread.join();
	UE_LOG(LogTemp, Display, TEXT("Accept_Thread End"));
}