diff options
-rw-r--r-- | ChangeLog | 9 | ||||
-rw-r--r-- | The Mana World.dev | 22 | ||||
-rw-r--r-- | src/game.cpp | 2 | ||||
-rw-r--r-- | src/gui/char_select.cpp | 6 | ||||
-rw-r--r-- | src/gui/char_server.cpp | 49 | ||||
-rw-r--r-- | src/gui/char_server.h | 10 | ||||
-rw-r--r-- | src/gui/login.cpp | 127 | ||||
-rw-r--r-- | src/gui/login.h | 29 | ||||
-rw-r--r-- | src/main.cpp | 19 | ||||
-rw-r--r-- | src/main.h | 3 | ||||
-rw-r--r-- | src/net/network.cpp | 131 | ||||
-rw-r--r-- | src/net/network.h | 12 | ||||
-rw-r--r-- | src/net/protocol.cpp | 51 | ||||
-rw-r--r-- | src/net/protocol.h | 3 |
14 files changed, 264 insertions, 209 deletions
@@ -1,3 +1,12 @@ +2005-10-16 Eugenio Favalli <elvenprogrammer@gmail.com> + + * The Mana World.dev, src/game.cpp, src/gui/char_select.cpp, + src/gui/char_server.cpp, src/gui/char_server.h, src/gui/connection.cpp, + src/gui/connection.h, src/gui/login.cpp, src/gui/login.h, src/main.cpp, + src/main.h, src/net/network.cpp, src/net/network.h, src/net/protocol.cpp, + src/net/protocol.h: The connection should be non-blocking now and fixed + the problem with sound not being played at startup. + 2005-10-15 Björn Steinbrink <B.Steinbrink@gmx.de> * src/engine.cpp: Moved some variables into the conditional block diff --git a/The Mana World.dev b/The Mana World.dev index 4712af6a..d9233ed4 100644 --- a/The Mana World.dev +++ b/The Mana World.dev @@ -1,7 +1,7 @@ [Project] FileName=The Mana World.dev Name=tmw -UnitCount=174 +UnitCount=176 Type=0 Ver=1 ObjFiles= @@ -1797,3 +1797,23 @@ Priority=1000 OverrideBuildCmd=0 BuildCmd= +[Unit175] +FileName=src\gui\connection.h +CompileCpp=1 +Folder=gui/header +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit176] +FileName=src\gui\connection.cpp +CompileCpp=1 +Folder=gui/source +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + diff --git a/src/game.cpp b/src/game.cpp index 9f267449..de2bb600 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -409,7 +409,7 @@ void do_exit() delete engine; delete player_node; destroyGuiWindows(); - close_session(); + closeConnection(); delete inventory; diff --git a/src/gui/char_select.cpp b/src/gui/char_select.cpp index b7258aba..46ead1dc 100644 --- a/src/gui/char_select.cpp +++ b/src/gui/char_select.cpp @@ -241,12 +241,12 @@ void CharSelectDialog::serverCharSelect() map_address = msg.readLong(); map_port = msg.readShort(); player_info = char_info[0]; - state = GAME_STATE; + state = CONNECTING_STATE; logger->log("CharSelect: Map: %s", map_path.c_str()); logger->log("CharSelect: Server: %s:%d", iptostring(map_address), map_port); - close_session(); + closeConnection(); } else if (msg.getId() == 0x006c) { @@ -279,7 +279,7 @@ void CharSelectDialog::serverCharSelect() errorMessage = "Unkown error with 0x0081"; break; } - close_session(); + closeConnection(); state = ERROR_STATE; } diff --git a/src/gui/char_server.cpp b/src/gui/char_server.cpp index a8f99d8f..22ac484b 100644 --- a/src/gui/char_server.cpp +++ b/src/gui/char_server.cpp @@ -46,7 +46,7 @@ char server[30]; ServerSelectDialog::ServerSelectDialog(): - Window("Select Server") + Window("Select Server"), mStatus(NET_IDLE) { serverListModel = new ServerListModel(); serverList = new ListBox(serverListModel); @@ -82,7 +82,7 @@ ServerSelectDialog::ServerSelectDialog(): if (n_server == 0) { // Disable Ok button - //okButton->char_server_dialog[2].flags |= D_DISABLED; + okButton->setEnabled(false); } else { // Select first server serverList->setSelected(1); @@ -104,13 +104,37 @@ ServerSelectDialog::~ServerSelectDialog() void ServerSelectDialog::action(const std::string& eventId) { if (eventId == "ok") { - server_char_server(serverList->getSelected()); + int index = serverList->getSelected(); + const char *host = iptostring(server_info[index]->address); + short port = server_info[index]->port; + openConnection(host, port); + mStatus = NET_CONNECTING; + //server_char_server(serverList->getSelected()); } else if (eventId == "cancel") { state = LOGIN_STATE; } } +void ServerSelectDialog::logic() +{ + switch (mStatus) + { + case NET_CONNECTING: + mStatus = pollConnection(); + break; + case NET_ERROR: + logger->log("ServerSelect::Unable to connect"); + errorMessage = "Unable to connect to char server"; + state = ERROR_STATE; + closeConnection(); + break; + case NET_CONNECTED: + selectServer(serverList->getSelected()); + //closeConnection(); + break; + } +} int ServerListModel::getNumberOfElements() { @@ -132,23 +156,8 @@ void charServerInputHandler(SDL_KeyboardEvent *keyEvent) } } -void server_char_server(int serverIndex) +void ServerSelectDialog::selectServer(int index) { - int ret; - state = LOGIN_STATE; - const char *ipstring = iptostring(server_info[serverIndex]->address); - - // Connect to char server - ret = open_session(ipstring, server_info[serverIndex]->port); - - if (ret == -1) - { - std::string str = std::string("Unable to connect to char server ") + - std::string(ipstring); - new OkDialog("Error", str); - return; - } - // Send login infos MessageOut outMsg; outMsg.writeShort(0x0065); @@ -234,7 +243,7 @@ void server_char_server(int serverIndex) } new OkDialog("Error", errorStr); skip(msg.getLength()); - close_session(); + closeConnection(); } else { diff --git a/src/gui/char_server.h b/src/gui/char_server.h index 70361496..f07b2f53 100644 --- a/src/gui/char_server.h +++ b/src/gui/char_server.h @@ -66,6 +66,11 @@ class ServerSelectDialog : public Window, public gcn::ActionListener { * Called when receiving actions from the widgets. */ void action(const std::string& eventId); + + /** + * Updates dialog logic + */ + void logic(); private: ServerListModel *serverListModel; @@ -73,10 +78,11 @@ class ServerSelectDialog : public Window, public gcn::ActionListener { gcn::Button *okButton; gcn::Button *cancelButton; gcn::ScrollArea *scrollArea; + int mStatus; + + void selectServer(int index); }; void charServerInputHandler(SDL_KeyboardEvent *keyEvent); -void server_char_server(int serverIndex); -char *server_list(int index, int *size); #endif diff --git a/src/gui/login.cpp b/src/gui/login.cpp index 6d1c896d..6846059c 100644 --- a/src/gui/login.cpp +++ b/src/gui/login.cpp @@ -89,7 +89,7 @@ WrongUsernameNoticeListener::action(const std::string &eventId) } LoginDialog::LoginDialog(): - Window("Login") + Window("Login"), mStatus(NET_IDLE), registration(false) { userLabel = new gcn::Label("Name:"); passLabel = new gcn::Label("Password:"); @@ -213,38 +213,11 @@ LoginDialog::action(const std::string& eventId) } else { - int ret = attemptLogin(user, passField->getText()); - - if (ret == LOGIN_WRONG_PASSWORD) - { - wrongLoginNotice = new OkDialog("Error", "Wrong Password", - &wrongPasswordNoticeListener); - } - else if (ret != LOGIN_OK) - { - std::string errorMsg = "Unknown error."; - - switch (ret) - { - case LOGIN_UNREGISTERED_ID: - errorMsg = "Unregistered ID."; - break; - case LOGIN_EXPIRED: - errorMsg = "This ID is expired"; - break; - case LOGIN_REJECTED: - errorMsg = "Rejected from server"; - break; - case LOGIN_BLOCKED: - errorMsg = "You have been blocked by the GM Team"; - break; - case LOGIN_USERNAME_TWICE: - errorMsg = "The username does already exist."; - break; - } - - wrongLoginNotice = new OkDialog("Error", errorMsg); - } + const std::string host(config.getValue("host", "animesites.de")); + short port = (short)config.getValue("port", 0); + // Attempt to connect to login server + openConnection(host.c_str(), port); + mStatus = NET_CONNECTING; } } else if (eventId == "cancel") @@ -315,12 +288,47 @@ LoginDialog::action(const std::string& eventId) else { // No errors detected, register the new user. - attemptLogin(user + "_M", passField->getText()); + const std::string host(config.getValue("host", "animesites.de")); + short port = (short)config.getValue("port", 0); + // Attempt to connect to login server + openConnection(host.c_str(), port); + mStatus = NET_CONNECTING; + registration = true; + //attemptLogin(user + "_M", passField->getText()); } } } void +LoginDialog::logic() +{ + switch (mStatus) + { + case NET_CONNECTING: + mStatus = pollConnection(); + break; + case NET_ERROR: + logger->log("Login::Unable to connect"); + errorMessage = "Unable to connect to login server"; + state = ERROR_STATE; + closeConnection(); + logger->log("Connection closed"); + break; + case NET_CONNECTED: + logger->log("Connected..."); + std::string user = userField->getText(); + const std::string password = passField->getText(); + if (registration) + { + user += "_M"; + } + attemptLogin(user, password); + closeConnection(); + break; + } +} + +void loginInputHandler(SDL_KeyboardEvent *keyEvent) { if (keyEvent->keysym.sym == SDLK_ESCAPE) @@ -329,24 +337,9 @@ loginInputHandler(SDL_KeyboardEvent *keyEvent) } } -int -attemptLogin(const std::string& user, const std::string& pass) +void +LoginDialog::attemptLogin(const std::string& user, const std::string& pass) { - int ret; - - // Connect to login server - ret = open_session( - config.getValue("host", "animesites.de").c_str(), - (short)config.getValue("port", 0)); - - if (ret == -1) { - state = LOGIN_STATE; - wrongLoginNotice = new OkDialog("Error", - "Unable to connect to login server"); - return LOGIN_NO_CONNECTION; - } - - // Send login infos MessageOut outMsg; outMsg.writeShort(0x0064); @@ -359,8 +352,8 @@ attemptLogin(const std::string& user, const std::string& pass) MessageIn msg = get_next_message(); if (state == ERROR_STATE) { - close_session(); - return LOGIN_UNKNOWN_ERROR; + closeConnection(); + return; } // Login ok @@ -393,47 +386,43 @@ attemptLogin(const std::string& user, const std::string& pass) iptostring(server_info[i]->address), server_info[i]->port); } + skip(msg.getLength()); state = CHAR_SERVER_STATE; - - skip(msg.getLength()); - ret = LOGIN_OK; } else if (msg.getId() == 0x006a) { int loginError = msg.readByte(); logger->log("Login::error code: %i", loginError); - ret = 0; + switch (loginError) { case 0: - ret = LOGIN_UNREGISTERED_ID; + errorMessage = "Unregistered ID"; break; case 1: - ret = LOGIN_WRONG_PASSWORD; + errorMessage = "Wrong password"; break; case 2: - ret = LOGIN_EXPIRED; + errorMessage = "Account expired"; break; case 3: - ret = LOGIN_REJECTED; + errorMessage = "Rejected from server"; break; case 4: - ret = LOGIN_BLOCKED; + errorMessage = "You have been blocked by the GM Team"; break; case 9: - ret = LOGIN_USERNAME_TWICE; + errorMessage = "This account is already logged in"; break; } skip(msg.getLength()); - state = LOGIN_STATE; + state = ERROR_STATE; } else { skip(msg.getLength()); - state = LOGIN_STATE; - ret = LOGIN_UNKNOWN_ERROR; + logger->log("Login::Unknown error"); + errorMessage = "Unknown error"; + state = ERROR_STATE; } // Todo: add other packets, also encrypted - - close_session(); - return ret; } diff --git a/src/gui/login.h b/src/gui/login.h index 5f841d37..ae3e8a0f 100644 --- a/src/gui/login.h +++ b/src/gui/login.h @@ -54,6 +54,11 @@ class LoginDialog : public Window, public gcn::ActionListener { * Called when receiving actions from the widgets. */ void action(const std::string& eventId); + + /** + * Updates dialog logic. + */ + void logic(); // Made them public to have the possibility to request focus // from external functions. @@ -69,6 +74,10 @@ class LoginDialog : public Window, public gcn::ActionListener { gcn::Button *okButton; gcn::Button *cancelButton; gcn::Button *registerButton; + int mStatus; + bool registration; + + void attemptLogin(const std::string& user, const std::string& pass); }; /** @@ -99,22 +108,7 @@ class WrongUsernameNoticeListener : public gcn::ActionListener { */ void loginInputHandler(SDL_KeyboardEvent *keyEvent); -/** - * Attempt to login to login server - * Return an error code if any, and then stay at LOGIN state. - * 0 means ok. - * 1 means Wrong Password - * 2 means unregistered ID - * 3 means rejected from server - * 4 means blocked by GM Team - * 5 means expired ID - * 6 means unable to connect to server - * 9 means username already existing - * -1 means unknown error - */ -int attemptLogin(const std::string& user, const std::string& pass); - -enum +/*enum { LOGIN_OK = 0, LOGIN_WRONG_PASSWORD, @@ -124,8 +118,9 @@ enum LOGIN_EXPIRED, LOGIN_NO_CONNECTION, LOGIN_USERNAME_TWICE = 9, + LOGIN_CONNECTING, LOGIN_UNKNOWN_ERROR = -1 -}; +};*/ #endif diff --git a/src/main.cpp b/src/main.cpp index 31a1b232..6ce9dd3a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -52,6 +52,8 @@ #include "gui/char_server.h" #include "gui/char_select.h" +#include "gui/connection.h" +#include "gui/error.h" #include "gui/gui.h" #include "gui/login.h" #include "gui/ok_dialog.h" @@ -421,6 +423,8 @@ int main(int argc, char *argv[]) void (*inputHandler)(SDL_KeyboardEvent*) = NULL; Image *login_wallpaper = NULL; + + sound.playMusic(TMW_DATADIR "data/music/Magick - Real.ogg"); while (state != EXIT_STATE) { @@ -494,18 +498,10 @@ int main(int argc, char *argv[]) login_wallpaper = NULL; logger->log("State: GAME"); - try { - map_start(); - game(); - } - catch (const char* err) { - state = ERROR_STATE; - new OkDialog("Error", err, &mapStartErrorListener); - } + game(); break; case UPDATE_STATE: logger->log("State: UPDATE"); - sound.playMusic(TMW_DATADIR "data/music/Magick - Real.ogg"); currentDialog = new UpdaterWindow(); inputHandler = updateInputHandler; break; @@ -514,6 +510,11 @@ int main(int argc, char *argv[]) currentDialog = new ErrorDialog(errorMessage); inputHandler = errorInputHandler; break; + case CONNECTING_STATE: + logger->log("State: CONNECTING"); + currentDialog = new ConnectionDialog(); + inputHandler = connectionInputHandler; + break; default: state = EXIT_STATE; break; @@ -42,7 +42,8 @@ enum { CHAR_DEL_STATE, GAME_STATE, ERROR_STATE, - UPDATE_STATE + UPDATE_STATE, + CONNECTING_STATE }; /* length definitions for several char[]s in order diff --git a/src/net/network.cpp b/src/net/network.cpp index 6e3b6c6c..e94acee7 100644 --- a/src/net/network.cpp +++ b/src/net/network.cpp @@ -26,6 +26,7 @@ #include <cassert> #include <sstream> #include <SDL_net.h> +#include <SDL_thread.h> #include "messagein.h" @@ -85,10 +86,13 @@ char *in = NULL; char *out = NULL; unsigned int in_size = 0; unsigned int out_size = 0; -bool connectionOpen = false; +int connectionOpen = NET_IDLE; TCPsocket sock; SDLNet_SocketSet set; +SDL_Thread *mThread = NULL; +SDL_mutex *mMutex = NULL; +IPaddress *ip = NULL; char *iptostring(int address) { @@ -103,32 +107,15 @@ char *iptostring(int address) return asciiIP; } -int open_session(const char* address, short port) +int connectionThread(void *ptr) { - assert(!connectionOpen); - - // Initialize SDL_net - if (SDLNet_Init() == -1) - { - logger->log("Error in SDLNet_Init(): %s", SDLNet_GetError()); - return -1; - } - - IPaddress ip; - - // Resolve host name - if (SDLNet_ResolveHost(&ip, address, port) == -1) - { - logger->log("Error in SDLNet_ResolveHost(): %s", SDLNet_GetError()); - return -1; - } - // Create the socket for the current session - sock = SDLNet_TCP_Open(&ip); + sock = SDLNet_TCP_Open((IPaddress *)ptr); if (!sock) { logger->log("Error in SDLNet_TCP_Open(): %s", SDLNet_GetError()); - return -1; + connectionOpen = NET_ERROR; + return NET_ERROR; } // Create a socket set to listen to socket @@ -136,7 +123,8 @@ int open_session(const char* address, short port) if (!set) { logger->log("Error in SDLNet_AllocSocketSet(): %s", SDLNet_GetError()); - return -1; + connectionOpen = NET_ERROR; + return NET_ERROR; } // Add the socket to the set @@ -144,7 +132,8 @@ int open_session(const char* address, short port) if (ret == -1) { logger->log("Error in SDLNet_AddSocket(): %s", SDLNet_GetError()); - return -1; + connectionOpen = NET_ERROR; + return NET_ERROR; } // Init buffers @@ -154,16 +143,98 @@ int open_session(const char* address, short port) memset(out, '\0', buffer_size); in_size = 0; out_size = 0; + + SDL_mutexP(mMutex); + logger->log("Network::Started session with %s:%i", + iptostring(((IPaddress *)ptr)->host), + ((IPaddress *)ptr)->port); + connectionOpen = NET_CONNECTED; + SDL_mutexV(mMutex); + return NET_CONNECTED; +} + +void openConnection(const char* address, short port) +{ + //assert(connectionOpen <= NET_IDLE); + + // Initialize SDL_net + if (SDLNet_Init() == -1) + { + logger->log("Error in SDLNet_Init(): %s", SDLNet_GetError()); + connectionOpen = NET_ERROR; + } - logger->log("Network::Started session with %s:%i", address, port); - connectionOpen = true; + ip = new IPaddress(); - return 0; + // Resolve host name + if (SDLNet_ResolveHost(ip, address, port) == -1) + { + logger->log("Error in SDLNet_ResolveHost(): %s", SDLNet_GetError()); + connectionOpen = NET_ERROR; + } + + connectionOpen = NET_CONNECTING; + // Create the synchronization lock + mMutex = SDL_CreateMutex(); + // Create the connection thread + mThread = SDL_CreateThread(connectionThread, ip); + if (mThread == NULL) { + logger->log("Unable to create connection thread"); + connectionOpen = NET_ERROR; + } +} + +int pollConnection() +{ + if (mMutex) + { + SDL_mutexP(mMutex); + } + + switch (connectionOpen) + { + case NET_IDLE: + case NET_CONNECTING: + break; + case NET_CONNECTED: + case NET_ERROR: + SDL_WaitThread(mThread, NULL); + mThread = NULL; + SDL_DestroyMutex(mMutex); + mMutex = NULL; + break; + } + + if (mMutex) + { + SDL_mutexV(mMutex); + } + return connectionOpen; } -void close_session() +void closeConnection() { - assert(connectionOpen); + //assert(connectionOpen > ); + + if (connectionOpen == NET_ERROR)return; + + if (mThread) + { + SDL_WaitThread(mThread, NULL); + mThread = NULL; + } + + if (mMutex) + { + SDL_DestroyMutex(mMutex); + mMutex = NULL; + } + + if (ip) + { + delete ip; + ip = NULL; + } // Remove the socket from the socket set int ret = SDLNet_TCP_DelSocket(set, sock); @@ -199,7 +270,7 @@ void close_session() SDLNet_Quit(); logger->log("Network::Closed session"); - connectionOpen = false; + connectionOpen = NET_IDLE; } void flush() diff --git a/src/net/network.h b/src/net/network.h index 47e71190..1038b954 100644 --- a/src/net/network.h +++ b/src/net/network.h @@ -24,16 +24,24 @@ #ifndef _TMW_NETWORK_ #define _TMW_NETWORK_ +#define NET_ERROR -1 +#define NET_CONNECTED 0 +#define NET_IDLE 1 +#define NET_CONNECTING 2 + class MessageIn; /** Convert an address from int format to string */ char *iptostring(int address); /** Open a session with a server */ -int open_session(const char* address, short port); +void openConnection(const char* address, short port); + +/** Returns the status of the current connection attempt. */ +int pollConnection(); /** Close a session */ -void close_session(); +void closeConnection(); /** Send and receive data waiting in the buffers */ void flush(); diff --git a/src/net/protocol.cpp b/src/net/protocol.cpp index b56745fa..516afa59 100644 --- a/src/net/protocol.cpp +++ b/src/net/protocol.cpp @@ -68,57 +68,6 @@ void set_coordinates(char *data, data[2] |= direction; } -void map_start() -{ - // Connect to map server - if (open_session(iptostring(map_address), map_port) == -1) - { - logger->log("Warning: Unable to connect to map server"); - throw "Unable to connect to map server"; - return; - } - - // Send login infos - MessageOut outMsg; - outMsg.writeShort(0x0072); - outMsg.writeLong(account_ID); - outMsg.writeLong(char_ID); - outMsg.writeLong(session_ID1); - outMsg.writeLong(session_ID2); - outMsg.writeByte(sex); - - // Skip a mysterious 4 bytes - while ((in_size < 4)|| (out_size > 0)) flush(); - skip(4); - - MessageIn msg = get_next_message(); - - if (msg.getId() == SMSG_LOGIN_SUCCESS) - { - unsigned char direction; - msg.readLong(); // server tick - msg.readCoordinates(startX, startY, direction); - msg.skip(2); // unknown - logger->log("Protocol: Player start position: (%d, %d), Direction: %d", - startX, startY, direction); - } - else if (msg.getId() == 0x0081) - { - logger->log("Warning: Map server D/C"); - } - else - { - logger->error("Unknown packet: map_start"); - } - - skip(msg.getLength()); - - // Send "map loaded" - // TODO: be able to reuse the same msg - MessageOut newMsg; - newMsg.writeShort(0x007d); -} - void walk(unsigned short x, unsigned short y, unsigned char direction) { char temp[3]; diff --git a/src/net/protocol.h b/src/net/protocol.h index 8609530a..c6e118d4 100644 --- a/src/net/protocol.h +++ b/src/net/protocol.h @@ -115,9 +115,6 @@ unsigned char get_dest_direction(char data); /** Encodes coords and direction in 3 bytes data */ void set_coordinates(char *data, unsigned short x, unsigned short y, unsigned char direction); -/** Initialize connection with map server */ -void map_start(); - /** Requests to walk */ void walk(unsigned short x, unsigned short y, unsigned char direction); |