1 #ifndef ERIS_PLAYER_H
2 #define ERIS_PLAYER_H
3
4 #include <Eris/Types.h>
5
6 #include "TransferInfo.h"
7
8 #include <Atlas/Objects/ObjectsFwd.h>
9
10 #include <sigc++/signal.h>
11
12 #include <vector>
13 #include <map>
14 #include <memory>
15
16 namespace Eris
17 {
18
19 class Connection;
20 class Avatar;
21 class AccountRouter;
22 class Timeout;
23 class SpawnPoint;
24
25 /** Type used to return available characters */
26 typedef std::map<std::string, Atlas::Objects::Entity::RootEntity> CharacterMap;
27
28 typedef std::map<std::string, Avatar*> ActiveCharacterMap;
29
30 /**
31 * @brief A store of spawn points.
32 */
33 typedef std::map<std::string, SpawnPoint> SpawnPointMap;
34
35 /// Encapsulates all the state of an Atlas Account, and methods that operation on that state
36
37 /** An Account object represents the encapsulation of a server account, and it's binding to a character in the
38 game world. Future versions of Eris will support multiple Account objects per Connection, allowing various
39 configurations of interface, proxies and so forth.
40 <br>
41 Account is also the mechanism by which Lobby and Avatars objects are made available to the client,
42 in response to login / create operations */
43
44 class Account : virtual public sigc::trackable
45 {
46 public:
47 /// Create a new Account associated with a Connection object
48 /**
49 Create a new Account object : currently only one is assumed, but multiple
50 Accounts might be supported in the future
51 @param con A valid (but not necessarily connected) Connection instance
52 */
53 Account(Connection *con);
54
55 virtual ~Account();
56
57 /// Login to the server using user-supplied account information
58 /** This is the basic way of logging into an existing account. Server-side
59 failures during the login process, such as the account being unknown
60 or an incorrect password being supplied, will result in the 'LoginFailure' signal being
61 emitted with some vaugely helpful error message, and an error code. The LoginSuccess
62 signal will be emitted upon sucessful completion of the login process.
63
64 @param uname The username of the account
65 @param pwd The correct password for the account
66 */
67 Result login(const std::string &uname, const std::string &pwd);
68
69 /// Attempt to create a new account on the server and log into it.
70 /* Create a new account on the server, if possible.
71 Server-side failures, such as an account already existing with the specified
72 username, will cause the 'LoginFailure' signal to be emitted with an error message
73 and a code. As for 'login', LoginSuccess wil be emitted if everything goes as plan.
74
75 @param uname The desired username of the account (eg 'ajr')
76 @param fullName The real name of the user (e.g 'Al Riddoch')
77 @param pwd The plaintext password for the new account
78 */
79
80 Result createAccount(const std::string &uname,
81 const std::string &fullName,
82 const std::string &pwd);
83
84 /* Create a new account on the server, if possible.
85 Server-side failures, such as an account already existing with the specified
86 username, will cause the 'LoginFailure' signal to be emitted with an error message
87 and a code. As for 'login', LoginSuccess wil be emitted if everything goes as plan.
88
89 This variant allows you to specify your own Account op, which is useful when you
90 want to create an account different from the standard one.
91
92 @param accountOp The account operation, which will be wrapped in a "Create" op.
93 */
94 Result createAccount(Atlas::Objects::Entity::Account accountOp);
95
96
97 /// Request logout from the server.
98 /** Initiate a clean disconnection from the server. The LogoutComplete
99 signal will be emitted when the process completes. Calling this on an Account
100 which is not logged in will produce an error. */
101 Result logout();
102
103 /// Check if the account is logged in.
104 /** Many operations will produce errors if the account is not logged in. */
105 bool isLoggedIn() const;
106
107 /// Returns a container of character types that the client is allowed to create.
108 const std::vector< std::string > & getCharacterTypes(void) const;
109
110 /// Get the characters owned by this account.
111 /**
112 Note you should call
113 refreshCharacterInfo, and wait for the GotAllCharacters signal, prior to the
114 initial call : otherwise, it will return an empty or incomplete list.
115 */
116 const CharacterMap& getCharacters();
117
118 /**
119 Update the character list (based on changes to play). The intention here is
120 that clients will call this method for some kind of'choose character' interface
121 or menu, and wait for the GotAllCharacters signal before displaying the list.
122 Alternatively, you can display the UI immediately, and add character entries
123 based on the GotCharacterInfo signal, which will be emitted once for each character.
124 */
125 Result refreshCharacterInfo();
126
127 /// Transfer all characters to this account and then do all steps in takeCharacter()
128 /**
129 @param id The id of the game entity to transfer and activate
130 @param key The possess_key to authenticate the game entity as ours
131 */
132 Result takeTransferredCharacter(const std::string &id, const std::string &key);
133
134 /// Enter the game using an existing character
135 /**
136 @param id The id of the game entity to activate; this must be owned by the account.
137 @result The Avatar that represents the character. Note ownership of this passes to
138 the caller.
139 */
140 Result takeCharacter(const std::string &id);
141
142 /// enter the game using a new character
143 Result createCharacter(const Atlas::Objects::Entity::RootEntity &character);
144
145 /// pop up the game's character creation dialog, if present
146 //void createCharacter();
147
148 /// returns true if the game has defined a character creation dialog
149 bool canCreateCharacter();
150
151 /**
152 * @brief Gets a list of active characters, i.e. entities on the server which the account can control.
153 * @returns A list of active characters on the server which the account can control.
154 */
155 const ActiveCharacterMap& getActiveCharacters() const;
156
157 /**
158 * @brief Gets the available spawn points from where the client can create new characters.
159 * @returns A store of available spawn points.
160 */
161 const SpawnPointMap& getSpawnPoints() const;
162
163 /**
164 Request de-activation of a character. The 'AvatarDeactivated' signal will
165 be emitted when the deactivation completes.
166 */
167 Result deactivateCharacter(Avatar* av);
168
169 /// returns the account ID if logged in
170 const std::string& getId() const;
171
172 /** Return the username of this account. */
173 const std::string& getUsername() const;
174
175 /**
176 * @brief Gets the parent types of the account.
177 * In normal operation this should be a list containing one element,
178 * which in most cases is either "player" or "admin".
179 * @returns A vector of the parent types of the account.
180 */
181 const std::list<std::string>& getParents() const;
182
183 /// Access the underlying Connection for this account
184 Connection* getConnection() const;
185
186 /**
187 * @brief Called when a logout of the avatar has been requested by the
188 * server.
189 *
190 * @note The avatar instance will be deleted by this method.
191 *
192 * @param avatar The avatar which is being logged out. This instance will
193 * be destroyed once this method is done.
194 */
195 void avatarLogoutRequested(Avatar* avatar);
196
197
198 // signals
199 /// emitted when a character has been retrieved from the server
200 sigc::signal<void, const Atlas::Objects::Entity::RootEntity&> GotCharacterInfo;
201
202 /// emitted when the entire character list had been updated
203 sigc::signal<void> GotAllCharacters;
204
205 /// Emitted when a server-side error occurs during account creation / login.
206 /**
207 The argument is an error message from the server - hopefully this will
208 become something more useful such as an enum code, in the future.
209 */
210 sigc::signal<void, const std::string &> LoginFailure;
211
212 /** Emitted when login or character creation is successful. */
213 sigc::signal<void> LoginSuccess;
214
215 /// Emitted when a logout completes
216 /** Depending on whether the logout completed with a positive server
217 acknowledgment or just timed out, the argument will be either true
218 (success, clean logout) or false (failure, timeout or other problem)
219 */
220 sigc::signal<void, bool> LogoutComplete;
221
222 /**
223 Emitted when creating a character or taking an existing one
224 succeeds.
225 */
226 sigc::signal<void, Avatar*> AvatarSuccess;
227
228 /**
229 Emitted when creating or taking a character fails for some reason.
230 String argument is the error message from the server.
231 */
232 sigc::signal<void, const std::string &> AvatarFailure;
233
234 /**
235 Emitted when an active avatar is deactivated. Clients <em>must not</em>
236 refer to the Avatar or View objects after this signal is emitted (it is
237 safe to access them in a slot connected to this signal)
238 */
239 sigc::signal<void, Avatar*> AvatarDeactivated;
240
241 protected:
242 friend class AccountRouter;
243 friend class Avatar; // so avatar can call deactivateCharacter
244
245 void sightCharacter(const Atlas::Objects::Operation::RootOperation& op);
246
247 void loginComplete(const Atlas::Objects::Entity::Account &p);
248 void loginError(const Atlas::Objects::Operation::Error& err);
249
250 Result internalLogin(const std::string &unm, const std::string &pwd);
251 void internalLogout(bool clean);
252
253 /// Callback for network re-establishment
254 void netConnected();
255
256 /// help! the plug is being pulled!
257 bool netDisconnecting();
258 void netFailure(const std::string& msg);
259
260 void loginResponse(const Atlas::Objects::Operation::RootOperation& op);
261 void logoutResponse(const Atlas::Objects::Operation::RootOperation& op);
262 void avatarResponse(const Atlas::Objects::Operation::RootOperation& op);
263 void avatarLogoutResponse(const Atlas::Objects::Operation::RootOperation& op);
264
265 void handleLogoutTimeout();
266 // void recvRemoteLogout(const Atlas::Objects::Operation::Logout &lo);
267
268 void handleLoginTimeout();
269
270 typedef enum
271 {
272 DISCONNECTED = 0, ///< Default state, no server account active
273 LOGGING_IN, ///< Login sent, waiting for initial INFO response
274 LOGGED_IN, ///< Fully logged into a server-side account
275 LOGGING_OUT, ///< Sent a logout op, waiting for the INFO response
276
277 TAKING_CHAR, ///< sent a LOOK op for a character, awaiting INFO response
278 CREATING_CHAR ///< send a character CREATE op, awaiting INFO response
279 } Status;
280
281 void internalDeactivateCharacter(Avatar* av);
282 virtual void updateFromObject(const Atlas::Objects::Entity::Account &p);
283
284 Connection* m_con; ///< underlying connection instance
285 Status m_status; ///< what the Player is currently doing
286 AccountRouter* m_router;
287
288 std::string m_accountId; ///< the account ID
289 std::string m_username; ///< The player's username ( != account object's ID)
290 std::string m_pass;
291
292 std::list< std::string > m_parents;
293 std::vector< std::string > m_characterTypes;
294 CharacterMap _characters; ///< characters belonging to this player
295 StringSet m_characterIds;
296 bool m_doingCharacterRefresh; ///< set if we're refreshing character data
297
298 ActiveCharacterMap m_activeCharacters;
299 std::unique_ptr<Timeout> m_timeout;
300
301 /**
302 * @brief A map of available spawn points.
303 * These are points from which a new avatar can be created.
304 */
305 SpawnPointMap m_spawnPoints;
306 };
307
canCreateCharacter()308 inline bool Account::canCreateCharacter()
309 {
310 return false;
311 }
312
getActiveCharacters()313 inline const ActiveCharacterMap& Account::getActiveCharacters() const
314 {
315 return m_activeCharacters;
316 }
317
getId()318 inline const std::string& Account::getId() const
319 {
320 return m_accountId;
321 }
322
getUsername()323 inline const std::string& Account::getUsername() const
324 {
325 return m_username;
326 }
327
getParents()328 inline const std::list<std::string>& Account::getParents() const
329 {
330 return m_parents;
331 }
332
333
getConnection()334 inline Connection* Account::getConnection() const
335 {
336 return m_con;
337 }
338
getSpawnPoints()339 inline const SpawnPointMap& Account::getSpawnPoints() const
340 {
341 return m_spawnPoints;
342 }
343
344
345 } // of namespace Eris
346
347 #endif
348