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:
@@ -30,6 +30,8 @@
|
|||||||
#include <playerinterface.h>
|
#include <playerinterface.h>
|
||||||
#include <handinterface.h>
|
#include <handinterface.h>
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
#define SERVER_WAIT_TIMEOUT_MSEC 50
|
#define SERVER_WAIT_TIMEOUT_MSEC 50
|
||||||
@@ -41,10 +43,29 @@ using namespace std;
|
|||||||
#define SERVER_DEAL_ADD_ALL_IN_DELAY_SEC 2
|
#define SERVER_DEAL_ADD_ALL_IN_DELAY_SEC 2
|
||||||
#define SERVER_SHOW_CARDS_DELAY_SEC 2
|
#define SERVER_SHOW_CARDS_DELAY_SEC 2
|
||||||
#define SERVER_PLAYER_TIMEOUT_ADD_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
|
// Helper functions
|
||||||
// TODO: these are hacks.
|
// 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)
|
static void SendNewRoundCards(ServerRecvThread &server, Game &curGame, int state)
|
||||||
{
|
{
|
||||||
// TODO: no switch needed here if game states are polymorphic
|
// 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.
|
// Check whether the player name is correct.
|
||||||
// Paranoia check, this is also done in netpacket.
|
// Partly, this is also done in netpacket.
|
||||||
if (joinGameData.playerName.empty() || joinGameData.playerName.size() > MAX_NAME_SIZE)
|
// 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);
|
server.SessionError(session, ERR_NET_INVALID_PLAYER_NAME);
|
||||||
return retVal;
|
return retVal;
|
||||||
@@ -297,26 +320,12 @@ ServerRecvStateInit::InternalProcess(ServerRecvThread &server, SessionWrapper se
|
|||||||
PlayerDataList::iterator player_end = tmpPlayerList.end();
|
PlayerDataList::iterator player_end = tmpPlayerList.end();
|
||||||
while (player_i != player_end)
|
while (player_i != player_end)
|
||||||
{
|
{
|
||||||
boost::shared_ptr<NetPacket> otherPlayerJoined(new NetPacketPlayerJoined);
|
server.GetSender().Send(session.sessionData->GetSocket(), CreateNetPacketPlayerJoined(*(*player_i)));
|
||||||
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);
|
|
||||||
|
|
||||||
++player_i;
|
++player_i;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send "Player Joined" to other fully connected clients.
|
// Send "Player Joined" to other fully connected clients.
|
||||||
boost::shared_ptr<NetPacket> thisPlayerJoined(new NetPacketPlayerJoined);
|
server.SendToAllPlayers(CreateNetPacketPlayerJoined(*tmpPlayerData));
|
||||||
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);
|
|
||||||
|
|
||||||
// Set player data for session.
|
// Set player data for session.
|
||||||
server.SetSessionPlayerData(session.sessionData, tmpPlayerData);
|
server.SetSessionPlayerData(session.sessionData, tmpPlayerData);
|
||||||
@@ -325,22 +334,21 @@ ServerRecvStateInit::InternalProcess(ServerRecvThread &server, SessionWrapper se
|
|||||||
session.sessionData->SetState(SessionData::Established);
|
session.sessionData->SetState(SessionData::Established);
|
||||||
}
|
}
|
||||||
else if (packet->ToNetPacketStartEvent())
|
else if (packet->ToNetPacketStartEvent())
|
||||||
|
{
|
||||||
|
int remainingSlots = server.GetGameData().maxNumberOfPlayers - server.GetCurNumberOfPlayers();
|
||||||
|
for (int i = 1; i <= remainingSlots; i++)
|
||||||
{
|
{
|
||||||
boost::shared_ptr<PlayerData> tmpPlayerData(
|
boost::shared_ptr<PlayerData> tmpPlayerData(
|
||||||
new PlayerData(m_curUniquePlayerId++, 0, PLAYER_TYPE_COMPUTER, PLAYER_RIGHTS_NORMAL));
|
new PlayerData(m_curUniquePlayerId++, 0, PLAYER_TYPE_COMPUTER, PLAYER_RIGHTS_NORMAL));
|
||||||
tmpPlayerData->SetName("Computer");
|
|
||||||
|
ostringstream name;
|
||||||
|
name << SERVER_COMPUTER_PLAYER_NAME << i;
|
||||||
|
tmpPlayerData->SetName(name.str());
|
||||||
|
|
||||||
// Send "Player Joined" to other fully connected clients.
|
// Send "Player Joined" to other fully connected clients.
|
||||||
boost::shared_ptr<NetPacket> thisPlayerJoined(new NetPacketPlayerJoined);
|
server.SendToAllPlayers(CreateNetPacketPlayerJoined(*tmpPlayerData));
|
||||||
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.AddComputerPlayer(tmpPlayerData);
|
server.AddComputerPlayer(tmpPlayerData);
|
||||||
|
}
|
||||||
|
|
||||||
server.InternalStartGame();
|
server.InternalStartGame();
|
||||||
server.SetState(SERVER_START_GAME_STATE::Instance());
|
server.SetState(SERVER_START_GAME_STATE::Instance());
|
||||||
@@ -360,6 +368,19 @@ ServerRecvStateInit::InternalProcess(ServerRecvThread &server, SessionWrapper se
|
|||||||
return retVal;
|
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()
|
AbstractServerRecvStateRunning::AbstractServerRecvStateRunning()
|
||||||
@@ -761,11 +782,8 @@ ServerRecvStateWaitPlayerAction::Process(ServerRecvThread &server)
|
|||||||
// If the player is computer controlled, let the engine act.
|
// If the player is computer controlled, let the engine act.
|
||||||
if (tmpPlayer->getMyType() == PLAYER_TYPE_COMPUTER)
|
if (tmpPlayer->getMyType() == PLAYER_TYPE_COMPUTER)
|
||||||
{
|
{
|
||||||
tmpPlayer->action();
|
server.SetState(ServerRecvStateComputerAction::Instance());
|
||||||
SendPlayerAction(server, tmpPlayer);
|
retVal = MSG_SOCK_INTERNAL_PENDING;
|
||||||
|
|
||||||
server.SetState(ServerRecvStateStartRound::Instance());
|
|
||||||
retVal = MSG_NET_GAME_SERVER_ACTION;
|
|
||||||
}
|
}
|
||||||
// If the player we are waiting for left, continue without him.
|
// If the player we are waiting for left, continue without him.
|
||||||
else if (!server.IsPlayerConnected(tmpPlayer->getMyName()))
|
else if (!server.IsPlayerConnected(tmpPlayer->getMyName()))
|
||||||
@@ -837,21 +855,50 @@ ServerRecvStateWaitPlayerAction::PerformPlayerAction(ServerRecvThread &server, b
|
|||||||
SendPlayerAction(server, player);
|
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);
|
boost::thread_specific_ptr<ServerRecvStateComputerAction> ServerRecvStateComputerAction::Ptr;
|
||||||
NetPacketPlayersActionDone::Data actionDoneData;
|
|
||||||
actionDoneData.gameState = static_cast<GameState>(curGame.getCurrentHand()->getActualRound());
|
ServerRecvStateComputerAction &
|
||||||
actionDoneData.playerId = player->getMyUniqueID();
|
ServerRecvStateComputerAction::Instance()
|
||||||
actionDoneData.playerAction = static_cast<PlayerAction>(player->getMyAction());
|
{
|
||||||
actionDoneData.totalPlayerBet = player->getMySet();
|
if (!Ptr.get())
|
||||||
actionDoneData.playerMoney = player->getMyCash();
|
Ptr.reset(new ServerRecvStateComputerAction);
|
||||||
static_cast<NetPacketPlayersActionDone *>(notifyActionDone.get())->SetData(actionDoneData);
|
|
||||||
server.SendToAllPlayers(notifyActionDone);
|
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);
|
virtual int InternalProcess(ServerRecvThread &server, SessionWrapper session, boost::shared_ptr<NetPacket> packet);
|
||||||
|
|
||||||
|
static boost::shared_ptr<NetPacket> CreateNetPacketPlayerJoined(const PlayerData &playerData);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
u_int16_t m_curUniquePlayerId;
|
u_int16_t m_curUniquePlayerId;
|
||||||
@@ -220,13 +222,36 @@ protected:
|
|||||||
virtual int InternalProcess(ServerRecvThread &server, SessionWrapper session, boost::shared_ptr<NetPacket> packet);
|
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 PerformPlayerAction(ServerRecvThread &server, boost::shared_ptr<PlayerInterface> player, PlayerAction action, int bet);
|
||||||
static void SendPlayerAction(ServerRecvThread &server, boost::shared_ptr<PlayerInterface> player);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
static boost::thread_specific_ptr<ServerRecvStateWaitPlayerAction> Ptr;
|
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
|
// State: Delay after dealing cards
|
||||||
class ServerRecvStateDealCardsDelay : public AbstractServerRecvStateReceiving, public AbstractServerRecvStateRunning, public AbstractServerRecvStateTimer
|
class ServerRecvStateDealCardsDelay : public AbstractServerRecvStateReceiving, public AbstractServerRecvStateRunning, public AbstractServerRecvStateTimer
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -72,6 +72,8 @@ public:
|
|||||||
void SendToAllPlayers(boost::shared_ptr<NetPacket> packet);
|
void SendToAllPlayers(boost::shared_ptr<NetPacket> packet);
|
||||||
void SendToAllButOnePlayers(boost::shared_ptr<NetPacket> packet, SOCKET except);
|
void SendToAllButOnePlayers(boost::shared_ptr<NetPacket> packet, SOCKET except);
|
||||||
|
|
||||||
|
Game &GetGame();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
struct Notification
|
struct Notification
|
||||||
@@ -128,7 +130,6 @@ protected:
|
|||||||
SenderThread &GetSender();
|
SenderThread &GetSender();
|
||||||
ReceiverHelper &GetReceiver();
|
ReceiverHelper &GetReceiver();
|
||||||
|
|
||||||
Game &GetGame();
|
|
||||||
const GameData &GetGameData() const;
|
const GameData &GetGameData() const;
|
||||||
const StartData &GetStartData() const;
|
const StartData &GetStartData() const;
|
||||||
void SetStartData(const StartData &startData);
|
void SetStartData(const StartData &startData);
|
||||||
@@ -175,6 +176,7 @@ friend class ServerRecvStateStartGame;
|
|||||||
friend class ServerRecvStateStartHand;
|
friend class ServerRecvStateStartHand;
|
||||||
friend class ServerRecvStateStartRound;
|
friend class ServerRecvStateStartRound;
|
||||||
friend class ServerRecvStateWaitPlayerAction;
|
friend class ServerRecvStateWaitPlayerAction;
|
||||||
|
friend class ServerRecvStateComputerAction;
|
||||||
friend class ServerRecvStateShowCardsDelay;
|
friend class ServerRecvStateShowCardsDelay;
|
||||||
friend class ServerRecvStateDealCardsDelay;
|
friend class ServerRecvStateDealCardsDelay;
|
||||||
friend class ServerRecvStateNextHandDelay;
|
friend class ServerRecvStateNextHandDelay;
|
||||||
|
|||||||
Reference in New Issue
Block a user