diff --git a/src/client/UnoClient.cpp b/src/client/UnoClient.cpp new file mode 100644 index 0000000..81f066e --- /dev/null +++ b/src/client/UnoClient.cpp @@ -0,0 +1,136 @@ +/** + * @file + * + * @author Yuzhe Guo + * @date 2025.12.06 + */ +#include "UnoClient.h" + +#include "../network/Message.h" +#include "../network/MessageSerializer.h" + +#include +#include + +namespace UNO::CLIENT { + void UnoClient::handleNetworkConnected() + { + NETWORK::JoinGamePayload messagePayload = {this->clientGameState_->getPlayerName()}; + NETWORK::Message message = {NETWORK::MessageStatus::OK, NETWORK::MessagePayloadType::JOIN_GAME, messagePayload}; + networkClient_->send(NETWORK::MessageSerializer::serialize(message)); + + this->clientGameState_->setClientGameStageConnected(); + gameUI_->updateUI(this->clientGameState_); + } + + void UnoClient::handleNetworkInitGame(const NETWORK::InitGamePayload &payload) + { + this->clientGameState_->init(payload.players, payload.discardPile, payload.handCard, payload.currentPlayerIndex, payload.playerId); + } + + void UnoClient::handleNetworkPlayCard(const NETWORK::PlayCardPayload &payload) + { + if (clientGameState_->getClientGameStage() == GAME::ClientGameStage::ACTIVE) { + clientGameState_->play(payload.card); + } + clientGameState_->updateStateByCard(payload.card); + } + + void UnoClient::handleNetworkDrawCard(const NETWORK::DrawCardPayload &payload) + { + if (clientGameState_->getClientGameStage() == GAME::ClientGameStage::ACTIVE) { + clientGameState_->draw(payload.cards); + } + clientGameState_->updateStateByDraw(); + } + + void UnoClient::handleNetworkEndGame(const NETWORK::EndGamePayload &payload) + { + this->clientGameState_->endGame(); + } + + void UnoClient::handleNetworkMessage(const std::string &message) + { + auto networkMessage = NETWORK::MessageSerializer::deserialize(message); + if (networkMessage.getMessagePayloadType() == NETWORK::MessagePayloadType::INIT_GAME) { + this->handleNetworkInitGame(std::get(networkMessage.getMessagePayload())); + } + if (networkMessage.getMessagePayloadType() == NETWORK::MessagePayloadType::DRAW_CARD) { + this->handleNetworkDrawCard(std::get(networkMessage.getMessagePayload())); + } + if (networkMessage.getMessagePayloadType() == NETWORK::MessagePayloadType::PLAY_CARD) { + this->handleNetworkPlayCard(std::get(networkMessage.getMessagePayload())); + } + if (networkMessage.getMessagePayloadType() == NETWORK::MessagePayloadType::END_GAME) { + this->handleNetworkEndGame(std::get(networkMessage.getMessagePayload())); + } + + if (networkMessage.getMessagePayloadType() == NETWORK::MessagePayloadType::EMPTY + || networkMessage.getMessagePayloadType() == NETWORK::MessagePayloadType::JOIN_GAME + || networkMessage.getMessagePayloadType() == NETWORK::MessagePayloadType::START_GAME) { + throw std::invalid_argument("Invalid message type from server"); + } + + gameUI_->updateUI(this->clientGameState_); + } + + void UnoClient::handlePlayerAction(PlayerAction action) + { + if (action.playerActionType == PlayerActionType::CONNECT) { + this->handlePlayerConnect(std::get(action.payload)); + } + if (action.playerActionType == PlayerActionType::START_GAME) { + this->handlePlayerStartGame(std::get(action.payload)); + } + if (action.playerActionType == PlayerActionType::PLAY_CARD) { + this->handlePlayerPlayCard(std::get(action.payload)); + } + if (action.playerActionType == PlayerActionType::DRAW_CARD) { + this->handlePlayerDrawCard(std::get(action.payload)); + } + } + + + void UnoClient::handlePlayerConnect(const PlayerConnectPayload &payload) + { + clientGameState_->setPlayerName(payload.playerName); + networkClient_->connect(payload.host, payload.port); + } + + + void UnoClient::handlePlayerStartGame(PlayerStartGamePayload payload) + { + NETWORK::StartGamePayload messagePayload = {}; + NETWORK::Message message = {NETWORK::MessageStatus::OK, NETWORK::MessagePayloadType::START_GAME, messagePayload}; + networkClient_->send(NETWORK::MessageSerializer::serialize(message)); + } + + void UnoClient::handlePlayerPlayCard(PlayerPlayCardPayload payload) + { + NETWORK::PlayCardPayload messagePayload = {payload.card}; + NETWORK::Message message = {NETWORK::MessageStatus::OK, NETWORK::MessagePayloadType::PLAY_CARD, messagePayload}; + networkClient_->send(NETWORK::MessageSerializer::serialize(message)); + } + + void UnoClient::handlePlayerDrawCard(PlayerDrawCardPayload payload) + { + NETWORK::DrawCardPayload messagePayload = {}; + NETWORK::Message message = {NETWORK::MessageStatus::OK, NETWORK::MessagePayloadType::DRAW_CARD, messagePayload}; + networkClient_->send(NETWORK::MessageSerializer::serialize(message)); + } + + UnoClient::UnoClient() + { + clientGameState_ = std::make_shared(); + networkClient_ = std::make_shared( + [this]() { this->handleNetworkConnected(); }, [this](const std::string &message) { this->handleNetworkMessage(message); }); + gameUI_ = std::make_shared([this](const PlayerAction &action) { this->handlePlayerAction(action); }); + } + + void UnoClient::run() + { + networkThread_ = std::thread([this]() { this->networkClient_->run(); }); + gameUI_->run(); + } + +} // namespace UNO::CLIENT \ No newline at end of file diff --git a/src/client/UnoClient.h b/src/client/UnoClient.h new file mode 100644 index 0000000..865670d --- /dev/null +++ b/src/client/UnoClient.h @@ -0,0 +1,51 @@ +/** + * @file UnoClient.h + * + * @author Yuzhe Guo + * @date 2025.12.06 + */ +#pragma once +#include "../game/GameState.h" +#include "../network/Message.h" +#include "../network/NetworkClient.h" +#include "../ui/GameUI.h" +#include "PlayerAction.h" + +#include +#include + + +namespace UNO::CLIENT { + class UnoClient { + private: + std::shared_ptr clientGameState_; + std::shared_ptr gameUI_; + std::shared_ptr networkClient_; + + std::thread networkThread_; + + private: + void handleNetworkConnected(); + + void handleNetworkMessage(const std::string &message); + + void handleNetworkInitGame(const NETWORK::InitGamePayload &payload); + void handleNetworkPlayCard(const NETWORK::PlayCardPayload &payload); + void handleNetworkDrawCard(const NETWORK::DrawCardPayload &payload); + void handleNetworkEndGame(const NETWORK::EndGamePayload &payload); + + + void handlePlayerAction(PlayerAction action); + + void handlePlayerConnect(const PlayerConnectPayload &payload); + void handlePlayerStartGame(PlayerStartGamePayload payload); + void handlePlayerPlayCard(PlayerPlayCardPayload payload); + void handlePlayerDrawCard(PlayerDrawCardPayload payload); + + public: + UnoClient(); + + void run(); + }; + +} // namespace UNO::CLIENT \ No newline at end of file diff --git a/src/client/main.cpp b/src/client/main.cpp new file mode 100644 index 0000000..9eb931d --- /dev/null +++ b/src/client/main.cpp @@ -0,0 +1,16 @@ +#include "UnoClient.h" + +#include + +int main() +{ + UNO::CLIENT::UnoClient client; + client.run(); + return 0; +} + +int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) +{ + main(); + return 0; +} \ No newline at end of file