-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathFramework.hpp
153 lines (130 loc) · 4.79 KB
/
Framework.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#pragma once
#include "stdafx.hpp"
#include "Asynchron.hpp"
#include "Session.h"
#include "SightManager.hpp"
const UINT THREADS_COUNT = 6;
using SessionPtr = shared_ptr<Session>;
void IOCPWorker();
void AIWorker();
void TimerWorker();
class IOCPFramework
{
public:
IOCPFramework();
~IOCPFramework();
void Awake();
void Start();
void Update();
void Release();
void BuildSessions();
void BuildNPCs();
void BuildThreads();
void Listen();
SessionPtr CreateNPC(const UINT index, ENTITY_CATEGORY type);
friend void IOCPWorker();
friend void AIWorker();
friend void TimerWorker();
friend class Session;
private:
void ProceedSignUp();
void ProceedLoginFailed(SOCKET sock, LOGIN_ERROR_TYPES reason);
void ProceedSignIn(Session* handle, const CSPacketSignIn* packet);
void RegisterSight(Session* who);
void InitializeSight(Session* who);
/// <summary>
/// 특정 세션의 시야 목록 갱신. NPC라면 송신은 안 한다.
/// 현재 시야 목록과 바뀐 시야 목록을 비교해서 전송.
/// </summary>
void UpdateSight(Session* who);
void CleanupSight(Session* who);
SessionPtr GetClient(const UINT index) const;
SessionPtr GetClientByID(const PID id) const;
SessionPtr GetClient(const PID) const = delete;
SessionPtr GetClientByID(const UINT) const = delete;
UINT GetClientsNumber() const volatile;
void Disconnect(const PID id);
void ConnectFrom(const PID) = delete;
void Disconnect(const UINT) = delete;
void RegisterPlayer(const PID id, const UINT place);
void DeregisterPlayer(const PID id);
void SetClientsNumber(const UINT number) volatile;
UINT AcquireClientsNumber() const volatile;
shared_ptr<Session> AcquireClient(const UINT index) const;
shared_ptr<Session> AcquireClientByID(const PID id) const;
shared_ptr<Session> AcquireClient(const shared_atomic<Session>& ptr) const volatile;
SOCKET AcquireNewbieSocket() const volatile;
PID AcquireNewbieID() const volatile;
SOCKET CreateSocket() const volatile;
shared_ptr<Session> FindPlaceForNewbie() const;
void ReleaseClientsNumber(const UINT number) volatile;
void ReleaseClient(const UINT home, shared_ptr<Session>& original);
void ReleaseNewbieSocket(const SOCKET n_socket) volatile;
void ReleaseNewbieID(const PID next) volatile;
/// <summary>
/// 패킷 생성
/// </summary>
template<typename MY_PACKET, typename ...Ty>
requires std::is_base_of_v<Packet, MY_PACKET>
std::pair<LPWSABUF, Asynchron*> CreateTicket(Ty&&... args) const;
/// <summary>
/// 클라이언트에게 새로운 접속을 알리고, 로컬 플레이어 세션을 생성하도록 명령한다.
/// </summary>
/// <param name="target">클라이언트의 세션</param>
/// <param name="who">새로 접속한 플레이어의 세션</param>
/// <param name="nickname">새로 접속한 플레이어의 별명</param>
int SendPlayerCreate(Session* target, const PID who, char* nickname) const;
/// <summary>
/// 클라이언트의 접속을 종료시키고, 다른 클라이언트에 알린다.
/// </summary>
/// <param name="target">클라이언트의 세션</param>
/// <param name="who">나가는 플레이어의 세션</param>
int SendSignOut(Session* target, const PID who) const;
/// <summary>
/// 시야 내에 개체가 들어왔음을 알린다.
/// </summary>
/// <param name="target">클라이언트의 세션</param>
/// <param name="cid">NPC, 특수 객체, 플레이어의 고유 식별자</param>
/// <param name="data">객체의 성분</param>
int SendAppearEntity(Session* target, PID cid, SCPacketAppearEntity data) const;
/// <summary>
/// 시야 내에서 개체가 사라졌음을 알린다.
/// </summary>
/// <param name="target">클라이언트의 세션</param>
/// <param name="cid">NPC, 특수 객체, 플레이어의 고유 식별자</param>
int SendDisppearEntity(Session* target, PID cid) const;
/// <summary>
/// 개체의 이동을 알린다. (플레이어 자신도 포함)
/// </summary>
/// <param name="target">클라이언트의 세션</param>
/// <param name="cid">NPC, 특수 객체, 플레이어의 고유 식별자</param>
/// <param name="nx"></param>
/// <param name="ny"></param>
int SendMoveEntity(Session* target, PID cid, float nx, float ny, MOVE_TYPES dir) const;
inline const HANDLE GetCompletionPort() const { return completionPort; }
SOCKET myListener;
SOCKADDR_IN myAddress;
INT szAddress;
HANDLE completionPort;
const ULONG_PTR serverKey;
Asynchron acceptOverlap;
DWORD acceptBytes;
char acceptCBuffer[BUFFSZ];
atomic<SOCKET> acceptNewbie;
std::array<shared_atomic<Session>, ENTITIES_MAX_NUMBER>::const_iterator acceptBeginPlace;
/// <summary>
/// NPC, 특수 객체, 플레이어를 저장하는 저장소
/// </summary>
std::array<shared_atomic<Session>, ENTITIES_MAX_NUMBER> clientsPool;
/// <summary>
/// 플레이어의 ID -> clientsPool의 번호 (CLIETNS_ORDER_BEGIN부터 시작)
/// </summary>
//concurrent_map<PID, UINT> myClients;
std::unordered_map<PID, UINT> myClients;
atomic<UINT> numberClients;
atomic<PID> orderClientIDs;
SightManager mySightManager;
std::vector<std::jthread> threadWorkers;
std::priority_queue<Timeline> timerQueue;
std::mutex timerMutex;
};