A network game is now automatically filled up with computer players up to the configured maximum number of players. This should maybe be optional?
This commit is contained in:
+3
-3
@@ -194,8 +194,8 @@ boost::shared_ptr<PlayerInterface> Game::getPlayerByUniqueId(unsigned id)
|
||||
|
||||
boost::shared_ptr<PlayerInterface> Game::getCurrentPlayer()
|
||||
{
|
||||
int curPlayerNum = getCurrentHand()->getCurrentBeRo()->getPlayersTurn();
|
||||
assert(curPlayerNum < getStartQuantityPlayers());
|
||||
return getPlayerArray()[curPlayerNum];
|
||||
int curPlayerNum = getCurrentHand()->getCurrentBeRo()->getPlayersTurn();
|
||||
assert(curPlayerNum < getStartQuantityPlayers());
|
||||
return getPlayerArray()[curPlayerNum];
|
||||
}
|
||||
|
||||
|
||||
@@ -30,6 +30,8 @@
|
||||
#include <playerinterface.h>
|
||||
#include <handinterface.h>
|
||||
|
||||
#include <sstream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
#define SERVER_WAIT_TIMEOUT_MSEC 50
|
||||
@@ -41,10 +43,29 @@ using namespace std;
|
||||
#define SERVER_DEAL_ADD_ALL_IN_DELAY_SEC 2
|
||||
#define SERVER_SHOW_CARDS_DELAY_SEC 2
|
||||
#define SERVER_PLAYER_TIMEOUT_ADD_DELAY_SEC 2
|
||||
#define SERVER_COMPUTER_ACTION_DELAY_SEC 2
|
||||
|
||||
#define SERVER_COMPUTER_PLAYER_NAME "Computer"
|
||||
|
||||
// Helper functions
|
||||
// TODO: these are hacks.
|
||||
|
||||
static void SendPlayerAction(ServerRecvThread &server, boost::shared_ptr<PlayerInterface> player)
|
||||
{
|
||||
Game &curGame = server.GetGame();
|
||||
assert(player);
|
||||
|
||||
boost::shared_ptr<NetPacket> notifyActionDone(new NetPacketPlayersActionDone);
|
||||
NetPacketPlayersActionDone::Data actionDoneData;
|
||||
actionDoneData.gameState = static_cast<GameState>(curGame.getCurrentHand()->getActualRound());
|
||||
actionDoneData.playerId = player->getMyUniqueID();
|
||||
actionDoneData.playerAction = static_cast<PlayerAction>(player->getMyAction());
|
||||
actionDoneData.totalPlayerBet = player->getMySet();
|
||||
actionDoneData.playerMoney = player->getMyCash();
|
||||
static_cast<NetPacketPlayersActionDone *>(notifyActionDone.get())->SetData(actionDoneData);
|
||||
server.SendToAllPlayers(notifyActionDone);
|
||||
}
|
||||
|
||||
static void SendNewRoundCards(ServerRecvThread &server, Game &curGame, int state)
|
||||
{
|
||||
// TODO: no switch needed here if game states are polymorphic
|
||||
@@ -256,8 +277,10 @@ ServerRecvStateInit::InternalProcess(ServerRecvThread &server, SessionWrapper se
|
||||
}
|
||||
|
||||
// Check whether the player name is correct.
|
||||
// Paranoia check, this is also done in netpacket.
|
||||
if (joinGameData.playerName.empty() || joinGameData.playerName.size() > MAX_NAME_SIZE)
|
||||
// Partly, this is also done in netpacket.
|
||||
// However, some disallowed names are checked only here.
|
||||
if (joinGameData.playerName.empty() || joinGameData.playerName.size() > MAX_NAME_SIZE
|
||||
|| joinGameData.playerName.substr(0, sizeof(SERVER_COMPUTER_PLAYER_NAME) - 1) == SERVER_COMPUTER_PLAYER_NAME)
|
||||
{
|
||||
server.SessionError(session, ERR_NET_INVALID_PLAYER_NAME);
|
||||
return retVal;
|
||||
@@ -297,26 +320,12 @@ ServerRecvStateInit::InternalProcess(ServerRecvThread &server, SessionWrapper se
|
||||
PlayerDataList::iterator player_end = tmpPlayerList.end();
|
||||
while (player_i != player_end)
|
||||
{
|
||||
boost::shared_ptr<NetPacket> otherPlayerJoined(new NetPacketPlayerJoined);
|
||||
NetPacketPlayerJoined::Data otherPlayerJoinedData;
|
||||
otherPlayerJoinedData.playerId = (*player_i)->GetUniqueId();
|
||||
otherPlayerJoinedData.playerName = (*player_i)->GetName();
|
||||
otherPlayerJoinedData.ptype = (*player_i)->GetType();
|
||||
static_cast<NetPacketPlayerJoined *>(otherPlayerJoined.get())->SetData(otherPlayerJoinedData);
|
||||
server.GetSender().Send(session.sessionData->GetSocket(), otherPlayerJoined);
|
||||
|
||||
server.GetSender().Send(session.sessionData->GetSocket(), CreateNetPacketPlayerJoined(*(*player_i)));
|
||||
++player_i;
|
||||
}
|
||||
|
||||
// Send "Player Joined" to other fully connected clients.
|
||||
boost::shared_ptr<NetPacket> thisPlayerJoined(new NetPacketPlayerJoined);
|
||||
NetPacketPlayerJoined::Data thisPlayerJoinedData;
|
||||
thisPlayerJoinedData.playerId = tmpPlayerData->GetUniqueId();
|
||||
thisPlayerJoinedData.playerName = tmpPlayerData->GetName();
|
||||
thisPlayerJoinedData.ptype = tmpPlayerData->GetType();
|
||||
thisPlayerJoinedData.prights = tmpPlayerData->GetRights();
|
||||
static_cast<NetPacketPlayerJoined *>(thisPlayerJoined.get())->SetData(thisPlayerJoinedData);
|
||||
server.SendToAllPlayers(thisPlayerJoined);
|
||||
server.SendToAllPlayers(CreateNetPacketPlayerJoined(*tmpPlayerData));
|
||||
|
||||
// Set player data for session.
|
||||
server.SetSessionPlayerData(session.sessionData, tmpPlayerData);
|
||||
@@ -326,21 +335,20 @@ ServerRecvStateInit::InternalProcess(ServerRecvThread &server, SessionWrapper se
|
||||
}
|
||||
else if (packet->ToNetPacketStartEvent())
|
||||
{
|
||||
boost::shared_ptr<PlayerData> tmpPlayerData(
|
||||
new PlayerData(m_curUniquePlayerId++, 0, PLAYER_TYPE_COMPUTER, PLAYER_RIGHTS_NORMAL));
|
||||
tmpPlayerData->SetName("Computer");
|
||||
int remainingSlots = server.GetGameData().maxNumberOfPlayers - server.GetCurNumberOfPlayers();
|
||||
for (int i = 1; i <= remainingSlots; i++)
|
||||
{
|
||||
boost::shared_ptr<PlayerData> tmpPlayerData(
|
||||
new PlayerData(m_curUniquePlayerId++, 0, PLAYER_TYPE_COMPUTER, PLAYER_RIGHTS_NORMAL));
|
||||
|
||||
// Send "Player Joined" to other fully connected clients.
|
||||
boost::shared_ptr<NetPacket> thisPlayerJoined(new NetPacketPlayerJoined);
|
||||
NetPacketPlayerJoined::Data thisPlayerJoinedData;
|
||||
thisPlayerJoinedData.playerId = tmpPlayerData->GetUniqueId();
|
||||
thisPlayerJoinedData.playerName = tmpPlayerData->GetName();
|
||||
thisPlayerJoinedData.ptype = tmpPlayerData->GetType();
|
||||
thisPlayerJoinedData.prights = tmpPlayerData->GetRights();
|
||||
static_cast<NetPacketPlayerJoined *>(thisPlayerJoined.get())->SetData(thisPlayerJoinedData);
|
||||
server.SendToAllPlayers(thisPlayerJoined);
|
||||
ostringstream name;
|
||||
name << SERVER_COMPUTER_PLAYER_NAME << i;
|
||||
tmpPlayerData->SetName(name.str());
|
||||
|
||||
server.AddComputerPlayer(tmpPlayerData);
|
||||
// Send "Player Joined" to other fully connected clients.
|
||||
server.SendToAllPlayers(CreateNetPacketPlayerJoined(*tmpPlayerData));
|
||||
server.AddComputerPlayer(tmpPlayerData);
|
||||
}
|
||||
|
||||
server.InternalStartGame();
|
||||
server.SetState(SERVER_START_GAME_STATE::Instance());
|
||||
@@ -360,6 +368,19 @@ ServerRecvStateInit::InternalProcess(ServerRecvThread &server, SessionWrapper se
|
||||
return retVal;
|
||||
}
|
||||
|
||||
boost::shared_ptr<NetPacket>
|
||||
ServerRecvStateInit::CreateNetPacketPlayerJoined(const PlayerData &playerData)
|
||||
{
|
||||
boost::shared_ptr<NetPacket> thisPlayerJoined(new NetPacketPlayerJoined);
|
||||
NetPacketPlayerJoined::Data thisPlayerJoinedData;
|
||||
thisPlayerJoinedData.playerId = playerData.GetUniqueId();
|
||||
thisPlayerJoinedData.playerName = playerData.GetName();
|
||||
thisPlayerJoinedData.ptype = playerData.GetType();
|
||||
thisPlayerJoinedData.prights = playerData.GetRights();
|
||||
static_cast<NetPacketPlayerJoined *>(thisPlayerJoined.get())->SetData(thisPlayerJoinedData);
|
||||
return thisPlayerJoined;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
AbstractServerRecvStateRunning::AbstractServerRecvStateRunning()
|
||||
@@ -761,11 +782,8 @@ ServerRecvStateWaitPlayerAction::Process(ServerRecvThread &server)
|
||||
// If the player is computer controlled, let the engine act.
|
||||
if (tmpPlayer->getMyType() == PLAYER_TYPE_COMPUTER)
|
||||
{
|
||||
tmpPlayer->action();
|
||||
SendPlayerAction(server, tmpPlayer);
|
||||
|
||||
server.SetState(ServerRecvStateStartRound::Instance());
|
||||
retVal = MSG_NET_GAME_SERVER_ACTION;
|
||||
server.SetState(ServerRecvStateComputerAction::Instance());
|
||||
retVal = MSG_SOCK_INTERNAL_PENDING;
|
||||
}
|
||||
// If the player we are waiting for left, continue without him.
|
||||
else if (!server.IsPlayerConnected(tmpPlayer->getMyName()))
|
||||
@@ -837,21 +855,50 @@ ServerRecvStateWaitPlayerAction::PerformPlayerAction(ServerRecvThread &server, b
|
||||
SendPlayerAction(server, player);
|
||||
}
|
||||
|
||||
void
|
||||
ServerRecvStateWaitPlayerAction::SendPlayerAction(ServerRecvThread &server, boost::shared_ptr<PlayerInterface> player)
|
||||
{
|
||||
Game &curGame = server.GetGame();
|
||||
assert(player);
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
boost::shared_ptr<NetPacket> notifyActionDone(new NetPacketPlayersActionDone);
|
||||
NetPacketPlayersActionDone::Data actionDoneData;
|
||||
actionDoneData.gameState = static_cast<GameState>(curGame.getCurrentHand()->getActualRound());
|
||||
actionDoneData.playerId = player->getMyUniqueID();
|
||||
actionDoneData.playerAction = static_cast<PlayerAction>(player->getMyAction());
|
||||
actionDoneData.totalPlayerBet = player->getMySet();
|
||||
actionDoneData.playerMoney = player->getMyCash();
|
||||
static_cast<NetPacketPlayersActionDone *>(notifyActionDone.get())->SetData(actionDoneData);
|
||||
server.SendToAllPlayers(notifyActionDone);
|
||||
boost::thread_specific_ptr<ServerRecvStateComputerAction> ServerRecvStateComputerAction::Ptr;
|
||||
|
||||
ServerRecvStateComputerAction &
|
||||
ServerRecvStateComputerAction::Instance()
|
||||
{
|
||||
if (!Ptr.get())
|
||||
Ptr.reset(new ServerRecvStateComputerAction);
|
||||
|
||||
return *Ptr;
|
||||
}
|
||||
|
||||
ServerRecvStateComputerAction::ServerRecvStateComputerAction()
|
||||
{
|
||||
}
|
||||
|
||||
ServerRecvStateComputerAction::~ServerRecvStateComputerAction()
|
||||
{
|
||||
}
|
||||
|
||||
int
|
||||
ServerRecvStateComputerAction::Process(ServerRecvThread &server)
|
||||
{
|
||||
int retVal = AbstractServerRecvStateReceiving::Process(server);
|
||||
|
||||
if (GetTimer().elapsed().total_seconds() >= SERVER_COMPUTER_ACTION_DELAY_SEC)
|
||||
{
|
||||
boost::shared_ptr<PlayerInterface> tmpPlayer = server.GetGame().getCurrentPlayer();
|
||||
|
||||
tmpPlayer->action();
|
||||
SendPlayerAction(server, tmpPlayer);
|
||||
|
||||
server.SetState(ServerRecvStateStartRound::Instance());
|
||||
retVal = MSG_NET_GAME_SERVER_ACTION;
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
int
|
||||
ServerRecvStateComputerAction::InternalProcess(ServerRecvThread &server, SessionWrapper session, boost::shared_ptr<NetPacket> packet)
|
||||
{
|
||||
return MSG_SOCK_INTERNAL_PENDING;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
@@ -120,6 +120,8 @@ protected:
|
||||
|
||||
virtual int InternalProcess(ServerRecvThread &server, SessionWrapper session, boost::shared_ptr<NetPacket> packet);
|
||||
|
||||
static boost::shared_ptr<NetPacket> CreateNetPacketPlayerJoined(const PlayerData &playerData);
|
||||
|
||||
private:
|
||||
|
||||
u_int16_t m_curUniquePlayerId;
|
||||
@@ -220,13 +222,36 @@ protected:
|
||||
virtual int InternalProcess(ServerRecvThread &server, SessionWrapper session, boost::shared_ptr<NetPacket> packet);
|
||||
|
||||
static void PerformPlayerAction(ServerRecvThread &server, boost::shared_ptr<PlayerInterface> player, PlayerAction action, int bet);
|
||||
static void SendPlayerAction(ServerRecvThread &server, boost::shared_ptr<PlayerInterface> player);
|
||||
|
||||
private:
|
||||
|
||||
static boost::thread_specific_ptr<ServerRecvStateWaitPlayerAction> Ptr;
|
||||
};
|
||||
|
||||
// State: Delay and computer action
|
||||
class ServerRecvStateComputerAction : public AbstractServerRecvStateReceiving, public AbstractServerRecvStateRunning, public AbstractServerRecvStateTimer
|
||||
{
|
||||
public:
|
||||
// Access the state singleton.
|
||||
static ServerRecvStateComputerAction &Instance();
|
||||
|
||||
virtual ~ServerRecvStateComputerAction();
|
||||
|
||||
// Overwrite default processing
|
||||
virtual int Process(ServerRecvThread &server);
|
||||
|
||||
protected:
|
||||
|
||||
// Protected constructor - this is a singleton.
|
||||
ServerRecvStateComputerAction();
|
||||
|
||||
virtual int InternalProcess(ServerRecvThread &server, SessionWrapper session, boost::shared_ptr<NetPacket> packet);
|
||||
|
||||
private:
|
||||
|
||||
static boost::thread_specific_ptr<ServerRecvStateComputerAction> Ptr;
|
||||
};
|
||||
|
||||
// State: Delay after dealing cards
|
||||
class ServerRecvStateDealCardsDelay : public AbstractServerRecvStateReceiving, public AbstractServerRecvStateRunning, public AbstractServerRecvStateTimer
|
||||
{
|
||||
|
||||
@@ -72,6 +72,8 @@ public:
|
||||
void SendToAllPlayers(boost::shared_ptr<NetPacket> packet);
|
||||
void SendToAllButOnePlayers(boost::shared_ptr<NetPacket> packet, SOCKET except);
|
||||
|
||||
Game &GetGame();
|
||||
|
||||
protected:
|
||||
|
||||
struct Notification
|
||||
@@ -128,7 +130,6 @@ protected:
|
||||
SenderThread &GetSender();
|
||||
ReceiverHelper &GetReceiver();
|
||||
|
||||
Game &GetGame();
|
||||
const GameData &GetGameData() const;
|
||||
const StartData &GetStartData() const;
|
||||
void SetStartData(const StartData &startData);
|
||||
@@ -175,6 +176,7 @@ friend class ServerRecvStateStartGame;
|
||||
friend class ServerRecvStateStartHand;
|
||||
friend class ServerRecvStateStartRound;
|
||||
friend class ServerRecvStateWaitPlayerAction;
|
||||
friend class ServerRecvStateComputerAction;
|
||||
friend class ServerRecvStateShowCardsDelay;
|
||||
friend class ServerRecvStateDealCardsDelay;
|
||||
friend class ServerRecvStateNextHandDelay;
|
||||
|
||||
Reference in New Issue
Block a user