mirror of
https://github.com/kierankihn/uno-game.git
synced 2025-12-27 02:13:18 +08:00
feat(network): add PlayerPublicState to InitGamePayload
- Introduced `PlayerPublicState` structure to represent player state. - Updated `InitGamePayload` to include `PlayerPublicState` for all players. - Enhanced `MessageSerializer` to handle serialization and deserialization of `PlayerPublicState`.
This commit is contained in:
@@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <variant>
|
#include <variant>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
|
||||||
namespace UNO::NETWORK {
|
namespace UNO::NETWORK {
|
||||||
@@ -29,12 +30,19 @@ namespace UNO::NETWORK {
|
|||||||
std::vector<GAME::Card> cards;
|
std::vector<GAME::Card> cards;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct PlayerPublicState {
|
||||||
|
std::string name;
|
||||||
|
size_t remainingCardCount;
|
||||||
|
bool isUno;
|
||||||
|
};
|
||||||
|
|
||||||
struct PlayCardPayload {
|
struct PlayCardPayload {
|
||||||
GAME::Card card;
|
GAME::Card card;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct InitGamePayload {
|
struct InitGamePayload {
|
||||||
size_t playerId;
|
size_t playerId;
|
||||||
|
std::vector<PlayerPublicState> players;
|
||||||
GAME::DiscardPile discardPile;
|
GAME::DiscardPile discardPile;
|
||||||
std::multiset<GAME::Card> handCard;
|
std::multiset<GAME::Card> handCard;
|
||||||
size_t currentPlayerIndex;
|
size_t currentPlayerIndex;
|
||||||
|
|||||||
@@ -28,6 +28,20 @@ namespace UNO::NETWORK {
|
|||||||
return serializeCards(cards.begin(), cards.end());
|
return serializeCards(cards.begin(), cards.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nlohmann::json MessageSerializer::serializePlayerPublicState(const PlayerPublicState &state)
|
||||||
|
{
|
||||||
|
return {{"name", state.name}, {"remaining_cards", state.remainingCardCount}, {"is_uno", state.isUno}};
|
||||||
|
}
|
||||||
|
|
||||||
|
nlohmann::json MessageSerializer::serializePlayerPublicStates(const std::vector<PlayerPublicState> &states)
|
||||||
|
{
|
||||||
|
nlohmann::json result = nlohmann::json::array();
|
||||||
|
for (const auto &state : states) {
|
||||||
|
result.push_back(serializePlayerPublicState(state));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
nlohmann::json MessageSerializer::serializePayload(const std::monostate &payload)
|
nlohmann::json MessageSerializer::serializePayload(const std::monostate &payload)
|
||||||
{
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@@ -56,6 +70,7 @@ namespace UNO::NETWORK {
|
|||||||
nlohmann::json MessageSerializer::serializePayload(const InitGamePayload &payload)
|
nlohmann::json MessageSerializer::serializePayload(const InitGamePayload &payload)
|
||||||
{
|
{
|
||||||
return {{"player_id", payload.playerId},
|
return {{"player_id", payload.playerId},
|
||||||
|
{"players", serializePlayerPublicStates(payload.players)},
|
||||||
{"discard_pile", serializeDiscardPile(payload.discardPile)},
|
{"discard_pile", serializeDiscardPile(payload.discardPile)},
|
||||||
{"hand_card", serializeCards(payload.handCard.begin(), payload.handCard.end())},
|
{"hand_card", serializeCards(payload.handCard.begin(), payload.handCard.end())},
|
||||||
{"current_player", payload.currentPlayerIndex}};
|
{"current_player", payload.currentPlayerIndex}};
|
||||||
@@ -215,6 +230,41 @@ namespace UNO::NETWORK {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PlayerPublicState MessageSerializer::deserializePlayerPublicState(const nlohmann::json &payload)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
if (payload.is_object() == false) {
|
||||||
|
throw std::invalid_argument("Invalid player public state: expected JSON object");
|
||||||
|
}
|
||||||
|
if (payload.at("name").is_string() == false) {
|
||||||
|
throw std::invalid_argument("Invalid 'name' field in player public state: expected string");
|
||||||
|
}
|
||||||
|
if (payload.at("remaining_cards").is_number_unsigned() == false) {
|
||||||
|
throw std::invalid_argument("Invalid 'remaining_cards' field in player public state: expected unsigned integer");
|
||||||
|
}
|
||||||
|
if (payload.at("is_uno").is_boolean() == false) {
|
||||||
|
throw std::invalid_argument("Invalid 'is_uno' field in player public state: expected boolean");
|
||||||
|
}
|
||||||
|
return {payload.at("name"), payload.at("remaining_cards"), payload.at("is_uno")};
|
||||||
|
}
|
||||||
|
catch (const nlohmann::json::out_of_range &) {
|
||||||
|
throw std::invalid_argument("Missing required field in player public state: expected 'name', 'remaining_cards', 'is_uno'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<PlayerPublicState> MessageSerializer::deserializePlayerPublicStates(const nlohmann::json &payload)
|
||||||
|
{
|
||||||
|
if (payload.is_array() == false) {
|
||||||
|
throw std::invalid_argument("Invalid players field in INIT_GAME payload: expected JSON array");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<PlayerPublicState> players;
|
||||||
|
for (const auto &entry : payload) {
|
||||||
|
players.push_back(deserializePlayerPublicState(entry));
|
||||||
|
}
|
||||||
|
return players;
|
||||||
|
}
|
||||||
|
|
||||||
std::monostate MessageSerializer::deserializeEmptyPayload(const nlohmann::json &payload)
|
std::monostate MessageSerializer::deserializeEmptyPayload(const nlohmann::json &payload)
|
||||||
{
|
{
|
||||||
if (payload.is_null() == false) {
|
if (payload.is_null() == false) {
|
||||||
@@ -299,13 +349,14 @@ namespace UNO::NETWORK {
|
|||||||
throw std::invalid_argument("Invalid 'current_player' field in INIT_GAME payload: expected unsigned integer");
|
throw std::invalid_argument("Invalid 'current_player' field in INIT_GAME payload: expected unsigned integer");
|
||||||
}
|
}
|
||||||
return {payload.at("player_id"),
|
return {payload.at("player_id"),
|
||||||
|
deserializePlayerPublicStates(payload.at("players")),
|
||||||
deserializeDiscardPile(payload.at("discard_pile")),
|
deserializeDiscardPile(payload.at("discard_pile")),
|
||||||
deserializeHandCard(payload.at("hand_card")),
|
deserializeHandCard(payload.at("hand_card")),
|
||||||
payload.at("current_player")};
|
payload.at("current_player")};
|
||||||
}
|
}
|
||||||
catch (const nlohmann::json::out_of_range &) {
|
catch (const nlohmann::json::out_of_range &) {
|
||||||
throw std::invalid_argument(
|
throw std::invalid_argument(
|
||||||
"Missing required field in INIT_GAME payload: expected 'discard_pile', 'hand_card', and 'current_player'");
|
"Missing required field in INIT_GAME payload: expected 'players', 'discard_pile', 'hand_card', and 'current_player'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -415,4 +466,4 @@ namespace UNO::NETWORK {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace UNO::NETWORK
|
} // namespace UNO::NETWORK
|
||||||
|
|||||||
@@ -24,6 +24,8 @@ namespace UNO::NETWORK {
|
|||||||
static nlohmann::json serializeCards(Iterator begin, Iterator end);
|
static nlohmann::json serializeCards(Iterator begin, Iterator end);
|
||||||
|
|
||||||
static nlohmann::json serializeDiscardPile(const GAME::DiscardPile &discardPile);
|
static nlohmann::json serializeDiscardPile(const GAME::DiscardPile &discardPile);
|
||||||
|
static nlohmann::json serializePlayerPublicState(const PlayerPublicState &state);
|
||||||
|
static nlohmann::json serializePlayerPublicStates(const std::vector<PlayerPublicState> &states);
|
||||||
|
|
||||||
static nlohmann::json serializePayload(const std::monostate &payload);
|
static nlohmann::json serializePayload(const std::monostate &payload);
|
||||||
static nlohmann::json serializePayload(const JoinGamePayload &payload);
|
static nlohmann::json serializePayload(const JoinGamePayload &payload);
|
||||||
@@ -43,6 +45,8 @@ namespace UNO::NETWORK {
|
|||||||
static GAME::Card deserializeCard(const nlohmann::json &card);
|
static GAME::Card deserializeCard(const nlohmann::json &card);
|
||||||
static GAME::DiscardPile deserializeDiscardPile(const nlohmann::json &discardPile);
|
static GAME::DiscardPile deserializeDiscardPile(const nlohmann::json &discardPile);
|
||||||
static std::multiset<GAME::Card> deserializeHandCard(const nlohmann::json &handCard);
|
static std::multiset<GAME::Card> deserializeHandCard(const nlohmann::json &handCard);
|
||||||
|
static PlayerPublicState deserializePlayerPublicState(const nlohmann::json &payload);
|
||||||
|
static std::vector<PlayerPublicState> deserializePlayerPublicStates(const nlohmann::json &payload);
|
||||||
|
|
||||||
static std::monostate deserializeEmptyPayload(const nlohmann::json &payload);
|
static std::monostate deserializeEmptyPayload(const nlohmann::json &payload);
|
||||||
static JoinGamePayload deserializeJoinGamePayload(const nlohmann::json &payload);
|
static JoinGamePayload deserializeJoinGamePayload(const nlohmann::json &payload);
|
||||||
@@ -58,4 +62,4 @@ namespace UNO::NETWORK {
|
|||||||
static Message deserializeMessage(const nlohmann::json &message);
|
static Message deserializeMessage(const nlohmann::json &message);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace UNO::NETWORK
|
} // namespace UNO::NETWORK
|
||||||
|
|||||||
@@ -61,8 +61,15 @@ namespace UNO::SERVER {
|
|||||||
void UnoServer::handleStartGame()
|
void UnoServer::handleStartGame()
|
||||||
{
|
{
|
||||||
serverGameState_.init();
|
serverGameState_.init();
|
||||||
|
std::vector<NETWORK::PlayerPublicState> players;
|
||||||
|
players.reserve(serverGameState_.getPlayers().size());
|
||||||
|
for (const auto &player : serverGameState_.getPlayers()) {
|
||||||
|
players.push_back({player.getName(), player.getRemainingCardCount(), player.getIsUno()});
|
||||||
|
}
|
||||||
|
size_t currentPlayerIndex = static_cast<size_t>(serverGameState_.getCurrentPlayer() - serverGameState_.getPlayers().begin());
|
||||||
for (size_t i = 0; i < playerCount; i++) {
|
for (size_t i = 0; i < playerCount; i++) {
|
||||||
NETWORK::InitGamePayload payload = {i, serverGameState_.getDiscardPile(), serverGameState_.getPlayers()[i].getCards(), 0};
|
NETWORK::InitGamePayload payload = {
|
||||||
|
i, players, serverGameState_.getDiscardPile(), serverGameState_.getPlayers()[i].getCards(), currentPlayerIndex};
|
||||||
this->networkServer_.send(
|
this->networkServer_.send(
|
||||||
gameIdToNetworkId.at(i),
|
gameIdToNetworkId.at(i),
|
||||||
NETWORK::MessageSerializer::serialize({NETWORK::MessageStatus::OK, NETWORK::MessagePayloadType::INIT_GAME, payload}));
|
NETWORK::MessageSerializer::serialize({NETWORK::MessageStatus::OK, NETWORK::MessagePayloadType::INIT_GAME, payload}));
|
||||||
@@ -132,4 +139,4 @@ namespace UNO::SERVER {
|
|||||||
this->networkServer_.run();
|
this->networkServer_.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace UNO::SERVER
|
} // namespace UNO::SERVER
|
||||||
|
|||||||
Reference in New Issue
Block a user