-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathPlayer.cpp
More file actions
165 lines (138 loc) · 3.41 KB
/
Copy pathPlayer.cpp
File metadata and controls
165 lines (138 loc) · 3.41 KB
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
154
155
156
157
158
159
160
161
162
163
164
165
#include "Player.h"
#include "Server.h"
#include "SqlClient.h"
#include "SqlClientManager.h"
#include "Character.h"
#include <string>
#include <mariadb/conncpp.hpp>
#include "./SQL/generated/dao.h"
#include "LogHelper.h"
#include "PlayerRepository.h"
#include "PlayerLoadData.h"
#include "PlayerQuest.h"
#include "PlayerItem.h"
#include "PlayerSkill.h"
#include "PlayerLevel.h"
#include "PlayerSaveData.h"
#include "PlayerEventBroker.h"
#include "PlayerEventBrokerProxy.h"
// todo : Player ID 디비에서 관리 개선 필요
static long next_player_id = 1;
Player::Player()
{
uuid_ = boost::uuids::random_generator()();
playerId_ = next_player_id++;
playerLazySaveAcc_ = 0.0f;
this->AddComponent<PlayerEventBroker>();
this->AddComponent<PlayerQuest>();
this->AddComponent<PlayerItem>();
this->AddComponent<PlayerSkill>();
this->AddComponent<PlayerLevel>();
}
Player::~Player()
{
}
void Player::SetSession(std::shared_ptr<GameSession> session)
{
session_ = session;
}
void Player::SetServer(GameServer* server)
{
server_ = server;
}
void Player::Possess(std::shared_ptr<Character> character)
{
character_ = character;
character_->SetPlayerId(playerId_);
// Player가 소유한 PlayerEventBroker를 Character가 동일하게 사용할 수 있도록
// 프록시 컴포넌트를 부착하고, 브로커의 소유자(Player)를 약하게 참조하게 한다.
auto* proxy = character_->AddComponent<PlayerEventBrokerProxy>();
proxy->SetBrokerOwner(weak_from_this());
}
void Player::Send(std::shared_ptr<send_message>& msg)
{
auto session = session_.lock();
if (session)
{
session->Send(msg);
}
else
{
LOG.error("Session expired! in send");
}
}
void Player::Close()
{
auto session = session_.lock();
if (session)
{
session->Close();
}
else
{
LOG.error("Session expired! in close");
}
}
bool Player::SwitchSession(std::shared_ptr<Player> player)
{
if (this == player.get())
{
LOG.error("Player is same! in switch_session");
return false;
}
// 기존 세션 정리
Close();
auto session = player->session_.lock();
if (!session)
{
LOG.error("Session expired! in switch_session");
return false;
}
session->SetPlayer(shared_from_this());
LOG.info("Switching session for player {} to new session", playerId_);
return true;
}
void Player::OnLoadedData(const PlayerLoadData & data)
{
LOG.info("Player {} loaded data: name={}, items={}, skills={}", playerId_, data.player.name, data.items.size(), data.skills.size());
SetName(data.player.name);
SetLevel(data.player.level);
ForEachComponent([&data](Component& component)
{
component.Load(data);
});
}
void Player::Update(float dt)
{
GameObject::Update(dt);
// 1분마다 플레이어 데이터를 디비에 저장하는 로직
playerLazySaveAcc_ += dt;
if (playerLazySaveAcc_ >= 60.0f)
{
SavePlayerData();
playerLazySaveAcc_ -= 60.0f;
}
}
std::optional<boost::asio::strand<boost::asio::thread_pool::executor_type>> Player::GetStrand()
{
if (auto session = session_.lock())
{
return session->strand_;
}
return std::nullopt;
}
void Player::SavePlayerData()
{
// 각 컴포넌트에서 플레이어 데이터를 수집
auto save_data = std::make_shared<PlayerSaveData>();
ForEachComponent([&save_data](Component& component)
{
if (component.IsDirty())
{
component.Save(save_data.get());
component.ClearDirty();
}
});
// 변경된 데이터만 비동기로 전달
PlayerRepository::AsyncSave(shared_from_this(), save_data);
}