Skip to content
This repository has been archived by the owner on Nov 17, 2022. It is now read-only.

서버 업데이트 #41

Merged
merged 8 commits into from
Dec 5, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions src/Server/GameInstance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,6 @@ void GameInstance::SetVelocity(double speed, double dir) {
vspeed = lengthdir_y(speed, dir);
}

RenderInstance& GameInstance::GetRenderInstance() {
return my_renders;
}

void GameInstance::SetBoundBox(const RECT& mask) {
CopyRect(&box, &mask);
}
Expand Down
1 change: 0 additions & 1 deletion src/Server/GameInstance.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ class GameInstance {
virtual const char* GetIdentifier() const;

RenderInstance& AssignRenderingInfo(double angle);
RenderInstance& GetRenderInstance();

void SetBoundBox(const RECT& mask);
int GetBoundLT() const;
Expand Down
72 changes: 31 additions & 41 deletions src/Server/Main.cpp
Original file line number Diff line number Diff line change
@@ -1,46 +1,34 @@
#include "stdafx.h"
#include "stdafx.h"
#include "Framework.h"
#include "CommonDatas.h"
#include "ServerFramework.h"
#include "Main.h"
#include "ServerFramework.h"


RenderInstance rendering_infos_last[RENDER_INST_COUNT];
// 스레드 프로세스
DWORD WINAPI ConnectProcess(LPVOID arg);
DWORD WINAPI GameProcess(LPVOID arg);

int main() {
WSADATA wsadata;
if (0 != WSAStartup(MAKEWORD(2, 2), &wsadata)) {
ErrorAbort("WSAStartup()");
return false;
}
ServerFramework f{};

my_socket = socket(AF_INET, SOCK_STREAM, 0);
if (INVALID_SOCKET == my_socket) {
ErrorAbort("socket()");
return false;
}
int main() {
f.Initialize();

BOOL option = TRUE;
if (SOCKET_ERROR == setsockopt(my_socket, SOL_SOCKET, SO_REUSEADDR
, reinterpret_cast<char*>(&option), sizeof(option))) {
ErrorAbort("setsockopt()");
return false;
}
CreateThread(NULL, 0, ConnectProcess, nullptr, 0, NULL);

ZeroMemory(&my_address, sizeof(my_address));
my_address.sin_family = AF_INET;
my_address.sin_addr.s_addr = htonl(INADDR_ANY);
my_address.sin_port = htons(COMMON_PORT);
Sleep(8000);
f.CreatePlayer();
f.SetGameProcess();

if (SOCKET_ERROR == bind(my_socket, reinterpret_cast<SOCKADDR*>(&my_address), my_address_size)) {
ErrorAbort("bind()");
return false;
// 클라이언트 연결
while (true)
{
}

if (SOCKET_ERROR == listen(my_socket, CLIENT_NUMBER_MAX + 1)) {
ErrorAbort("listen()");
return false;
}
CCharacter::CCharacter() : GameInstance() {
SetRenderType(RENDER_TYPES::CHARACTER);
SetBoundBox(RECT{ -6, -6, 6, 6 });
}

AtomicPrintLn("서버 시작");

Expand Down Expand Up @@ -96,23 +84,25 @@ int main() {

DWORD WINAPI ConnectProcess(LPVOID arg) {
while (true) {
SOCKET listen_socket = f.GetListenSocket();
SOCKET client_socket;
SOCKADDR_IN client_address;
int my_addr_size = sizeof(client_address);

SetEvent(event_accept);
f.SetConnectProcess();

client_socket = accept(my_socket, reinterpret_cast<SOCKADDR*>(&client_address), &my_addr_size);
client_socket = accept(listen_socket, reinterpret_cast<SOCKADDR*>(&client_address), &my_addr_size);
if (INVALID_SOCKET == client_socket) {
ErrorDisplay("connect()");
continue;
}


BOOL option = FALSE;
setsockopt(my_socket, IPPROTO_TCP, TCP_NODELAY
, reinterpret_cast<const char*>(&option), sizeof(option));

auto client = new ClientSession(client_socket, NULL, players_number++);
auto client = new ClientSession(client_socket, NULL, f.GetPlayerNumber());

auto th = CreateThread(NULL, 0, GameProcess, (LPVOID)(client), 0, NULL);
if (NULL == th) {
Expand All @@ -121,11 +111,11 @@ DWORD WINAPI ConnectProcess(LPVOID arg) {
}
CloseHandle(th);

players.push_back(client);
f.AddPlayer(client);

AtomicPrintLn("클라이언트 접속: ", client_socket, ", 수: ", players_number);
AtomicPrintLn("클라이언트 접속: ", client_socket, ", 수: ", f.GetPlayerNumber());

WaitForSingleObject(event_accept, INFINITE);
WaitForSingleObject(f.GetAcceptEvent(), INFINITE);
}

return 0;
Expand All @@ -136,7 +126,7 @@ DWORD WINAPI GameProcess(LPVOID arg) {
SOCKET client_socket = client->my_socket;

while (true) {
WaitForSingleObject(event_game_communicate, INFINITE);
WaitForSingleObject(f.GetGameProcessEvent(), INFINITE);

PACKETS header;
ZeroMemory(&header, HEADER_SIZE);
Expand Down Expand Up @@ -222,14 +212,14 @@ DWORD WINAPI GameProcess(LPVOID arg) {
// 3. 게임 처리

// 4. 렌더링 정보 작성
BakeRenderingInfos();
f.CreateRenderingInfos();

// 5. 렌더링 정보 전송
SendRenderingInfos(client_socket);
f.SendRenderingInfos(client_socket);

// 6. 대기
Sleep(FRAME_TIME);
SetEvent(event_game_communicate);
f.SetGameProcess();
}

return 0;
Expand Down
113 changes: 2 additions & 111 deletions src/Server/Main.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
#pragma once
#pragma once
#include "stdafx.h"
#include "CommonDatas.h"
#include "GameInstance.h"

CRITICAL_SECTION client_permission, print_permission;

class CCharacter : public GameInstance {
public:
Expand Down Expand Up @@ -43,116 +44,6 @@ class ClientSession {
~ClientSession();
};

/* 소켓 */
SOCKET my_socket; // 서버 소켓
SOCKADDR_IN my_address; // 서버 주소
int my_address_size = sizeof(my_address);

/* 다중 스레드 정보 */
HANDLE event_accept; // 클라이언트 수용 신호
HANDLE event_game_communicate; // 게임 처리 신호
HANDLE event_quit; // 종료 신호
CRITICAL_SECTION permission_client, permission_;

/* 플레이어 관련 속성 */
vector<ClientSession*> players; // 플레이어 목록
int player_process_index; // 현재 처리 중인 플레이어의 순번 [0~client_number)
int players_number; // 지금 접속한 플레이어의 수
int player_number_last; // 마지막에 추가된 플레이어의 번호
int player_captain; // 방장 플레이어
int player_winner; // 승리한 플레이어

/* 게임 관련 속성 */
vector<GameInstance*> instances; // 인스턴스 목록
normal_distribution<> random_distrubution; // 서버의 무작위 분포 범위
default_random_engine randomizer;

bool game_started;
int** PLAYER_SPAWN_PLACES; // 플레이어가 맨 처음에 생성될 위치의 배열
const int SPAWN_DISTANCE = 300; // 플레이어 생성 위치를 정할 때 사용하는 거리 값

/* 스레드 선언 */
DWORD WINAPI ConnectProcess(LPVOID arg); // 다중, 수신 스레드
DWORD WINAPI GameProcess(LPVOID arg); // 단일, 송신 스레드

void Initialize();
void Startup();
void Ready();
void Cleanup();

void ClientConnect();
void ClientDisconnect(int player_index);

// 정해둔 스폰 지점에 플레이어 캐릭터들을 생성한다.
void CreatePlayerCharacters();

void ProceedContinuation(); // 게임 진행 확인
bool CheckClientNumber(); // 접속한 클라이언트 수 확인
bool ValidateSocketMessage(int socket_state); // 받은 소켓 메시지 검증
void BakeRenderingInfos(); // 렌더링 정보 만들기
void SendRenderingInfos(SOCKET my_socket); // 렌더링 정보 보내기

inline DWORD WINAPI AwaitClientAcceptEvent() {
AtomicPrintLn("AwaitClientAcceptEvent()");
return WaitForSingleObject(event_accept, INFINITE);
}

inline DWORD WINAPI AwaitReceiveEvent() {
AtomicPrintLn("AwaitReceiveEvent()");
return WaitForSingleObject(event_game_communicate, INFINITE);
}

// 지정한 위치에 인스턴스를 생성한다.
template<class _GameClass = GameInstance>
_GameClass* Instantiate(double x = 0.0, double y = 0.0) {
auto result = new _GameClass();
result->x = x;
result->y = y;

instances.push_back(result);

return result;
}

// 지정한 인스턴스를 삭제한다.
template<class _GameClass = GameInstance>
void Kill(_GameClass* target) {
auto loc = find_if(instances.begin(), instances.end(), [target] (const auto& lhs) {
return (lhs == target);
});

if (loc != instances.end()) {
target->OnDestroy();
instances.erase(loc);
}
}

// 두 게임 인스턴스의 충돌을 검사한다.
template<class _GameClass1, class _GameClass2>
inline _GameClass2* CheckCollision(_GameClass1* self, _GameClass2* other) {
if (self && other && self != other) {
if (self->IsCollideWith(other))
return other;
}
return nullptr;
}

// 어떤 게임 인스턴스에게 충돌하는 인스턴스를, 식별자 fid를 기반으로 찾아낸다.
template<class _GameClassTarget, class _GameClassSelf>
_GameClassTarget* SeekCollision(_GameClassSelf* self, const char* fid) {
if (self && !instances.empty()) {
auto CopyList = vector<GameInstance*>(instances);

auto it = std::find_if(CopyList.begin(), CopyList.end(), [&] (GameInstance* inst) {
auto iid = inst->GetIdentifier();
auto id_check = strcmp(iid, fid);

return (0 == id_check);
});

if (it != CopyList.end()) {
return dynamic_cast<_GameClassTarget*>(*it);
}
}
return nullptr;
}
Loading