create participant, move code

This commit is contained in:
ebbit1q 2025-09-18 12:02:09 +02:00
parent 74bbef53b2
commit 74b5241544
11 changed files with 1084 additions and 669 deletions

View file

@ -0,0 +1,621 @@
#include "server_abstract_participant.h"
#include "../../color.h"
#include "../../deck_list.h"
#include "../../deck_list_card_node.h"
#include "../../get_pb_extension.h"
#include "../../rng_abstract.h"
#include "../../trice_limits.h"
#include "../server.h"
#include "../server_abstractuserinterface.h"
#include "../server_database_interface.h"
#include "../server_room.h"
#include "pb/command_attach_card.pb.h"
#include "pb/command_change_zone_properties.pb.h"
#include "pb/command_concede.pb.h"
#include "pb/command_create_arrow.pb.h"
#include "pb/command_create_counter.pb.h"
#include "pb/command_create_token.pb.h"
#include "pb/command_deck_select.pb.h"
#include "pb/command_del_counter.pb.h"
#include "pb/command_delete_arrow.pb.h"
#include "pb/command_draw_cards.pb.h"
#include "pb/command_dump_zone.pb.h"
#include "pb/command_flip_card.pb.h"
#include "pb/command_game_say.pb.h"
#include "pb/command_inc_card_counter.pb.h"
#include "pb/command_inc_counter.pb.h"
#include "pb/command_kick_from_game.pb.h"
#include "pb/command_leave_game.pb.h"
#include "pb/command_move_card.pb.h"
#include "pb/command_mulligan.pb.h"
#include "pb/command_next_turn.pb.h"
#include "pb/command_ready_start.pb.h"
#include "pb/command_reveal_cards.pb.h"
#include "pb/command_reverse_turn.pb.h"
#include "pb/command_roll_die.pb.h"
#include "pb/command_set_active_phase.pb.h"
#include "pb/command_set_card_attr.pb.h"
#include "pb/command_set_card_counter.pb.h"
#include "pb/command_set_counter.pb.h"
#include "pb/command_set_sideboard_lock.pb.h"
#include "pb/command_set_sideboard_plan.pb.h"
#include "pb/command_shuffle.pb.h"
#include "pb/command_undo_draw.pb.h"
#include "pb/context_concede.pb.h"
#include "pb/context_connection_state_changed.pb.h"
#include "pb/context_deck_select.pb.h"
#include "pb/context_move_card.pb.h"
#include "pb/context_mulligan.pb.h"
#include "pb/context_ready_start.pb.h"
#include "pb/context_set_sideboard_lock.pb.h"
#include "pb/context_undo_draw.pb.h"
#include "pb/event_attach_card.pb.h"
#include "pb/event_change_zone_properties.pb.h"
#include "pb/event_create_arrow.pb.h"
#include "pb/event_create_counter.pb.h"
#include "pb/event_create_token.pb.h"
#include "pb/event_del_counter.pb.h"
#include "pb/event_delete_arrow.pb.h"
#include "pb/event_destroy_card.pb.h"
#include "pb/event_draw_cards.pb.h"
#include "pb/event_dump_zone.pb.h"
#include "pb/event_flip_card.pb.h"
#include "pb/event_game_say.pb.h"
#include "pb/event_move_card.pb.h"
#include "pb/event_player_properties_changed.pb.h"
#include "pb/event_reveal_cards.pb.h"
#include "pb/event_reverse_turn.pb.h"
#include "pb/event_roll_die.pb.h"
#include "pb/event_set_card_attr.pb.h"
#include "pb/event_set_card_counter.pb.h"
#include "pb/event_set_counter.pb.h"
#include "pb/event_shuffle.pb.h"
#include "pb/response.pb.h"
#include "pb/response_deck_download.pb.h"
#include "pb/response_dump_zone.pb.h"
#include "pb/serverinfo_player.pb.h"
#include "pb/serverinfo_user.pb.h"
#include "server_arrow.h"
#include "server_card.h"
#include "server_cardzone.h"
#include "server_counter.h"
#include "server_game.h"
#include "server_player.h"
#include <QDebug>
#include <QRegularExpression>
#include <algorithm>
Server_AbstractParticipant::Server_AbstractParticipant(Server_Game *_game,
int _playerId,
const ServerInfo_User &_userInfo,
bool _judge,
Server_AbstractUserInterface *_userInterface)
: ServerInfo_User_Container(_userInfo), game(_game), userInterface(_userInterface), pingTime(0),
playerId(_playerId), judge(_judge)
{
}
Server_Spectator::Server_Spectator(Server_Game *_game,
int _playerId,
const ServerInfo_User &_userInfo,
bool _judge,
Server_AbstractUserInterface *_userInterface)
: Server_AbstractParticipant(_game, _playerId, _userInfo, _judge, _userInterface)
{
spectator = true;
}
Server_AbstractParticipant::~Server_AbstractParticipant() = default;
void Server_AbstractParticipant::removeFromGame()
{
QMutexLocker locker(&playerMutex);
if (userInterface) {
userInterface->playerRemovedFromGame(game);
}
}
bool Server_AbstractParticipant::updatePingTime() // returns true if ping time changed
{
QMutexLocker locker(&playerMutex);
int oldPingTime = pingTime;
if (userInterface) {
pingTime = userInterface->getLastCommandTime();
} else {
pingTime = -1;
}
return pingTime != oldPingTime;
}
void Server_AbstractParticipant::getProperties(ServerInfo_PlayerProperties &result, bool withUserInfo)
{
result.set_player_id(playerId);
if (withUserInfo) {
copyUserInfo(*(result.mutable_user_info()), true);
}
result.set_spectator(spectator);
result.set_judge(judge);
result.set_ping_seconds(pingTime);
getPlayerProperties(result);
}
void Server_AbstractParticipant::getPlayerProperties(ServerInfo_PlayerProperties & /*result*/)
{
}
Response::ResponseCode Server_AbstractParticipant::cmdLeaveGame(const Command_LeaveGame & /*cmd*/,
ResponseContainer & /*rc*/,
GameEventStorage & /*ges*/)
{
game->removeParticipant(this, Event_Leave::USER_LEFT);
return Response::RespOk;
}
Response::ResponseCode Server_AbstractParticipant::cmdKickFromGame(const Command_KickFromGame &cmd,
ResponseContainer & /*rc*/,
GameEventStorage & /*ges*/)
{
if ((game->getHostId() != playerId) && !(userInfo->user_level() & ServerInfo_User::IsModerator)) {
return Response::RespFunctionNotAllowed;
}
if (!game->kickParticipant(cmd.player_id())) {
return Response::RespNameNotFound;
}
return Response::RespOk;
}
Response::ResponseCode Server_AbstractParticipant::cmdDeckSelect(const Command_DeckSelect & /*cmd*/,
ResponseContainer & /*rc*/,
GameEventStorage & /*ges*/)
{
return Response::RespFunctionNotAllowed;
}
Response::ResponseCode Server_AbstractParticipant::cmdSetSideboardPlan(const Command_SetSideboardPlan & /*cmd*/,
ResponseContainer & /*rc*/,
GameEventStorage & /*ges*/)
{
return Response::RespFunctionNotAllowed;
}
Response::ResponseCode Server_AbstractParticipant::cmdSetSideboardLock(const Command_SetSideboardLock & /*cmd*/,
ResponseContainer & /*rc*/,
GameEventStorage & /*ges*/)
{
return Response::RespFunctionNotAllowed;
}
Response::ResponseCode Server_AbstractParticipant::cmdConcede(const Command_Concede & /*cmd*/,
ResponseContainer & /*rc*/,
GameEventStorage & /*ges*/)
{
return Response::RespFunctionNotAllowed;
}
Response::ResponseCode Server_AbstractParticipant::cmdUnconcede(const Command_Unconcede & /*cmd*/,
ResponseContainer & /*rc*/,
GameEventStorage & /*ges*/)
{
return Response::RespFunctionNotAllowed;
}
Response::ResponseCode
Server_AbstractParticipant::cmdJudge(const Command_Judge &cmd, ResponseContainer &rc, GameEventStorage &ges)
{
if (!judge) {
return Response::RespFunctionNotAllowed;
}
Server_Player *player = this->game->getPlayer(cmd.target_id());
ges.setForcedByJudge(playerId);
if (player == nullptr) {
return Response::RespContextError;
}
for (int i = 0; i < cmd.game_command_size(); ++i) {
player->processGameCommand(cmd.game_command(i), rc, ges);
}
return Response::RespOk;
}
Response::ResponseCode Server_AbstractParticipant::cmdReadyStart(const Command_ReadyStart & /*cmd*/,
ResponseContainer & /*rc*/,
GameEventStorage & /*ges*/)
{
return Response::RespFunctionNotAllowed;
}
Response::ResponseCode
Server_AbstractParticipant::cmdGameSay(const Command_GameSay &cmd, ResponseContainer & /*rc*/, GameEventStorage &ges)
{
if (spectator) {
/* Spectators can only talk if:
* (a) the game creator allows it
* (b) the spectator is a moderator/administrator
* (c) the spectator is a judge
*/
bool isModOrJudge = (userInfo->user_level() & (ServerInfo_User::IsModerator | ServerInfo_User::IsJudge));
if (!isModOrJudge && !game->getSpectatorsCanTalk()) {
return Response::RespFunctionNotAllowed;
}
}
if (!userInterface->addSaidMessageSize(static_cast<int>(cmd.message().size()))) {
return Response::RespChatFlood;
}
Event_GameSay event;
event.set_message(cmd.message());
ges.enqueueGameEvent(event, playerId);
game->getRoom()->getServer()->getDatabaseInterface()->logMessage(
userInfo->id(), QString::fromStdString(userInfo->name()), QString::fromStdString(userInfo->address()),
textFromStdString(cmd.message()), Server_DatabaseInterface::MessageTargetGame, game->getGameId(),
game->getDescription());
return Response::RespOk;
}
Response::ResponseCode Server_AbstractParticipant::cmdShuffle(const Command_Shuffle & /*cmd*/,
ResponseContainer & /*rc*/,
GameEventStorage & /*ges*/)
{
return Response::RespFunctionNotAllowed;
}
Response::ResponseCode Server_AbstractParticipant::cmdMulligan(const Command_Mulligan & /*cmd*/,
ResponseContainer & /*rc*/,
GameEventStorage & /*ges*/)
{
return Response::RespFunctionNotAllowed;
}
Response::ResponseCode Server_AbstractParticipant::cmdRollDie(const Command_RollDie & /*cmd*/,
ResponseContainer & /*rc*/,
GameEventStorage & /*ges*/) const
{
return Response::RespFunctionNotAllowed;
}
Response::ResponseCode Server_AbstractParticipant::cmdDrawCards(const Command_DrawCards & /*cmd*/,
ResponseContainer & /*rc*/,
GameEventStorage & /*ges*/)
{
return Response::RespFunctionNotAllowed;
}
Response::ResponseCode Server_AbstractParticipant::cmdUndoDraw(const Command_UndoDraw & /*cmd*/,
ResponseContainer & /*rc*/,
GameEventStorage & /*ges*/)
{
return Response::RespFunctionNotAllowed;
}
Response::ResponseCode Server_AbstractParticipant::cmdMoveCard(const Command_MoveCard & /*cmd*/,
ResponseContainer & /*rc*/,
GameEventStorage & /*ges*/)
{
return Response::RespFunctionNotAllowed;
}
Response::ResponseCode Server_AbstractParticipant::cmdFlipCard(const Command_FlipCard & /*cmd*/,
ResponseContainer & /*rc*/,
GameEventStorage & /*ges*/)
{
return Response::RespFunctionNotAllowed;
}
Response::ResponseCode Server_AbstractParticipant::cmdAttachCard(const Command_AttachCard & /*cmd*/,
ResponseContainer & /*rc*/,
GameEventStorage & /*ges*/)
{
return Response::RespFunctionNotAllowed;
}
Response::ResponseCode Server_AbstractParticipant::cmdCreateToken(const Command_CreateToken & /*cmd*/,
ResponseContainer & /*rc*/,
GameEventStorage & /*ges*/)
{
return Response::RespFunctionNotAllowed;
}
Response::ResponseCode Server_AbstractParticipant::cmdCreateArrow(const Command_CreateArrow & /*cmd*/,
ResponseContainer & /*rc*/,
GameEventStorage & /*ges*/)
{
return Response::RespFunctionNotAllowed;
}
Response::ResponseCode Server_AbstractParticipant::cmdDeleteArrow(const Command_DeleteArrow & /*cmd*/,
ResponseContainer & /*rc*/,
GameEventStorage & /*ges*/)
{
return Response::RespFunctionNotAllowed;
}
Response::ResponseCode Server_AbstractParticipant::cmdSetCardAttr(const Command_SetCardAttr & /*cmd*/,
ResponseContainer & /*rc*/,
GameEventStorage & /*ges*/)
{
return Response::RespFunctionNotAllowed;
}
Response::ResponseCode Server_AbstractParticipant::cmdSetCardCounter(const Command_SetCardCounter & /*cmd*/,
ResponseContainer & /*rc*/,
GameEventStorage & /*ges*/)
{
return Response::RespFunctionNotAllowed;
}
Response::ResponseCode Server_AbstractParticipant::cmdIncCardCounter(const Command_IncCardCounter & /*cmd*/,
ResponseContainer & /*rc*/,
GameEventStorage & /*ges*/)
{
return Response::RespFunctionNotAllowed;
}
Response::ResponseCode Server_AbstractParticipant::cmdIncCounter(const Command_IncCounter & /*cmd*/,
ResponseContainer & /*rc*/,
GameEventStorage & /*ges*/)
{
return Response::RespFunctionNotAllowed;
}
Response::ResponseCode Server_AbstractParticipant::cmdCreateCounter(const Command_CreateCounter & /*cmd*/,
ResponseContainer & /*rc*/,
GameEventStorage & /*ges*/)
{
return Response::RespFunctionNotAllowed;
}
Response::ResponseCode Server_AbstractParticipant::cmdSetCounter(const Command_SetCounter & /*cmd*/,
ResponseContainer & /*rc*/,
GameEventStorage & /*ges*/)
{
return Response::RespFunctionNotAllowed;
}
Response::ResponseCode Server_AbstractParticipant::cmdDelCounter(const Command_DelCounter & /*cmd*/,
ResponseContainer & /*rc*/,
GameEventStorage & /*ges*/)
{
return Response::RespFunctionNotAllowed;
}
Response::ResponseCode Server_AbstractParticipant::cmdNextTurn(const Command_NextTurn & /*cmd*/,
ResponseContainer & /*rc*/,
GameEventStorage & /*ges*/)
{
if (!game->getGameStarted()) {
return Response::RespGameNotStarted;
}
if (!judge) {
return Response::RespFunctionNotAllowed;
}
game->nextTurn();
return Response::RespOk;
}
Response::ResponseCode Server_AbstractParticipant::cmdSetActivePhase(const Command_SetActivePhase &cmd,
ResponseContainer & /*rc*/,
GameEventStorage & /*ges*/)
{
if (!game->getGameStarted()) {
return Response::RespGameNotStarted;
}
if (!judge) {
return Response::RespFunctionNotAllowed;
}
game->setActivePhase(cmd.phase());
return Response::RespOk;
}
Response::ResponseCode Server_AbstractParticipant::cmdDumpZone(const Command_DumpZone & /*cmd*/,
ResponseContainer & /*rc*/,
GameEventStorage & /*ges*/)
{
return Response::RespFunctionNotAllowed;
}
Response::ResponseCode Server_AbstractParticipant::cmdRevealCards(const Command_RevealCards & /*cmd*/,
ResponseContainer & /*rc*/,
GameEventStorage & /*ges*/)
{
return Response::RespFunctionNotAllowed;
}
Response::ResponseCode Server_AbstractParticipant::cmdChangeZoneProperties(const Command_ChangeZoneProperties & /*cmd*/,
ResponseContainer & /*rc*/,
GameEventStorage & /*ges*/)
{
return Response::RespFunctionNotAllowed;
}
Response::ResponseCode Server_AbstractParticipant::cmdReverseTurn(const Command_ReverseTurn & /*cmd*/,
ResponseContainer & /*rc*/,
GameEventStorage &ges)
{
if (!judge) {
if (spectator) {
return Response::RespFunctionNotAllowed;
}
if (!game->getGameStarted()) {
return Response::RespGameNotStarted;
}
}
bool reversedTurn = game->reverseTurnOrder();
Event_ReverseTurn event;
event.set_reversed(reversedTurn);
ges.enqueueGameEvent(event, playerId);
return Response::RespOk;
}
Response::ResponseCode
Server_AbstractParticipant::processGameCommand(const GameCommand &command, ResponseContainer &rc, GameEventStorage &ges)
{
switch ((GameCommand::GameCommandType)getPbExtension(command)) {
case GameCommand::KICK_FROM_GAME:
return cmdKickFromGame(command.GetExtension(Command_KickFromGame::ext), rc, ges);
break;
case GameCommand::LEAVE_GAME:
return cmdLeaveGame(command.GetExtension(Command_LeaveGame::ext), rc, ges);
break;
case GameCommand::GAME_SAY:
return cmdGameSay(command.GetExtension(Command_GameSay::ext), rc, ges);
break;
case GameCommand::SHUFFLE:
return cmdShuffle(command.GetExtension(Command_Shuffle::ext), rc, ges);
break;
case GameCommand::MULLIGAN:
return cmdMulligan(command.GetExtension(Command_Mulligan::ext), rc, ges);
break;
case GameCommand::ROLL_DIE:
return cmdRollDie(command.GetExtension(Command_RollDie::ext), rc, ges);
break;
case GameCommand::DRAW_CARDS:
return cmdDrawCards(command.GetExtension(Command_DrawCards::ext), rc, ges);
break;
case GameCommand::UNDO_DRAW:
return cmdUndoDraw(command.GetExtension(Command_UndoDraw::ext), rc, ges);
break;
case GameCommand::FLIP_CARD:
return cmdFlipCard(command.GetExtension(Command_FlipCard::ext), rc, ges);
break;
case GameCommand::ATTACH_CARD:
return cmdAttachCard(command.GetExtension(Command_AttachCard::ext), rc, ges);
break;
case GameCommand::CREATE_TOKEN:
return cmdCreateToken(command.GetExtension(Command_CreateToken::ext), rc, ges);
break;
case GameCommand::CREATE_ARROW:
return cmdCreateArrow(command.GetExtension(Command_CreateArrow::ext), rc, ges);
break;
case GameCommand::DELETE_ARROW:
return cmdDeleteArrow(command.GetExtension(Command_DeleteArrow::ext), rc, ges);
break;
case GameCommand::SET_CARD_ATTR:
return cmdSetCardAttr(command.GetExtension(Command_SetCardAttr::ext), rc, ges);
break;
case GameCommand::SET_CARD_COUNTER:
return cmdSetCardCounter(command.GetExtension(Command_SetCardCounter::ext), rc, ges);
break;
case GameCommand::INC_CARD_COUNTER:
return cmdIncCardCounter(command.GetExtension(Command_IncCardCounter::ext), rc, ges);
break;
case GameCommand::READY_START:
return cmdReadyStart(command.GetExtension(Command_ReadyStart::ext), rc, ges);
break;
case GameCommand::CONCEDE:
return cmdConcede(command.GetExtension(Command_Concede::ext), rc, ges);
break;
case GameCommand::INC_COUNTER:
return cmdIncCounter(command.GetExtension(Command_IncCounter::ext), rc, ges);
break;
case GameCommand::CREATE_COUNTER:
return cmdCreateCounter(command.GetExtension(Command_CreateCounter::ext), rc, ges);
break;
case GameCommand::SET_COUNTER:
return cmdSetCounter(command.GetExtension(Command_SetCounter::ext), rc, ges);
break;
case GameCommand::DEL_COUNTER:
return cmdDelCounter(command.GetExtension(Command_DelCounter::ext), rc, ges);
break;
case GameCommand::NEXT_TURN:
return cmdNextTurn(command.GetExtension(Command_NextTurn::ext), rc, ges);
break;
case GameCommand::SET_ACTIVE_PHASE:
return cmdSetActivePhase(command.GetExtension(Command_SetActivePhase::ext), rc, ges);
break;
case GameCommand::DUMP_ZONE:
return cmdDumpZone(command.GetExtension(Command_DumpZone::ext), rc, ges);
break;
case GameCommand::REVEAL_CARDS:
return cmdRevealCards(command.GetExtension(Command_RevealCards::ext), rc, ges);
break;
case GameCommand::MOVE_CARD:
return cmdMoveCard(command.GetExtension(Command_MoveCard::ext), rc, ges);
break;
case GameCommand::SET_SIDEBOARD_PLAN:
return cmdSetSideboardPlan(command.GetExtension(Command_SetSideboardPlan::ext), rc, ges);
break;
case GameCommand::DECK_SELECT:
return cmdDeckSelect(command.GetExtension(Command_DeckSelect::ext), rc, ges);
break;
case GameCommand::SET_SIDEBOARD_LOCK:
return cmdSetSideboardLock(command.GetExtension(Command_SetSideboardLock::ext), rc, ges);
break;
case GameCommand::CHANGE_ZONE_PROPERTIES:
return cmdChangeZoneProperties(command.GetExtension(Command_ChangeZoneProperties::ext), rc, ges);
break;
case GameCommand::UNCONCEDE:
return cmdUnconcede(command.GetExtension(Command_Unconcede::ext), rc, ges);
break;
case GameCommand::JUDGE:
return cmdJudge(command.GetExtension(Command_Judge::ext), rc, ges);
break;
case GameCommand::REVERSE_TURN:
return cmdReverseTurn(command.GetExtension(Command_ReverseTurn::ext), rc, ges);
break;
default:
return Response::RespInvalidCommand;
}
}
void Server_AbstractParticipant::sendGameEvent(const GameEventContainer &cont)
{
QMutexLocker locker(&playerMutex);
if (userInterface) {
userInterface->sendProtocolItem(cont);
}
}
void Server_AbstractParticipant::setUserInterface(Server_AbstractUserInterface *_userInterface)
{
playerMutex.lock();
userInterface = _userInterface;
playerMutex.unlock();
pingTime = _userInterface ? 0 : -1;
Event_PlayerPropertiesChanged event;
event.mutable_player_properties()->set_ping_seconds(pingTime);
GameEventStorage ges;
ges.setGameEventContext(Context_ConnectionStateChanged());
ges.enqueueGameEvent(event, playerId);
ges.sendToGame(game);
}
void Server_AbstractParticipant::disconnectClient()
{
if (!(userInfo->user_level() & ServerInfo_User::IsRegistered) || spectator) {
game->removeParticipant(this, Event_Leave::USER_DISCONNECTED);
} else {
setUserInterface(nullptr);
}
}
void Server_AbstractParticipant::getInfo(ServerInfo_Player *info,
Server_AbstractParticipant * /*recipient*/,
bool /* omniscient */,
bool withUserInfo)
{
getProperties(*info->mutable_properties(), withUserInfo);
}

View file

@ -0,0 +1,191 @@
#ifndef ABSTRACT_PARTICIPANT_H
#define ABSTRACT_PARTICIPANT_H
#include "../../serverinfo_user_container.h"
#include "pb/card_attributes.pb.h"
#include "pb/response.pb.h"
#include "server_arrowtarget.h"
#include <QMutex>
class Server_Game;
class Server_AbstractUserInterface;
class ServerInfo_User;
class ServerInfo_Player;
class ServerInfo_PlayerProperties;
class GameEventContainer;
class GameEventStorage;
class ResponseContainer;
class GameCommand;
class Command_KickFromGame;
class Command_LeaveGame;
class Command_GameSay;
class Command_Shuffle;
class Command_Mulligan;
class Command_RollDie;
class Command_DrawCards;
class Command_UndoDraw;
class Command_FlipCard;
class Command_AttachCard;
class Command_CreateToken;
class Command_CreateArrow;
class Command_DeleteArrow;
class Command_SetCardAttr;
class Command_SetCardCounter;
class Command_IncCardCounter;
class Command_ReadyStart;
class Command_Concede;
class Command_Unconcede;
class Command_Judge;
class Command_IncCounter;
class Command_CreateCounter;
class Command_SetCounter;
class Command_DelCounter;
class Command_NextTurn;
class Command_SetActivePhase;
class Command_DumpZone;
class Command_RevealCards;
class Command_ReverseTurn;
class Command_MoveCard;
class Command_SetSideboardPlan;
class Command_DeckSelect;
class Command_SetSideboardLock;
class Command_ChangeZoneProperties;
class Server_AbstractParticipant : public Server_ArrowTarget, public ServerInfo_User_Container
{
Q_OBJECT
protected:
Server_Game *game;
Server_AbstractUserInterface *userInterface;
int pingTime;
int playerId;
bool spectator;
bool judge;
void getPlayerProperties(ServerInfo_PlayerProperties &result);
mutable QMutex playerMutex;
public:
Server_AbstractParticipant(Server_Game *_game,
int _playerId,
const ServerInfo_User &_userInfo,
bool _judge,
Server_AbstractUserInterface *_handler);
~Server_AbstractParticipant() override;
virtual void prepareDestroy();
void removeFromGame();
Server_AbstractUserInterface *getUserInterface() const
{
return userInterface;
}
void setUserInterface(Server_AbstractUserInterface *_userInterface);
void disconnectClient();
int getPlayerId() const
{
return playerId;
}
bool getSpectator() const
{
return spectator;
}
bool getJudge() const
{
return judge;
}
Server_Game *getGame() const
{
return game;
}
int getPingTime() const
{
return pingTime;
}
bool updatePingTime();
void getProperties(ServerInfo_PlayerProperties &result, bool withUserInfo);
virtual Response::ResponseCode
cmdLeaveGame(const Command_LeaveGame &cmd, ResponseContainer &rc, GameEventStorage &ges);
virtual Response::ResponseCode
cmdKickFromGame(const Command_KickFromGame &cmd, ResponseContainer &rc, GameEventStorage &ges);
virtual Response::ResponseCode cmdConcede(const Command_Concede &cmd, ResponseContainer &rc, GameEventStorage &ges);
virtual Response::ResponseCode
cmdUnconcede(const Command_Unconcede &cmd, ResponseContainer &rc, GameEventStorage &ges);
virtual Response::ResponseCode cmdJudge(const Command_Judge &cmd, ResponseContainer &rc, GameEventStorage &ges);
virtual Response::ResponseCode
cmdReadyStart(const Command_ReadyStart &cmd, ResponseContainer &rc, GameEventStorage &ges);
virtual Response::ResponseCode
cmdDeckSelect(const Command_DeckSelect &cmd, ResponseContainer &rc, GameEventStorage &ges);
virtual Response::ResponseCode
cmdSetSideboardPlan(const Command_SetSideboardPlan &cmd, ResponseContainer &rc, GameEventStorage &ges);
virtual Response::ResponseCode
cmdSetSideboardLock(const Command_SetSideboardLock &cmd, ResponseContainer &rc, GameEventStorage &ges);
virtual Response::ResponseCode cmdGameSay(const Command_GameSay &cmd, ResponseContainer &rc, GameEventStorage &ges);
virtual Response::ResponseCode cmdShuffle(const Command_Shuffle &cmd, ResponseContainer &rc, GameEventStorage &ges);
virtual Response::ResponseCode
cmdMulligan(const Command_Mulligan &cmd, ResponseContainer &rc, GameEventStorage &ges);
virtual Response::ResponseCode
cmdRollDie(const Command_RollDie &cmd, ResponseContainer &rc, GameEventStorage &ges) const;
virtual Response::ResponseCode
cmdDrawCards(const Command_DrawCards &cmd, ResponseContainer &rc, GameEventStorage &ges);
virtual Response::ResponseCode
cmdUndoDraw(const Command_UndoDraw &cmd, ResponseContainer &rc, GameEventStorage &ges);
virtual Response::ResponseCode
cmdMoveCard(const Command_MoveCard &cmd, ResponseContainer &rc, GameEventStorage &ges);
virtual Response::ResponseCode
cmdFlipCard(const Command_FlipCard &cmd, ResponseContainer &rc, GameEventStorage &ges);
virtual Response::ResponseCode
cmdAttachCard(const Command_AttachCard &cmd, ResponseContainer &rc, GameEventStorage &ges);
virtual Response::ResponseCode
cmdCreateToken(const Command_CreateToken &cmd, ResponseContainer &rc, GameEventStorage &ges);
virtual Response::ResponseCode
cmdCreateArrow(const Command_CreateArrow &cmd, ResponseContainer &rc, GameEventStorage &ges);
virtual Response::ResponseCode
cmdDeleteArrow(const Command_DeleteArrow &cmd, ResponseContainer &rc, GameEventStorage &ges);
virtual Response::ResponseCode
cmdSetCardAttr(const Command_SetCardAttr &cmd, ResponseContainer &rc, GameEventStorage &ges);
virtual Response::ResponseCode
cmdSetCardCounter(const Command_SetCardCounter &cmd, ResponseContainer &rc, GameEventStorage &ges);
virtual Response::ResponseCode
cmdIncCardCounter(const Command_IncCardCounter &cmd, ResponseContainer &rc, GameEventStorage &ges);
virtual Response::ResponseCode
cmdIncCounter(const Command_IncCounter &cmd, ResponseContainer &rc, GameEventStorage &ges);
virtual Response::ResponseCode
cmdCreateCounter(const Command_CreateCounter &cmd, ResponseContainer &rc, GameEventStorage &ges);
virtual Response::ResponseCode
cmdSetCounter(const Command_SetCounter &cmd, ResponseContainer &rc, GameEventStorage &ges);
virtual Response::ResponseCode
cmdDelCounter(const Command_DelCounter &cmd, ResponseContainer &rc, GameEventStorage &ges);
virtual Response::ResponseCode
cmdNextTurn(const Command_NextTurn &cmd, ResponseContainer &rc, GameEventStorage &ges);
virtual Response::ResponseCode
cmdSetActivePhase(const Command_SetActivePhase &cmd, ResponseContainer &rc, GameEventStorage &ges);
virtual Response::ResponseCode
cmdDumpZone(const Command_DumpZone &cmd, ResponseContainer &rc, GameEventStorage &ges);
virtual Response::ResponseCode
cmdRevealCards(const Command_RevealCards &cmd, ResponseContainer &rc, GameEventStorage &ges);
virtual Response::ResponseCode
cmdReverseTurn(const Command_ReverseTurn & /*cmd*/, ResponseContainer & /*rc*/, GameEventStorage &ges);
virtual Response::ResponseCode
cmdChangeZoneProperties(const Command_ChangeZoneProperties &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode processGameCommand(const GameCommand &command, ResponseContainer &rc, GameEventStorage &ges);
void sendGameEvent(const GameEventContainer &event);
virtual void
getInfo(ServerInfo_Player *info, Server_AbstractParticipant *recipient, bool omniscient, bool withUserInfo);
};
class Server_Spectator : public Server_AbstractParticipant
{
Q_OBJECT
public:
Server_Spectator(Server_Game *_game,
int _playerId,
const ServerInfo_User &_userInfo,
bool _judge,
Server_AbstractUserInterface *_handler);
};
#endif

View file

@ -318,7 +318,7 @@ void Server_CardZone::addWritePermission(int playerId)
playersWithWritePermission.insert(playerId); playersWithWritePermission.insert(playerId);
} }
void Server_CardZone::getInfo(ServerInfo_Zone *info, Server_Player *playerWhosAsking, bool omniscient) void Server_CardZone::getInfo(ServerInfo_Zone *info, Server_AbstractParticipant *recipient, bool omniscient)
{ {
info->set_name(name.toStdString()); info->set_name(name.toStdString());
info->set_type(type); info->set_type(type);
@ -327,10 +327,10 @@ void Server_CardZone::getInfo(ServerInfo_Zone *info, Server_Player *playerWhosAs
info->set_always_reveal_top_card(alwaysRevealTopCard); info->set_always_reveal_top_card(alwaysRevealTopCard);
info->set_always_look_at_top_card(alwaysLookAtTopCard); info->set_always_look_at_top_card(alwaysLookAtTopCard);
const auto selfPlayerAsking = playerWhosAsking == player || omniscient; const bool selfPlayerAsking = recipient == player || omniscient;
const auto zonesSelfCanSee = type != ServerInfo_Zone::HiddenZone; const bool zonesSelfCanSee = type != ServerInfo_Zone::HiddenZone;
const auto otherPlayerAsking = playerWhosAsking != player; const bool otherPlayerAsking = recipient != player;
const auto zonesOthersCanSee = type == ServerInfo_Zone::PublicZone; const bool zonesOthersCanSee = type == ServerInfo_Zone::PublicZone;
if ((selfPlayerAsking && zonesSelfCanSee) || (otherPlayerAsking && zonesOthersCanSee)) { if ((selfPlayerAsking && zonesSelfCanSee) || (otherPlayerAsking && zonesOthersCanSee)) {
QListIterator<Server_Card *> cardIterator(cards); QListIterator<Server_Card *> cardIterator(cards);
while (cardIterator.hasNext()) while (cardIterator.hasNext())

View file

@ -29,6 +29,7 @@
class Server_Card; class Server_Card;
class Server_Player; class Server_Player;
class Server_AbstractParticipant;
class Server_Game; class Server_Game;
class GameEventStorage; class GameEventStorage;
@ -87,7 +88,7 @@ public:
{ {
return player; return player;
} }
void getInfo(ServerInfo_Zone *info, Server_Player *playerWhosAsking, bool omniscient); void getInfo(ServerInfo_Zone *info, Server_AbstractParticipant *recipient, bool omniscient);
int getFreeGridColumn(int x, int y, const QString &cardName, bool dontStackSameName) const; int getFreeGridColumn(int x, int y, const QString &cardName, bool dontStackSameName) const;
bool isColumnEmpty(int x, int y) const; bool isColumnEmpty(int x, int y) const;

View file

@ -101,10 +101,10 @@ Server_Game::~Server_Game()
gameClosed = true; gameClosed = true;
sendGameEventContainer(prepareGameEvent(Event_GameClosed(), -1)); sendGameEventContainer(prepareGameEvent(Event_GameClosed(), -1));
for (auto *anyPlayer : players.values()) { for (auto *participant : participants.values()) {
anyPlayer->prepareDestroy(); participant->prepareDestroy();
} }
players.clear(); participants.clear();
room->removeGame(this); room->removeGame(this);
delete creatorInfo; delete creatorInfo;
@ -189,36 +189,23 @@ void Server_Game::pingClockTimeout()
bool allPlayersInactive = true; bool allPlayersInactive = true;
int playerCount = 0; int playerCount = 0;
for (auto *anyPlayer : players) { for (auto *participant : participants) {
if (anyPlayer == nullptr) if (participant == nullptr)
continue; continue;
if (!anyPlayer->getSpectator()) { if (!participant->getSpectator()) {
++playerCount; ++playerCount;
} }
int oldPingTime = anyPlayer->getPingTime(); if (participant->updatePingTime()) {
int newPingTime;
{
QMutexLocker playerMutexLocker(&anyPlayer->playerMutex);
if (anyPlayer->getUserInterface()) {
newPingTime = anyPlayer->getUserInterface()->getLastCommandTime();
} else {
newPingTime = -1;
}
}
if ((newPingTime != -1) && (!anyPlayer->getSpectator() || anyPlayer->getPlayerId() == hostId)) {
allPlayersInactive = false;
}
if ((abs(oldPingTime - newPingTime) > 1) || ((newPingTime == -1) && (oldPingTime != -1)) ||
((newPingTime != -1) && (oldPingTime == -1))) {
anyPlayer->setPingTime(newPingTime);
Event_PlayerPropertiesChanged event; Event_PlayerPropertiesChanged event;
event.mutable_player_properties()->set_ping_seconds(newPingTime); event.mutable_player_properties()->set_ping_seconds(participant->getPingTime());
ges.enqueueGameEvent(event, anyPlayer->getPlayerId()); ges.enqueueGameEvent(event, participant->getPlayerId());
}
if ((participant->getPingTime() != -1) &&
(!participant->getSpectator() || participant->getPlayerId() == hostId)) {
allPlayersInactive = false;
} }
} }
ges.sendToGame(this); ges.sendToGame(this);
@ -233,16 +220,32 @@ void Server_Game::pingClockTimeout()
} }
} }
QMap<int, Server_Player *> Server_Game::getPlayers() const // copies pointers to new map
{
QMap<int, Server_Player *> players;
QMutexLocker locker(&gameMutex);
for (int id : participants.keys()) {
auto *participant = participants[id];
if (!participant->getSpectator()) {
players[id] = static_cast<Server_Player *>(participant);
}
}
return players;
}
Server_Player *Server_Game::getPlayer(int id) const
{
auto *participant = participants.value(id);
if (!participant->getSpectator()) {
return static_cast<Server_Player *>(participant);
} else {
return nullptr;
}
}
int Server_Game::getPlayerCount() const int Server_Game::getPlayerCount() const
{ {
QMutexLocker locker(&gameMutex); return participants.size() - getSpectatorCount();
int result = 0;
for (Server_Player *anyPlayer : players.values()) {
if (!anyPlayer->getSpectator())
++result;
}
return result;
} }
int Server_Game::getSpectatorCount() const int Server_Game::getSpectatorCount() const
@ -250,15 +253,15 @@ int Server_Game::getSpectatorCount() const
QMutexLocker locker(&gameMutex); QMutexLocker locker(&gameMutex);
int result = 0; int result = 0;
for (Server_Player *anyPlayer : players.values()) { for (Server_AbstractParticipant *participant : participants.values()) {
if (anyPlayer->getSpectator()) if (participant->getSpectator())
++result; ++result;
} }
return result; return result;
} }
void Server_Game::createGameStateChangedEvent(Event_GameStateChanged *event, void Server_Game::createGameStateChangedEvent(Event_GameStateChanged *event,
Server_Player *playerWhosAsking, Server_AbstractParticipant *recipient,
bool omniscient, bool omniscient,
bool withUserInfo) bool withUserInfo)
{ {
@ -270,8 +273,8 @@ void Server_Game::createGameStateChangedEvent(Event_GameStateChanged *event,
} else } else
event->set_game_started(false); event->set_game_started(false);
for (Server_Player *anyPlayer : players.values()) { for (Server_AbstractParticipant *participant : participants.values()) {
anyPlayer->getInfo(event->add_player_list(), playerWhosAsking, omniscient, withUserInfo); participant->getInfo(event->add_player_list(), recipient, omniscient, withUserInfo);
} }
} }
@ -294,21 +297,21 @@ void Server_Game::sendGameStateToPlayers()
createGameStateChangedEvent(&spectatorNormalEvent, nullptr, false, false); createGameStateChangedEvent(&spectatorNormalEvent, nullptr, false, false);
// send game state info to clients according to their role in the game // send game state info to clients according to their role in the game
for (Server_Player *anyPlayer : players.values()) { for (auto *participant : participants.values()) {
GameEventContainer *gec; GameEventContainer *gec;
if (anyPlayer->getSpectator()) { if (participant->getSpectator()) {
if (spectatorsSeeEverything || anyPlayer->getJudge()) { if (spectatorsSeeEverything || participant->getJudge()) {
gec = prepareGameEvent(omniscientEvent, -1); gec = prepareGameEvent(omniscientEvent, -1);
} else { } else {
gec = prepareGameEvent(spectatorNormalEvent, -1); gec = prepareGameEvent(spectatorNormalEvent, -1);
} }
} else { } else {
Event_GameStateChanged event; Event_GameStateChanged event;
createGameStateChangedEvent(&event, anyPlayer, false, false); createGameStateChangedEvent(&event, participant, false, false);
gec = prepareGameEvent(event, -1); gec = prepareGameEvent(event, -1);
} }
anyPlayer->sendGameEvent(*gec); participant->sendGameEvent(*gec);
delete gec; delete gec;
} }
} }
@ -322,28 +325,27 @@ void Server_Game::doStartGameIfReady(bool forceStartGame)
return; return;
} }
for (Server_Player *anyPlayer : players.values()) { auto players = getPlayers();
if (!anyPlayer->getReadyStart() && !anyPlayer->getSpectator()) { for (auto *player : players.values()) {
if (!player->getReadyStart()) {
if (forceStartGame) { if (forceStartGame) {
// Player is not ready to start, so kick them // Player is not ready to start, so kick them
// TODO: Move them to Spectators instead // TODO: Move them to Spectators instead
kickPlayer(anyPlayer->getPlayerId()); kickParticipant(player->getPlayerId());
} else { } else {
return; return;
} }
} }
} }
for (Server_Player *anyPlayer : players.values()) { for (Server_Player *player : players.values()) {
if (!anyPlayer->getSpectator()) { player->setupZones();
anyPlayer->setupZones();
}
} }
gameStarted = true; gameStarted = true;
for (Server_Player *anyPlayer : players.values()) { for (auto *player : players.values()) {
anyPlayer->setConceded(false); player->setConceded(false);
anyPlayer->setReadyStart(false); player->setReadyStart(false);
} }
if (firstGameStarted) { if (firstGameStarted) {
@ -392,8 +394,9 @@ void Server_Game::stopGameIfFinished()
QMutexLocker locker(&gameMutex); QMutexLocker locker(&gameMutex);
int playing = 0; int playing = 0;
for (Server_Player *anyPlayer : players.values()) { auto players = getPlayers();
if (!anyPlayer->getConceded() && !anyPlayer->getSpectator()) for (auto *player : players.values()) {
if (!player->getConceded())
++playing; ++playing;
} }
if (playing > 1) if (playing > 1)
@ -401,9 +404,9 @@ void Server_Game::stopGameIfFinished()
gameStarted = false; gameStarted = false;
for (Server_Player *anyPlayer : players.values()) { for (auto *player : players.values()) {
anyPlayer->clearZones(); player->clearZones();
anyPlayer->setConceded(false); player->setConceded(false);
} }
sendGameStateToPlayers(); sendGameStateToPlayers();
@ -424,8 +427,8 @@ Response::ResponseCode Server_Game::checkJoin(ServerInfo_User *user,
bool asJudge) bool asJudge)
{ {
Server_DatabaseInterface *databaseInterface = room->getServer()->getDatabaseInterface(); Server_DatabaseInterface *databaseInterface = room->getServer()->getDatabaseInterface();
for (Server_Player *anyPlayer : players.values()) { for (auto *participant : participants.values()) {
if (anyPlayer->getUserInfo()->name() == user->name()) if (participant->getUserInfo()->name() == user->name())
return Response::RespContextError; return Response::RespContextError;
} }
@ -459,8 +462,8 @@ bool Server_Game::containsUser(const QString &userName) const
{ {
QMutexLocker locker(&gameMutex); QMutexLocker locker(&gameMutex);
for (Server_Player *anyPlayer : players.values()) { for (auto *participant : participants.values()) {
if (anyPlayer->getUserInfo()->name() == userName.toStdString()) if (participant->getUserInfo()->name() == userName.toStdString())
return true; return true;
} }
return false; return false;
@ -474,17 +477,23 @@ void Server_Game::addPlayer(Server_AbstractUserInterface *userInterface,
{ {
QMutexLocker locker(&gameMutex); QMutexLocker locker(&gameMutex);
Server_Player *newPlayer = new Server_Player(this, nextPlayerId++, userInterface->copyUserInfo(true, true, true), Server_AbstractParticipant *newParticipant;
spectator, judge, userInterface); if (spectator) {
newParticipant = new Server_Spectator(this, nextPlayerId++, userInterface->copyUserInfo(true, true, true),
judge, userInterface);
} else {
newParticipant = new Server_Player(this, nextPlayerId++, userInterface->copyUserInfo(true, true, true), judge,
userInterface);
}
newPlayer->moveToThread(thread()); newParticipant->moveToThread(thread());
Event_Join joinEvent; Event_Join joinEvent;
newPlayer->getProperties(*joinEvent.mutable_player_properties(), true); newParticipant->getProperties(*joinEvent.mutable_player_properties(), true);
sendGameEventContainer(prepareGameEvent(joinEvent, -1)); sendGameEventContainer(prepareGameEvent(joinEvent, -1));
const QString playerName = QString::fromStdString(newPlayer->getUserInfo()->name()); const QString playerName = QString::fromStdString(newParticipant->getUserInfo()->name());
players.insert(newPlayer->getPlayerId(), newPlayer); participants.insert(newParticipant->getPlayerId(), newParticipant);
if (spectator) { if (spectator) {
allSpectatorsEver.insert(playerName); allSpectatorsEver.insert(playerName);
} else { } else {
@ -492,8 +501,8 @@ void Server_Game::addPlayer(Server_AbstractUserInterface *userInterface,
// if the original creator of the game joins, give them host status back // if the original creator of the game joins, give them host status back
// FIXME: transferring host to spectators has side effects // FIXME: transferring host to spectators has side effects
if (newPlayer->getUserInfo()->name() == creatorInfo->name()) { if (newParticipant->getUserInfo()->name() == creatorInfo->name()) {
hostId = newPlayer->getPlayerId(); hostId = newParticipant->getPlayerId();
sendGameEventContainer(prepareGameEvent(Event_GameHostChanged(), hostId)); sendGameEventContainer(prepareGameEvent(Event_GameHostChanged(), hostId));
} }
} }
@ -507,41 +516,42 @@ void Server_Game::addPlayer(Server_AbstractUserInterface *userInterface,
emit gameInfoChanged(gameInfo); emit gameInfoChanged(gameInfo);
} }
if ((newPlayer->getUserInfo()->user_level() & ServerInfo_User::IsRegistered) && !spectator) if ((newParticipant->getUserInfo()->user_level() & ServerInfo_User::IsRegistered) && !spectator)
room->getServer()->addPersistentPlayer(playerName, room->getId(), gameId, newPlayer->getPlayerId()); room->getServer()->addPersistentPlayer(playerName, room->getId(), gameId, newParticipant->getPlayerId());
userInterface->playerAddedToGame(gameId, room->getId(), newPlayer->getPlayerId()); userInterface->playerAddedToGame(gameId, room->getId(), newParticipant->getPlayerId());
createGameJoinedEvent(newPlayer, rc, false); createGameJoinedEvent(newParticipant, rc, false);
} }
void Server_Game::removePlayer(Server_Player *player, Event_Leave::LeaveReason reason) void Server_Game::removeParticipant(Server_AbstractParticipant *participant, Event_Leave::LeaveReason reason)
{ {
room->getServer()->removePersistentPlayer(QString::fromStdString(player->getUserInfo()->name()), room->getId(), room->getServer()->removePersistentPlayer(QString::fromStdString(participant->getUserInfo()->name()), room->getId(),
gameId, player->getPlayerId()); gameId, participant->getPlayerId());
players.remove(player->getPlayerId()); participants.remove(participant->getPlayerId());
bool spectator = participant->getSpectator();
GameEventStorage ges; GameEventStorage ges;
removeArrowsRelatedToPlayer(ges, player); if (!spectator) {
unattachCards(ges, player); auto *player = static_cast<Server_Player *>(participant);
removeArrowsRelatedToPlayer(ges, player);
unattachCards(ges, player);
}
Event_Leave event; Event_Leave event;
event.set_reason(reason); event.set_reason(reason);
ges.enqueueGameEvent(event, player->getPlayerId()); ges.enqueueGameEvent(event, participant->getPlayerId());
ges.sendToGame(this); ges.sendToGame(this);
bool playerActive = activePlayer == player->getPlayerId(); bool playerActive = activePlayer == participant->getPlayerId();
bool playerHost = hostId == player->getPlayerId(); bool playerHost = hostId == participant->getPlayerId();
bool spectator = player->getSpectator(); participant->prepareDestroy();
player->prepareDestroy();
if (playerHost) { if (playerHost) {
int newHostId = -1; int newHostId = -1;
for (Server_Player *otherPlayer : players.values()) { for (auto *otherPlayer : getPlayers().values()) {
if (!otherPlayer->getSpectator()) { newHostId = otherPlayer->getPlayerId();
newHostId = otherPlayer->getPlayerId(); break;
break;
}
} }
if (newHostId != -1) { if (newHostId != -1) {
hostId = newHostId; hostId = newHostId;
@ -573,28 +583,28 @@ void Server_Game::removeArrowsRelatedToPlayer(GameEventStorage &ges, Server_Play
// Remove all arrows of other players pointing to the player being removed or to one of his cards. // Remove all arrows of other players pointing to the player being removed or to one of his cards.
// Also remove all arrows starting at one of his cards. This is necessary since players can create // Also remove all arrows starting at one of his cards. This is necessary since players can create
// arrows that start at another person's cards. // arrows that start at another person's cards.
for (Server_Player *anyPlayer : players.values()) { for (Server_Player *anyPlayer : getPlayers().values()) {
QList<Server_Arrow *> arrows = anyPlayer->getArrows().values(); QList<Server_Arrow *> arrows = anyPlayer->getArrows().values();
QList<Server_Arrow *> toDelete; QList<Server_Arrow *> toDelete;
for (int i = 0; i < arrows.size(); ++i) { for (int i = 0; i < arrows.size(); ++i) {
Server_Arrow *a = arrows[i]; Server_Arrow *arrow = arrows[i];
Server_Card *targetCard = qobject_cast<Server_Card *>(a->getTargetItem()); Server_Card *targetCard = qobject_cast<Server_Card *>(arrow->getTargetItem());
if (targetCard) { if (targetCard) {
if (targetCard->getZone() != nullptr && targetCard->getZone()->getPlayer() == player) if (targetCard->getZone() != nullptr && targetCard->getZone()->getPlayer() == player)
toDelete.append(a); toDelete.append(arrow);
} else if (static_cast<Server_Player *>(a->getTargetItem()) == player) } else if (static_cast<Server_Player *>(arrow->getTargetItem()) == player)
toDelete.append(a); toDelete.append(arrow);
// Don't use else here! It has to happen regardless of whether targetCard == 0. // Don't use else here! It has to happen regardless of whether targetCard == 0.
if (a->getStartCard()->getZone() != nullptr && a->getStartCard()->getZone()->getPlayer() == player) if (arrow->getStartCard()->getZone() != nullptr && arrow->getStartCard()->getZone()->getPlayer() == player)
toDelete.append(a); toDelete.append(arrow);
} }
for (int i = 0; i < toDelete.size(); ++i) { for (int i = 0; i < toDelete.size(); ++i) {
Event_DeleteArrow event; Event_DeleteArrow event;
event.set_arrow_id(toDelete[i]->getId()); event.set_arrow_id(toDelete[i]->getId());
ges.enqueueGameEvent(event, anyPlayer->getPlayerId()); ges.enqueueGameEvent(event, player->getPlayerId());
anyPlayer->deleteArrow(toDelete[i]->getId()); player->deleteArrow(toDelete[i]->getId());
} }
} }
} }
@ -621,19 +631,19 @@ void Server_Game::unattachCards(GameEventStorage &ges, Server_Player *player)
} }
} }
bool Server_Game::kickPlayer(int playerId) bool Server_Game::kickParticipant(int playerId)
{ {
QMutexLocker locker(&gameMutex); QMutexLocker locker(&gameMutex);
Server_Player *playerToKick = players.value(playerId); auto *participant = participants.value(playerId);
if (!playerToKick) if (!participant)
return false; return false;
GameEventContainer *gec = prepareGameEvent(Event_Kicked(), -1); GameEventContainer *gec = prepareGameEvent(Event_Kicked(), -1);
playerToKick->sendGameEvent(*gec); participant->sendGameEvent(*gec);
delete gec; delete gec;
removePlayer(playerToKick, Event_Leave::USER_KICKED); removeParticipant(participant, Event_Leave::USER_KICKED);
return true; return true;
} }
@ -655,16 +665,16 @@ void Server_Game::setActivePhase(int _activePhase)
{ {
QMutexLocker locker(&gameMutex); QMutexLocker locker(&gameMutex);
for (Server_Player *anyPlayer : players.values()) { for (auto *player : getPlayers().values()) {
QList<Server_Arrow *> toDelete = anyPlayer->getArrows().values(); QList<Server_Arrow *> toDelete = player->getArrows().values();
for (int i = 0; i < toDelete.size(); ++i) { for (int i = 0; i < toDelete.size(); ++i) {
Server_Arrow *a = toDelete[i]; Server_Arrow *a = toDelete[i];
Event_DeleteArrow event; Event_DeleteArrow event;
event.set_arrow_id(a->getId()); event.set_arrow_id(a->getId());
sendGameEventContainer(prepareGameEvent(event, anyPlayer->getPlayerId())); sendGameEventContainer(prepareGameEvent(event, player->getPlayerId()));
anyPlayer->deleteArrow(a->getId()); player->deleteArrow(a->getId());
} }
} }
@ -679,15 +689,17 @@ void Server_Game::nextTurn()
{ {
QMutexLocker locker(&gameMutex); QMutexLocker locker(&gameMutex);
if (players.isEmpty()) { if (participants.isEmpty()) {
qWarning() << "Server_Game::nextTurn was called while players is empty; gameId = " << gameId; qWarning() << "Server_Game::nextTurn was called while players is empty; gameId = " << gameId;
return; return;
} }
auto players = getPlayers();
const QList<int> keys = players.keys(); const QList<int> keys = players.keys();
int listPos = -1; int listPos = -1;
if (activePlayer != -1) if (activePlayer != -1) {
listPos = keys.indexOf(activePlayer); listPos = keys.indexOf(activePlayer);
}
do { do {
if (turnOrderReversed) { if (turnOrderReversed) {
--listPos; --listPos;
@ -700,19 +712,21 @@ void Server_Game::nextTurn()
listPos = 0; listPos = 0;
} }
} }
} while (players.value(keys[listPos])->getSpectator() || players.value(keys[listPos])->getConceded()); } while (players.value(keys[listPos])->getConceded());
setActivePlayer(keys[listPos]); setActivePlayer(keys[listPos]);
} }
void Server_Game::createGameJoinedEvent(Server_Player *joiningPlayer, ResponseContainer &rc, bool resuming) void Server_Game::createGameJoinedEvent(Server_AbstractParticipant *joiningParticipant,
ResponseContainer &rc,
bool resuming)
{ {
Event_GameJoined event1; Event_GameJoined event1;
getInfo(*event1.mutable_game_info()); getInfo(*event1.mutable_game_info());
event1.set_host_id(hostId); event1.set_host_id(hostId);
event1.set_player_id(joiningPlayer->getPlayerId()); event1.set_player_id(joiningParticipant->getPlayerId());
event1.set_spectator(joiningPlayer->getSpectator()); event1.set_spectator(joiningParticipant->getSpectator());
event1.set_judge(joiningPlayer->getJudge()); event1.set_judge(joiningParticipant->getJudge());
event1.set_resuming(resuming); event1.set_resuming(resuming);
if (resuming) { if (resuming) {
const QStringList &allGameTypes = room->getGameTypes(); const QStringList &allGameTypes = room->getGameTypes();
@ -730,10 +744,9 @@ void Server_Game::createGameJoinedEvent(Server_Player *joiningPlayer, ResponseCo
event2.set_active_player_id(activePlayer); event2.set_active_player_id(activePlayer);
event2.set_active_phase(activePhase); event2.set_active_phase(activePhase);
for (auto *anyPlayer : players.values()) { bool omniscient = joiningParticipant->getSpectator() && (spectatorsSeeEverything || joiningParticipant->getJudge());
anyPlayer->getInfo(event2.add_player_list(), joiningPlayer, for (auto *participant : participants.values()) {
(joiningPlayer->getSpectator() && (spectatorsSeeEverything || joiningPlayer->getJudge())), participant->getInfo(event2.add_player_list(), joiningParticipant, omniscient, true);
true);
} }
rc.enqueuePostResponseItem(ServerMessage::GAME_EVENT_CONTAINER, prepareGameEvent(event2, -1)); rc.enqueuePostResponseItem(ServerMessage::GAME_EVENT_CONTAINER, prepareGameEvent(event2, -1));
@ -746,12 +759,13 @@ void Server_Game::sendGameEventContainer(GameEventContainer *cont,
QMutexLocker locker(&gameMutex); QMutexLocker locker(&gameMutex);
cont->set_game_id(gameId); cont->set_game_id(gameId);
for (Server_Player *anyPlayer : players.values()) { for (auto *participant : participants.values()) {
const bool playerPrivate = (anyPlayer->getPlayerId() == privatePlayerId) || const bool playerPrivate =
(anyPlayer->getSpectator() && (spectatorsSeeEverything || anyPlayer->getJudge())); (participant->getPlayerId() == privatePlayerId) ||
(participant->getSpectator() && (spectatorsSeeEverything || participant->getJudge()));
if ((recipients.testFlag(GameEventStorageItem::SendToPrivate) && playerPrivate) || if ((recipients.testFlag(GameEventStorageItem::SendToPrivate) && playerPrivate) ||
(recipients.testFlag(GameEventStorageItem::SendToOthers) && !playerPrivate)) (recipients.testFlag(GameEventStorageItem::SendToOthers) && !playerPrivate))
anyPlayer->sendGameEvent(*cont); participant->sendGameEvent(*cont);
} }
if (recipients.testFlag(GameEventStorageItem::SendToPrivate)) { if (recipients.testFlag(GameEventStorageItem::SendToPrivate)) {
cont->set_seconds_elapsed(secondsElapsed - startTimeOfThisGame); cont->set_seconds_elapsed(secondsElapsed - startTimeOfThisGame);

View file

@ -37,6 +37,7 @@ class GameEventContainer;
class GameReplay; class GameReplay;
class Server_Room; class Server_Room;
class Server_Player; class Server_Player;
class Server_AbstractParticipant;
class ServerInfo_User; class ServerInfo_User;
class ServerInfo_Player; class ServerInfo_Player;
class ServerInfo_Game; class ServerInfo_Game;
@ -51,7 +52,7 @@ private:
int nextPlayerId; int nextPlayerId;
int hostId; int hostId;
ServerInfo_User *creatorInfo; ServerInfo_User *creatorInfo;
QMap<int, Server_Player *> players; QMap<int, Server_AbstractParticipant *> participants;
QSet<QString> allPlayersEver, allSpectatorsEver; QSet<QString> allPlayersEver, allSpectatorsEver;
bool gameStarted; bool gameStarted;
bool gameClosed; bool gameClosed;
@ -78,7 +79,7 @@ private:
GameReplay *currentReplay; GameReplay *currentReplay;
void createGameStateChangedEvent(Event_GameStateChanged *event, void createGameStateChangedEvent(Event_GameStateChanged *event,
Server_Player *playerWhosAsking, Server_AbstractParticipant *recipient,
bool omniscient, bool omniscient,
bool withUserInfo); bool withUserInfo);
void storeGameInformation(); void storeGameInformation();
@ -130,9 +131,11 @@ public:
} }
int getPlayerCount() const; int getPlayerCount() const;
int getSpectatorCount() const; int getSpectatorCount() const;
const QMap<int, Server_Player *> &getPlayers() const QMap<int, Server_Player *> getPlayers() const;
Server_Player *getPlayer(int id) const;
const QMap<int, Server_AbstractParticipant *> &getParticipants() const
{ {
return players; return participants;
} }
int getGameId() const int getGameId() const
{ {
@ -182,10 +185,10 @@ public:
bool spectator, bool spectator,
bool judge, bool judge,
bool broadcastUpdate = true); bool broadcastUpdate = true);
void removePlayer(Server_Player *player, Event_Leave::LeaveReason reason); void removeParticipant(Server_AbstractParticipant *participant, Event_Leave::LeaveReason reason);
void removeArrowsRelatedToPlayer(GameEventStorage &ges, Server_Player *player); void removeArrowsRelatedToPlayer(GameEventStorage &ges, Server_Player *player);
void unattachCards(GameEventStorage &ges, Server_Player *player); void unattachCards(GameEventStorage &ges, Server_Player *player);
bool kickPlayer(int playerId); bool kickParticipant(int playerId);
void startGameIfReady(bool forceStartGame); void startGameIfReady(bool forceStartGame);
void stopGameIfFinished(); void stopGameIfFinished();
int getActivePlayer() const int getActivePlayer() const
@ -208,7 +211,7 @@ public:
return turnOrderReversed = !turnOrderReversed; return turnOrderReversed = !turnOrderReversed;
} }
void createGameJoinedEvent(Server_Player *player, ResponseContainer &rc, bool resuming); void createGameJoinedEvent(Server_AbstractParticipant *participant, ResponseContainer &rc, bool resuming);
GameEventContainer * GameEventContainer *
prepareGameEvent(const ::google::protobuf::Message &gameEvent, int playerId, GameEventContext *context = 0); prepareGameEvent(const ::google::protobuf::Message &gameEvent, int playerId, GameEventContext *context = 0);

View file

@ -108,13 +108,12 @@ struct MoveCardStruct
Server_Player::Server_Player(Server_Game *_game, Server_Player::Server_Player(Server_Game *_game,
int _playerId, int _playerId,
const ServerInfo_User &_userInfo, const ServerInfo_User &_userInfo,
bool _spectator,
bool _judge, bool _judge,
Server_AbstractUserInterface *_userInterface) Server_AbstractUserInterface *_userInterface)
: ServerInfo_User_Container(_userInfo), game(_game), userInterface(_userInterface), deck(nullptr), pingTime(0), : Server_AbstractParticipant(_game, _playerId, _userInfo, _judge, _userInterface), deck(nullptr), nextCardId(0),
playerId(_playerId), spectator(_spectator), judge(_judge), nextCardId(0), readyStart(false), conceded(false), readyStart(false), conceded(false), sideboardLocked(true)
sideboardLocked(true)
{ {
spectator = false;
} }
Server_Player::~Server_Player() = default; Server_Player::~Server_Player() = default;
@ -124,12 +123,7 @@ void Server_Player::prepareDestroy()
delete deck; delete deck;
deck = nullptr; deck = nullptr;
playerMutex.lock(); removeFromGame();
if (userInterface) {
userInterface->playerRemovedFromGame(game);
}
playerMutex.unlock();
clearZones(); clearZones();
deleteLater(); deleteLater();
@ -269,25 +263,6 @@ void Server_Player::clearZones()
lastDrawList.clear(); lastDrawList.clear();
} }
void Server_Player::getProperties(ServerInfo_PlayerProperties &result, bool withUserInfo)
{
result.set_player_id(playerId);
if (withUserInfo) {
copyUserInfo(*(result.mutable_user_info()), true);
}
result.set_spectator(spectator);
if (!spectator) {
result.set_conceded(conceded);
result.set_sideboard_locked(sideboardLocked);
result.set_ready_start(readyStart);
}
result.set_judge(judge);
if (deck) {
result.set_deck_hash(deck->getDeckHash().toStdString());
}
result.set_ping_seconds(pingTime);
}
void Server_Player::addZone(Server_CardZone *zone) void Server_Player::addZone(Server_CardZone *zone)
{ {
zones.insert(zone->getName(), zone); zones.insert(zone->getName(), zone);
@ -541,8 +516,7 @@ Response::ResponseCode Server_Player::moveCard(GameEventStorage &ges,
if (startzone != targetzone) { if (startzone != targetzone) {
// Delete all arrows from and to the card // Delete all arrows from and to the card
const QList<Server_Player *> &players = game->getPlayers().values(); for (auto *player : game->getPlayers().values()) {
for (auto player : players) {
QList<int> arrowsToDelete; QList<int> arrowsToDelete;
for (Server_Arrow *arrow : player->getArrows()) { for (Server_Arrow *arrow : player->getArrows()) {
if ((arrow->getStartCard() == card) || (arrow->getTargetItem() == card)) if ((arrow->getStartCard() == card) || (arrow->getTargetItem() == card))
@ -781,34 +755,9 @@ Response::ResponseCode Server_Player::setCardAttrHelper(GameEventStorage &ges,
return Response::RespOk; return Response::RespOk;
} }
Response::ResponseCode
Server_Player::cmdLeaveGame(const Command_LeaveGame & /*cmd*/, ResponseContainer & /*rc*/, GameEventStorage & /*ges*/)
{
game->removePlayer(this, Event_Leave::USER_LEFT);
return Response::RespOk;
}
Response::ResponseCode
Server_Player::cmdKickFromGame(const Command_KickFromGame &cmd, ResponseContainer & /*rc*/, GameEventStorage & /*ges*/)
{
if ((game->getHostId() != playerId) && !(userInfo->user_level() & ServerInfo_User::IsModerator)) {
return Response::RespFunctionNotAllowed;
}
if (!game->kickPlayer(cmd.player_id())) {
return Response::RespNameNotFound;
}
return Response::RespOk;
}
Response::ResponseCode Response::ResponseCode
Server_Player::cmdDeckSelect(const Command_DeckSelect &cmd, ResponseContainer &rc, GameEventStorage &ges) Server_Player::cmdDeckSelect(const Command_DeckSelect &cmd, ResponseContainer &rc, GameEventStorage &ges)
{ {
if (spectator) {
return Response::RespFunctionNotAllowed;
}
DeckList *newDeck; DeckList *newDeck;
if (cmd.has_deck_id()) { if (cmd.has_deck_id()) {
try { try {
@ -853,9 +802,6 @@ Response::ResponseCode Server_Player::cmdSetSideboardPlan(const Command_SetSideb
ResponseContainer & /*rc*/, ResponseContainer & /*rc*/,
GameEventStorage & /*ges*/) GameEventStorage & /*ges*/)
{ {
if (spectator) {
return Response::RespFunctionNotAllowed;
}
if (readyStart) { if (readyStart) {
return Response::RespContextError; return Response::RespContextError;
} }
@ -879,9 +825,6 @@ Response::ResponseCode Server_Player::cmdSetSideboardLock(const Command_SetSideb
ResponseContainer & /*rc*/, ResponseContainer & /*rc*/,
GameEventStorage &ges) GameEventStorage &ges)
{ {
if (spectator) {
return Response::RespFunctionNotAllowed;
}
if (readyStart) { if (readyStart) {
return Response::RespContextError; return Response::RespContextError;
} }
@ -908,9 +851,6 @@ Response::ResponseCode Server_Player::cmdSetSideboardLock(const Command_SetSideb
Response::ResponseCode Response::ResponseCode
Server_Player::cmdConcede(const Command_Concede & /*cmd*/, ResponseContainer & /*rc*/, GameEventStorage &ges) Server_Player::cmdConcede(const Command_Concede & /*cmd*/, ResponseContainer & /*rc*/, GameEventStorage &ges)
{ {
if (spectator) {
return Response::RespFunctionNotAllowed;
}
if (!game->getGameStarted()) { if (!game->getGameStarted()) {
return Response::RespGameNotStarted; return Response::RespGameNotStarted;
} }
@ -939,7 +879,7 @@ Server_Player::cmdConcede(const Command_Concede & /*cmd*/, ResponseContainer & /
CardToMove cardToMove; CardToMove cardToMove;
cardToMove.set_card_id(card->getId()); cardToMove.set_card_id(card->getId());
for (const auto &player : game->getPlayers()) { for (const auto *player : game->getPlayers()) {
if (player == nullptr || player->getUserInfo() == nullptr) { if (player == nullptr || player->getUserInfo() == nullptr) {
continue; continue;
} }
@ -984,9 +924,6 @@ Server_Player::cmdConcede(const Command_Concede & /*cmd*/, ResponseContainer & /
Response::ResponseCode Response::ResponseCode
Server_Player::cmdUnconcede(const Command_Unconcede & /*cmd*/, ResponseContainer & /*rc*/, GameEventStorage &ges) Server_Player::cmdUnconcede(const Command_Unconcede & /*cmd*/, ResponseContainer & /*rc*/, GameEventStorage &ges)
{ {
if (spectator) {
return Response::RespFunctionNotAllowed;
}
if (!game->getGameStarted()) { if (!game->getGameStarted()) {
return Response::RespGameNotStarted; return Response::RespGameNotStarted;
} }
@ -1008,31 +945,9 @@ Server_Player::cmdUnconcede(const Command_Unconcede & /*cmd*/, ResponseContainer
return Response::RespOk; return Response::RespOk;
} }
Response::ResponseCode Server_Player::cmdJudge(const Command_Judge &cmd, ResponseContainer &rc, GameEventStorage &ges)
{
if (!judge)
return Response::RespFunctionNotAllowed;
Server_Player *player = this->game->getPlayers().value(cmd.target_id());
ges.setForcedByJudge(playerId);
if (player == nullptr)
return Response::RespContextError;
for (int i = 0; i < cmd.game_command_size(); ++i) {
player->processGameCommand(cmd.game_command(i), rc, ges);
}
return Response::RespOk;
}
Response::ResponseCode Response::ResponseCode
Server_Player::cmdReadyStart(const Command_ReadyStart &cmd, ResponseContainer & /*rc*/, GameEventStorage &ges) Server_Player::cmdReadyStart(const Command_ReadyStart &cmd, ResponseContainer & /*rc*/, GameEventStorage &ges)
{ {
if (spectator) {
return Response::RespFunctionNotAllowed;
}
if (!deck || game->getGameStarted()) { if (!deck || game->getGameStarted()) {
return Response::RespContextError; return Response::RespContextError;
} }
@ -1060,43 +975,9 @@ Server_Player::cmdReadyStart(const Command_ReadyStart &cmd, ResponseContainer &
return Response::RespOk; return Response::RespOk;
} }
Response::ResponseCode
Server_Player::cmdGameSay(const Command_GameSay &cmd, ResponseContainer & /*rc*/, GameEventStorage &ges)
{
if (spectator) {
/* Spectators can only talk if:
* (a) the game creator allows it
* (b) the spectator is a moderator/administrator
* (c) the spectator is a judge
*/
bool isModOrJudge = (userInfo->user_level() & (ServerInfo_User::IsModerator | ServerInfo_User::IsJudge));
if (!isModOrJudge && !game->getSpectatorsCanTalk()) {
return Response::RespFunctionNotAllowed;
}
}
if (!userInterface->addSaidMessageSize(static_cast<int>(cmd.message().size()))) {
return Response::RespChatFlood;
}
Event_GameSay event;
event.set_message(cmd.message());
ges.enqueueGameEvent(event, playerId);
game->getRoom()->getServer()->getDatabaseInterface()->logMessage(
userInfo->id(), QString::fromStdString(userInfo->name()), QString::fromStdString(userInfo->address()),
textFromStdString(cmd.message()), Server_DatabaseInterface::MessageTargetGame, game->getGameId(),
game->getDescription());
return Response::RespOk;
}
Response::ResponseCode Response::ResponseCode
Server_Player::cmdShuffle(const Command_Shuffle &cmd, ResponseContainer & /*rc*/, GameEventStorage &ges) Server_Player::cmdShuffle(const Command_Shuffle &cmd, ResponseContainer & /*rc*/, GameEventStorage &ges)
{ {
if (spectator) {
return Response::RespFunctionNotAllowed;
}
if (!game->getGameStarted()) { if (!game->getGameStarted()) {
return Response::RespGameNotStarted; return Response::RespGameNotStarted;
} }
@ -1129,10 +1010,6 @@ Server_Player::cmdShuffle(const Command_Shuffle &cmd, ResponseContainer & /*rc*/
Response::ResponseCode Response::ResponseCode
Server_Player::cmdMulligan(const Command_Mulligan &cmd, ResponseContainer & /*rc*/, GameEventStorage &ges) Server_Player::cmdMulligan(const Command_Mulligan &cmd, ResponseContainer & /*rc*/, GameEventStorage &ges)
{ {
if (spectator) {
return Response::RespFunctionNotAllowed;
}
if (!game->getGameStarted()) { if (!game->getGameStarted()) {
return Response::RespGameNotStarted; return Response::RespGameNotStarted;
} }
@ -1170,9 +1047,6 @@ Server_Player::cmdMulligan(const Command_Mulligan &cmd, ResponseContainer & /*rc
Response::ResponseCode Response::ResponseCode
Server_Player::cmdRollDie(const Command_RollDie &cmd, ResponseContainer & /*rc*/, GameEventStorage &ges) const Server_Player::cmdRollDie(const Command_RollDie &cmd, ResponseContainer & /*rc*/, GameEventStorage &ges) const
{ {
if (spectator) {
return Response::RespFunctionNotAllowed;
}
if (conceded) { if (conceded) {
return Response::RespContextError; return Response::RespContextError;
} }
@ -1199,10 +1073,6 @@ Server_Player::cmdRollDie(const Command_RollDie &cmd, ResponseContainer & /*rc*/
Response::ResponseCode Response::ResponseCode
Server_Player::cmdDrawCards(const Command_DrawCards &cmd, ResponseContainer & /*rc*/, GameEventStorage &ges) Server_Player::cmdDrawCards(const Command_DrawCards &cmd, ResponseContainer & /*rc*/, GameEventStorage &ges)
{ {
if (spectator) {
return Response::RespFunctionNotAllowed;
}
if (!game->getGameStarted()) { if (!game->getGameStarted()) {
return Response::RespGameNotStarted; return Response::RespGameNotStarted;
} }
@ -1216,10 +1086,6 @@ Server_Player::cmdDrawCards(const Command_DrawCards &cmd, ResponseContainer & /*
Response::ResponseCode Response::ResponseCode
Server_Player::cmdUndoDraw(const Command_UndoDraw & /*cmd*/, ResponseContainer & /*rc*/, GameEventStorage &ges) Server_Player::cmdUndoDraw(const Command_UndoDraw & /*cmd*/, ResponseContainer & /*rc*/, GameEventStorage &ges)
{ {
if (spectator) {
return Response::RespFunctionNotAllowed;
}
if (!game->getGameStarted()) { if (!game->getGameStarted()) {
return Response::RespGameNotStarted; return Response::RespGameNotStarted;
} }
@ -1244,10 +1110,6 @@ Server_Player::cmdUndoDraw(const Command_UndoDraw & /*cmd*/, ResponseContainer &
Response::ResponseCode Response::ResponseCode
Server_Player::cmdMoveCard(const Command_MoveCard &cmd, ResponseContainer & /*rc*/, GameEventStorage &ges) Server_Player::cmdMoveCard(const Command_MoveCard &cmd, ResponseContainer & /*rc*/, GameEventStorage &ges)
{ {
if (spectator) {
return Response::RespFunctionNotAllowed;
}
if (!game->getGameStarted()) { if (!game->getGameStarted()) {
return Response::RespGameNotStarted; return Response::RespGameNotStarted;
} }
@ -1255,7 +1117,7 @@ Server_Player::cmdMoveCard(const Command_MoveCard &cmd, ResponseContainer & /*rc
return Response::RespContextError; return Response::RespContextError;
} }
Server_Player *startPlayer = game->getPlayers().value(cmd.has_start_player_id() ? cmd.start_player_id() : playerId); Server_Player *startPlayer = game->getPlayer(cmd.has_start_player_id() ? cmd.start_player_id() : playerId);
if (!startPlayer) { if (!startPlayer) {
return Response::RespNameNotFound; return Response::RespNameNotFound;
} }
@ -1268,7 +1130,7 @@ Server_Player::cmdMoveCard(const Command_MoveCard &cmd, ResponseContainer & /*rc
return Response::RespContextError; return Response::RespContextError;
} }
Server_Player *targetPlayer = game->getPlayers().value(cmd.target_player_id()); Server_Player *targetPlayer = game->getPlayer(cmd.target_player_id());
if (!targetPlayer) { if (!targetPlayer) {
return Response::RespNameNotFound; return Response::RespNameNotFound;
} }
@ -1292,10 +1154,6 @@ Server_Player::cmdMoveCard(const Command_MoveCard &cmd, ResponseContainer & /*rc
Response::ResponseCode Response::ResponseCode
Server_Player::cmdFlipCard(const Command_FlipCard &cmd, ResponseContainer & /*rc*/, GameEventStorage &ges) Server_Player::cmdFlipCard(const Command_FlipCard &cmd, ResponseContainer & /*rc*/, GameEventStorage &ges)
{ {
if (spectator) {
return Response::RespFunctionNotAllowed;
}
if (!game->getGameStarted()) { if (!game->getGameStarted()) {
return Response::RespGameNotStarted; return Response::RespGameNotStarted;
} }
@ -1344,10 +1202,6 @@ Server_Player::cmdFlipCard(const Command_FlipCard &cmd, ResponseContainer & /*rc
Response::ResponseCode Response::ResponseCode
Server_Player::cmdAttachCard(const Command_AttachCard &cmd, ResponseContainer & /*rc*/, GameEventStorage &ges) Server_Player::cmdAttachCard(const Command_AttachCard &cmd, ResponseContainer & /*rc*/, GameEventStorage &ges)
{ {
if (spectator) {
return Response::RespFunctionNotAllowed;
}
if (!game->getGameStarted()) { if (!game->getGameStarted()) {
return Response::RespGameNotStarted; return Response::RespGameNotStarted;
} }
@ -1370,7 +1224,7 @@ Server_Player::cmdAttachCard(const Command_AttachCard &cmd, ResponseContainer &
Server_Card *targetCard = nullptr; Server_Card *targetCard = nullptr;
if (cmd.has_target_player_id()) { if (cmd.has_target_player_id()) {
targetPlayer = game->getPlayers().value(cmd.target_player_id()); targetPlayer = game->getPlayer(cmd.target_player_id());
if (!targetPlayer) { if (!targetPlayer) {
return Response::RespNameNotFound; return Response::RespNameNotFound;
} }
@ -1404,10 +1258,8 @@ Server_Player::cmdAttachCard(const Command_AttachCard &cmd, ResponseContainer &
return Response::RespContextError; return Response::RespContextError;
} }
QMapIterator<int, Server_Player *> playerIterator(game->getPlayers()); for (auto *player : game->getPlayers()) {
while (playerIterator.hasNext()) { QList<Server_Arrow *> _arrows = player->getArrows().values();
Server_Player *p = playerIterator.next().value();
QList<Server_Arrow *> _arrows = p->getArrows().values();
QList<Server_Arrow *> toDelete; QList<Server_Arrow *> toDelete;
for (auto a : _arrows) { for (auto a : _arrows) {
auto *tCard = qobject_cast<Server_Card *>(a->getTargetItem()); auto *tCard = qobject_cast<Server_Card *>(a->getTargetItem());
@ -1418,8 +1270,8 @@ Server_Player::cmdAttachCard(const Command_AttachCard &cmd, ResponseContainer &
for (auto &i : toDelete) { for (auto &i : toDelete) {
Event_DeleteArrow event; Event_DeleteArrow event;
event.set_arrow_id(i->getId()); event.set_arrow_id(i->getId());
ges.enqueueGameEvent(event, p->getPlayerId()); ges.enqueueGameEvent(event, player->getPlayerId());
p->deleteArrow(i->getId()); player->deleteArrow(i->getId());
} }
} }
@ -1458,10 +1310,6 @@ Server_Player::cmdAttachCard(const Command_AttachCard &cmd, ResponseContainer &
Response::ResponseCode Response::ResponseCode
Server_Player::cmdCreateToken(const Command_CreateToken &cmd, ResponseContainer &rc, GameEventStorage &ges) Server_Player::cmdCreateToken(const Command_CreateToken &cmd, ResponseContainer &rc, GameEventStorage &ges)
{ {
if (spectator) {
return Response::RespFunctionNotAllowed;
}
if (!game->getGameStarted()) { if (!game->getGameStarted()) {
return Response::RespGameNotStarted; return Response::RespGameNotStarted;
} }
@ -1609,8 +1457,7 @@ Server_Player::cmdCreateToken(const Command_CreateToken &cmd, ResponseContainer
} }
// Copy Arrows // Copy Arrows
const QList<Server_Player *> &players = game->getPlayers().values(); for (auto *player : game->getPlayers().values()) {
for (auto player : players) {
QList<int> changedArrowIds; QList<int> changedArrowIds;
for (Server_Arrow *arrow : player->getArrows()) { for (Server_Arrow *arrow : player->getArrows()) {
bool sendGameEvent = false; bool sendGameEvent = false;
@ -1698,10 +1545,6 @@ void Server_Player::sendCreateTokenEvents(Server_CardZone *zone,
Response::ResponseCode Response::ResponseCode
Server_Player::cmdCreateArrow(const Command_CreateArrow &cmd, ResponseContainer & /*rc*/, GameEventStorage &ges) Server_Player::cmdCreateArrow(const Command_CreateArrow &cmd, ResponseContainer & /*rc*/, GameEventStorage &ges)
{ {
if (spectator) {
return Response::RespFunctionNotAllowed;
}
if (!game->getGameStarted()) { if (!game->getGameStarted()) {
return Response::RespGameNotStarted; return Response::RespGameNotStarted;
} }
@ -1709,8 +1552,8 @@ Server_Player::cmdCreateArrow(const Command_CreateArrow &cmd, ResponseContainer
return Response::RespContextError; return Response::RespContextError;
} }
Server_Player *startPlayer = game->getPlayers().value(cmd.start_player_id()); Server_Player *startPlayer = game->getPlayer(cmd.start_player_id());
Server_Player *targetPlayer = game->getPlayers().value(cmd.target_player_id()); Server_Player *targetPlayer = game->getPlayer(cmd.target_player_id());
if (!startPlayer || !targetPlayer) { if (!startPlayer || !targetPlayer) {
return Response::RespNameNotFound; return Response::RespNameNotFound;
} }
@ -1778,10 +1621,6 @@ Server_Player::cmdCreateArrow(const Command_CreateArrow &cmd, ResponseContainer
Response::ResponseCode Response::ResponseCode
Server_Player::cmdDeleteArrow(const Command_DeleteArrow &cmd, ResponseContainer & /*rc*/, GameEventStorage &ges) Server_Player::cmdDeleteArrow(const Command_DeleteArrow &cmd, ResponseContainer & /*rc*/, GameEventStorage &ges)
{ {
if (spectator) {
return Response::RespFunctionNotAllowed;
}
if (!game->getGameStarted()) { if (!game->getGameStarted()) {
return Response::RespGameNotStarted; return Response::RespGameNotStarted;
} }
@ -1803,10 +1642,6 @@ Server_Player::cmdDeleteArrow(const Command_DeleteArrow &cmd, ResponseContainer
Response::ResponseCode Response::ResponseCode
Server_Player::cmdSetCardAttr(const Command_SetCardAttr &cmd, ResponseContainer & /*rc*/, GameEventStorage &ges) Server_Player::cmdSetCardAttr(const Command_SetCardAttr &cmd, ResponseContainer & /*rc*/, GameEventStorage &ges)
{ {
if (spectator) {
return Response::RespFunctionNotAllowed;
}
if (!game->getGameStarted()) { if (!game->getGameStarted()) {
return Response::RespGameNotStarted; return Response::RespGameNotStarted;
} }
@ -1821,10 +1656,6 @@ Server_Player::cmdSetCardAttr(const Command_SetCardAttr &cmd, ResponseContainer
Response::ResponseCode Response::ResponseCode
Server_Player::cmdSetCardCounter(const Command_SetCardCounter &cmd, ResponseContainer & /*rc*/, GameEventStorage &ges) Server_Player::cmdSetCardCounter(const Command_SetCardCounter &cmd, ResponseContainer & /*rc*/, GameEventStorage &ges)
{ {
if (spectator) {
return Response::RespFunctionNotAllowed;
}
if (!game->getGameStarted()) { if (!game->getGameStarted()) {
return Response::RespGameNotStarted; return Response::RespGameNotStarted;
} }
@ -1857,10 +1688,6 @@ Server_Player::cmdSetCardCounter(const Command_SetCardCounter &cmd, ResponseCont
Response::ResponseCode Response::ResponseCode
Server_Player::cmdIncCardCounter(const Command_IncCardCounter &cmd, ResponseContainer & /*rc*/, GameEventStorage &ges) Server_Player::cmdIncCardCounter(const Command_IncCardCounter &cmd, ResponseContainer & /*rc*/, GameEventStorage &ges)
{ {
if (spectator) {
return Response::RespFunctionNotAllowed;
}
if (!game->getGameStarted()) { if (!game->getGameStarted()) {
return Response::RespGameNotStarted; return Response::RespGameNotStarted;
} }
@ -1897,10 +1724,6 @@ Server_Player::cmdIncCardCounter(const Command_IncCardCounter &cmd, ResponseCont
Response::ResponseCode Response::ResponseCode
Server_Player::cmdIncCounter(const Command_IncCounter &cmd, ResponseContainer & /*rc*/, GameEventStorage &ges) Server_Player::cmdIncCounter(const Command_IncCounter &cmd, ResponseContainer & /*rc*/, GameEventStorage &ges)
{ {
if (spectator) {
return Response::RespFunctionNotAllowed;
}
if (!game->getGameStarted()) { if (!game->getGameStarted()) {
return Response::RespGameNotStarted; return Response::RespGameNotStarted;
} }
@ -1926,10 +1749,6 @@ Server_Player::cmdIncCounter(const Command_IncCounter &cmd, ResponseContainer &
Response::ResponseCode Response::ResponseCode
Server_Player::cmdCreateCounter(const Command_CreateCounter &cmd, ResponseContainer & /*rc*/, GameEventStorage &ges) Server_Player::cmdCreateCounter(const Command_CreateCounter &cmd, ResponseContainer & /*rc*/, GameEventStorage &ges)
{ {
if (spectator) {
return Response::RespFunctionNotAllowed;
}
if (!game->getGameStarted()) { if (!game->getGameStarted()) {
return Response::RespGameNotStarted; return Response::RespGameNotStarted;
} }
@ -1956,10 +1775,6 @@ Server_Player::cmdCreateCounter(const Command_CreateCounter &cmd, ResponseContai
Response::ResponseCode Response::ResponseCode
Server_Player::cmdSetCounter(const Command_SetCounter &cmd, ResponseContainer & /*rc*/, GameEventStorage &ges) Server_Player::cmdSetCounter(const Command_SetCounter &cmd, ResponseContainer & /*rc*/, GameEventStorage &ges)
{ {
if (spectator) {
return Response::RespFunctionNotAllowed;
}
if (!game->getGameStarted()) { if (!game->getGameStarted()) {
return Response::RespGameNotStarted; return Response::RespGameNotStarted;
} }
@ -1985,10 +1800,6 @@ Server_Player::cmdSetCounter(const Command_SetCounter &cmd, ResponseContainer &
Response::ResponseCode Response::ResponseCode
Server_Player::cmdDelCounter(const Command_DelCounter &cmd, ResponseContainer & /*rc*/, GameEventStorage &ges) Server_Player::cmdDelCounter(const Command_DelCounter &cmd, ResponseContainer & /*rc*/, GameEventStorage &ges)
{ {
if (spectator) {
return Response::RespFunctionNotAllowed;
}
if (!game->getGameStarted()) { if (!game->getGameStarted()) {
return Response::RespGameNotStarted; return Response::RespGameNotStarted;
} }
@ -2017,14 +1828,8 @@ Server_Player::cmdNextTurn(const Command_NextTurn & /*cmd*/, ResponseContainer &
return Response::RespGameNotStarted; return Response::RespGameNotStarted;
} }
if (!judge) { if (conceded && !judge) {
if (spectator) { return Response::RespContextError;
return Response::RespFunctionNotAllowed;
}
if (conceded) {
return Response::RespContextError;
}
} }
game->nextTurn(); game->nextTurn();
@ -2040,10 +1845,6 @@ Response::ResponseCode Server_Player::cmdSetActivePhase(const Command_SetActiveP
} }
if (!judge) { if (!judge) {
if (spectator) {
return Response::RespFunctionNotAllowed;
}
if (conceded) { if (conceded) {
return Response::RespContextError; return Response::RespContextError;
} }
@ -2065,7 +1866,7 @@ Server_Player::cmdDumpZone(const Command_DumpZone &cmd, ResponseContainer &rc, G
return Response::RespGameNotStarted; return Response::RespGameNotStarted;
} }
Server_Player *otherPlayer = game->getPlayers().value(cmd.player_id()); Server_Player *otherPlayer = game->getPlayer(cmd.player_id());
if (!otherPlayer) { if (!otherPlayer) {
return Response::RespNameNotFound; return Response::RespNameNotFound;
} }
@ -2141,10 +1942,6 @@ Server_Player::cmdDumpZone(const Command_DumpZone &cmd, ResponseContainer &rc, G
Response::ResponseCode Response::ResponseCode
Server_Player::cmdRevealCards(const Command_RevealCards &cmd, ResponseContainer & /*rc*/, GameEventStorage &ges) Server_Player::cmdRevealCards(const Command_RevealCards &cmd, ResponseContainer & /*rc*/, GameEventStorage &ges)
{ {
if (spectator) {
return Response::RespFunctionNotAllowed;
}
if (!game->getGameStarted()) { if (!game->getGameStarted()) {
return Response::RespGameNotStarted; return Response::RespGameNotStarted;
} }
@ -2153,7 +1950,7 @@ Server_Player::cmdRevealCards(const Command_RevealCards &cmd, ResponseContainer
} }
if (cmd.has_player_id()) { if (cmd.has_player_id()) {
Server_Player *otherPlayer = game->getPlayers().value(cmd.player_id()); Server_Player *otherPlayer = game->getPlayer(cmd.player_id());
if (!otherPlayer) if (!otherPlayer)
return Response::RespNameNotFound; return Response::RespNameNotFound;
} }
@ -2252,9 +2049,9 @@ Server_Player::cmdRevealCards(const Command_RevealCards &cmd, ResponseContainer
ges.enqueueGameEvent(eventOthers, playerId, GameEventStorageItem::SendToOthers); ges.enqueueGameEvent(eventOthers, playerId, GameEventStorageItem::SendToOthers);
} else { } else {
if (cmd.grant_write_access()) { if (cmd.grant_write_access()) {
const QList<int> &playerIds = game->getPlayers().keys(); const QList<int> &participantIds = game->getParticipants().keys();
for (int _playerId : playerIds) { for (int anyParticipantId : participantIds) {
zone->addWritePermission(_playerId); zone->addWritePermission(anyParticipantId);
} }
} }
@ -2304,182 +2101,22 @@ Response::ResponseCode Server_Player::cmdChangeZoneProperties(const Command_Chan
} }
Response::ResponseCode Response::ResponseCode
Server_Player::cmdReverseTurn(const Command_ReverseTurn & /*cmd*/, ResponseContainer & /*rc*/, GameEventStorage &ges) Server_Player::cmdReverseTurn(const Command_ReverseTurn &cmd, ResponseContainer &rc, GameEventStorage &ges)
{ {
if (spectator) {
return Response::RespFunctionNotAllowed;
}
if (!game->getGameStarted()) { if (!judge && conceded) {
return Response::RespGameNotStarted;
}
if (conceded) {
return Response::RespContextError; return Response::RespContextError;
} }
return Server_AbstractParticipant::cmdReverseTurn(cmd, rc, ges);
bool reversedTurn = game->reverseTurnOrder();
Event_ReverseTurn event;
event.set_reversed(reversedTurn);
ges.enqueueGameEvent(event, playerId);
return Response::RespOk;
}
Response::ResponseCode
Server_Player::processGameCommand(const GameCommand &command, ResponseContainer &rc, GameEventStorage &ges)
{
switch ((GameCommand::GameCommandType)getPbExtension(command)) {
case GameCommand::KICK_FROM_GAME:
return cmdKickFromGame(command.GetExtension(Command_KickFromGame::ext), rc, ges);
break;
case GameCommand::LEAVE_GAME:
return cmdLeaveGame(command.GetExtension(Command_LeaveGame::ext), rc, ges);
break;
case GameCommand::GAME_SAY:
return cmdGameSay(command.GetExtension(Command_GameSay::ext), rc, ges);
break;
case GameCommand::SHUFFLE:
return cmdShuffle(command.GetExtension(Command_Shuffle::ext), rc, ges);
break;
case GameCommand::MULLIGAN:
return cmdMulligan(command.GetExtension(Command_Mulligan::ext), rc, ges);
break;
case GameCommand::ROLL_DIE:
return cmdRollDie(command.GetExtension(Command_RollDie::ext), rc, ges);
break;
case GameCommand::DRAW_CARDS:
return cmdDrawCards(command.GetExtension(Command_DrawCards::ext), rc, ges);
break;
case GameCommand::UNDO_DRAW:
return cmdUndoDraw(command.GetExtension(Command_UndoDraw::ext), rc, ges);
break;
case GameCommand::FLIP_CARD:
return cmdFlipCard(command.GetExtension(Command_FlipCard::ext), rc, ges);
break;
case GameCommand::ATTACH_CARD:
return cmdAttachCard(command.GetExtension(Command_AttachCard::ext), rc, ges);
break;
case GameCommand::CREATE_TOKEN:
return cmdCreateToken(command.GetExtension(Command_CreateToken::ext), rc, ges);
break;
case GameCommand::CREATE_ARROW:
return cmdCreateArrow(command.GetExtension(Command_CreateArrow::ext), rc, ges);
break;
case GameCommand::DELETE_ARROW:
return cmdDeleteArrow(command.GetExtension(Command_DeleteArrow::ext), rc, ges);
break;
case GameCommand::SET_CARD_ATTR:
return cmdSetCardAttr(command.GetExtension(Command_SetCardAttr::ext), rc, ges);
break;
case GameCommand::SET_CARD_COUNTER:
return cmdSetCardCounter(command.GetExtension(Command_SetCardCounter::ext), rc, ges);
break;
case GameCommand::INC_CARD_COUNTER:
return cmdIncCardCounter(command.GetExtension(Command_IncCardCounter::ext), rc, ges);
break;
case GameCommand::READY_START:
return cmdReadyStart(command.GetExtension(Command_ReadyStart::ext), rc, ges);
break;
case GameCommand::CONCEDE:
return cmdConcede(command.GetExtension(Command_Concede::ext), rc, ges);
break;
case GameCommand::INC_COUNTER:
return cmdIncCounter(command.GetExtension(Command_IncCounter::ext), rc, ges);
break;
case GameCommand::CREATE_COUNTER:
return cmdCreateCounter(command.GetExtension(Command_CreateCounter::ext), rc, ges);
break;
case GameCommand::SET_COUNTER:
return cmdSetCounter(command.GetExtension(Command_SetCounter::ext), rc, ges);
break;
case GameCommand::DEL_COUNTER:
return cmdDelCounter(command.GetExtension(Command_DelCounter::ext), rc, ges);
break;
case GameCommand::NEXT_TURN:
return cmdNextTurn(command.GetExtension(Command_NextTurn::ext), rc, ges);
break;
case GameCommand::SET_ACTIVE_PHASE:
return cmdSetActivePhase(command.GetExtension(Command_SetActivePhase::ext), rc, ges);
break;
case GameCommand::DUMP_ZONE:
return cmdDumpZone(command.GetExtension(Command_DumpZone::ext), rc, ges);
break;
case GameCommand::REVEAL_CARDS:
return cmdRevealCards(command.GetExtension(Command_RevealCards::ext), rc, ges);
break;
case GameCommand::MOVE_CARD:
return cmdMoveCard(command.GetExtension(Command_MoveCard::ext), rc, ges);
break;
case GameCommand::SET_SIDEBOARD_PLAN:
return cmdSetSideboardPlan(command.GetExtension(Command_SetSideboardPlan::ext), rc, ges);
break;
case GameCommand::DECK_SELECT:
return cmdDeckSelect(command.GetExtension(Command_DeckSelect::ext), rc, ges);
break;
case GameCommand::SET_SIDEBOARD_LOCK:
return cmdSetSideboardLock(command.GetExtension(Command_SetSideboardLock::ext), rc, ges);
break;
case GameCommand::CHANGE_ZONE_PROPERTIES:
return cmdChangeZoneProperties(command.GetExtension(Command_ChangeZoneProperties::ext), rc, ges);
break;
case GameCommand::UNCONCEDE:
return cmdUnconcede(command.GetExtension(Command_Unconcede::ext), rc, ges);
break;
case GameCommand::JUDGE:
return cmdJudge(command.GetExtension(Command_Judge::ext), rc, ges);
break;
case GameCommand::REVERSE_TURN:
return cmdReverseTurn(command.GetExtension(Command_ReverseTurn::ext), rc, ges);
break;
default:
return Response::RespInvalidCommand;
}
}
void Server_Player::sendGameEvent(const GameEventContainer &cont)
{
QMutexLocker locker(&playerMutex);
if (userInterface) {
userInterface->sendProtocolItem(cont);
}
}
void Server_Player::setUserInterface(Server_AbstractUserInterface *_userInterface)
{
playerMutex.lock();
userInterface = _userInterface;
playerMutex.unlock();
pingTime = _userInterface ? 0 : -1;
Event_PlayerPropertiesChanged event;
event.mutable_player_properties()->set_ping_seconds(pingTime);
GameEventStorage ges;
ges.setGameEventContext(Context_ConnectionStateChanged());
ges.enqueueGameEvent(event, playerId);
ges.sendToGame(game);
}
void Server_Player::disconnectClient()
{
if (!(userInfo->user_level() & ServerInfo_User::IsRegistered) || spectator) {
game->removePlayer(this, Event_Leave::USER_DISCONNECTED);
} else {
setUserInterface(nullptr);
}
} }
void Server_Player::getInfo(ServerInfo_Player *info, void Server_Player::getInfo(ServerInfo_Player *info,
Server_Player *playerWhosAsking, Server_AbstractParticipant *recipient,
bool omniscient, bool omniscient,
bool withUserInfo) bool withUserInfo)
{ {
getProperties(*info->mutable_properties(), withUserInfo); getProperties(*info->mutable_properties(), withUserInfo);
if (playerWhosAsking == this) { if (recipient == this) {
if (deck) { if (deck) {
info->set_deck_list(deck->writeToString_Native().toStdString()); info->set_deck_list(deck->writeToString_Native().toStdString());
} }
@ -2494,6 +2131,16 @@ void Server_Player::getInfo(ServerInfo_Player *info,
} }
for (Server_CardZone *zone : zones) { for (Server_CardZone *zone : zones) {
zone->getInfo(info->add_zone_list(), playerWhosAsking, omniscient); zone->getInfo(info->add_zone_list(), recipient, omniscient);
}
}
void Server_Player::getPlayerProperties(ServerInfo_PlayerProperties &result)
{
result.set_conceded(conceded);
result.set_sideboard_locked(sideboardLocked);
result.set_ready_start(readyStart);
if (deck) {
result.set_deck_hash(deck->getDeckHash().toStdString());
} }
} }

View file

@ -2,13 +2,10 @@
#define PLAYER_H #define PLAYER_H
#include "../../serverinfo_user_container.h" #include "../../serverinfo_user_container.h"
#include "pb/card_attributes.pb.h" #include "server_abstract_participant.h"
#include "pb/response.pb.h"
#include "server_arrowtarget.h"
#include <QList> #include <QList>
#include <QMap> #include <QMap>
#include <QMutex>
#include <QString> #include <QString>
class DeckList; class DeckList;
@ -28,85 +25,36 @@ class GameEventStorage;
class ResponseContainer; class ResponseContainer;
class GameCommand; class GameCommand;
class Command_KickFromGame; class Server_Player : public Server_AbstractParticipant
class Command_LeaveGame;
class Command_GameSay;
class Command_Shuffle;
class Command_Mulligan;
class Command_RollDie;
class Command_DrawCards;
class Command_UndoDraw;
class Command_FlipCard;
class Command_AttachCard;
class Command_CreateToken;
class Command_CreateArrow;
class Command_DeleteArrow;
class Command_SetCardAttr;
class Command_SetCardCounter;
class Command_IncCardCounter;
class Command_ReadyStart;
class Command_Concede;
class Command_Unconcede;
class Command_Judge;
class Command_IncCounter;
class Command_CreateCounter;
class Command_SetCounter;
class Command_DelCounter;
class Command_NextTurn;
class Command_SetActivePhase;
class Command_DumpZone;
class Command_RevealCards;
class Command_ReverseTurn;
class Command_MoveCard;
class Command_SetSideboardPlan;
class Command_DeckSelect;
class Command_SetSideboardLock;
class Command_ChangeZoneProperties;
class Server_Player : public Server_ArrowTarget, public ServerInfo_User_Container
{ {
Q_OBJECT Q_OBJECT
private: private:
class MoveCardCompareFunctor; class MoveCardCompareFunctor;
Server_Game *game;
Server_AbstractUserInterface *userInterface;
DeckList *deck; DeckList *deck;
QMap<QString, Server_CardZone *> zones; QMap<QString, Server_CardZone *> zones;
QMap<int, Server_Counter *> counters; QMap<int, Server_Counter *> counters;
QMap<int, Server_Arrow *> arrows; QMap<int, Server_Arrow *> arrows;
QList<int> lastDrawList; QList<int> lastDrawList;
int pingTime;
int playerId;
bool spectator;
bool judge;
int nextCardId; int nextCardId;
bool readyStart; bool readyStart;
bool conceded; bool conceded;
bool sideboardLocked; bool sideboardLocked;
void revealTopCardIfNeeded(Server_CardZone *zone, GameEventStorage &ges); void revealTopCardIfNeeded(Server_CardZone *zone, GameEventStorage &ges);
void sendCreateTokenEvents(Server_CardZone *zone, Server_Card *card, int xCoord, int yCoord, GameEventStorage &ges); void sendCreateTokenEvents(Server_CardZone *zone, Server_Card *card, int xCoord, int yCoord, GameEventStorage &ges);
void getPlayerProperties(ServerInfo_PlayerProperties &result);
public: public:
mutable QMutex playerMutex;
Server_Player(Server_Game *_game, Server_Player(Server_Game *_game,
int _playerId, int _playerId,
const ServerInfo_User &_userInfo, const ServerInfo_User &_userInfo,
bool _spectator,
bool _judge, bool _judge,
Server_AbstractUserInterface *_handler); Server_AbstractUserInterface *_handler);
~Server_Player() override; ~Server_Player() override;
void prepareDestroy(); void prepareDestroy() override;
const DeckList *getDeckList() const const DeckList *getDeckList() const
{ {
return deck; return deck;
} }
Server_AbstractUserInterface *getUserInterface() const
{
return userInterface;
}
void setUserInterface(Server_AbstractUserInterface *_userInterface);
void disconnectClient();
bool getReadyStart() const bool getReadyStart() const
{ {
return readyStart; return readyStart;
@ -115,18 +63,6 @@ public:
{ {
readyStart = _readyStart; readyStart = _readyStart;
} }
int getPlayerId() const
{
return playerId;
}
bool getSpectator() const
{
return spectator;
}
bool getJudge() const
{
return judge;
}
bool getConceded() const bool getConceded() const
{ {
return conceded; return conceded;
@ -136,10 +72,6 @@ public:
conceded = _conceded; conceded = _conceded;
} }
Server_Game *getGame() const
{
return game;
}
const QMap<QString, Server_CardZone *> &getZones() const const QMap<QString, Server_CardZone *> &getZones() const
{ {
return zones; return zones;
@ -153,16 +85,6 @@ public:
return arrows; return arrows;
} }
int getPingTime() const
{
return pingTime;
}
void setPingTime(int _pingTime)
{
pingTime = _pingTime;
}
void getProperties(ServerInfo_PlayerProperties &result, bool withUserInfo);
int newCardId(); int newCardId();
int newCounterId() const; int newCounterId() const;
int newArrowId() const; int newArrowId() const;
@ -195,54 +117,72 @@ public:
const QString &attrValue, const QString &attrValue,
Server_Card *unzonedCard = nullptr); Server_Card *unzonedCard = nullptr);
Response::ResponseCode cmdLeaveGame(const Command_LeaveGame &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode Response::ResponseCode
cmdKickFromGame(const Command_KickFromGame &cmd, ResponseContainer &rc, GameEventStorage &ges); cmdConcede(const Command_Concede &cmd, ResponseContainer &rc, GameEventStorage &ges) override;
Response::ResponseCode cmdConcede(const Command_Concede &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdUnconcede(const Command_Unconcede &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdJudge(const Command_Judge &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdReadyStart(const Command_ReadyStart &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdDeckSelect(const Command_DeckSelect &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode Response::ResponseCode
cmdSetSideboardPlan(const Command_SetSideboardPlan &cmd, ResponseContainer &rc, GameEventStorage &ges); cmdUnconcede(const Command_Unconcede &cmd, ResponseContainer &rc, GameEventStorage &ges) override;
Response::ResponseCode Response::ResponseCode
cmdSetSideboardLock(const Command_SetSideboardLock &cmd, ResponseContainer &rc, GameEventStorage &ges); cmdReadyStart(const Command_ReadyStart &cmd, ResponseContainer &rc, GameEventStorage &ges) override;
Response::ResponseCode cmdGameSay(const Command_GameSay &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdShuffle(const Command_Shuffle &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdMulligan(const Command_Mulligan &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdRollDie(const Command_RollDie &cmd, ResponseContainer &rc, GameEventStorage &ges) const;
Response::ResponseCode cmdDrawCards(const Command_DrawCards &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdUndoDraw(const Command_UndoDraw &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdMoveCard(const Command_MoveCard &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdFlipCard(const Command_FlipCard &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdAttachCard(const Command_AttachCard &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdCreateToken(const Command_CreateToken &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdCreateArrow(const Command_CreateArrow &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdDeleteArrow(const Command_DeleteArrow &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdSetCardAttr(const Command_SetCardAttr &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode Response::ResponseCode
cmdSetCardCounter(const Command_SetCardCounter &cmd, ResponseContainer &rc, GameEventStorage &ges); cmdDeckSelect(const Command_DeckSelect &cmd, ResponseContainer &rc, GameEventStorage &ges) override;
Response::ResponseCode Response::ResponseCode
cmdIncCardCounter(const Command_IncCardCounter &cmd, ResponseContainer &rc, GameEventStorage &ges); cmdSetSideboardPlan(const Command_SetSideboardPlan &cmd, ResponseContainer &rc, GameEventStorage &ges) override;
Response::ResponseCode cmdIncCounter(const Command_IncCounter &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode Response::ResponseCode
cmdCreateCounter(const Command_CreateCounter &cmd, ResponseContainer &rc, GameEventStorage &ges); cmdSetSideboardLock(const Command_SetSideboardLock &cmd, ResponseContainer &rc, GameEventStorage &ges) override;
Response::ResponseCode cmdSetCounter(const Command_SetCounter &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdDelCounter(const Command_DelCounter &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdNextTurn(const Command_NextTurn &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode Response::ResponseCode
cmdSetActivePhase(const Command_SetActivePhase &cmd, ResponseContainer &rc, GameEventStorage &ges); cmdShuffle(const Command_Shuffle &cmd, ResponseContainer &rc, GameEventStorage &ges) override;
Response::ResponseCode cmdDumpZone(const Command_DumpZone &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdRevealCards(const Command_RevealCards &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode Response::ResponseCode
cmdReverseTurn(const Command_ReverseTurn & /*cmd*/, ResponseContainer & /*rc*/, GameEventStorage &ges); cmdMulligan(const Command_Mulligan &cmd, ResponseContainer &rc, GameEventStorage &ges) override;
Response::ResponseCode Response::ResponseCode
cmdChangeZoneProperties(const Command_ChangeZoneProperties &cmd, ResponseContainer &rc, GameEventStorage &ges); cmdRollDie(const Command_RollDie &cmd, ResponseContainer &rc, GameEventStorage &ges) const override;
Response::ResponseCode
cmdDrawCards(const Command_DrawCards &cmd, ResponseContainer &rc, GameEventStorage &ges) override;
Response::ResponseCode
cmdUndoDraw(const Command_UndoDraw &cmd, ResponseContainer &rc, GameEventStorage &ges) override;
Response::ResponseCode
cmdMoveCard(const Command_MoveCard &cmd, ResponseContainer &rc, GameEventStorage &ges) override;
Response::ResponseCode
cmdFlipCard(const Command_FlipCard &cmd, ResponseContainer &rc, GameEventStorage &ges) override;
Response::ResponseCode
cmdAttachCard(const Command_AttachCard &cmd, ResponseContainer &rc, GameEventStorage &ges) override;
Response::ResponseCode
cmdCreateToken(const Command_CreateToken &cmd, ResponseContainer &rc, GameEventStorage &ges) override;
Response::ResponseCode
cmdCreateArrow(const Command_CreateArrow &cmd, ResponseContainer &rc, GameEventStorage &ges) override;
Response::ResponseCode
cmdDeleteArrow(const Command_DeleteArrow &cmd, ResponseContainer &rc, GameEventStorage &ges) override;
Response::ResponseCode
cmdSetCardAttr(const Command_SetCardAttr &cmd, ResponseContainer &rc, GameEventStorage &ges) override;
Response::ResponseCode
cmdSetCardCounter(const Command_SetCardCounter &cmd, ResponseContainer &rc, GameEventStorage &ges) override;
Response::ResponseCode
cmdIncCardCounter(const Command_IncCardCounter &cmd, ResponseContainer &rc, GameEventStorage &ges) override;
Response::ResponseCode
cmdIncCounter(const Command_IncCounter &cmd, ResponseContainer &rc, GameEventStorage &ges) override;
Response::ResponseCode
cmdCreateCounter(const Command_CreateCounter &cmd, ResponseContainer &rc, GameEventStorage &ges) override;
Response::ResponseCode
cmdSetCounter(const Command_SetCounter &cmd, ResponseContainer &rc, GameEventStorage &ges) override;
Response::ResponseCode
cmdDelCounter(const Command_DelCounter &cmd, ResponseContainer &rc, GameEventStorage &ges) override;
Response::ResponseCode
cmdNextTurn(const Command_NextTurn &cmd, ResponseContainer &rc, GameEventStorage &ges) override;
Response::ResponseCode
cmdSetActivePhase(const Command_SetActivePhase &cmd, ResponseContainer &rc, GameEventStorage &ges) override;
Response::ResponseCode
cmdDumpZone(const Command_DumpZone &cmd, ResponseContainer &rc, GameEventStorage &ges) override;
Response::ResponseCode
cmdRevealCards(const Command_RevealCards &cmd, ResponseContainer &rc, GameEventStorage &ges) override;
Response::ResponseCode
cmdReverseTurn(const Command_ReverseTurn & /*cmd*/, ResponseContainer & /*rc*/, GameEventStorage &ges) override;
Response::ResponseCode cmdChangeZoneProperties(const Command_ChangeZoneProperties &cmd,
ResponseContainer &rc,
GameEventStorage &ges) override;
Response::ResponseCode processGameCommand(const GameCommand &command, ResponseContainer &rc, GameEventStorage &ges); void getInfo(ServerInfo_Player *info,
void sendGameEvent(const GameEventContainer &event); Server_AbstractParticipant *playerWhosAsking,
bool omniscient,
void getInfo(ServerInfo_Player *info, Server_Player *playerWhosAsking, bool omniscient, bool withUserInfo); bool withUserInfo) override;
}; };
#endif #endif

View file

@ -329,11 +329,11 @@ void Server::externalUserLeft(const QString &userName)
continue; continue;
QMutexLocker gameLocker(&game->gameMutex); QMutexLocker gameLocker(&game->gameMutex);
Server_Player *player = game->getPlayers().value(userGamesIterator.value().second); auto *participant = game->getParticipants().value(userGamesIterator.value().second);
if (!player) if (!participant)
continue; continue;
player->disconnectClient(); participant->disconnectClient();
} }
roomsLock.unlock(); roomsLock.unlock();
@ -480,8 +480,8 @@ void Server::externalGameCommandContainerReceived(const CommandContainer &cont,
} }
QMutexLocker gameLocker(&game->gameMutex); QMutexLocker gameLocker(&game->gameMutex);
Server_Player *player = game->getPlayers().value(playerId); auto *participant = game->getParticipants().value(playerId);
if (!player) { if (!participant) {
qDebug() << "externalGameCommandContainerReceived: player id=" << playerId << "not found"; qDebug() << "externalGameCommandContainerReceived: player id=" << playerId << "not found";
throw Response::RespNotInRoom; throw Response::RespNotInRoom;
} }
@ -491,7 +491,7 @@ void Server::externalGameCommandContainerReceived(const CommandContainer &cont,
const GameCommand &sc = cont.game_command(i); const GameCommand &sc = cont.game_command(i);
qDebug() << "[ISL]" << getSafeDebugString(sc); qDebug() << "[ISL]" << getSafeDebugString(sc);
Response::ResponseCode resp = player->processGameCommand(sc, responseContainer, ges); Response::ResponseCode resp = participant->processGameCommand(sc, responseContainer, ges);
if (resp != Response::RespOk) if (resp != Response::RespOk)
finalResponseCode = resp; finalResponseCode = resp;
@ -499,9 +499,7 @@ void Server::externalGameCommandContainerReceived(const CommandContainer &cont,
ges.sendToGame(game); ges.sendToGame(game);
if (finalResponseCode != Response::RespNothing) { if (finalResponseCode != Response::RespNothing) {
player->playerMutex.lock(); participant->getUserInterface()->sendResponseContainer(responseContainer, finalResponseCode);
player->getUserInterface()->sendResponseContainer(responseContainer, finalResponseCode);
player->playerMutex.unlock();
} }
} catch (Response::ResponseCode code) { } catch (Response::ResponseCode code) {
Response response; Response response;

View file

@ -103,14 +103,14 @@ void Server_AbstractUserInterface::joinPersistentGames(ResponseContainer &rc)
continue; continue;
QMutexLocker gameLocker(&game->gameMutex); QMutexLocker gameLocker(&game->gameMutex);
Server_Player *player = game->getPlayers().value(pr.getPlayerId()); auto *participant = game->getParticipants().value(pr.getPlayerId());
if (!player) if (!participant)
continue; continue;
player->setUserInterface(this); participant->setUserInterface(this);
playerAddedToGame(game->getGameId(), room->getId(), player->getPlayerId()); playerAddedToGame(game->getGameId(), room->getId(), participant->getPlayerId());
game->createGameJoinedEvent(player, rc, true); game->createGameJoinedEvent(participant, rc, true);
} }
server->roomsLock.unlock(); server->roomsLock.unlock();
} }

View file

@ -73,7 +73,7 @@ void Server_ProtocolHandler::prepareDestroy()
continue; continue;
} }
game->gameMutex.lock(); game->gameMutex.lock();
Server_Player *p = game->getPlayers().value(gameIterator.value().second); Server_Player *p = game->getPlayer(gameIterator.value().second);
if (!p) { if (!p) {
game->gameMutex.unlock(); game->gameMutex.unlock();
room->gamesLock.unlock(); room->gamesLock.unlock();
@ -257,8 +257,8 @@ Response::ResponseCode Server_ProtocolHandler::processGameCommandContainer(const
} }
QMutexLocker gameLocker(&game->gameMutex); QMutexLocker gameLocker(&game->gameMutex);
Server_Player *player = game->getPlayers().value(roomIdAndPlayerId.second); auto *participant = game->getParticipants().value(roomIdAndPlayerId.second);
if (!player) if (!participant)
return Response::RespNotInRoom; return Response::RespNotInRoom;
resetIdleTimer(); resetIdleTimer();
@ -289,7 +289,7 @@ Response::ResponseCode Server_ProtocolHandler::processGameCommandContainer(const
} }
} }
Response::ResponseCode resp = player->processGameCommand(sc, rc, ges); Response::ResponseCode resp = participant->processGameCommand(sc, rc, ges);
if (resp != Response::RespOk) if (resp != Response::RespOk)
finalResponseCode = resp; finalResponseCode = resp;