#include "PacketHandler.h" #include "DatabaseManager.h" #include "Logger.h" #include "SessionManager.h" #include "SwordLogic.h" #include #include #include boost::asio::awaitable PacketHandler::HandlePacket(std::shared_ptr session, const Packet packet) { switch (static_cast(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(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(PacketID::Chat); chatHeader.size = static_cast(chatMsg.size()); std::vector 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; }