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"));
}