Chat messages are now working.

This commit is contained in:
lotodore
2007-05-25 16:03:12 +00:00
parent d01ecaf885
commit 13a731e041
21 changed files with 761 additions and 337 deletions
+46 -12
View File
@@ -146,8 +146,6 @@ Server Request/Notification: Player's Turn
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Game State:
0xF0 - Preflop Small Blind (no action requested)
0xF1 - Preflop Big Blind (no action requested)
0x00 - Preflop
0x01 - Flop
0x02 - Turn
@@ -168,23 +166,23 @@ Client Reply/Request: Player's Action
[ Game State is confirmed to ensure consistency. ]
Player Action:
0 - None (e.g. Small Blind or Big Blind in Preflop)
1 - Fold
2 - Check
3 - Call
4 - Bet
5 - Raise
6 - All in
0x00 - None (e.g. Small Blind or Big Blind in Preflop)
0x01 - Fold
0x02 - Check
0x03 - Call
0x04 - Bet
0x05 - Raise
0x06 - All in
Player Bet:
0 - states fold, check, call, all in
> 0 - states bet, raise
0 (ignored) - states fold, check, call, all in
> 0 - states bet, raise
Server Notification: Player's Action Done
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Message Type = 9 | Message Length = 12 |
| Message Type = 9 | Message Length = 28 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Game State | Player Id |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
@@ -199,6 +197,10 @@ Server Notification: Player's Action Done
| Current Hand Bets |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Additional Game States:
0xF0 - Preflop Small Blind (no action requested)
0xF1 - Preflop Big Blind (no action requested)
Server Reply: Player's Action Rejected
@@ -228,6 +230,38 @@ Rejection Reason:
0xFFFF - Other reason
Client Request: Send Chat Text
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Message Type = 11 | Message Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Text Length | Reserved |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| \
\ Text (UTF-8) /
| +-------------------------------+
/ | padding |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Server Notification: Chat Text
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Message Type = 12 | Message Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Text Length | Player Id |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| \
\ Text (UTF-8) /
| +-------------------------------+
/ | padding |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Server Reply: Error
0 1 2 3
+1 -2
View File
@@ -94,14 +94,13 @@ void ServerGuiWrapper::meInAction() {}
void ServerGuiWrapper::logPlayerActionMsg(string playerName, int action, int setValue) {}
void ServerGuiWrapper::logNewGameHandMsg(int gameID, int handID) {}
void ServerGuiWrapper::chatAppendMsg(std::string msg) {}
void ServerGuiWrapper::SignalNetClientConnect(int actionID) { if (myClientcb) myClientcb->SignalNetClientConnect(actionID); }
void ServerGuiWrapper::SignalNetClientGameInfo(int actionID) { if (myClientcb) myClientcb->SignalNetClientGameInfo(actionID); }
void ServerGuiWrapper::SignalNetClientError(int errorID, int osErrorID) { if (myClientcb) myClientcb->SignalNetClientError(errorID, osErrorID); }
void ServerGuiWrapper::SignalNetClientPlayerJoined(const string &playerName) { if (myClientcb) myClientcb->SignalNetClientPlayerJoined(playerName); }
void ServerGuiWrapper::SignalNetClientPlayerLeft(const string &playerName) { if (myClientcb) myClientcb->SignalNetClientPlayerLeft(playerName); }
void ServerGuiWrapper::SignalNetClientGameStart(boost::shared_ptr<Game> game) { if (myClientcb) myClientcb->SignalNetClientGameStart(game); }
void ServerGuiWrapper::SignalNetClientChatMsg(const string &playerName, const string &msg) { if (myClientcb) myClientcb->SignalNetClientChatMsg(playerName, msg); }
void ServerGuiWrapper::SignalNetServerSuccess(int actionID) { if (myServercb) myServercb->SignalNetServerSuccess(actionID); }
void ServerGuiWrapper::SignalNetServerError(int errorID, int osErrorID) { if (myServercb) myServercb->SignalNetServerError(errorID, osErrorID); }
+1 -2
View File
@@ -77,13 +77,12 @@ public:
void logPlayerActionMsg(std::string playerName, int action, int setValue) ;
void logNewGameHandMsg(int gameID, int handID) ;
void chatAppendMsg(std::string msg);
void SignalNetClientConnect(int actionID);
void SignalNetClientGameInfo(int actionID);
void SignalNetClientError(int errorID, int osErrorID);
void SignalNetClientPlayerJoined(const std::string &playerName);
void SignalNetClientPlayerLeft(const std::string &playerName);
void SignalNetClientChatMsg(const std::string &playerName, const std::string &msg);
void SignalNetClientGameStart(boost::shared_ptr<Game> game);
-4
View File
@@ -92,10 +92,6 @@ public:
//log.cpp
virtual void logPlayerActionMsg(std::string playName, int action, int setValue) =0;
virtual void logNewGameHandMsg(int gameID, int HandID) =0;
//chat
virtual void chatAppendMsg(std::string msg) =0;
};
#endif
+1 -2
View File
@@ -92,14 +92,13 @@ void GuiWrapper::meInAction() { myW->signalMeInAction(); }
void GuiWrapper::logPlayerActionMsg(string playerName, int action, int setValue) { myLog->signalLogPlayerActionMsg(QString::fromUtf8(playerName.c_str()), action, setValue); }
void GuiWrapper::logNewGameHandMsg(int gameID, int handID) { myLog->signalLogNewGameHandMsg(gameID, handID); }
void GuiWrapper::chatAppendMsg(string msg) { myChat->receiveMessage(msg); }
void GuiWrapper::SignalNetClientConnect(int actionID) { myW->signalNetClientConnect(actionID); }
void GuiWrapper::SignalNetClientGameInfo(int actionID) { myW->signalNetClientGameInfo(actionID); }
void GuiWrapper::SignalNetClientError(int errorID, int osErrorID) { myW->signalNetClientError(errorID, osErrorID); }
void GuiWrapper::SignalNetClientPlayerJoined(const string &playerName) { myW->signalNetClientPlayerJoined(QString::fromUtf8(playerName.c_str())); }
void GuiWrapper::SignalNetClientPlayerLeft(const string &playerName) { myW->signalNetClientPlayerLeft(QString::fromUtf8(playerName.c_str())); }
void GuiWrapper::SignalNetClientGameStart(boost::shared_ptr<Game> game) { myW->signalNetClientGameStart(game); }
void GuiWrapper::SignalNetClientChatMsg(const string &playerName, const string &msg) { myChat->signalChatMessage(QString::fromUtf8(playerName.c_str()), QString::fromUtf8(msg.c_str())); }
void GuiWrapper::SignalNetServerSuccess(int actionID) { }
void GuiWrapper::SignalNetServerError(int errorID, int osErrorID) { }
+1 -2
View File
@@ -85,13 +85,12 @@ public:
void logPlayerActionMsg(std::string playerName, int action, int setValue) ;
void logNewGameHandMsg(int gameID, int handID) ;
void chatAppendMsg(std::string msg);
void SignalNetClientConnect(int actionID);
void SignalNetClientGameInfo(int actionID);
void SignalNetClientError(int errorID, int osErrorID);
void SignalNetClientPlayerJoined(const std::string &playerName);
void SignalNetClientPlayerLeft(const std::string &playerName);
void SignalNetClientChatMsg(const std::string &playerName, const std::string &msg);
void SignalNetClientGameStart(boost::shared_ptr<Game> game);
+4 -3
View File
@@ -27,7 +27,8 @@ using namespace std;
Chat::Chat(mainWindowImpl* w, ConfigFile *c) : myW(w), myConfig(c)
{
myW->setChat(this);
connect(this, SIGNAL(signalChatMessage(QString, QString)), this, SLOT(receiveMessage(QString, QString)));
}
Chat::~Chat()
@@ -42,9 +43,9 @@ void Chat::sendMessage() {
myW->lineEdit_ChatInput->setText("");
}
void Chat::receiveMessage(std::string message) {
void Chat::receiveMessage(QString playerName, QString message) {
myW->textBrowser_Chat->append(QString::fromUtf8(message.c_str()));
myW->textBrowser_Chat->append(playerName + ": " + message);
checkInvisible();
}
+4 -1
View File
@@ -39,10 +39,13 @@ public:
~Chat();
signals:
void signalChatMessage(QString playerName, QString msg);
public slots:
void sendMessage();
void receiveMessage(std::string);
void receiveMessage(QString playerName, QString msg);
void checkInvisible();
private:
+3 -1
View File
@@ -22,7 +22,7 @@
#define _CLIENTCALLBACK_H_
#include <string>
#include <boost/shared_ptr.hpp>
#include <boost/shared_ptr.hpp>
class Game;
@@ -38,6 +38,8 @@ public:
virtual void SignalNetClientGameStart(boost::shared_ptr<Game> game) = 0;
virtual void SignalNetClientPlayerJoined(const std::string &playerName) = 0;
virtual void SignalNetClientPlayerLeft(const std::string &playerName) = 0;
virtual void SignalNetClientChatMsg(const std::string &playerName, const std::string &msg) = 0;
};
#endif
+29 -15
View File
@@ -32,6 +32,7 @@ class ClientThread;
class ClientCallback;
class ResolverThread;
class Game;
class NetPacket;
class ClientState
{
@@ -166,8 +167,24 @@ protected:
ClientStateStartSession();
};
// Abstract State: Receiving
class AbstractClientStateReceiving : public ClientState
{
public:
virtual ~AbstractClientStateReceiving();
// select on socket.
virtual int Process(ClientThread &client);
protected:
virtual int InternalProcess(ClientThread &client, boost::shared_ptr<NetPacket> packet) = 0;
AbstractClientStateReceiving();
};
// State: Wait for Session ACK.
class ClientStateWaitSession : public ClientState
class ClientStateWaitSession : public AbstractClientStateReceiving
{
public:
// Access the state singleton.
@@ -175,17 +192,17 @@ public:
virtual ~ClientStateWaitSession();
// select on socket.
virtual int Process(ClientThread &client);
protected:
// Protected constructor - this is a singleton.
ClientStateWaitSession();
virtual int InternalProcess(ClientThread &client, boost::shared_ptr<NetPacket> packet);
};
// State: Wait for start of the game or start info.
class ClientStateWaitGame : public ClientState
class ClientStateWaitGame : public AbstractClientStateReceiving
{
public:
// Access the state singleton.
@@ -193,17 +210,16 @@ public:
virtual ~ClientStateWaitGame();
// select on socket.
virtual int Process(ClientThread &client);
protected:
// Protected constructor - this is a singleton.
ClientStateWaitGame();
virtual int InternalProcess(ClientThread &client, boost::shared_ptr<NetPacket> packet);
};
// State: Wait for start of the next hand.
class ClientStateWaitHand : public ClientState
class ClientStateWaitHand : public AbstractClientStateReceiving
{
public:
// Access the state singleton.
@@ -211,17 +227,16 @@ public:
virtual ~ClientStateWaitHand();
// select on socket.
virtual int Process(ClientThread &client);
protected:
// Protected constructor - this is a singleton.
ClientStateWaitHand();
virtual int InternalProcess(ClientThread &client, boost::shared_ptr<NetPacket> packet);
};
// State: Hand Loop.
class ClientStateRunHand : public ClientState
class ClientStateRunHand : public AbstractClientStateReceiving
{
public:
// Access the state singleton.
@@ -229,14 +244,13 @@ public:
virtual ~ClientStateRunHand();
// select on socket.
virtual int Process(ClientThread &client);
protected:
// Protected constructor - this is a singleton.
ClientStateRunHand();
virtual int InternalProcess(ClientThread &client, boost::shared_ptr<NetPacket> packet);
static int GetHighestSet(Game &curGame);
static void SetHighestSet(Game &curGame, int highestSet);
static int GetPlayersTurn(Game &curGame);
+5 -1
View File
@@ -52,6 +52,7 @@ public:
const std::string &playerName);
void SendPlayerAction();
void SendChatMessage(const std::string &msg);
ClientCallback &GetCallback();
GuiInterface &GetGui();
@@ -84,7 +85,9 @@ protected:
void AddPlayerData(boost::shared_ptr<PlayerData> playerData);
void RemovePlayerData(unsigned playerId);
PlayerDataList GetMappedPlayerDataList() const;
void MapPlayerDataList();
const PlayerDataList &GetPlayerDataList() const;
boost::shared_ptr<PlayerData> GetPlayerDataByUniqueId(unsigned id);
private:
@@ -105,6 +108,7 @@ private:
unsigned m_curGameId;
int m_guiPlayerNum;
friend class AbstractClientStateReceiving;
friend class ClientStateInit;
friend class ClientStateStartResolve;
friend class ClientStateResolving;
+106 -91
View File
@@ -357,6 +357,43 @@ ClientStateStartSession::Process(ClientThread &client)
//-----------------------------------------------------------------------------
AbstractClientStateReceiving::AbstractClientStateReceiving()
{
}
AbstractClientStateReceiving::~AbstractClientStateReceiving()
{
}
int
AbstractClientStateReceiving::Process(ClientThread &client)
{
int retVal = MSG_SOCK_INTERNAL_PENDING;
// delegate to receiver helper class
boost::shared_ptr<NetPacket> tmpPacket = client.GetReceiver().Recv(client.GetContext().GetSocket());
if (tmpPacket.get())
{
if (tmpPacket->ToNetPacketChatText())
{
// Chat message - display it in the GUI.
NetPacketChatText::Data chatData;
tmpPacket->ToNetPacketChatText()->GetData(chatData);
boost::shared_ptr<PlayerData> tmpPlayer = client.GetPlayerDataByUniqueId(chatData.playerId);
if (tmpPlayer.get())
client.GetCallback().SignalNetClientChatMsg(tmpPlayer->GetName(), chatData.text);
}
else
retVal = InternalProcess(client, tmpPacket);
}
return retVal;
}
//-----------------------------------------------------------------------------
ClientStateWaitSession &
ClientStateWaitSession::Instance()
{
@@ -373,43 +410,36 @@ ClientStateWaitSession::~ClientStateWaitSession()
}
int
ClientStateWaitSession::Process(ClientThread &client)
ClientStateWaitSession::InternalProcess(ClientThread &client, boost::shared_ptr<NetPacket> packet)
{
int retVal = MSG_SOCK_INTERNAL_PENDING;
ClientContext &context = client.GetContext();
// delegate to receiver helper class
boost::shared_ptr<NetPacket> tmpPacket = client.GetReceiver().Recv(context.GetSocket());
if (tmpPacket.get())
if (packet->ToNetPacketJoinGameAck())
{
if (tmpPacket->ToNetPacketJoinGameAck())
{
// Everything is fine - we joined the game.
// Initialize game configuration.
NetPacketJoinGameAck::Data joinGameAckData;
tmpPacket->ToNetPacketJoinGameAck()->GetData(joinGameAckData);
client.SetGameData(joinGameAckData.gameData);
client.SetGuiPlayerNum(joinGameAckData.yourPlayerNum);
// Everything is fine - we joined the game.
// Initialize game configuration.
NetPacketJoinGameAck::Data joinGameAckData;
packet->ToNetPacketJoinGameAck()->GetData(joinGameAckData);
client.SetGameData(joinGameAckData.gameData);
client.SetGuiPlayerNum(joinGameAckData.yourPlayerNum);
// TODO: Type Human is fixed here.
boost::shared_ptr<PlayerData> playerData(
new PlayerData(joinGameAckData.yourPlayerUniqueId, joinGameAckData.yourPlayerNum, PLAYER_TYPE_HUMAN));
playerData->SetName(context.GetPlayerName());
client.AddPlayerData(playerData);
// TODO: Type Human is fixed here.
boost::shared_ptr<PlayerData> playerData(
new PlayerData(joinGameAckData.yourPlayerUniqueId, joinGameAckData.yourPlayerNum, PLAYER_TYPE_HUMAN));
playerData->SetName(context.GetPlayerName());
client.AddPlayerData(playerData);
client.SetState(ClientStateWaitGame::Instance());
retVal = MSG_SOCK_SESSION_DONE;
}
else if (tmpPacket->ToNetPacketError())
{
// Server reported an error.
NetPacketError::Data errorData;
tmpPacket->ToNetPacketError()->GetData(errorData);
// Show the error.
throw ClientException(errorData.errorCode, 0);
}
client.SetState(ClientStateWaitGame::Instance());
retVal = MSG_SOCK_SESSION_DONE;
}
else if (packet->ToNetPacketError())
{
// Server reported an error.
NetPacketError::Data errorData;
packet->ToNetPacketError()->GetData(errorData);
// Show the error.
throw ClientException(errorData.errorCode, 0);
}
return retVal;
@@ -433,45 +463,39 @@ ClientStateWaitGame::~ClientStateWaitGame()
}
int
ClientStateWaitGame::Process(ClientThread &client)
ClientStateWaitGame::InternalProcess(ClientThread &client, boost::shared_ptr<NetPacket> packet)
{
int retVal = MSG_SOCK_INTERNAL_PENDING;
ClientContext &context = client.GetContext();
// delegate to receiver helper class
boost::shared_ptr<NetPacket> tmpPacket = client.GetReceiver().Recv(context.GetSocket());
if (tmpPacket.get())
if (packet->ToNetPacketGameStart())
{
if (tmpPacket->ToNetPacketGameStart())
{
// Start the network game as client.
NetPacketGameStart::Data gameStartData;
tmpPacket->ToNetPacketGameStart()->GetData(gameStartData);
// Start the network game as client.
NetPacketGameStart::Data gameStartData;
packet->ToNetPacketGameStart()->GetData(gameStartData);
client.SetStartData(gameStartData.startData);
client.SetStartData(gameStartData.startData);
client.SetState(ClientStateWaitHand::Instance());
retVal = MSG_NET_GAME_CLIENT_START;
}
else if (tmpPacket->ToNetPacketPlayerJoined())
{
// Another player joined the network game.
NetPacketPlayerJoined::Data netPlayerData;
tmpPacket->ToNetPacketPlayerJoined()->GetData(netPlayerData);
client.SetState(ClientStateWaitHand::Instance());
retVal = MSG_NET_GAME_CLIENT_START;
}
else if (packet->ToNetPacketPlayerJoined())
{
// Another player joined the network game.
NetPacketPlayerJoined::Data netPlayerData;
packet->ToNetPacketPlayerJoined()->GetData(netPlayerData);
boost::shared_ptr<PlayerData> playerData(
new PlayerData(netPlayerData.playerId, netPlayerData.playerNumber, netPlayerData.ptype));
playerData->SetName(netPlayerData.playerName);
client.AddPlayerData(playerData);
}
else if (tmpPacket->ToNetPacketPlayerLeft())
{
// Another player left the network game.
NetPacketPlayerLeft::Data netPlayerData;
tmpPacket->ToNetPacketPlayerLeft()->GetData(netPlayerData);
client.RemovePlayerData(netPlayerData.playerId);
}
boost::shared_ptr<PlayerData> playerData(
new PlayerData(netPlayerData.playerId, netPlayerData.playerNumber, netPlayerData.ptype));
playerData->SetName(netPlayerData.playerName);
client.AddPlayerData(playerData);
}
else if (packet->ToNetPacketPlayerLeft())
{
// Another player left the network game.
NetPacketPlayerLeft::Data netPlayerData;
packet->ToNetPacketPlayerLeft()->GetData(netPlayerData);
client.RemovePlayerData(netPlayerData.playerId);
}
// TODO: handle error packet
@@ -496,33 +520,27 @@ ClientStateWaitHand::~ClientStateWaitHand()
}
int
ClientStateWaitHand::Process(ClientThread &client)
ClientStateWaitHand::InternalProcess(ClientThread &client, boost::shared_ptr<NetPacket> packet)
{
int retVal = MSG_SOCK_INTERNAL_PENDING;
ClientContext &context = client.GetContext();
// Delegate to receiver helper class.
boost::shared_ptr<NetPacket> tmpPacket = client.GetReceiver().Recv(context.GetSocket());
if (tmpPacket.get())
if (packet->ToNetPacketHandStart())
{
if (tmpPacket->ToNetPacketHandStart())
{
// Hand was started.
// These are the cards. Good luck.
NetPacketHandStart::Data tmpData;
tmpPacket->ToNetPacketHandStart()->GetData(tmpData);
int myCards[2];
myCards[0] = (int)tmpData.yourCards[0];
myCards[1] = (int)tmpData.yourCards[1];
client.GetGame()->getPlayerArray()[0]->setMyCards(myCards);
client.GetGame()->initHand();
client.GetGame()->startHand();
client.GetGui().dealHoleCards();
client.SetState(ClientStateRunHand::Instance());
// Hand was started.
// These are the cards. Good luck.
NetPacketHandStart::Data tmpData;
packet->ToNetPacketHandStart()->GetData(tmpData);
int myCards[2];
myCards[0] = (int)tmpData.yourCards[0];
myCards[1] = (int)tmpData.yourCards[1];
client.GetGame()->getPlayerArray()[0]->setMyCards(myCards);
client.GetGame()->initHand();
client.GetGame()->startHand();
client.GetGui().dealHoleCards();
client.SetState(ClientStateRunHand::Instance());
retVal = MSG_NET_GAME_CLIENT_HAND;
}
retVal = MSG_NET_GAME_CLIENT_HAND;
}
return MSG_SOCK_INTERNAL_PENDING;
@@ -546,20 +564,17 @@ ClientStateRunHand::~ClientStateRunHand()
}
int
ClientStateRunHand::Process(ClientThread &client)
ClientStateRunHand::InternalProcess(ClientThread &client, boost::shared_ptr<NetPacket> packet)
{
ClientContext &context = client.GetContext();
// Delegate to receiver helper class.
boost::shared_ptr<NetPacket> tmpPacket = client.GetReceiver().Recv(context.GetSocket());
if (tmpPacket.get())
if (packet.get())
{
boost::shared_ptr<Game> curGame = client.GetGame();
if (tmpPacket->ToNetPacketPlayersActionDone())
if (packet->ToNetPacketPlayersActionDone())
{
NetPacketPlayersActionDone::Data actionDoneData;
tmpPacket->ToNetPacketPlayersActionDone()->GetData(actionDoneData);
packet->ToNetPacketPlayersActionDone()->GetData(actionDoneData);
PlayerInterface *tmpPlayer = curGame->getPlayerByUniqueId(actionDoneData.playerId);
assert(tmpPlayer); // TODO: throw exception
@@ -587,10 +602,10 @@ ClientStateRunHand::Process(ClientThread &client)
client.GetGui().refreshAction();
client.GetGui().refreshCash();
}
else if (tmpPacket->ToNetPacketPlayersTurn())
else if (packet->ToNetPacketPlayersTurn())
{
NetPacketPlayersTurn::Data turnData;
tmpPacket->ToNetPacketPlayersTurn()->GetData(turnData);
packet->ToNetPacketPlayersTurn()->GetData(turnData);
PlayerInterface *tmpPlayer = curGame->getPlayerByUniqueId(turnData.playerId);
assert(tmpPlayer); // TODO: throw exception
+45 -4
View File
@@ -96,6 +96,19 @@ ClientThread::SendPlayerAction()
GetSender().Send(GetContext().GetSocket(), action);
}
void
ClientThread::SendChatMessage(const std::string &msg)
{
// Warning: This function is called in the context of the GUI thread.
// Create a network packet containing the chat message.
boost::shared_ptr<NetPacket> chat(new NetPacketSendChatText);
NetPacketSendChatText::Data chatData;
chatData.text = msg;
static_cast<NetPacketSendChatText *>(chat.get())->SetData(chatData);
// The sender is thread-safe, so just dump the packet.
GetSender().Send(GetContext().GetSocket(), chat);
}
ClientCallback &
ClientThread::GetCallback()
{
@@ -133,7 +146,8 @@ ClientThread::Main()
// EngineFactory erstellen
boost::shared_ptr<EngineFactory> factory(new ClientEngineFactory); // LocalEngine erstellen
m_game.reset(new Game(&m_gui, factory, GetMappedPlayerDataList(), GetGameData(), GetStartData(), m_curGameId++));
MapPlayerDataList();
m_game.reset(new Game(&m_gui, factory, GetPlayerDataList(), GetGameData(), GetStartData(), m_curGameId++));
GetCallback().SignalNetClientGameStart(m_game);
}
}
@@ -268,8 +282,8 @@ ClientThread::RemovePlayerData(unsigned playerId)
GetCallback().SignalNetClientPlayerLeft(playerName);
}
PlayerDataList
ClientThread::GetMappedPlayerDataList() const
void
ClientThread::MapPlayerDataList()
{
PlayerDataList mappedList;
@@ -293,6 +307,33 @@ ClientThread::GetMappedPlayerDataList() const
// Sort the list by player number.
mappedList.sort(*boost::lambda::_1 < *boost::lambda::_2);
return mappedList;
m_playerDataList = mappedList;
SetGuiPlayerNum(0);
}
const PlayerDataList &
ClientThread::GetPlayerDataList() const
{
return m_playerDataList;
}
boost::shared_ptr<PlayerData>
ClientThread::GetPlayerDataByUniqueId(unsigned id)
{
boost::shared_ptr<PlayerData> tmpPlayer;
PlayerDataList::const_iterator i = m_playerDataList.begin();
PlayerDataList::const_iterator end = m_playerDataList.end();
while (i != end)
{
if ((*i)->GetUniqueId() == id)
{
tmpPlayer = *i;
break;
}
++i;
}
return tmpPlayer;
}
+228 -8
View File
@@ -37,6 +37,8 @@ using namespace std;
#define NET_TYPE_PLAYERS_ACTION 0x0008
#define NET_TYPE_PLAYERS_ACTION_DONE 0x0009
#define NET_TYPE_PLAYERS_ACTION_REJECTED 0x000A
#define NET_TYPE_SEND_CHAT_TEXT 0x000B
#define NET_TYPE_CHAT_TEXT 0x000C
#define NET_TYPE_ERROR 0x0400
@@ -75,7 +77,6 @@ struct GCC_PACKED NetPacketJoinGameData
u_int16_t playerFlags;
u_int16_t playerNameLength;
u_int16_t reserved;
char password[1];
};
struct GCC_PACKED NetPacketJoinGameAckData
@@ -105,7 +106,6 @@ struct GCC_PACKED NetPacketPlayerJoinedData
u_int16_t playerNumber;
u_int16_t playerFlags;
u_int16_t playerNameLength;
char playerName[1];
};
struct GCC_PACKED NetPacketPlayerLeftData
@@ -166,6 +166,21 @@ struct GCC_PACKED NetPacketPlayersActionRejectedData
u_int16_t reserved;
};
struct GCC_PACKED NetPacketSendChatTextData
{
NetPacketHeader head;
u_int16_t textLength;
u_int16_t reserved;
};
struct GCC_PACKED NetPacketChatTextData
{
NetPacketHeader head;
u_int16_t textLength;
u_int16_t playerId;
char text[1];
};
struct GCC_PACKED NetPacketErrorData
{
NetPacketHeader head;
@@ -229,6 +244,12 @@ NetPacket::Create(char *data, unsigned &dataSize)
case NET_TYPE_PLAYERS_ACTION_REJECTED:
tmpPacket = boost::shared_ptr<NetPacket>(new NetPacketPlayersActionRejected);
break;
case NET_TYPE_SEND_CHAT_TEXT:
tmpPacket = boost::shared_ptr<NetPacket>(new NetPacketSendChatText);
break;
case NET_TYPE_CHAT_TEXT:
tmpPacket = boost::shared_ptr<NetPacket>(new NetPacketChatText);
break;
case NET_TYPE_ERROR:
tmpPacket = boost::shared_ptr<NetPacket>(new NetPacketError);
break;
@@ -373,6 +394,18 @@ NetPacket::ToNetPacketPlayersActionRejected() const
return NULL;
}
const NetPacketSendChatText *
NetPacket::ToNetPacketSendChatText() const
{
return NULL;
}
const NetPacketChatText *
NetPacket::ToNetPacketChatText() const
{
return NULL;
}
const NetPacketError *
NetPacket::ToNetPacketError() const
{
@@ -461,8 +494,9 @@ NetPacketJoinGame::SetData(const NetPacketJoinGame::Data &inData)
tmpData->passwordLength = htons(passwordLen);
tmpData->playerFlags = htons((inData.ptype == PLAYER_TYPE_HUMAN) ? NET_PLAYER_FLAG_HUMAN : 0);
tmpData->playerNameLength = htons(playerNameLen);
memcpy(tmpData->password, inData.password.c_str(), passwordLen);
memcpy(tmpData->password + ADD_PADDING(passwordLen), inData.playerName.c_str(), playerNameLen);
char *passwordPtr = (char *)tmpData + sizeof(NetPacketJoinGameData);
memcpy(passwordPtr, inData.password.c_str(), passwordLen);
memcpy(passwordPtr + ADD_PADDING(passwordLen), inData.playerName.c_str(), playerNameLen);
}
void
@@ -478,8 +512,9 @@ NetPacketJoinGame::GetData(NetPacketJoinGame::Data &outData) const
outData.ptype = (ntohs(tmpData->playerFlags) & NET_PLAYER_FLAG_HUMAN) ? PLAYER_TYPE_HUMAN : PLAYER_TYPE_COMPUTER;
u_int16_t passwordLen = ntohs(tmpData->passwordLength);
outData.password = string(tmpData->password, passwordLen);
outData.playerName = string(tmpData->password + ADD_PADDING(passwordLen), ntohs(tmpData->playerNameLength));
char *passwordPtr = (char *)tmpData + sizeof(NetPacketJoinGameData);
outData.password = string(passwordPtr, passwordLen);
outData.playerName = string(passwordPtr + ADD_PADDING(passwordLen), ntohs(tmpData->playerNameLength));
}
const NetPacketJoinGame *
@@ -640,7 +675,8 @@ NetPacketPlayerJoined::SetData(const NetPacketPlayerJoined::Data &inData)
tmpData->playerId = htons(inData.playerId);
tmpData->playerNumber = htons(inData.playerNumber);
tmpData->playerNameLength = htons(playerNameLen);
memcpy(tmpData->playerName, inData.playerName.c_str(), playerNameLen);
char *namePtr = (char *)tmpData + sizeof(NetPacketPlayerJoinedData);
memcpy(namePtr, inData.playerName.c_str(), playerNameLen);
}
void
@@ -653,7 +689,8 @@ NetPacketPlayerJoined::GetData(NetPacketPlayerJoined::Data &outData) const
outData.ptype = (ntohs(tmpData->playerFlags) & NET_PLAYER_FLAG_HUMAN) ? PLAYER_TYPE_HUMAN : PLAYER_TYPE_COMPUTER;
outData.playerId = ntohs(tmpData->playerId);
outData.playerNumber = ntohs(tmpData->playerNumber);
outData.playerName = string(tmpData->playerName, ntohs(tmpData->playerNameLength));
char *namePtr = (char *)tmpData + sizeof(NetPacketPlayerJoinedData);
outData.playerName = string(namePtr, ntohs(tmpData->playerNameLength));
}
const NetPacketPlayerJoined *
@@ -1196,6 +1233,189 @@ NetPacketPlayersActionRejected::Check(const NetPacketHeader* data) const
//-----------------------------------------------------------------------------
NetPacketSendChatText::NetPacketSendChatText()
: NetPacket(NET_TYPE_SEND_CHAT_TEXT, sizeof(NetPacketSendChatTextData))
{
}
NetPacketSendChatText::~NetPacketSendChatText()
{
}
boost::shared_ptr<NetPacket>
NetPacketSendChatText::Clone() const
{
boost::shared_ptr<NetPacket> newPacket(new NetPacketSendChatText);
try
{
newPacket->SetRawData(GetRawData());
} catch (const NetException &)
{
// Need to return the new packet anyway.
}
return newPacket;
}
void
NetPacketSendChatText::SetData(const NetPacketSendChatText::Data &inData)
{
u_int16_t textLen = (u_int16_t)inData.text.length();
if (!textLen || textLen > MAX_CHAT_TEXT_SIZE)
throw NetException(ERR_NET_INVALID_CHAT_TEXT, 0);
// Resize the packet so that the data fits in.
Resize((u_int16_t)
(sizeof(NetPacketSendChatTextData) + ADD_PADDING(textLen)));
NetPacketSendChatTextData *tmpData = (NetPacketSendChatTextData *)GetRawData();
assert(tmpData);
// Set the data.
tmpData->textLength = htons(textLen);
char *textPtr = (char *)tmpData + sizeof(NetPacketSendChatTextData);
memcpy(textPtr, inData.text.c_str(), textLen);
}
void
NetPacketSendChatText::GetData(NetPacketSendChatText::Data &outData) const
{
// We assume that the data is valid. Validity has already been checked.
NetPacketSendChatTextData *tmpData = (NetPacketSendChatTextData *)GetRawData();
assert(tmpData);
char *textPtr = (char *)tmpData + sizeof(NetPacketSendChatTextData);
outData.text = string(textPtr, ntohs(tmpData->textLength));
}
const NetPacketSendChatText *
NetPacketSendChatText::ToNetPacketSendChatText() const
{
return this;
}
void
NetPacketSendChatText::Check(const NetPacketHeader* data) const
{
assert(data);
u_int16_t dataLen = ntohs(data->length);
if (dataLen < sizeof(NetPacketSendChatTextData))
{
throw NetException(ERR_SOCK_INVALID_PACKET, 0);
}
NetPacketSendChatTextData *tmpData = (NetPacketSendChatTextData *)data;
int textLength = ntohs(tmpData->textLength);
// Generous checking - larger packets are allowed.
if (dataLen <
sizeof(NetPacketSendChatTextData)
+ ADD_PADDING(textLength))
{
throw NetException(ERR_SOCK_INVALID_PACKET, 0);
}
// Check string sizes.
if (!textLength
|| textLength > MAX_CHAT_TEXT_SIZE)
{
throw NetException(ERR_SOCK_INVALID_PACKET, 0);
}
}
//-----------------------------------------------------------------------------
NetPacketChatText::NetPacketChatText()
: NetPacket(NET_TYPE_CHAT_TEXT, sizeof(NetPacketChatTextData))
{
}
NetPacketChatText::~NetPacketChatText()
{
}
boost::shared_ptr<NetPacket>
NetPacketChatText::Clone() const
{
boost::shared_ptr<NetPacket> newPacket(new NetPacketChatText);
try
{
newPacket->SetRawData(GetRawData());
} catch (const NetException &)
{
// Need to return the new packet anyway.
}
return newPacket;
}
void
NetPacketChatText::SetData(const NetPacketChatText::Data &inData)
{
u_int16_t textLen = (u_int16_t)inData.text.length();
if (!textLen || textLen > MAX_CHAT_TEXT_SIZE)
throw NetException(ERR_NET_INVALID_CHAT_TEXT, 0);
// Resize the packet so that the data fits in.
Resize((u_int16_t)
(sizeof(NetPacketChatTextData) + ADD_PADDING(textLen)));
NetPacketChatTextData *tmpData = (NetPacketChatTextData *)GetRawData();
assert(tmpData);
// Set the data.
tmpData->playerId = htons(inData.playerId);
tmpData->textLength = htons(textLen);
char *textPtr = (char *)tmpData + sizeof(NetPacketChatTextData);
memcpy(textPtr, inData.text.c_str(), textLen);
}
void
NetPacketChatText::GetData(NetPacketChatText::Data &outData) const
{
// We assume that the data is valid. Validity has already been checked.
NetPacketChatTextData *tmpData = (NetPacketChatTextData *)GetRawData();
assert(tmpData);
outData.playerId = ntohs(tmpData->playerId);
char *textPtr = (char *)tmpData + sizeof(NetPacketChatTextData);
outData.text = string(textPtr, ntohs(tmpData->textLength));
}
const NetPacketChatText *
NetPacketChatText::ToNetPacketChatText() const
{
return this;
}
void
NetPacketChatText::Check(const NetPacketHeader* data) const
{
assert(data);
u_int16_t dataLen = ntohs(data->length);
if (dataLen < sizeof(NetPacketChatTextData))
{
throw NetException(ERR_SOCK_INVALID_PACKET, 0);
}
NetPacketChatTextData *tmpData = (NetPacketChatTextData *)data;
int textLength = ntohs(tmpData->textLength);
// Generous checking - larger packets are allowed.
if (dataLen <
sizeof(NetPacketChatTextData)
+ ADD_PADDING(textLength))
{
throw NetException(ERR_SOCK_INVALID_PACKET, 0);
}
// Check string sizes.
if (!textLength
|| textLength > MAX_CHAT_TEXT_SIZE)
{
throw NetException(ERR_SOCK_INVALID_PACKET, 0);
}
}
//-----------------------------------------------------------------------------
NetPacketError::NetPacketError()
: NetPacket(NET_TYPE_ERROR, sizeof(NetPacketErrorData))
{
+200 -173
View File
@@ -41,6 +41,66 @@ ServerRecvState::~ServerRecvState()
//-----------------------------------------------------------------------------
ServerRecvStateReceiving::ServerRecvStateReceiving()
{
}
ServerRecvStateReceiving::~ServerRecvStateReceiving()
{
}
int
ServerRecvStateReceiving::Process(ServerRecvThread &server)
{
int retVal = MSG_SOCK_INTERNAL_PENDING;
SOCKET recvSock = server.Select();
if (recvSock != INVALID_SOCKET)
{
SessionWrapper session = server.GetSession(recvSock);
boost::shared_ptr<NetPacket> packet;
try
{
packet = server.GetReceiver().Recv(recvSock);
} catch (const NetException &)
{
if (session.sessionData.get())
{
// TODO: Deactivate player.
server.CloseSessionDelayed(session);
return retVal;
}
}
// Ignore if no session / no packet.
if (packet.get() && session.sessionData.get())
{
if (packet->ToNetPacketSendChatText()) // Chat text is always allowed.
{
if (session.playerData.get()) // Only forward if this player is known.
{
// Forward chat text to all players.
// TODO: Some limitation needed.
NetPacketSendChatText::Data inChatData;
packet->ToNetPacketSendChatText()->GetData(inChatData);
boost::shared_ptr<NetPacket> outChat(new NetPacketChatText);
NetPacketChatText::Data outChatData;
outChatData.playerId = session.playerData->GetUniqueId();
outChatData.text = inChatData.text;
static_cast<NetPacketChatText *>(outChat.get())->SetData(outChatData);
server.SendToAllPlayers(outChat);
}
}
else
retVal = InternalProcess(server, session, packet); // Let other class handle this.
}
}
return retVal;
}
//-----------------------------------------------------------------------------
ServerRecvStateInit &
ServerRecvStateInit::Instance()
{
@@ -71,137 +131,116 @@ ServerRecvStateInit::HandleNewConnection(ServerRecvThread &server, boost::shared
}
int
ServerRecvStateInit::Process(ServerRecvThread &server)
ServerRecvStateInit::InternalProcess(ServerRecvThread &server, SessionWrapper session, boost::shared_ptr<NetPacket> packet)
{
int retVal = MSG_SOCK_INIT_DONE;
SOCKET recvSock = server.Select();
if (recvSock != INVALID_SOCKET)
// Session should be in initial state.
if (session.sessionData->GetState() != SessionData::Init)
{
SessionWrapper session = server.GetSession(recvSock);
boost::shared_ptr<NetPacket> packet;
try
{
packet = server.GetReceiver().Recv(recvSock);
} catch (const NetException &)
{
if (session.sessionData.get())
{
server.CloseSessionDelayed(session);
return retVal;
}
}
// Ignore if no session / no packet.
if (packet.get() && session.sessionData.get())
{
// Session should be in initial state.
if (session.sessionData->GetState() != SessionData::Init)
{
server.SessionError(session, ERR_SOCK_INVALID_STATE);
return retVal;
}
// Only accept join game packets.
const NetPacketJoinGame *tmpPacket = packet->ToNetPacketJoinGame();
if (!tmpPacket)
{
server.SessionError(session, ERR_SOCK_INVALID_PACKET);
return retVal;
}
NetPacketJoinGame::Data joinGameData;
tmpPacket->GetData(joinGameData);
// Check the protocol version.
if (joinGameData.versionMajor != NET_VERSION_MAJOR)
{
server.SessionError(session, ERR_NET_VERSION_NOT_SUPPORTED);
return retVal;
}
size_t curNumPlayers = server.GetCurNumberOfPlayers();
// Check the number of players.
if (curNumPlayers >= (size_t)server.GetGameData().numberOfPlayers)
{
server.SessionError(session, ERR_NET_SERVER_FULL);
return retVal;
}
// Check the server password.
if (!server.CheckPassword(joinGameData.password))
{
server.SessionError(session, ERR_NET_INVALID_PASSWORD);
return retVal;
}
// 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)
{
server.SessionError(session, ERR_NET_INVALID_PLAYER_NAME);
return retVal;
}
// Check whether this player is already connected.
if (server.IsPlayerConnected(joinGameData.playerName))
{
server.SessionError(session, ERR_NET_PLAYER_NAME_IN_USE);
return retVal;
}
// Create player data object.
boost::shared_ptr<PlayerData> tmpPlayerData(
new PlayerData(m_curUniquePlayerId++, server.GetNextPlayerNumber(), joinGameData.ptype));
tmpPlayerData->SetName(joinGameData.playerName);
tmpPlayerData->SetNetSessionData(session.sessionData);
// Send ACK to client.
boost::shared_ptr<NetPacket> answer(new NetPacketJoinGameAck);
NetPacketJoinGameAck::Data joinGameAckData;
joinGameAckData.sessionId = session.sessionData->GetId(); // TODO: currently unused.
joinGameAckData.yourPlayerUniqueId = tmpPlayerData->GetUniqueId();
joinGameAckData.yourPlayerNum = tmpPlayerData->GetNumber();
joinGameAckData.gameData = server.GetGameData();
static_cast<NetPacketJoinGameAck *>(answer.get())->SetData(joinGameAckData);
server.GetSender().Send(recvSock, answer);
// Send notifications for connected players to client.
PlayerDataList tmpPlayerList = server.GetPlayerDataList();
PlayerDataList::iterator player_i = tmpPlayerList.begin();
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.playerNumber = (*player_i)->GetNumber();
otherPlayerJoinedData.ptype = (*player_i)->GetType();
static_cast<NetPacketPlayerJoined *>(otherPlayerJoined.get())->SetData(otherPlayerJoinedData);
server.GetSender().Send(session.sessionData->GetSocket(), otherPlayerJoined);
++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.playerNumber = tmpPlayerData->GetNumber();
thisPlayerJoinedData.ptype = tmpPlayerData->GetType();
static_cast<NetPacketPlayerJoined *>(thisPlayerJoined.get())->SetData(thisPlayerJoinedData);
server.SendToAllPlayers(thisPlayerJoined);
// Set player data for session.
server.SetSessionPlayerData(session.sessionData, tmpPlayerData);
// Session is now established.
session.sessionData->SetState(SessionData::Established);
}
server.SessionError(session, ERR_SOCK_INVALID_STATE);
return retVal;
}
// Only accept join game packets.
const NetPacketJoinGame *tmpPacket = packet->ToNetPacketJoinGame();
if (!tmpPacket)
{
server.SessionError(session, ERR_SOCK_INVALID_PACKET);
return retVal;
}
NetPacketJoinGame::Data joinGameData;
tmpPacket->GetData(joinGameData);
// Check the protocol version.
if (joinGameData.versionMajor != NET_VERSION_MAJOR)
{
server.SessionError(session, ERR_NET_VERSION_NOT_SUPPORTED);
return retVal;
}
size_t curNumPlayers = server.GetCurNumberOfPlayers();
// Check the number of players.
if (curNumPlayers >= (size_t)server.GetGameData().numberOfPlayers)
{
server.SessionError(session, ERR_NET_SERVER_FULL);
return retVal;
}
// Check the server password.
if (!server.CheckPassword(joinGameData.password))
{
server.SessionError(session, ERR_NET_INVALID_PASSWORD);
return retVal;
}
// 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)
{
server.SessionError(session, ERR_NET_INVALID_PLAYER_NAME);
return retVal;
}
// Check whether this player is already connected.
if (server.IsPlayerConnected(joinGameData.playerName))
{
server.SessionError(session, ERR_NET_PLAYER_NAME_IN_USE);
return retVal;
}
// Create player data object.
boost::shared_ptr<PlayerData> tmpPlayerData(
new PlayerData(m_curUniquePlayerId++, server.GetNextPlayerNumber(), joinGameData.ptype));
tmpPlayerData->SetName(joinGameData.playerName);
tmpPlayerData->SetNetSessionData(session.sessionData);
// Send ACK to client.
boost::shared_ptr<NetPacket> answer(new NetPacketJoinGameAck);
NetPacketJoinGameAck::Data joinGameAckData;
joinGameAckData.sessionId = session.sessionData->GetId(); // TODO: currently unused.
joinGameAckData.yourPlayerUniqueId = tmpPlayerData->GetUniqueId();
joinGameAckData.yourPlayerNum = tmpPlayerData->GetNumber();
joinGameAckData.gameData = server.GetGameData();
static_cast<NetPacketJoinGameAck *>(answer.get())->SetData(joinGameAckData);
server.GetSender().Send(session.sessionData->GetSocket(), answer);
// Send notifications for connected players to client.
PlayerDataList tmpPlayerList = server.GetPlayerDataList();
PlayerDataList::iterator player_i = tmpPlayerList.begin();
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.playerNumber = (*player_i)->GetNumber();
otherPlayerJoinedData.ptype = (*player_i)->GetType();
static_cast<NetPacketPlayerJoined *>(otherPlayerJoined.get())->SetData(otherPlayerJoinedData);
server.GetSender().Send(session.sessionData->GetSocket(), otherPlayerJoined);
++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.playerNumber = tmpPlayerData->GetNumber();
thisPlayerJoinedData.ptype = tmpPlayerData->GetType();
static_cast<NetPacketPlayerJoined *>(thisPlayerJoined.get())->SetData(thisPlayerJoinedData);
server.SendToAllPlayers(thisPlayerJoined);
// Set player data for session.
server.SetSessionPlayerData(session.sessionData, tmpPlayerData);
// Session is now established.
session.sessionData->SetState(SessionData::Established);
return retVal;
}
@@ -463,62 +502,50 @@ ServerRecvStateWaitPlayerAction::~ServerRecvStateWaitPlayerAction()
{
}
void
ServerRecvStateWaitPlayerAction::HandleNewConnection(ServerRecvThread &server, boost::shared_ptr<ConnectData> connData)
{
// C++ really sucks concerning multiple inheritance *sigh*.
// So this is a copy & paste from ServerRecvStateRunning.
// Do not accept new connections in this state.
server.RejectNewConnection(connData);
}
int
ServerRecvStateWaitPlayerAction::Process(ServerRecvThread &server)
ServerRecvStateWaitPlayerAction::InternalProcess(ServerRecvThread &server, SessionWrapper session, boost::shared_ptr<NetPacket> packet)
{
int retVal = MSG_SOCK_INTERNAL_PENDING;
SOCKET recvSock = server.Select();
if (recvSock != INVALID_SOCKET)
if (packet->ToNetPacketPlayersAction())
{
SessionWrapper session = server.GetSession(recvSock);
boost::shared_ptr<NetPacket> packet;
try
{
packet = server.GetReceiver().Recv(recvSock);
} catch (const NetException &)
{
if (session.sessionData.get())
{
server.CloseSessionDelayed(session);
return retVal;
}
}
NetPacketPlayersAction::Data actionData;
packet->ToNetPacketPlayersAction()->GetData(actionData);
Game &curGame = server.GetGame();
PlayerInterface *tmpPlayer = curGame.getPlayerByUniqueId(session.playerData->GetUniqueId());
assert(tmpPlayer); // TODO throw exception
// Ignore if no session / no packet.
if (packet.get() && session.sessionData.get())
{
if (packet->ToNetPacketPlayersAction())
{
NetPacketPlayersAction::Data actionData;
packet->ToNetPacketPlayersAction()->GetData(actionData);
Game &curGame = server.GetGame();
PlayerInterface *tmpPlayer = curGame.getPlayerByUniqueId(session.playerData->GetUniqueId());
assert(tmpPlayer); // TODO throw exception
tmpPlayer->setMyAction(actionData.playerAction);
tmpPlayer->setMySet(actionData.playerBet);
tmpPlayer->setMyAction(actionData.playerAction);
tmpPlayer->setMySet(actionData.playerBet);
if (tmpPlayer->getMySet() > GetHighestSet(curGame))
SetHighestSet(curGame, tmpPlayer->getMySet());
if (tmpPlayer->getMySet() > GetHighestSet(curGame))
SetHighestSet(curGame, tmpPlayer->getMySet());
boost::shared_ptr<NetPacket> notifyActionDone(new NetPacketPlayersActionDone);
NetPacketPlayersActionDone::Data actionDoneData;
actionDoneData.gameState = static_cast<GameState>(curGame.getCurrentHand()->getActualRound());
actionDoneData.playerId = session.playerData->GetUniqueId();
actionDoneData.playerAction = actionData.playerAction;
actionDoneData.totalPlayerBet = tmpPlayer->getMySet();
actionDoneData.playerMoney = tmpPlayer->getMyCash();
actionDoneData.potSize = curGame.getCurrentHand()->getBoard()->getPot();
actionDoneData.curHandBets = curGame.getCurrentHand()->getBoard()->getSets();
static_cast<NetPacketPlayersActionDone *>(notifyActionDone.get())->SetData(actionDoneData);
server.SendToAllPlayers(notifyActionDone);
boost::shared_ptr<NetPacket> notifyActionDone(new NetPacketPlayersActionDone);
NetPacketPlayersActionDone::Data actionDoneData;
actionDoneData.gameState = static_cast<GameState>(curGame.getCurrentHand()->getActualRound());
actionDoneData.playerId = session.playerData->GetUniqueId();
actionDoneData.playerAction = actionData.playerAction;
actionDoneData.totalPlayerBet = tmpPlayer->getMySet();
actionDoneData.playerMoney = tmpPlayer->getMyCash();
actionDoneData.potSize = curGame.getCurrentHand()->getBoard()->getPot();
actionDoneData.curHandBets = curGame.getCurrentHand()->getBoard()->getSets();
static_cast<NetPacketPlayersActionDone *>(notifyActionDone.get())->SetData(actionDoneData);
server.SendToAllPlayers(notifyActionDone);
server.SetState(ServerRecvStateStartRound::Instance());
retVal = MSG_NET_GAME_SERVER_ACTION;
}
}
server.SetState(ServerRecvStateStartRound::Instance());
retVal = MSG_NET_GAME_SERVER_ACTION;
}
return retVal;
+52
View File
@@ -33,6 +33,7 @@
#define MAX_PACKET_SIZE 256
#define MAX_NAME_SIZE 64
#define MAX_PASSWORD_SIZE 64
#define MAX_CHAT_TEXT_SIZE 128
struct NetPacketHeader;
@@ -47,6 +48,8 @@ class NetPacketPlayersTurn;
class NetPacketPlayersAction;
class NetPacketPlayersActionDone;
class NetPacketPlayersActionRejected;
class NetPacketSendChatText;
class NetPacketChatText;
class NetPacketError;
class NetPacket
@@ -76,6 +79,8 @@ public:
virtual const NetPacketPlayersAction *ToNetPacketPlayersAction() const;
virtual const NetPacketPlayersActionDone *ToNetPacketPlayersActionDone() const;
virtual const NetPacketPlayersActionRejected *ToNetPacketPlayersActionRejected() const;
virtual const NetPacketSendChatText *ToNetPacketSendChatText() const;
virtual const NetPacketChatText *ToNetPacketChatText() const;
virtual const NetPacketError *ToNetPacketError() const;
protected:
@@ -343,6 +348,53 @@ protected:
virtual void Check(const NetPacketHeader* data) const;
};
class NetPacketSendChatText : public NetPacket
{
public:
struct Data
{
std::string text;
};
NetPacketSendChatText();
virtual ~NetPacketSendChatText();
virtual boost::shared_ptr<NetPacket> Clone() const;
void SetData(const Data &inData);
void GetData(Data &outData) const;
virtual const NetPacketSendChatText *ToNetPacketSendChatText() const;
protected:
virtual void Check(const NetPacketHeader* data) const;
};
class NetPacketChatText : public NetPacket
{
public:
struct Data
{
u_int16_t playerId;
std::string text;
};
NetPacketChatText();
virtual ~NetPacketChatText();
virtual boost::shared_ptr<NetPacket> Clone() const;
void SetData(const Data &inData);
void GetData(Data &outData) const;
virtual const NetPacketChatText *ToNetPacketChatText() const;
protected:
virtual void Check(const NetPacketHeader* data) const;
};
class NetPacketError : public NetPacket
{
public:
+27 -10
View File
@@ -21,7 +21,7 @@
#ifndef _SERVERRECVSTATE_H_
#define _SERVERRECVSTATE_H_
#include <net/connectdata.h>
#include <net/serverrecvthread.h>
#include <playerdata.h>
#define SERVER_INITIAL_STATE ServerRecvStateInit
@@ -29,7 +29,6 @@
class Game;
class PlayerInterface;
class ServerRecvThread;
class ServerCallback;
class ServerRecvState
@@ -44,8 +43,25 @@ public:
virtual int Process(ServerRecvThread &server) = 0;
};
// Abstract State: Receiving.
class ServerRecvStateReceiving : public ServerRecvState
{
public:
virtual ~ServerRecvStateReceiving();
// Globally handle packets which are allowed in all running states.
// Calls InternalProcess if packet has not been processed.
virtual int Process(ServerRecvThread &server);
protected:
ServerRecvStateReceiving();
virtual int InternalProcess(ServerRecvThread &server, SessionWrapper session, boost::shared_ptr<NetPacket> packet) = 0;
};
// State: Initialization.
class ServerRecvStateInit : public ServerRecvState
class ServerRecvStateInit : public ServerRecvStateReceiving
{
public:
// Access the state singleton.
@@ -56,14 +72,13 @@ public:
//
virtual void HandleNewConnection(ServerRecvThread &server, boost::shared_ptr<ConnectData> data);
//
virtual int Process(ServerRecvThread &server);
protected:
// Protected constructor - this is a singleton.
ServerRecvStateInit();
virtual int InternalProcess(ServerRecvThread &server, SessionWrapper session, boost::shared_ptr<NetPacket> packet);
private:
unsigned m_curUniquePlayerId;
@@ -75,10 +90,11 @@ class ServerRecvStateRunning : public ServerRecvState
public:
virtual ~ServerRecvStateRunning();
//
// Reject new connections.
virtual void HandleNewConnection(ServerRecvThread &server, boost::shared_ptr<ConnectData> data);
protected:
ServerRecvStateRunning();
};
@@ -140,7 +156,7 @@ protected:
};
// State: Wait for a player action.
class ServerRecvStateWaitPlayerAction : public ServerRecvStateRunning
class ServerRecvStateWaitPlayerAction : public ServerRecvStateReceiving
{
public:
// Access the state singleton.
@@ -148,14 +164,15 @@ public:
virtual ~ServerRecvStateWaitPlayerAction();
//
virtual int Process(ServerRecvThread &server);
virtual void HandleNewConnection(ServerRecvThread &server, boost::shared_ptr<ConnectData> data);
protected:
// Protected constructor - this is a singleton.
ServerRecvStateWaitPlayerAction();
virtual int InternalProcess(ServerRecvThread &server, SessionWrapper session, boost::shared_ptr<NetPacket> packet);
static int GetHighestSet(Game &curGame);
static void SetHighestSet(Game &curGame, int highestSet);
};
+1
View File
@@ -163,6 +163,7 @@ private:
ConfigFile *m_playerConfig;
friend class ServerRecvStateInit;
friend class ServerRecvStateReceiving;
friend class ServerRecvStateRunning;
friend class ServerRecvStateStartGame;
friend class ServerRecvStateStartHand;
+1
View File
@@ -48,6 +48,7 @@
#define ERR_NET_INVALID_PASSWORD_STR 105
#define ERR_NET_PLAYER_NAME_IN_USE 106
#define ERR_NET_INVALID_PLAYER_NAME 107
#define ERR_NET_INVALID_CHAT_TEXT 108
// This is an internal message which is not reported.
#define MSG_SOCK_INTERNAL_PENDING 0
+5 -5
View File
@@ -185,12 +185,12 @@ void Session::terminateNetworkServer()
void Session::sendClientPlayerAction()
{
if (!myNetClient)
return;
return; // only act if client is running.
myNetClient->SendPlayerAction();
}
void Session::sendChatMessage(std::string message) {
//hi lothar --> zum testen schick ich es gleich wieder zurück an die gui. wie du siehst klappt es ;-)
myGui->chatAppendMsg(message);
void Session::sendChatMessage(const std::string &message) {
if (!myNetClient)
return; // only act if client is running.
myNetClient->SendChatMessage(message);
}
+1 -1
View File
@@ -59,7 +59,7 @@ public:
void setCurrentGameID(const int& theValue) { currentGameID = theValue; }
int getCurrentGameID() const { return currentGameID; }
void sendChatMessage(std::string message);
void sendChatMessage(const std::string &message);
private: