SuperTuxKart
lobby_protocol.hpp
1 //
2 // SuperTuxKart - a fun racing game with go-kart
3 // Copyright (C) 2013-2015 SuperTuxKart-Team
4 //
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License
7 // as published by the Free Software Foundation; either version 3
8 // of the 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 General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 
19 #ifndef LOBBY_PROTOCOL_HPP
20 #define LOBBY_PROTOCOL_HPP
21 
22 #include "network/protocol.hpp"
23 #include "utils/stk_process.hpp"
24 
25 class GameSetup;
27 class PeerVote;
28 class RemoteKartInfo;
29 class Track;
30 
31 #include <atomic>
32 #include <cassert>
33 #include <map>
34 #include <memory>
35 #include <mutex>
36 #include <string>
37 #include <thread>
38 #include <vector>
39 
46 class LobbyProtocol : public Protocol
47 {
48 public:
50  enum : uint8_t
51  {
52  LE_CONNECTION_REQUESTED = 1, // a connection to the server
53  LE_CONNECTION_REFUSED, // Connection to server refused
54  LE_CONNECTION_ACCEPTED, // Connection to server accepted
55  LE_SERVER_INFO, // inform client about server info
56  LE_REQUEST_BEGIN, // begin of kart selection
57  LE_UPDATE_PLAYER_LIST, // inform client about player list update
58  LE_KART_SELECTION, // Player selected kart
59  LE_PLAYER_DISCONNECTED, // Client disconnected
60  LE_CLIENT_LOADED_WORLD, // Client finished loading world
61  LE_LOAD_WORLD, // Clients should load world
62  LE_START_RACE, // Server to client to start race
63  LE_START_SELECTION, // inform client to start selection
64  LE_RACE_FINISHED, // race has finished, display result
65  LE_RACE_FINISHED_ACK, // client went back to lobby
66  LE_BACK_LOBBY, // Force clients to go back to lobby
67  LE_VOTE, // Track vote
68  LE_CHAT, // Client chat message
69  LE_SERVER_OWNERSHIP, // Tell client he is now the server owner
70  LE_KICK_HOST, // Server owner kicks some other peer in game
71  LE_CHANGE_TEAM, // Client wants to change his team
72  LE_BAD_TEAM, // Tell server owner that the team is unbalanced
73  LE_BAD_CONNECTION, // High ping or too many packets loss
74  LE_CONFIG_SERVER, // Server owner config server game mode or difficulty
75  LE_CHANGE_HANDICAP, // Client changes handicap
76  LE_LIVE_JOIN, // Client live join or spectate
77  LE_LIVE_JOIN_ACK, // Server tell client live join or spectate succeed
78  LE_KART_INFO, // Client or server exchange new kart info
79  LE_CLIENT_BACK_LOBBY, // Client tell server to go back lobby
80  LE_REPORT_PLAYER, // Client report some player in server
81  // (like abusive behaviour)
82  LE_ASSETS_UPDATE, // Client tell server with updated assets
83  LE_COMMAND, // Command
84  };
85 
86  enum RejectReason : uint8_t
87  {
88  RR_BUSY = 0,
89  RR_BANNED = 1,
90  RR_INCORRECT_PASSWORD = 2,
91  RR_INCOMPATIBLE_DATA = 3,
92  RR_TOO_MANY_PLAYERS = 4,
93  RR_INVALID_PLAYER = 5
94  };
95 
96  enum BackLobbyReason : uint8_t
97  {
98  BLR_NONE = 0,
99  BLR_NO_GAME_FOR_LIVE_JOIN = 1,
100  BLR_NO_PLACE_FOR_LIVE_JOIN = 2,
101  BLR_ONE_PLAYER_IN_RANKED_MATCH = 3,
102  BLR_SERVER_ONWER_QUITED_THE_GAME = 4,
103  BLR_SPECTATING_NEXT_GAME = 5
104  };
105 
106 protected:
107  const ProcessType m_process_type;
110  std::map<uint32_t, PeerVote> m_peers_votes;
111 
113  std::atomic<uint64_t> m_end_voting_period;
114 
117 
118  std::thread m_start_game_thread;
119 
120  static std::weak_ptr<LobbyProtocol> m_lobby[PT_COUNT];
121 
124  std::atomic<uint32_t> m_estimated_remaining_time;
125 
128  std::atomic<uint32_t> m_estimated_progress;
129 
133 
135  mutable std::mutex m_current_track_mutex;
136 
138  std::string m_current_track;
139 
142 
143  // ------------------------------------------------------------------------
144  void configRemoteKart(
145  const std::vector<std::shared_ptr<NetworkPlayerProfile> >& players,
146  int local_player_size) const;
147  // ------------------------------------------------------------------------
148  void joinStartGameThread()
149  {
150  if (m_start_game_thread.joinable())
151  m_start_game_thread.join();
152  }
153  // ------------------------------------------------------------------------
154  void addLiveJoiningKart(int kart_id, const RemoteKartInfo& rki,
155  int live_join_util_ticks) const;
156  // ------------------------------------------------------------------------
157  void exitGameState();
158 public:
159 
161  template<typename Singleton, typename... Types>
162  static std::shared_ptr<Singleton> create(Types ...args)
163  {
164  ProcessType pt = STKProcess::getType();
165  assert(m_lobby[pt].expired());
166  auto ret = std::make_shared<Singleton>(args...);
167  m_lobby[pt] = ret;
168  return std::dynamic_pointer_cast<Singleton>(ret);
169  } // create
170 
171  // ------------------------------------------------------------------------
173  template<class T> static std::shared_ptr<T> get()
174  {
175  ProcessType pt = STKProcess::getType();
176  if (std::shared_ptr<LobbyProtocol> lp = m_lobby[pt].lock())
177  {
178  std::shared_ptr<T> new_type = std::dynamic_pointer_cast<T>(lp);
179  if (new_type)
180  return new_type;
181  }
182  return nullptr;
183  } // get
184 
185  // ------------------------------------------------------------------------
187  template<class T> static std::shared_ptr<T> getByType(ProcessType pt)
188  {
189  if (std::shared_ptr<LobbyProtocol> lp = m_lobby[pt].lock())
190  {
191  std::shared_ptr<T> new_type = std::dynamic_pointer_cast<T>(lp);
192  if (new_type)
193  return new_type;
194  }
195  return nullptr;
196  } // get
197 
198  // ------------------------------------------------------------------------
199 
200  LobbyProtocol();
201  virtual ~LobbyProtocol();
202  virtual void setup() = 0;
203  virtual void update(int ticks) = 0;
204  virtual void finishedLoadingWorld() = 0;
205  virtual void loadWorld();
206  virtual bool allPlayersReady() const = 0;
207  virtual bool isRacing() const = 0;
208  void startVotingPeriod(float max_time);
209  float getRemainingVotingTime();
210  bool isVotingOver();
211  // ------------------------------------------------------------------------
213  float getMaxVotingTime() { return m_max_voting_time / 1000.0f; }
214  // ------------------------------------------------------------------------
216  GameSetup* getGameSetup() const { return m_game_setup; }
217  // ------------------------------------------------------------------------
219  int getNumberOfVotes() const { return (int)m_peers_votes.size(); }
220  // -----------------------------------------------------------------------
221  void addVote(uint32_t host_id, const PeerVote &vote);
222  // -----------------------------------------------------------------------
223  const PeerVote* getVote(uint32_t host_id) const;
224  // -----------------------------------------------------------------------
225  void resetVotingTime() { m_end_voting_period.store(0); }
226  // -----------------------------------------------------------------------
228  const std::map<uint32_t, PeerVote>& getAllVotes() const
229  { return m_peers_votes; }
230  // -----------------------------------------------------------------------
231  std::pair<uint32_t, uint32_t> getGameStartedProgress() const
232  {
233  return std::make_pair(m_estimated_remaining_time.load(),
234  m_estimated_progress.load());
235  }
236  // ------------------------------------------------------------------------
237  void setGameStartedProgress(const std::pair<uint32_t, uint32_t>& p)
238  {
239  m_estimated_remaining_time.store(p.first);
240  m_estimated_progress.store(p.second);
241  }
242  // ------------------------------------------------------------------------
243  void resetGameStartedProgress()
244  {
245  m_estimated_remaining_time.store(std::numeric_limits<uint32_t>::max());
246  m_estimated_progress.store(std::numeric_limits<uint32_t>::max());
247  }
248  // ------------------------------------------------------------------------
249  bool hasLiveJoiningRecently() const;
250  // ------------------------------------------------------------------------
251  void storePlayingTrack(const std::string& track_ident)
252  {
253  std::lock_guard<std::mutex> lock(m_current_track_mutex);
254  m_current_track = track_ident;
255  }
256  // ------------------------------------------------------------------------
257  std::string getPlayingTrackIdent() const
258  {
259  std::lock_guard<std::mutex> lock(m_current_track_mutex);
260  return m_current_track;
261  }
262  // ------------------------------------------------------------------------
263  Track* getPlayingTrack() const;
264 }; // class LobbyProtocol
265 
266 #endif // LOBBY_PROTOCOL_HPP
Used to store the needed data about the players that join a game. This class stores all the possible ...
Definition: game_setup.hpp:43
Base class for both client and server lobby. The lobbies are started when a server opens a game,...
Definition: lobby_protocol.hpp:47
float getRemainingVotingTime()
Returns the remaining voting time in seconds.
Definition: lobby_protocol.cpp:194
void startVotingPeriod(float max_time)
Starts the voting period time with the specified maximum time.
Definition: lobby_protocol.cpp:186
virtual void update(int ticks)=0
Called by the protocol listener, synchronously with the main loop.
std::map< uint32_t, PeerVote > m_peers_votes
Vote from each peer.
Definition: lobby_protocol.hpp:110
bool isVotingOver()
Returns if the voting period is over.
Definition: lobby_protocol.cpp:205
const std::map< uint32_t, PeerVote > & getAllVotes() const
Returns all voting data.
Definition: lobby_protocol.hpp:228
std::atomic< uint32_t > m_estimated_remaining_time
Estimated current started game remaining time, uint32_t max if not available.
Definition: lobby_protocol.hpp:124
int m_last_live_join_util_ticks
Save the last live join ticks, for physical objects to update current transformation in server,...
Definition: lobby_protocol.hpp:132
int getNumberOfVotes() const
Returns the number of votes received so far.
Definition: lobby_protocol.hpp:219
virtual void loadWorld()
Starts the sychronization protocol and the RaceEventManager.
Definition: lobby_protocol.cpp:75
GameSetup * getGameSetup() const
Returns the game setup data structure.
Definition: lobby_protocol.hpp:216
std::string m_current_track
Store current playing track in name.
Definition: lobby_protocol.hpp:138
std::atomic< uint64_t > m_end_voting_period
Timer user for voting periods in both lobbies.
Definition: lobby_protocol.hpp:113
float getMaxVotingTime()
Returns the maximum floating time in seconds.
Definition: lobby_protocol.hpp:213
static std::shared_ptr< T > get()
Returns the singleton client or server lobby protocol.
Definition: lobby_protocol.hpp:173
virtual void setup()=0
A previous GameSetup is deleted and a new one is created.
Definition: lobby_protocol.cpp:171
GameSetup * m_game_setup
Stores data about the online game to play.
Definition: lobby_protocol.hpp:141
uint64_t m_max_voting_time
The maximum voting time.
Definition: lobby_protocol.hpp:116
static std::shared_ptr< T > getByType(ProcessType pt)
Returns specific singleton client or server lobby protocol.
Definition: lobby_protocol.hpp:187
const PeerVote * getVote(uint32_t host_id) const
Returns the voting data for one host.
Definition: lobby_protocol.cpp:224
std::mutex m_current_track_mutex
Mutex to protect m_current_track.
Definition: lobby_protocol.hpp:135
static std::shared_ptr< Singleton > create(Types ...args)
Creates either a client or server lobby protocol as a singleton.
Definition: lobby_protocol.hpp:162
void addVote(uint32_t host_id, const PeerVote &vote)
Adds a vote.
Definition: lobby_protocol.cpp:215
std::atomic< uint32_t > m_estimated_progress
Estimated current started game progress in 0-100%, uint32_t max if not available.
Definition: lobby_protocol.hpp:128
Contains the profile of a player.
Definition: network_player_profile.hpp:42
A simple structure to store a vote from a client: track name, number of laps and reverse or not.
Definition: peer_vote.hpp:30
Abstract class used to define the global protocol functions.
Definition: protocol.hpp:68
Definition: remote_kart_info.hpp:52
Definition: singleton.hpp:87
Definition: track.hpp:115
Generic protocols declarations.