173 lines
5.5 KiB
C++
173 lines
5.5 KiB
C++
#include "PacketHandler.h"
|
|
#include "DatabaseManager.h"
|
|
#include "Logger.h"
|
|
#include "Protocol.pb.h"
|
|
#include "SessionManager.h"
|
|
#include "SwordLogic.h"
|
|
#include <boost/asio/use_awaitable.hpp>
|
|
#include <cstring>
|
|
#include <string>
|
|
|
|
boost::asio::awaitable<void>
|
|
PacketHandler::HandlePacket(std::shared_ptr<Session> session,
|
|
const Packet packet) {
|
|
switch (static_cast<PacketID>(packet.header.id)) {
|
|
case PacketID::Ping: {
|
|
Logger::Log("Ping 수신됨");
|
|
session->SendPacket(PacketID::Ping);
|
|
} break;
|
|
|
|
case PacketID::CS_Login: {
|
|
Protocol::CS_Login pkt;
|
|
if (!pkt.ParseFromArray(packet.payload.data(), packet.payload.size())) {
|
|
Logger::Log("로그인 패킷 파싱 실패");
|
|
co_return;
|
|
}
|
|
|
|
std::string nickname = pkt.nickname();
|
|
auto userData = co_await DatabaseManager::GetInstance().LoadUser(nickname);
|
|
|
|
// 골드와 검 레벨 설정 (닉네임은 TryJoin에서 설정)
|
|
session->SetGold(userData.gold);
|
|
session->SetSwordLevel(userData.swordLevel);
|
|
|
|
Protocol::SC_LoginResult loginResult;
|
|
|
|
// 중복 체크
|
|
if (!SessionManager::GetInstance().TryJoin(session, userData.nickname)) {
|
|
Logger::Log("중복 로그인 거부: ", nickname);
|
|
loginResult.set_success(false);
|
|
session->SendPacket(PacketID::SC_LoginResult, loginResult);
|
|
co_return;
|
|
}
|
|
|
|
Logger::Log("클라이언트 로그인 성공: ", nickname,
|
|
" (Gold: ", session->GetGold(),
|
|
", Level: ", session->GetSwordLevel(), ")");
|
|
|
|
loginResult.set_success(true);
|
|
loginResult.set_gold(session->GetGold());
|
|
loginResult.set_sword_level(session->GetSwordLevel());
|
|
session->SendPacket(PacketID::SC_LoginResult, loginResult);
|
|
} break;
|
|
|
|
case PacketID::CS_UpgradeSword: {
|
|
auto currentLevel = session->GetSwordLevel();
|
|
auto cost = SwordLogic::GetUpgradeCost(currentLevel);
|
|
auto currentGold = session->GetGold();
|
|
|
|
Protocol::SC_UpgradeResult res;
|
|
if (currentGold < cost) {
|
|
// 골드 부족
|
|
res.set_result(2);
|
|
} else {
|
|
session->SetGold(currentGold - cost);
|
|
auto result = SwordLogic::TryUpgrade(currentLevel);
|
|
res.set_result(result);
|
|
|
|
// 성공
|
|
if (result == 1) {
|
|
session->SetSwordLevel(currentLevel + 1);
|
|
// 파괴
|
|
} else if (result == 0) {
|
|
session->SetSwordLevel(0);
|
|
}
|
|
|
|
co_await DatabaseManager::GetInstance().SaveUser(
|
|
session->GetNickname(), session->GetGold(), session->GetSwordLevel());
|
|
}
|
|
|
|
res.set_current_level(session->GetSwordLevel());
|
|
res.set_current_gold(session->GetGold());
|
|
|
|
// 결과 패킷 전송
|
|
session->SendPacket(PacketID::SC_UpgradeResult, res);
|
|
|
|
// 브로드캐스트
|
|
if (currentGold >= cost) {
|
|
uint32_t attemptedLevel = currentLevel + 1;
|
|
std::string resultText;
|
|
if (res.result() == 1) {
|
|
resultText = "를 달성했습니다!";
|
|
} else if (res.result() == 0) {
|
|
resultText = " 시도 중 검이 파괴되었습니다!";
|
|
} else {
|
|
resultText = " 달성에 실패했습니다!";
|
|
}
|
|
|
|
std::string chatMsg = "채팅] " + session->GetNickname() +
|
|
" 님이 검 강화 단계 " +
|
|
std::to_string(attemptedLevel) + resultText;
|
|
|
|
PacketHeader chatHeader;
|
|
chatHeader.id = static_cast<uint16_t>(PacketID::Chat);
|
|
chatHeader.size = static_cast<uint16_t>(chatMsg.size());
|
|
|
|
std::vector<uint8_t> chatPayload(chatMsg.begin(), chatMsg.end());
|
|
SessionManager::GetInstance().Broadcast(chatHeader, chatPayload);
|
|
|
|
Logger::Log("강화 시도 [", session->GetNickname(),
|
|
"]: ", (int)res.result(), " (레벨: ", currentLevel, "->",
|
|
res.current_level(), ")");
|
|
}
|
|
} break;
|
|
|
|
case PacketID::CS_SellSword: {
|
|
auto currentLevel = session->GetSwordLevel();
|
|
auto price = SwordLogic::GetSellPrice(currentLevel);
|
|
auto newGold = session->GetGold() + price;
|
|
|
|
session->SetGold(newGold);
|
|
session->SetSwordLevel(0);
|
|
|
|
co_await DatabaseManager::GetInstance().SaveUser(
|
|
session->GetNickname(), session->GetGold(), session->GetSwordLevel());
|
|
|
|
Protocol::SC_SellResult res;
|
|
res.set_earned_gold(price);
|
|
res.set_total_gold(newGold);
|
|
|
|
session->SendPacket(PacketID::SC_SellResult, res);
|
|
|
|
Logger::Log("검 판매 [", session->GetNickname(), "]: ", price,
|
|
" 골드 획득");
|
|
} break;
|
|
|
|
case PacketID::Chat: {
|
|
std::string msg(packet.payload.begin(), packet.payload.end());
|
|
Logger::Log("채팅 [", session->GetNickname(), "]: ", msg);
|
|
SessionManager::GetInstance().Broadcast(packet.header, packet.payload);
|
|
} break;
|
|
|
|
case PacketID::CS_RankingRequest: {
|
|
Protocol::CS_RankingRequest pkt;
|
|
if (!pkt.ParseFromArray(packet.payload.data(), packet.payload.size())) {
|
|
Logger::Log("랭킹 요청 패킷 파싱 실패");
|
|
co_return;
|
|
}
|
|
|
|
auto rankResult = co_await DatabaseManager::GetInstance().GetRanking(
|
|
(int)pkt.type(), session->GetNickname());
|
|
|
|
Protocol::SC_RankingList res;
|
|
res.set_type(pkt.type());
|
|
res.set_my_rank(rankResult.myRank);
|
|
res.set_my_value(rankResult.myValue);
|
|
|
|
for (const auto &entry : rankResult.topEntries) {
|
|
auto *newEntry = res.add_entries();
|
|
newEntry->set_rank(entry.rank);
|
|
newEntry->set_nickname(entry.nickname);
|
|
newEntry->set_value(entry.value);
|
|
}
|
|
|
|
session->SendPacket(PacketID::SC_RankingList, res);
|
|
} break;
|
|
|
|
default:
|
|
Logger::Log("알 수 없는 패킷 ID: ", packet.header.id);
|
|
break;
|
|
}
|
|
|
|
co_return;
|
|
}
|