feat(client): introduce UnoClient with network and UI integration

- Added `UnoClient` class to handle network, UI, and player actions.
- Implemented methods for processing network and player events.
- Created entry point in `main.cpp` for client execution.
This commit is contained in:
Kieran Kihn
2025-12-09 20:03:21 +08:00
parent 5eee316acf
commit 25a0a66c93
3 changed files with 203 additions and 0 deletions

136
src/client/UnoClient.cpp Normal file
View File

@@ -0,0 +1,136 @@
/**
* @file
*
* @author Yuzhe Guo
* @date 2025.12.06
*/
#include "UnoClient.h"
#include "../network/Message.h"
#include "../network/MessageSerializer.h"
#include <memory>
#include <utility>
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<NETWORK::InitGamePayload>(networkMessage.getMessagePayload()));
}
if (networkMessage.getMessagePayloadType() == NETWORK::MessagePayloadType::DRAW_CARD) {
this->handleNetworkDrawCard(std::get<NETWORK::DrawCardPayload>(networkMessage.getMessagePayload()));
}
if (networkMessage.getMessagePayloadType() == NETWORK::MessagePayloadType::PLAY_CARD) {
this->handleNetworkPlayCard(std::get<NETWORK::PlayCardPayload>(networkMessage.getMessagePayload()));
}
if (networkMessage.getMessagePayloadType() == NETWORK::MessagePayloadType::END_GAME) {
this->handleNetworkEndGame(std::get<NETWORK::EndGamePayload>(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<PlayerConnectPayload>(action.payload));
}
if (action.playerActionType == PlayerActionType::START_GAME) {
this->handlePlayerStartGame(std::get<PlayerStartGamePayload>(action.payload));
}
if (action.playerActionType == PlayerActionType::PLAY_CARD) {
this->handlePlayerPlayCard(std::get<PlayerPlayCardPayload>(action.payload));
}
if (action.playerActionType == PlayerActionType::DRAW_CARD) {
this->handlePlayerDrawCard(std::get<PlayerDrawCardPayload>(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<GAME::ClientGameState>();
networkClient_ = std::make_shared<NETWORK::NetworkClient>(
[this]() { this->handleNetworkConnected(); }, [this](const std::string &message) { this->handleNetworkMessage(message); });
gameUI_ = std::make_shared<UI::GameUI>([this](const PlayerAction &action) { this->handlePlayerAction(action); });
}
void UnoClient::run()
{
networkThread_ = std::thread([this]() { this->networkClient_->run(); });
gameUI_->run();
}
} // namespace UNO::CLIENT

51
src/client/UnoClient.h Normal file
View File

@@ -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 <memory>
#include <thread>
namespace UNO::CLIENT {
class UnoClient {
private:
std::shared_ptr<GAME::ClientGameState> clientGameState_;
std::shared_ptr<UI::GameUI> gameUI_;
std::shared_ptr<NETWORK::NetworkClient> 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

16
src/client/main.cpp Normal file
View File

@@ -0,0 +1,16 @@
#include "UnoClient.h"
#include <windows.h>
int main()
{
UNO::CLIENT::UnoClient client;
client.run();
return 0;
}
int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
main();
return 0;
}