146 lines
4.6 KiB
C++
146 lines
4.6 KiB
C++
#include "PacketHandler.h"
|
|
#include "DatabaseManager.h"
|
|
#include "Logger.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: {
|
|
if (packet.payload.size() < sizeof(PKT_CS_Login)) {
|
|
Logger::Log("로그인 패킷 크기가 올바르지 않습니다.");
|
|
co_return;
|
|
}
|
|
|
|
const PKT_CS_Login *loginPkt =
|
|
reinterpret_cast<const PKT_CS_Login *>(packet.payload.data());
|
|
std::string nickname(loginPkt->nickname);
|
|
|
|
auto userData = co_await DatabaseManager::GetInstance().LoadUser(nickname);
|
|
|
|
// 골드와 검 레벨 설정 (닉네임은 TryJoin에서 설정)
|
|
session->SetGold(userData.gold);
|
|
session->SetSwordLevel(userData.swordLevel);
|
|
|
|
PKT_SC_LoginResult loginResult;
|
|
|
|
// 중복 체크
|
|
if (!SessionManager::GetInstance().TryJoin(session, userData.nickname)) {
|
|
Logger::Log("중복 로그인 거부: ", nickname);
|
|
loginResult.result = 0;
|
|
session->SendPacket(PacketID::SC_LoginResult, loginResult);
|
|
co_return;
|
|
}
|
|
|
|
Logger::Log("클라이언트 로그인 성공: ", nickname,
|
|
" (Gold: ", session->GetGold(),
|
|
", Level: ", session->GetSwordLevel(), ")");
|
|
|
|
loginResult.result = 1;
|
|
session->SendPacket(PacketID::SC_LoginResult, loginResult);
|
|
} break;
|
|
|
|
case PacketID::CS_UpgradeSword: {
|
|
uint32_t currentLevel = session->GetSwordLevel();
|
|
uint64_t cost = SwordLogic::GetUpgradeCost(currentLevel);
|
|
uint64_t currentGold = session->GetGold();
|
|
|
|
PKT_SC_UpgradeResult res;
|
|
if (currentGold < cost) {
|
|
// 골드 부족
|
|
res.result = 2;
|
|
} else {
|
|
session->SetGold(currentGold - cost);
|
|
uint8_t result = SwordLogic::TryUpgrade(currentLevel);
|
|
res.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.currentLevel = session->GetSwordLevel();
|
|
res.currentGold = 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.currentLevel, ")");
|
|
}
|
|
} break;
|
|
|
|
case PacketID::CS_SellSword: {
|
|
uint32_t currentLevel = session->GetSwordLevel();
|
|
uint64_t price = SwordLogic::GetSellPrice(currentLevel);
|
|
uint64_t newGold = session->GetGold() + price;
|
|
|
|
session->SetGold(newGold);
|
|
session->SetSwordLevel(0);
|
|
|
|
co_await DatabaseManager::GetInstance().SaveUser(
|
|
session->GetNickname(), session->GetGold(), session->GetSwordLevel());
|
|
|
|
PKT_SC_SellResult res;
|
|
res.earnedGold = price;
|
|
res.totalGold = 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;
|
|
|
|
default:
|
|
Logger::Log("알 수 없는 패킷 ID: ", packet.header.id);
|
|
break;
|
|
}
|
|
|
|
co_return;
|
|
}
|