summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEugenio Favalli <elvenprogrammer@gmail.com>2005-10-16 13:42:33 +0000
committerEugenio Favalli <elvenprogrammer@gmail.com>2005-10-16 13:42:33 +0000
commit59167f0f02dfd2c8463b2f3d93a8ac219dcc012e (patch)
tree3dd32d4594c1a194c4cc19e1614ea01290417431 /src
parentd205342bb908207f7921c444e539072e006be241 (diff)
downloadmana-59167f0f02dfd2c8463b2f3d93a8ac219dcc012e.tar.gz
mana-59167f0f02dfd2c8463b2f3d93a8ac219dcc012e.tar.bz2
mana-59167f0f02dfd2c8463b2f3d93a8ac219dcc012e.tar.xz
mana-59167f0f02dfd2c8463b2f3d93a8ac219dcc012e.zip
The connection should be non-blocking now and fixed the problem with sound not being played at startup.
Diffstat (limited to 'src')
-rw-r--r--src/game.cpp2
-rw-r--r--src/gui/char_select.cpp6
-rw-r--r--src/gui/char_server.cpp49
-rw-r--r--src/gui/char_server.h10
-rw-r--r--src/gui/login.cpp127
-rw-r--r--src/gui/login.h29
-rw-r--r--src/main.cpp19
-rw-r--r--src/main.h3
-rw-r--r--src/net/network.cpp131
-rw-r--r--src/net/network.h12
-rw-r--r--src/net/protocol.cpp51
-rw-r--r--src/net/protocol.h3
12 files changed, 234 insertions, 208 deletions
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;
diff --git a/src/main.h b/src/main.h
index b8d2a052..cd3a0ff2 100644
--- a/src/main.h
+++ b/src/main.h
@@ -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);