1 //
2 //  SuperTuxKart - a fun racing game with go-kart
3 //  Copyright (C) 2018 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 CLIENT_LOBBY_HPP
20 #define CLIENT_LOBBY_HPP
21 
22 #include "input/input.hpp"
23 #include "network/protocols/lobby_protocol.hpp"
24 #include "utils/cpp2011.hpp"
25 
26 #include <enet/enet.h>
27 
28 #include <atomic>
29 #include <map>
30 #include <memory>
31 #include <set>
32 
33 enum PeerDisconnectInfo : unsigned int;
34 enum KartTeam : int8_t;
35 enum HandicapLevel : uint8_t;
36 
37 class BareNetworkString;
38 class Server;
39 
40 struct LobbyPlayer
41 {
42     irr::core::stringw m_user_name;
43     int m_local_player_id;
44     uint32_t m_host_id;
45     KartTeam m_kart_team;
46     HandicapLevel m_handicap;
47     uint32_t m_online_id;
48     /* Icon used in networking lobby, see NetworkingLobby::loadedFromFile. */
49     int m_icon_id;
50     std::string m_country_code;
51     /* Icon id for spectator in NetworkingLobby::loadedFromFile is 5. */
isSpectatorLobbyPlayer52     bool isSpectator() const { return m_icon_id == 5; }
isAILobbyPlayer53     bool isAI() const { return m_icon_id == 6; }
54 };
55 
56 class ClientLobby : public LobbyProtocol
57 {
58 private:
59     void disconnectedPlayer(Event* event);
60     void connectionAccepted(Event* event); //!< Callback function on connection acceptation
61     void connectionRefused(Event* event); //!< Callback function on connection refusal
62     void startGame(Event* event);
63     void startSelection(Event* event);
64     void raceFinished(Event* event);
65     void backToLobby(Event *event);
66     // race votes
67     void receivePlayerVote(Event* event);
68     void updatePlayerList(Event* event);
69     void handleChat(Event* event);
70     void handleServerInfo(Event* event);
71     void reportSuccess(Event* event);
72     void handleBadTeam();
73     void handleBadConnection();
74     void becomingServerOwner();
75 
76     std::shared_ptr<Server> m_server;
77 
78     enum ClientState : unsigned int
79     {
80         NONE,
81         LINKED,
82         REQUESTING_CONNECTION,
83         CONNECTED,              // means in the lobby room
84         SELECTING_ASSETS,       // in the kart selection or tracks screen
85         RACING,                 // racing
86         RACE_FINISHED,          // race result shown
87         DONE,
88         EXITING
89     };
90 
91     bool m_waiting_for_game;
92 
93     bool m_server_auto_game_time;
94 
95     bool m_received_server_result;
96 
97     bool m_auto_started;
98 
99     bool m_first_connect;
100 
101     bool m_spectator;
102 
103     bool m_server_live_joinable;
104 
105     bool m_server_send_live_load_world;
106 
107     bool m_server_enabled_chat;
108 
109     bool m_server_enabled_track_voting;
110 
111     bool m_server_enabled_report_player;
112 
113     uint64_t m_auto_back_to_lobby_time;
114 
115     uint64_t m_start_live_game_time;
116 
117     /** The state of the finite state machine. */
118     std::atomic<ClientState> m_state;
119 
120     std::set<std::string> m_available_karts;
121     std::set<std::string> m_available_tracks;
122 
123     void addAllPlayers(Event* event);
124     void finalizeConnectionRequest(NetworkString* header,
125                                    BareNetworkString* rest, bool encrypt);
126 
127     std::map<PeerDisconnectInfo, irr::core::stringw> m_disconnected_msg;
128 
129     std::vector<LobbyPlayer> m_lobby_players;
130 
131     std::vector<float> m_ranking_changes;
132 
133     irr::core::stringw m_total_players;
134 
135     void liveJoinAcknowledged(Event* event);
136     void handleKartInfo(Event* event);
137     void finishLiveJoin();
138     std::vector<std::shared_ptr<NetworkPlayerProfile> >
139          decodePlayers(const BareNetworkString& data,
140          std::shared_ptr<STKPeer> peer = nullptr,
141          bool* is_spectator = NULL) const;
142     void getKartsTracksNetworkString(BareNetworkString* ns);
143 public:
144              ClientLobby(std::shared_ptr<Server> s);
145     virtual ~ClientLobby();
146     void doneWithResults();
receivedServerResult()147     bool receivedServerResult()            { return m_received_server_result; }
148     void startingRaceNow();
getAvailableKarts() const149     const std::set<std::string>& getAvailableKarts() const
150                                                   { return m_available_karts; }
getAvailableTracks() const151     const std::set<std::string>& getAvailableTracks() const
152                                                  { return m_available_tracks; }
153     virtual bool notifyEvent(Event* event) OVERRIDE;
154     virtual bool notifyEventAsynchronous(Event* event) OVERRIDE;
155     virtual void finishedLoadingWorld() OVERRIDE;
156     virtual void setup() OVERRIDE;
157     virtual void update(int ticks) OVERRIDE;
asynchronousUpdate()158     virtual void asynchronousUpdate() OVERRIDE {}
allPlayersReady() const159     virtual bool allPlayersReady() const OVERRIDE
160                                            { return m_state.load() >= RACING; }
waitingForServerRespond() const161     bool waitingForServerRespond() const
162                             { return m_state.load() == REQUESTING_CONNECTION; }
isLobbyReady() const163     bool isLobbyReady() const                      { return !m_first_connect; }
isWaitingForGame() const164     bool isWaitingForGame() const                { return m_waiting_for_game; }
isServerAutoGameTime() const165     bool isServerAutoGameTime() const       { return m_server_auto_game_time; }
isRacing() const166     virtual bool isRacing() const OVERRIDE { return m_state.load() == RACING; }
167     void requestKartInfo(uint8_t kart_id);
setSpectator(bool val)168     void setSpectator(bool val)                          { m_spectator = val; }
isSpectator() const169     bool isSpectator() const
170                      { return m_spectator && m_state.load() != RACE_FINISHED; }
171     void startLiveJoinKartSelection();
172     void sendChat(irr::core::stringw text, KartTeam team);
getLobbyPlayers() const173     const std::vector<LobbyPlayer>& getLobbyPlayers() const
174                                                     { return m_lobby_players; }
isServerLiveJoinable() const175     bool isServerLiveJoinable() const        { return m_server_live_joinable; }
176     void changeSpectateTarget(PlayerAction action, int value,
177                               Input::InputType type) const;
178     void addSpectateHelperMessage() const;
serverEnabledChat() const179     bool serverEnabledChat() const            { return m_server_enabled_chat; }
serverEnabledTrackVoting() const180     bool serverEnabledTrackVoting() const
181                                       { return m_server_enabled_track_voting; }
serverEnabledReportPlayer() const182     bool serverEnabledReportPlayer() const
183                                      { return m_server_enabled_report_player; }
getRankingChanges() const184     const std::vector<float>& getRankingChanges() const
185                                                   { return m_ranking_changes; }
186     void handleClientCommand(const std::string& cmd);
187     void updateAssetsToServer();
getCurrentState() const188     ClientState getCurrentState() const { return m_state.load(); }
getJoinedServer() const189     std::shared_ptr<Server> getJoinedServer() const { return m_server; }
190 };
191 
192 #endif // CLIENT_LOBBY_HPP
193