// Ryzom - MMORPG Framework
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
#ifndef FAR_TP_H
#define FAR_TP_H
#include "nel/misc/co_task.h"
#include
#include
#include "game_share/security_check.h"
class CLoginStateMachine : private NLMISC::CCoTask
{
public:
enum TState
{
/// initial state
st_start,
/// display login screen and options
st_login,
/// auto login using cmd lien parameters (used with patch reboot)
st_auto_login,
/// display the shard list
st_shard_list,
/// lauch the configurator and close ryzom
st_start_config,
/// run the scan data thread
st_scan_data,
/// display the eula and wait for validation
st_display_eula,
/// check the data to determine need for patch
st_check_patch,
/// display the list of optional patch category for patching
st_display_cat,
/// run the patch process and display progress
st_patch,
/// terminate the client and quit
st_close_client,
/// display the reboot screen and wait validation
st_reboot_screen,
/// restart the client with login bypass params
st_restart_client,
/// connect to the FS (start the 'in game' mode)
st_connect,
/// show the outgame browser
st_browser_screen,
/// ingame state
st_ingame,
/// leave the current shard (the exit action progress, Far TP part 1.1; Server Hop part 1-2)
st_leave_shard,
/// let the main loop finish the current frame and leave it (Far TP part 1.2)
st_enter_far_tp_main_loop,
/// disconnect from the FS (Far TP part 2)
st_disconnect,
/// connect to a new FS (Far TP & Server Hop part 3.1)
st_reconnect_fs,
/// after reconnecting, bypass character selection ui & select the same character (Far TP & Server Hop part 3.2)
st_reconnect_select_char,
/// after reconnecting and receiving ready, send ready (Far TP part 3.3)
st_reconnect_ready,
/// between global menu exit and sending ready (Server Hop part 3.3)
st_exit_global_menu,
/// error while reconnecting
st_reconnect_error,
/// Rate a ring session. should pop a web windows pointing the rate session page
st_rate_session,
/// create account
st_create_account,
/// try to login with alternate login system
st_alt_login,
/// pseudo state to leave the state machine
st_end,
///
st_unknown
};
/// For displaying
static const std::string& toString(TState state);
enum TEvent
{
/// the client click the 'quit' button
ev_quit,
/// the client is connecting without authentication (dev mode)
ev_skip_all_login,
/// the init is done
ev_init_done,
/// the client push the 'config' button
ev_game_conf,
/// the client push the 'scan data' button
ev_data_scan,
/// the client push the 'scan data' button
ev_close_data_scan,
/// the login is validated and cookie is received
ev_login_ok,
/// the login check as failed
ev_bad_login,
/// the client has selected a shard
ev_shard_selected,
/// the patch checker says we need to ev_patch_needed
ev_patch_needed,
/// the patch check says we are clean, no patch needed
ev_no_patch,
/// the user validate the category screen, patch can begin
ev_run_patch,
/// the client validate the patch result
ev_close_patch,
/// Client accept the eula screen
ev_accept_eula,
/// Client decline the eula screen
ev_decline_eula,
/// the client valide the reboot message box
ev_reboot,
/// the ingame session terminates (CONNECTION:SERVER_QUIT_OK msg)
ev_ingame_return,
/// the far tp main loop is entered
ev_far_tp_main_loop_entered,
/// the lua script (from web usually) starts the client connection to a shard
ev_connect,
/// the connection fail for some reason
ev_conn_failed,
/// the connection was dropped by the server
ev_conn_dropped,
/// the client enters the game main loop
ev_enter_game,
// a self reconnetion is complete, get back to outgame menu
ev_self_reconnected,
/// characters received (CONNECTION:USER_CHARS msg)
ev_chars_received,
/// characters received but empty (CONNECTION:NO_USER_CHAR msg)
ev_no_user_char,
/// ready received (CONNECTION:READY msg)
ev_ready_received,
/// reselect character (CONNECTION:RECO
// ev_reselect_char,
/// reconnect ok received (CONNECTION:SERVER_RECONNECT_OK msg)
ev_reconnect_ok_received,
/// global menu exited
ev_global_menu_exited,
/// The client click the 'relog' button
ev_relog,
/// the client push the 'create account' button
ev_create_account,
/// the client push the 'create account' button
ev_close_create_account,
/// the client want to use alternate login system
ev_login_not_alt,
///
ev_unknown
};
/// For displaying
static const std::string& toString(TEvent event);
private:
TState _CurrentState;
std::list _NextEvents;
public:
// Create the state machine with the wanted start.
// Note that, because it is a co-task, restarting the state machine after it has finished
// require to delete then recreate this object
CLoginStateMachine() :
_CurrentState(st_start)
{
}
TState getCurrentState()
{
return _CurrentState;
}
void pushEvent(TEvent eventId);
TEvent waitEvent();
private:
void run();
};
extern CLoginStateMachine LoginSM;
void initLoginScreen();
void initShardDisplay();
void initDataScan();
bool initCreateAccount();
void initEula();
void initPatchCheck();
void initCatDisplay();
void initAutoLogin();
void initAltLogin();
void initPatch();
//void initWebBrowser();
void initReboot();
void ConnectToShard();
void waitForUserCharReceived();
/**
*/
class CFarTP
{
public:
// See definition of _URLTable for url binding
enum TJoinMode
{
LaunchEditor,
JoinSession,
JoinMainland,
NbJoinModes
};
CFarTP() : _Reason(NULL), _SessionIdToJoinFast(0), _InGameMode(false), _PreviousR2EdEnabled(false), _ReselectingChar(false), _IsServerHopEmbedded(false), _HookedForEditor(false), _DSSDown(false) /*, _SelfReconnecting(false)*/ {}
// Get the address of a front-end service via http, then begin Far TP
bool requestFarTPToSession(TSessionId sessionId, uint8 charSlot, CFarTP::TJoinMode joinMode, bool bailOutIfSessionVanished);
// Ask the EGS to pop the top position if applicable
void requestReturnToPreviousSession(TSessionId rejectedSessionId=TSessionId(0));
// Store the result of a JoinSession request for the next disconnection request
void setJoinSessionResult(TSessionId sessionId, const CSecurityCode& securityCode);
// Tell to ignore the next Far TP request, it will be replaced by a Far TP to the edition session (allows to shortcut anim-mainland-edition by anim-edition)
void hookNextFarTPForEditor();
/// Begin a Character Reselect sequence
void requestReconnection();
// These states can overlap
bool isIngame() const { return _InGameMode; }
bool isFarTPInProgress() const;
bool isServerHopInProgress() const;
bool isLeavingEGS() const { return (LoginSM.getCurrentState() == CLoginStateMachine::st_leave_shard); }
bool isLeavingShard() const; // from begin of Far TP to disconnection
bool isJoiningShard() const; // from reconnection to game entering
bool isReselectingChar() const { return _ReselectingChar; }
bool isServerHopEmbedded() const { return _IsServerHopEmbedded; }
bool isFastDisconnectGranted() const { return _SessionIdToJoinFast != 0; }
// Far TP from the main loop
void farTPmainLoop();
void writeSecurityCodeForDisconnection(NLMISC::IStream& msgout);
void onServerQuitOk();
void onServerQuitAbort();
void disconnectFromPreviousShard();
void connectToNewShard();
bool reselectCharacter();
void selectCharAndEnter();
void sendReady();
void onFailure();
void onDssDown(bool forceReturn=false);
void setIngame() { _InGameMode = true; }
void setOutgame() { _InGameMode = false; }
void setMainLoopEntered() { setIngame(); _ReselectingChar = false; }
void beginEmbeddedServerHop() { _IsServerHopEmbedded = true; setOutgame(); _ReselectingChar = false; }
void endEmbeddedServerHop() { _IsServerHopEmbedded = false; setIngame(); _ReselectingChar = true; }
void setURLBase(const std::string& urlBase) { _URLBase = urlBase; }
private:
// called back from session browser after a far tp request
void joinSessionResult(uint32 userId, TSessionId sessionId, uint32 result, const std::string &shardAddr, const std::string &participantStatus);
std::string *_Reason;
static const char *_URLTable[NbJoinModes];
std::string _URLBase;
TSessionId _SessionIdToJoinFast; // if non 0, fast disconnection allowed to session
CSecurityCode _SecurityCodeForDisconnection;
bool _InGameMode; // formerly known as EnterWorld
bool _PreviousR2EdEnabled;
bool _ReselectingChar;
bool _IsServerHopEmbedded; // allows to embed a server hop inside a char reselect (e.g. click on Launch Editor of PLAY with a character on a remote shard)
bool _HookedForEditor; // allows to Far TP to editor instead of following the next Far TP request
bool _DSSDown; // remembers a DSSDown event if occurs during a FarTP
// bool _SelfReconnecting; // allows to disconnect after character selection and reconnect until the player can choose another character
};
extern CFarTP FarTP;
#endif // FAR_TP_H