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