1 /***************************************************************************** 2 * PokerTH - The open source texas holdem engine * 3 * Copyright (C) 2006-2012 Felix Hammer, Florian Thauer, Lothar May * 4 * * 5 * This program is free software: you can redistribute it and/or modify * 6 * it under the terms of the GNU Affero General Public License as * 7 * published by the Free Software Foundation, either version 3 of the * 8 * License, or (at your option) any later version. * 9 * * 10 * This program is distributed in the hope that it will be useful, * 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 13 * GNU Affero General Public License for more details. * 14 * * 15 * You should have received a copy of the GNU Affero General Public License * 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. * 17 * * 18 * * 19 * Additional permission under GNU AGPL version 3 section 7 * 20 * * 21 * If you modify this program, or any covered work, by linking or * 22 * combining it with the OpenSSL project's OpenSSL library (or a * 23 * modified version of that library), containing parts covered by the * 24 * terms of the OpenSSL or SSLeay licenses, the authors of PokerTH * 25 * (Felix Hammer, Florian Thauer, Lothar May) grant you additional * 26 * permission to convey the resulting work. * 27 * Corresponding Source for a non-source form of such a combination * 28 * shall include the source code for the parts of OpenSSL used as well * 29 * as that of the covered work. * 30 *****************************************************************************/ 31 /* State of a network game. */ 32 33 #ifndef _SERVERGAMESTATE_H_ 34 #define _SERVERGAMESTATE_H_ 35 36 #include <boost/asio.hpp> 37 #include <playerdata.h> 38 #include <net/sessionmanager.h> 39 40 41 #ifdef _MSC_VER 42 #pragma warning(push) 43 #pragma warning(disable : 4250) 44 #endif 45 46 #define SERVER_INITIAL_STATE ServerGameStateInit 47 48 class Game; 49 class ServerGame; 50 class PlayerInterface; 51 class ServerCallback; 52 53 class ServerGameState 54 { 55 public: 56 virtual ~ServerGameState(); 57 virtual void Enter(boost::shared_ptr<ServerGame> server) = 0; 58 virtual void Exit(boost::shared_ptr<ServerGame> server) = 0; 59 60 virtual void NotifyGameAdminChanged(boost::shared_ptr<ServerGame> server) = 0; 61 virtual void NotifySessionRemoved(boost::shared_ptr<ServerGame> server) = 0; 62 63 // Handling of a new player session. 64 virtual void HandleNewPlayer(boost::shared_ptr<ServerGame> server, boost::shared_ptr<SessionData> session) = 0; 65 // Handling of a new spectator session. 66 virtual void HandleNewSpectator(boost::shared_ptr<ServerGame> server, boost::shared_ptr<SessionData> session) = 0; 67 68 // Main processing function of the current state. 69 virtual void ProcessPacket(boost::shared_ptr<ServerGame> server, boost::shared_ptr<SessionData> session, boost::shared_ptr<NetPacket> packet) = 0; 70 }; 71 72 // Abstract State: Receiving. 73 class AbstractServerGameStateReceiving : public ServerGameState 74 { 75 public: 76 virtual ~AbstractServerGameStateReceiving(); 77 78 // Globally handle packets which are allowed in all running states. 79 // Calls InternalProcess if packet has not been processed. 80 virtual void ProcessPacket(boost::shared_ptr<ServerGame> server, boost::shared_ptr<SessionData> session, boost::shared_ptr<NetPacket> packet); 81 82 static boost::shared_ptr<NetPacket> CreateNetPacketPlayerJoined(unsigned gameId, const PlayerData &playerData); 83 static boost::shared_ptr<NetPacket> CreateNetPacketSpectatorJoined(unsigned gameId, const PlayerData &playerData); 84 static boost::shared_ptr<NetPacket> CreateNetPacketJoinGameAck(const ServerGame &server, const PlayerData &playerData, bool spectateOnly); 85 static boost::shared_ptr<NetPacket> CreateNetPacketHandStart(const ServerGame &server); 86 87 static void AcceptNewSession(boost::shared_ptr<ServerGame> server, boost::shared_ptr<SessionData> session, bool spectateOnly); 88 89 protected: 90 91 virtual void InternalProcessPacket(boost::shared_ptr<ServerGame> server, boost::shared_ptr<SessionData> session, boost::shared_ptr<NetPacket> packet) = 0; 92 }; 93 94 // State: Initialization. 95 class ServerGameStateInit : public AbstractServerGameStateReceiving 96 { 97 public: 98 static ServerGameStateInit &Instance(); 99 virtual void Enter(boost::shared_ptr<ServerGame> server); 100 virtual void Exit(boost::shared_ptr<ServerGame> server); 101 102 virtual ~ServerGameStateInit(); 103 104 virtual void NotifyGameAdminChanged(boost::shared_ptr<ServerGame> server); 105 virtual void NotifySessionRemoved(boost::shared_ptr<ServerGame> server); 106 107 virtual void HandleNewPlayer(boost::shared_ptr<ServerGame> server, boost::shared_ptr<SessionData> session); 108 virtual void HandleNewSpectator(boost::shared_ptr<ServerGame> server, boost::shared_ptr<SessionData> session); 109 110 protected: 111 ServerGameStateInit(); 112 113 void RegisterAdminTimer(boost::shared_ptr<ServerGame> server); 114 void UnregisterAdminTimer(boost::shared_ptr<ServerGame> server); 115 void RegisterAutoStartTimer(boost::shared_ptr<ServerGame> server); 116 void UnregisterAutoStartTimer(boost::shared_ptr<ServerGame> server); 117 void TimerAutoStart(const boost::system::error_code &ec, boost::shared_ptr<ServerGame> server); 118 void TimerAdminWarning(const boost::system::error_code &ec, boost::shared_ptr<ServerGame> server); 119 void TimerAdminTimeout(const boost::system::error_code &ec, boost::shared_ptr<ServerGame> server); 120 void SendStartEvent(ServerGame &server, bool fillWithComputerPlayers); 121 122 virtual void InternalProcessPacket(boost::shared_ptr<ServerGame> server, boost::shared_ptr<SessionData> session, boost::shared_ptr<NetPacket> packet); 123 124 private: 125 static ServerGameStateInit s_state; 126 }; 127 128 // Wait for Ack of start event and start game. 129 class ServerGameStateStartGame : public AbstractServerGameStateReceiving 130 { 131 public: 132 static ServerGameStateStartGame &Instance(); 133 virtual void Enter(boost::shared_ptr<ServerGame> server); 134 virtual void Exit(boost::shared_ptr<ServerGame> server); 135 136 virtual ~ServerGameStateStartGame(); 137 NotifyGameAdminChanged(boost::shared_ptr<ServerGame>)138 virtual void NotifyGameAdminChanged(boost::shared_ptr<ServerGame> /*server*/) {} NotifySessionRemoved(boost::shared_ptr<ServerGame>)139 virtual void NotifySessionRemoved(boost::shared_ptr<ServerGame> /*server*/) {} 140 virtual void HandleNewPlayer(boost::shared_ptr<ServerGame> server, boost::shared_ptr<SessionData> session); 141 virtual void HandleNewSpectator(boost::shared_ptr<ServerGame> server, boost::shared_ptr<SessionData> session); 142 143 protected: 144 ServerGameStateStartGame(); 145 146 virtual void InternalProcessPacket(boost::shared_ptr<ServerGame> server, boost::shared_ptr<SessionData> session, boost::shared_ptr<NetPacket> packet); 147 void TimerTimeout(const boost::system::error_code &ec, boost::shared_ptr<ServerGame> server); 148 void DoStart(boost::shared_ptr<ServerGame> server); 149 150 private: 151 static ServerGameStateStartGame s_state; 152 }; 153 154 class AbstractServerGameStateRunning : public AbstractServerGameStateReceiving 155 { 156 public: 157 virtual ~AbstractServerGameStateRunning(); 158 159 virtual void HandleNewPlayer(boost::shared_ptr<ServerGame> server, boost::shared_ptr<SessionData> session); 160 virtual void HandleNewSpectator(boost::shared_ptr<ServerGame> server, boost::shared_ptr<SessionData> session); 161 162 protected: 163 virtual void InternalProcessPacket(boost::shared_ptr<ServerGame> server, boost::shared_ptr<SessionData> session, boost::shared_ptr<NetPacket> packet); 164 }; 165 166 // State: Within hand. 167 class ServerGameStateHand : public AbstractServerGameStateRunning 168 { 169 public: 170 static ServerGameStateHand &Instance(); 171 virtual void Enter(boost::shared_ptr<ServerGame> server); 172 virtual void Exit(boost::shared_ptr<ServerGame> server); 173 174 virtual ~ServerGameStateHand(); 175 NotifyGameAdminChanged(boost::shared_ptr<ServerGame>)176 virtual void NotifyGameAdminChanged(boost::shared_ptr<ServerGame> /*server*/) {} NotifySessionRemoved(boost::shared_ptr<ServerGame>)177 virtual void NotifySessionRemoved(boost::shared_ptr<ServerGame> /*server*/) {} 178 179 protected: 180 ServerGameStateHand(); 181 182 virtual void InternalProcessPacket(boost::shared_ptr<ServerGame> server, boost::shared_ptr<SessionData> session, boost::shared_ptr<NetPacket> packet); 183 void TimerLoop(const boost::system::error_code &ec, boost::shared_ptr<ServerGame> server); 184 void EngineLoop(boost::shared_ptr<ServerGame> server); 185 void TimerShowCards(const boost::system::error_code &ec, boost::shared_ptr<ServerGame> server); 186 void TimerComputerAction(const boost::system::error_code &ec, boost::shared_ptr<ServerGame> server); 187 void TimerNextHand(const boost::system::error_code &ec, boost::shared_ptr<ServerGame> server); 188 void TimerNextGame(const boost::system::error_code &ec, boost::shared_ptr<ServerGame> server, unsigned winnerPlayerId); 189 int GetDealCardsDelaySec(ServerGame &server); 190 static void StartNewHand(boost::shared_ptr<ServerGame> server); 191 static void CheckPlayerTimeouts(boost::shared_ptr<ServerGame> server); 192 static void ReactivatePlayers(boost::shared_ptr<ServerGame> server); 193 static void InitRejoiningPlayers(boost::shared_ptr<ServerGame> server); 194 static void InitNewSpectators(boost::shared_ptr<ServerGame> server); 195 static void PerformRejoin(boost::shared_ptr<ServerGame> server, boost::shared_ptr<SessionData> session); 196 static void SendGameData(boost::shared_ptr<ServerGame> server, boost::shared_ptr<SessionData> session); 197 198 private: 199 static ServerGameStateHand s_state; 200 201 friend class ServerGameStateStartGame; 202 friend class ServerGameStateWaitNextHand; 203 }; 204 205 // State: Wait for a player action. 206 class ServerGameStateWaitPlayerAction : public AbstractServerGameStateRunning 207 { 208 public: 209 static ServerGameStateWaitPlayerAction &Instance(); 210 virtual void Enter(boost::shared_ptr<ServerGame> server); 211 virtual void Exit(boost::shared_ptr<ServerGame> server); 212 213 virtual ~ServerGameStateWaitPlayerAction(); 214 NotifyGameAdminChanged(boost::shared_ptr<ServerGame>)215 virtual void NotifyGameAdminChanged(boost::shared_ptr<ServerGame> /*server*/) {} NotifySessionRemoved(boost::shared_ptr<ServerGame>)216 virtual void NotifySessionRemoved(boost::shared_ptr<ServerGame> /*server*/) {} 217 218 protected: 219 ServerGameStateWaitPlayerAction(); 220 221 virtual void InternalProcessPacket(boost::shared_ptr<ServerGame> server, boost::shared_ptr<SessionData> session, boost::shared_ptr<NetPacket> packet); 222 void TimerTimeout(const boost::system::error_code &ec, boost::shared_ptr<ServerGame> server); 223 224 private: 225 static ServerGameStateWaitPlayerAction s_state; 226 }; 227 228 // State: Wait for the next hand. 229 class ServerGameStateWaitNextHand : public AbstractServerGameStateRunning 230 { 231 public: 232 static ServerGameStateWaitNextHand &Instance(); 233 virtual void Enter(boost::shared_ptr<ServerGame> server); 234 virtual void Exit(boost::shared_ptr<ServerGame> server); 235 236 virtual ~ServerGameStateWaitNextHand(); 237 NotifyGameAdminChanged(boost::shared_ptr<ServerGame>)238 virtual void NotifyGameAdminChanged(boost::shared_ptr<ServerGame> /*server*/) {} NotifySessionRemoved(boost::shared_ptr<ServerGame>)239 virtual void NotifySessionRemoved(boost::shared_ptr<ServerGame> /*server*/) {} 240 241 protected: 242 ServerGameStateWaitNextHand(); 243 244 virtual void InternalProcessPacket(boost::shared_ptr<ServerGame> server, boost::shared_ptr<SessionData> session, boost::shared_ptr<NetPacket> packet); 245 void TimerTimeout(const boost::system::error_code &ec, boost::shared_ptr<ServerGame> server); 246 247 private: 248 static ServerGameStateWaitNextHand s_state; 249 }; 250 251 class ServerGameStateFinal : public ServerGameState 252 { 253 public: 254 static ServerGameStateFinal &Instance(); 255 ~ServerGameStateFinal()256 virtual ~ServerGameStateFinal() {} Enter(boost::shared_ptr<ServerGame>)257 virtual void Enter(boost::shared_ptr<ServerGame> /*server*/) {} Exit(boost::shared_ptr<ServerGame>)258 virtual void Exit(boost::shared_ptr<ServerGame> /*server*/) {} 259 NotifyGameAdminChanged(boost::shared_ptr<ServerGame>)260 virtual void NotifyGameAdminChanged(boost::shared_ptr<ServerGame> /*server*/) {} NotifySessionRemoved(boost::shared_ptr<ServerGame>)261 virtual void NotifySessionRemoved(boost::shared_ptr<ServerGame> /*server*/) {} 262 263 // Handling of a new session. HandleNewPlayer(boost::shared_ptr<ServerGame>,boost::shared_ptr<SessionData>)264 virtual void HandleNewPlayer(boost::shared_ptr<ServerGame> /*server*/, boost::shared_ptr<SessionData> /*session*/) {} HandleNewSpectator(boost::shared_ptr<ServerGame>,boost::shared_ptr<SessionData>)265 virtual void HandleNewSpectator(boost::shared_ptr<ServerGame> /*server*/, boost::shared_ptr<SessionData> /*session*/) {} 266 267 // Main processing function of the current state. ProcessPacket(boost::shared_ptr<ServerGame>,boost::shared_ptr<SessionData>,boost::shared_ptr<NetPacket>)268 virtual void ProcessPacket(boost::shared_ptr<ServerGame> /*server*/, boost::shared_ptr<SessionData> /*session*/, boost::shared_ptr<NetPacket> /*packet*/) {} 269 270 protected: ServerGameStateFinal()271 ServerGameStateFinal() {} 272 273 private: 274 static ServerGameStateFinal s_state; 275 }; 276 277 #ifdef _MSC_VER 278 #pragma warning(pop) 279 #endif 280 281 #endif 282