summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorHello=) <hello@themanaworld.org>2024-03-28 03:58:45 +0300
committerHello=) <hello@themanaworld.org>2024-03-28 03:58:45 +0300
commitdb0b1da0060f5eb4b2af040c22ea9373d36970af (patch)
treedc2bdc0478c341bf4368fee4993c20e52f2d41c1 /src
downloadguildbot-db0b1da0060f5eb4b2af040c22ea9373d36970af.tar.gz
guildbot-db0b1da0060f5eb4b2af040c22ea9373d36970af.tar.bz2
guildbot-db0b1da0060f5eb4b2af040c22ea9373d36970af.tar.xz
guildbot-db0b1da0060f5eb4b2af040c22ea9373d36970af.zip
Initial commit of Guild Bot, as seen in:
$ sha256sum guildsrc.zip ef61469ab59ce3f5dd3289505e89bd5b84e3a82b89cda90d25ae3c41f7464beb guildsrc.zip Verification shown its source 100% match to currently running version on TMWA. The following changes were made VS version found in guildsrc.zip: 1) src/build and src/dist content completely removed. Rationale: build-time artifacts; binaries contained login/password. 2) Executable flag (+x) removed from src/automation.cpp and src/main.cpp. Rationale: executable CPP sources are weird thing. No change to file content. 3) src/main.cpp changes: 3 lines: std::string main_username = "test"; std::string main_pw = "test"; std::string main_host = "127.0.0.1"; Rationale: avoid leaking real production credentials and ensure experimenters dont hammer real TMW prod server by experiments. Effort been made to preserve original file timestamps, etc. However toplevel src/ dir date adjusted to date of mentioned changes.
Diffstat (limited to 'src')
-rw-r--r--src/.dep.inc5
-rw-r--r--src/.gitignore2
-rw-r--r--src/Makefile109
-rw-r--r--src/automation.cpp855
-rw-r--r--src/automation.h77
-rw-r--r--src/game.cpp103
-rw-r--r--src/game.h37
-rw-r--r--src/logindata.h42
-rw-r--r--src/main.cpp153
-rw-r--r--src/main.h40
-rw-r--r--src/nbproject/Makefile-Debug.mk175
-rw-r--r--src/nbproject/Makefile-Release.mk176
-rw-r--r--src/nbproject/Makefile-impl.mk123
-rw-r--r--src/nbproject/Makefile-variables.mk24
-rw-r--r--src/nbproject/Package-Debug.bash74
-rw-r--r--src/nbproject/Package-Release.bash74
-rw-r--r--src/nbproject/configurations.xml131
-rw-r--r--src/nbproject/private/configurations.xml43
-rw-r--r--src/nbproject/private/private.properties0
-rw-r--r--src/nbproject/private/private.xml4
-rw-r--r--src/nbproject/project.properties0
-rw-r--r--src/nbproject/project.xml15
-rw-r--r--src/net/charserverhandler.cpp166
-rw-r--r--src/net/charserverhandler.cpp~167
-rw-r--r--src/net/charserverhandler.h52
-rw-r--r--src/net/chathandler.cpp146
-rw-r--r--src/net/chathandler.cpp~147
-rw-r--r--src/net/chathandler.h38
-rw-r--r--src/net/loginhandler.cpp126
-rw-r--r--src/net/loginhandler.cpp~119
-rw-r--r--src/net/loginhandler.h45
-rw-r--r--src/net/maploginhandler.cpp62
-rw-r--r--src/net/maploginhandler.cpp~62
-rw-r--r--src/net/maploginhandler.h37
-rw-r--r--src/net/messagehandler.cpp45
-rw-r--r--src/net/messagehandler.h48
-rw-r--r--src/net/messagein.cpp198
-rw-r--r--src/net/messagein.h97
-rw-r--r--src/net/messageout.cpp116
-rw-r--r--src/net/messageout.h65
-rw-r--r--src/net/nethandler.cpp182
-rw-r--r--src/net/nethandler.cpp~183
-rw-r--r--src/net/nethandler.h33
-rw-r--r--src/net/network.cpp442
-rw-r--r--src/net/network.cpp~443
-rw-r--r--src/net/network.h103
-rw-r--r--src/net/packet.cpp40
-rw-r--r--src/net/packet.h47
-rw-r--r--src/net/protocol.cpp79
-rw-r--r--src/net/protocol.h118
-rw-r--r--src/onlinelist.cpp145
-rw-r--r--src/onlinelist.h86
-rw-r--r--src/serverinfo.h37
-rw-r--r--src/utils/mutex.h91
-rw-r--r--src/utils/specialfolder.cpp78
-rw-r--r--src/utils/specialfolder.h30
-rw-r--r--src/utils/stringutils.cpp177
-rw-r--r--src/utils/stringutils.h142
58 files changed, 6454 insertions, 0 deletions
diff --git a/src/.dep.inc b/src/.dep.inc
new file mode 100644
index 0000000..4560e55
--- /dev/null
+++ b/src/.dep.inc
@@ -0,0 +1,5 @@
+# This code depends on make tool being used
+DEPFILES=$(wildcard $(addsuffix .d, ${OBJECTFILES}))
+ifneq (${DEPFILES},)
+include ${DEPFILES}
+endif
diff --git a/src/.gitignore b/src/.gitignore
new file mode 100644
index 0000000..e2cae22
--- /dev/null
+++ b/src/.gitignore
@@ -0,0 +1,2 @@
+/build/
+/dist/
diff --git a/src/Makefile b/src/Makefile
new file mode 100644
index 0000000..e137db5
--- /dev/null
+++ b/src/Makefile
@@ -0,0 +1,109 @@
+#
+# There exist several targets which are by default empty and which can be
+# used for execution of your targets. These targets are usually executed
+# before and after some main targets. They are:
+#
+# .build-pre: called before 'build' target
+# .build-post: called after 'build' target
+# .clean-pre: called before 'clean' target
+# .clean-post: called after 'clean' target
+# .clobber-pre: called before 'clobber' target
+# .clobber-post: called after 'clobber' target
+# .all-pre: called before 'all' target
+# .all-post: called after 'all' target
+# .help-pre: called before 'help' target
+# .help-post: called after 'help' target
+#
+# Targets beginning with '.' are not intended to be called on their own.
+#
+# Main targets can be executed directly, and they are:
+#
+# build build a specific configuration
+# clean remove built files from a configuration
+# clobber remove all built files
+# all build all configurations
+# help print help mesage
+#
+# Targets .build-impl, .clean-impl, .clobber-impl, .all-impl, and
+# .help-impl are implemented in nbproject/makefile-impl.mk.
+#
+# Available make variables:
+#
+# CND_BASEDIR base directory for relative paths
+# CND_DISTDIR default top distribution directory (build artifacts)
+# CND_BUILDDIR default top build directory (object files, ...)
+# CONF name of current configuration
+# CND_PLATFORM_${CONF} platform name (current configuration)
+# CND_ARTIFACT_DIR_${CONF} directory of build artifact (current configuration)
+# CND_ARTIFACT_NAME_${CONF} name of build artifact (current configuration)
+# CND_ARTIFACT_PATH_${CONF} path to build artifact (current configuration)
+# CND_PACKAGE_DIR_${CONF} directory of package (current configuration)
+# CND_PACKAGE_NAME_${CONF} name of package (current configuration)
+# CND_PACKAGE_PATH_${CONF} path to package (current configuration)
+#
+# NOCDDL
+
+
+# Environment
+MKDIR=mkdir
+CP=cp
+CCADMIN=CCadmin
+RANLIB=ranlib
+
+
+# build
+build: .build-post
+
+.build-pre:
+# Add your pre 'build' code here...
+
+.build-post: .build-impl
+# Add your post 'build' code here...
+
+
+# clean
+clean: .clean-post
+
+.clean-pre:
+# Add your pre 'clean' code here...
+
+.clean-post: .clean-impl
+# Add your post 'clean' code here...
+
+
+# clobber
+clobber: .clobber-post
+
+.clobber-pre:
+# Add your pre 'clobber' code here...
+
+.clobber-post: .clobber-impl
+# Add your post 'clobber' code here...
+
+
+# all
+all: .all-post
+
+.all-pre:
+# Add your pre 'all' code here...
+
+.all-post: .all-impl
+# Add your post 'all' code here...
+
+
+# help
+help: .help-post
+
+.help-pre:
+# Add your pre 'help' code here...
+
+.help-post: .help-impl
+# Add your post 'help' code here...
+
+
+
+# include project implementation makefile
+include nbproject/Makefile-impl.mk
+
+# include project make variables
+include nbproject/Makefile-variables.mk
diff --git a/src/automation.cpp b/src/automation.cpp
new file mode 100644
index 0000000..48babd7
--- /dev/null
+++ b/src/automation.cpp
@@ -0,0 +1,855 @@
+/*
+ *
+ * Automation.cpp: The Ruined Place Chat Bot.
+ *
+ */
+
+#include <iostream>
+#include <string>
+#include <set>
+#include <deque>
+#include <sstream>
+#include <fstream>
+#include <map>
+#include <cstdlib>
+
+#include "automation.h"
+#include "game.h"
+#include "main.h"
+#include "utils/stringutils.h"
+#include "utils/specialfolder.h"
+#include "net/nethandler.h"
+
+static Automation *automationHandler = NULL;
+
+std::set<member> guildMembers;
+std::deque<whispermsg> whispers;
+std::deque<whispermsg> information;
+std::set<std::string> onlineList;
+std::set<memberinvite> inviteList;
+std::map<std::string, std::string> guildMOTD;
+
+bool automation = true;
+bool repeatfix = false;
+bool load = true;
+bool hideOnLoad = true; // Hide all online/offline notifications on startup - creates a lot of spam!
+
+int message_timer = 0;
+
+Automation::Automation()
+{
+ automationHandler = this;
+}
+
+Automation::~Automation()
+{
+ delete automationHandler;
+}
+
+Automation *Automation::getAutomationHandler()
+{
+ return automationHandler;
+}
+
+/* Commands/chat recieved through whisper. */
+void Automation::commandHandler(std::string message, std::string nick)
+{
+
+ std::string::size_type pos = message.find(' ');
+ std::string type(message, 0, pos);
+ std::string args(message, pos == std::string::npos ? message.size() : pos + 1);
+
+ /*start of code that deals with invitations - could do with a rewrite*/
+ std::set<memberinvite>::iterator it3;
+ bool invited = false;
+ memberinvite invitedMember;
+
+ for (it3=inviteList.begin(); it3 != inviteList.end(); it3++)
+ {
+ if (it3->name == nick)
+ {
+ invited = true;
+ invitedMember = *it3;
+ }
+ }
+
+ if (invited)
+ {
+ if (removeColors(type) == "yes")
+ {
+ inviteList.erase(invitedMember);
+ addMember(nick, invitedMember.guildName, 0);
+ addMessage(nick+ " has joined the Guild.",
+ invitedMember.guildName, "Info", 1);
+ return;
+ }
+ else if (removeColors(type) == "no")
+ {
+ inviteList.erase(invitedMember);
+ return;
+ }
+ }
+
+ /* end */
+
+ if (!automation || !inGuild(nick))
+ {
+ whisper(nick, colorText("You are currently not in a guild."
+ " For more information or to discuss the possibility"
+ " of adding you own guild please contact Jero."), 1);
+ return;
+ }
+
+ if (type[0] == '!')
+ {
+ debugMsg("("+findByName(nick).guildName+") Command: "+
+ nick+": "+type +" "+args);
+ //note incorrect commands will be logged twice.
+ }
+
+ if (accessLevel(args) != -1)
+ {
+ member tmp = findByName(nick);
+ if (tmp.status == 0)
+ {
+ guildMembers.erase(tmp);
+ tmp.status = 1;
+ addMessage(tmp.name+ " is now Online.", tmp.guildName, "Info", 1);
+ guildMembers.insert(tmp);
+ whisper(tmp.name, colorText("Welcome to the "+tmp.guildName+"! ("+
+ toString(countOnline(tmp.guildName)) +" Members are Online)"), 1);
+ }
+ }
+
+ if (type == "!invite" && accessLevel(nick) >= 5) /* This command is only available to admin*/
+ {
+ if (!args.empty() && accessLevel(args) != -1)
+ {
+ if (inGuild(args))
+ {
+ whisper(nick, colorText("The user is in another guild."), 1);
+ }
+ else
+ {
+ if (onlineList.find(args) != onlineList.end())
+ {
+ memberinvite tmp= {args, findByName(nick).guildName};
+ inviteList.insert(tmp);
+ whisper(args, colorText("You have been invited to the "+
+ findByName(nick).guildName+ " guild chat. If you "
+ "would like to accept this invitation"
+ " please reply \"yes\" and if not then \"no\" ." ), 1);
+ }
+ else
+ {
+ whisper(nick, colorText("The user is offline or hidden."), 1);
+ }
+
+ }
+ }
+ }
+ else if (type == "!test" && accessLevel(nick) == 20) /* This command is only available to admin*/
+ {
+ addMessage("A test will be running shortly.",
+ findByName(nick).guildName, "Info", 0);
+ testMsg();
+ }
+ else if (type == "!disband" && accessLevel(nick) >= 10) /* This command is only available to guild masters*/
+ {
+ std::string guild = findByName(nick).guildName;
+ debugMsg(guild + " disbanded.");
+ addMessage("The "+guild +" guild has been disbanded.","global", "Info", 1);
+
+ std::set<member>::iterator it2;
+ for (it2=guildMembers.begin(); it2 != guildMembers.end(); it2++)
+ {
+ if (it2->guildName == guild)
+ guildMembers.erase(it2);
+ }
+
+ saveMembers();
+ }
+ else if (type == "!removeguild" && accessLevel(nick) == 20) /* This command is only available to admin*/
+ {
+
+ if (!args.empty())
+ {
+ debugMsg(args + "removed.");
+ std::set<member>::iterator it2;
+ for (it2=guildMembers.begin(); it2 != guildMembers.end(); it2++)
+ {
+ if (it2->guildName == args)
+ guildMembers.erase(it2);
+ }
+
+ addMessage("The "+args +" guild has been removed.","global", "Info", 1);
+ saveMembers();
+ }
+
+ }
+ else if (type == "!addguild" && accessLevel(nick) == 20)
+ {
+ if (!args.empty())
+ {
+ std::string::size_type pos2 = args.find(',');
+ std::string name = args.substr(0, pos2);
+ std::string guildName = args.substr(pos2+1, args.size());
+
+ addMember(name, guildName, 10);
+ addMessage("The "+guildName+" guild has been created.","global", "Info", 1);
+ }
+ }
+ else if (type == "!info")
+ {
+ std::stringstream message;
+ message << "Player name: "+nick+", Access Level: "<< accessLevel(nick)
+ << ", Guild:" << findByName(nick).guildName
+ << ", No. Of Online Players: " <<
+ countOnline(findByName(nick).guildName);
+
+ whisper(nick, colorText(message.str()), 1);
+
+ std::string MOTD = getMOTD(findByName(nick).guildName);
+ if (MOTD != "")
+ whisper(nick, colorText("Guild MOTD: "+MOTD), 1);
+
+ }
+ else if (type == "!ping") /* A simple response to check if the bot is active. */
+ {
+ whisper(nick, colorText("Pong."), 0);
+ }
+ else if (type == "!remove")
+ {
+ if (!args.empty())
+ {
+ if (hasPermission(nick, args, 0) && inGuild(args))
+ {
+ removeMember(args);
+ whisper(args, "You have been removed from the Guild", 0);
+ addMessage(args+ " has been removed from the Guild.",
+ findByName(nick).guildName, "Info", 1);
+ saveMembers();
+ }
+ }
+ }
+ else if (type == "!setmotd" && accessLevel(nick) >= 5)
+ {
+ std::map<std::string, std::string>::iterator it;
+ it=guildMOTD.find(findByName(nick).guildName);
+
+ if (it != guildMOTD.end())
+ {
+ guildMOTD.erase(it);
+ guildMOTD.insert(std::pair<std::string, std::string>(findByName(nick).guildName, args));
+ }
+ else
+ {
+ guildMOTD.insert(std::pair<std::string, std::string>(findByName(nick).guildName, args));
+ }
+
+ whisper(nick, colorText("MOTD Set:" + args), 1);
+ }
+ else if (type == "!removemotd" && accessLevel(nick) >= 5)
+ {
+ std::map<std::string, std::string>::iterator it;
+ it=guildMOTD.find(findByName(nick).guildName);
+
+ if (it != guildMOTD.end())
+ {
+ guildMOTD.erase(it);
+ whisper(nick, colorText("The MOTD has been Removed."), 1);
+ }
+ else
+ {
+ whisper(nick, colorText("No MOTD set."), 1);
+ }
+
+ }
+ else if (type == "!setaccess") /* This command is only available to admin*/
+ {
+ if (!args.empty())
+ {
+ std::string::size_type pos = args.find(' ');
+ std::string level(args, 0, pos);
+ std::string name(args, pos == std::string::npos ? args.size() : pos + 1);
+ int access = toInt(level);
+
+ if (hasPermission(nick, name, access) && inGuild(name)
+ && !name.empty() && !level.empty())
+ {
+ member update = findByName(name);
+ guildMembers.erase(update);
+ update.accesslevel = access;
+ guildMembers.insert(update);
+ whisper(nick, colorText("Player name:" + name +
+ ", Access Level: "+level), 1);
+ }
+ saveMembers();
+ }
+ }
+ else if (type == "!leave")
+ {
+ std::string guild = findByName(nick).guildName;
+ whisper(nick, "You have left the Guild", 0);
+ removeMember(nick);
+ addMessage(nick+ " has left the Guild.", guild, "Info", 1);
+ saveMembers();
+ }
+ else if (type == "!help")
+ {
+ whisper(nick, colorText("Guild ChatBot. The "
+ "commands are: !invite <name>, !leave, !listonline, !listmembers, !info. "
+ "If you would like to hide information messages use !hideinfo, "
+ "and to make them visible again use !showinfo."), 1);
+
+ if (accessLevel(nick) >= 5)
+ {
+ whisper(nick, colorText(
+ "You are also able to add a guild MOTD using !setmotd, this can be removed using !removemotd."), 1);
+ }
+
+ if (accessLevel(nick) >= 10)
+ {
+ whisper(nick, colorText(
+ "You also have access to the guild master commands these are"
+ " !remove <name>, !disband, !setaccess <access level> <name>"
+ "(the access level must be less than or equal to your own)."), 1);
+ }
+ else if (accessLevel(nick) <= 10 && accessLevel(nick) > 0)
+ {
+ whisper(nick, colorText(
+ "You also have access to the guild moderator commands these are"
+ " !remove <name>, !setaccess <access level> <name>"
+ "(the access level must be less than or equal to your own)."), 1);
+ }
+
+ if (accessLevel(nick) == 20)
+ {
+ whisper(nick, colorText(
+ "You also have access to the admin commands these are !test,"
+ " !addguild <name>,<guild name> (the comma is important)"
+ " and !removeguild <name>."), 1);
+ whisper(nick, colorText(
+ " To send a message to all guilds use !global <message>, "
+ "!listallonline, !joinguild <guild name> (lets you join another guilds chat)"), 1);
+ }
+ }
+ else if (type == "!hideinfo")
+ {
+ whisper(nick, colorText("Information messages hidden."), 1);
+ member tmp = findByName(nick);
+ guildMembers.erase(tmp);
+ tmp.info = 0;
+ guildMembers.insert(tmp);
+ }
+ else if (type == "!online")
+ {
+ whisper(nick, colorText("You are online."), 1);
+ member tmp = findByName(nick);
+ guildMembers.erase(tmp);
+ tmp.status = 1;
+ guildMembers.insert(tmp);
+ }
+ else if (type == "!offline")
+ {
+ whisper(nick, colorText("You have gone offline."), 1);
+ member tmp = findByName(nick);
+ guildMembers.erase(tmp);
+ tmp.status = 0;
+ guildMembers.insert(tmp);
+ }
+ else if (type == "!joinguild" && accessLevel(nick) == 20)
+ {
+ whisper(nick, colorText("You've joined "+args+"."), 1);
+ member tmp = findByName(nick);
+ guildMembers.erase(tmp);
+ tmp.guildName = args;
+ guildMembers.insert(tmp);
+ }
+ else if (type == "!showinfo")
+ {
+ whisper(nick, colorText("Information messages vissible."), 1);
+ member tmp = findByName(nick);
+ guildMembers.erase(tmp);
+ tmp.info = 1;
+ guildMembers.insert(tmp);
+ }
+ else if (type == "!global" && accessLevel(nick) == 20) /* This command is only available to admin*/
+ {
+ if (!args.empty())
+ {
+ addMessage(args, "global", "Info", 0);
+ }
+ }
+ else if (type == "!listonline")
+ {
+ std::set<member>::iterator it;
+ std::string message;
+ std::stringstream list;
+ list << "List of online Guild Members: ";
+
+ for (it=guildMembers.begin(); it != guildMembers.end(); it++)
+ {
+
+ if (list.str().length() + it->name.length() > 250 && it->status == 1
+ && it->guildName == findByName(nick).guildName)
+ {
+ message = list.str();
+ message[message.length()-2] = '.';
+ whisper(nick,colorText(message), 1);
+ list.str("");
+ list << it->name + ", ";
+ }
+ else if (it->status == 1 && it->guildName == findByName(nick).guildName)
+ {
+ list << it->name + ", ";
+ }
+
+ }
+ message = list.str();
+ message[message.length()-2] = '.';
+ whisper(nick,colorText(message), 1);
+ }
+ else if (type == "!getonlineinfo")
+ {
+ std::set<member>::iterator it;
+ std::string message;
+ std::stringstream list;
+ list << "OL";
+
+ for (it=guildMembers.begin(); it != guildMembers.end(); it++)
+ {
+ int status = it->status;
+ if (it->accesslevel >= 10)
+ status += 2;
+
+ if (list.str().length() + it->name.length()+2 > 400
+ && it->guildName == findByName(nick).guildName)
+ {
+ list << "#";
+ message = list.str();
+ whisper(nick,colorText(message), 1);
+ list.str("");
+ list << "oL#";
+ list << it->name;
+ list << status;
+ }
+ else if (it->guildName == findByName(nick).guildName)
+ {
+ list << "#";
+ list << it->name;
+ list << status;
+ }
+
+ }
+ message = list.str();
+ whisper(nick,colorText(message), 1);
+ }
+ else if (type == "!listallonline" && accessLevel(nick) == 20)
+ {
+ std::set<member>::iterator it;
+ std::string message;
+ std::stringstream list;
+ list << "List of online Players: ";
+
+ for (it=guildMembers.begin(); it != guildMembers.end(); it++)
+ {
+
+ if (list.str().length() + it->name.length() > 250 && it->status == 1)
+ {
+ message = list.str();
+ message[message.length()-2] = '.';
+ whisper(nick,colorText(message), 1);
+ list.str("");
+ list << it->name + ", ";
+ }
+ else if (it->status == 1)
+ {
+ list << it->name + ", ";
+ }
+
+ }
+ message = list.str();
+ message[message.length()-2] = '.';
+ whisper(nick,colorText(message), 1);
+ }
+ else if (type == "!listmembers")
+ {
+ std::set<member>::iterator it;
+ std::string message;
+ std::stringstream list;
+ list << "List of Guild Members: ";
+
+ for (it=guildMembers.begin(); it != guildMembers.end(); it++)
+ {
+
+ if (list.str().length() + it->name.length() > 250
+ && it->guildName == findByName(nick).guildName)
+ {
+ message = list.str();
+ message[message.length()-2] = '.';
+ whisper(nick,colorText(message), 1);
+ list.str("");
+ list << it->name + ", ";
+ }
+ else if (it->guildName == findByName(nick).guildName)
+ {
+ list << it->name + ", ";
+ }
+
+ }
+ message = list.str();
+ message[message.length()-2] = '.';
+ whisper(nick,colorText(message), 1);
+ }
+ else
+ {
+ std::size_t found;
+ found=message.find("*AFK*");
+
+ if (found == std::string::npos)
+ addMessage(removeColors(message), findByName(nick).guildName, nick, 0);
+ }
+}
+
+/* hooks directly into the main game logic. */
+void Automation::logic()
+{
+ if (message_timer == 0)
+ message_timer = cur_time;
+
+ if (get_elapsed_time(message_timer) > 10 && hideOnLoad)
+ {
+ hideOnLoad = false;
+ debugMsg("Online/Offline messages unhidden.");
+ }
+
+ if (!whispers.empty())// with SDL_Delay(10) this should send around 100 messages per second.
+ {
+ NetHandler::getNetInstance()->privateMessage(whispers.front().name,
+ whispers.front().message);
+ whispers.pop_front();
+ }
+ else if (!information.empty())
+ {
+ NetHandler::getNetInstance()->privateMessage(information.front().name,
+ information.front().message);
+ information.pop_front();
+ }
+}
+
+void Automation::addMember(std::string name, std::string guildName, int access)
+{
+ member addme = {name, guildName, 0, access, 1};
+ guildMembers.insert(addme);
+
+ if (!load)
+ {
+ debugMsg("Member Added: "+ name+", Access Level: "+
+ toString(access) + " Guild Name: " + guildName);
+ saveMembers();
+ }
+}
+
+void Automation::removeMember(std::string name)
+{
+ debugMsg("Member Removed: "+ name);
+ guildMembers.erase(findByName(name));
+ saveMembers();
+}
+
+/*Checks to see whether a player is on the guildbot.*/
+bool Automation::inGuild(std::string name)
+{
+ std::set<member>::iterator it;
+
+ for (it=guildMembers.begin() ; it != guildMembers.end(); it++)
+ if (it->name == name)
+ return true;
+
+ return false;
+}
+
+/* Updates member online status, this uses 4144's online list.*/
+void Automation::updateOnline(std::set<std::string> &onlinePlayers)
+{
+ debugMsg("Update Online List.");
+ onlineList = onlinePlayers;
+ std::set<member>::iterator it;
+ std::set<member>::iterator it2;
+ std::set<member> updateStatus; //used for applying changes
+
+ //figure out status changes
+ for (it=guildMembers.begin(); it != guildMembers.end(); it++ )
+ {
+ if (it->accesslevel < 0)
+ continue;
+
+ member old = *it;
+
+ if (onlinePlayers.find(it->name) != onlinePlayers.end() && it->status == 0)
+ {
+ old.status = 1;
+ updateStatus.insert(old);
+ }
+ else if (onlinePlayers.find(it->name) == onlinePlayers.end() && it->status == 1)
+ {
+ old.status = 0;
+ updateStatus.insert(old);
+ }
+ }
+
+ //apply status changes
+ for (it2=updateStatus.begin(); it2 != updateStatus.end(); it2++)
+ {
+ member tmp = *it2;
+ if (it2->status == 1)
+ {
+ guildMembers.erase(findByName(it2->name));
+
+ /*if (hideOnLoad != true)*/
+ addMessage(tmp.name+ " is now Online.", tmp.guildName, "Info", 1);
+
+ guildMembers.insert(tmp);
+ whisper(tmp.name, colorText("Welcome to the "+tmp.guildName+"! ("+
+ toString(countOnline(tmp.guildName)) +" Members are Online)"), 1);
+
+ std::string MOTD = getMOTD(tmp.guildName);
+ if (MOTD != "")
+ whisper(tmp.name, colorText(MOTD), 1);
+
+ }
+ else if (it2->status == 0)
+ {
+ guildMembers.erase(findByName(it2->name));
+ guildMembers.insert(tmp);
+ addMessage(tmp.name+ " is now Offline.", tmp.guildName, "Info", 1);
+ }
+
+ }
+}
+
+/* Sends messages to all those in the specified guild. */
+void Automation::addMessage(std::string msg, std::string guildName,
+ std::string sender, int p)
+{
+ std::set<member>::iterator it;
+ for (it=guildMembers.begin(); it != guildMembers.end(); it++)
+ {
+ if (sender == "Info" && it->info == 0)
+ continue;
+
+ if (it->name != sender && it->status == 1 && (it->guildName == guildName
+ || guildName == "global"))
+ {
+ if (sender == "Info")
+ whisper(it->name,"##0"+msg, p);
+ else
+ whisper(it->name, colorText(sender) +": "+"##0"+msg, p);
+ }
+ }
+}
+
+void Automation::debugMsg(std::string msg)
+{
+ std::string message = removeColors("GuildBot: "+msg);
+ //logger->log(message.c_str());
+}
+
+/* Adds the whispers to the required queue*/
+void Automation::whisper(std::string name, std::string msg, int priority)
+{
+ whispermsg newmsg = {name, msg};
+
+ if (priority == 0)
+ whispers.push_back(newmsg);
+ else
+ information.push_back(newmsg);
+}
+
+void Automation::showOptions()
+{
+ debugMsg("List of Guild Members:");
+ std::set<member>::iterator it;
+
+ for ( it=guildMembers.begin() ; it != guildMembers.end(); it++ )
+ {
+ std::stringstream status;
+ status << " Status: " << it->status;
+ status << " Access Level: " << it->accesslevel;
+ status << " Guild: " << it->guildName;
+ debugMsg("Character name: "+ it->name + status.str());
+ }
+}
+
+/* Saves the member file */
+void Automation::saveMembers()
+{
+ mLocalDataDir += ".";
+#if defined WIN32
+ mLocalDataDir = getSpecialFolderLocation(CSIDL_LOCAL_APPDATA);
+ mLocalDataDir += "/ManaGuild";
+ std::string namelist = mLocalDataDir + "/guildmembers.txt";
+#else
+ std::string namelist = "guildmembers.txt";
+#endif
+ std::ofstream guildMemberFile(namelist.c_str());
+
+ if (guildMemberFile.is_open())
+ {
+ debugMsg("Save Guild Member File.");
+ std::set<member>::iterator it;
+
+ for (it=guildMembers.begin(); it != guildMembers.end(); it++)
+ guildMemberFile << it->name.c_str() << ","
+ << it->accesslevel << ","
+ << it->guildName << std::endl;
+
+ guildMemberFile.close();
+ }
+ else
+ {
+ debugMsg("Guild Member File save failed.");
+ }
+}
+
+/* Loads the member file */
+void Automation::loadMembers()
+{
+ mLocalDataDir += ".";
+#if defined WIN32
+ mLocalDataDir = getSpecialFolderLocation(CSIDL_LOCAL_APPDATA);
+ mLocalDataDir += "/ManaGuild";
+ std::string namelist = mLocalDataDir + "/guildmembers.txt";
+#else
+ std::string namelist = "guildmembers.txt";
+#endif
+ std::string line;
+ std::ifstream guildMemberFile(namelist.c_str());
+
+ if (guildMemberFile.is_open())
+ {
+ debugMsg("Load Guild Member File.");
+ while (!guildMemberFile.eof() )
+ {
+ getline (guildMemberFile,line);
+ if (!line.empty())
+ {
+ /* Messy pretend tokenizer*/
+ std::string::size_type pos = line.find(',');
+ std::string::size_type pos2 = line.find(',', pos+1);
+ std::string guildName = line.substr(pos2+1, line.size());
+ std::string name = line.substr(0, pos);
+ int access = toInt(line.substr(pos+1, pos2));
+ addMember(name, guildName, access);
+ }
+ }
+
+ guildMemberFile.close();
+ }
+ else
+ {
+ debugMsg("Guild Member File open failed. If this is your "
+ "first time runing the chat bot please ignore this message.");
+ }
+
+ load = false;
+}
+
+/* Color parts of the text to avoid bans from chat spam, also looks pretty. */
+std::string Automation::colorText(std::string text)
+{
+ if (repeatfix)
+ text = "##3"+text;
+ else
+ text = "##2"+text;
+
+ repeatfix = !repeatfix;
+
+ return text;
+}
+
+/* Returns the number of members online in a specified guild. */
+int Automation::countOnline(std::string guildName)
+{
+ int count = 0;
+ std::set<member>::iterator it;
+
+ for (it=guildMembers.begin(); it != guildMembers.end(); it++)
+ if (it->status == 1 && (it->guildName == guildName || guildName == "global"))
+ count++;
+
+ return count;
+}
+
+void Automation::clearMembers()
+{
+ debugMsg("Clear Members.");
+ guildMembers.clear();
+}
+
+int Automation::accessLevel(std::string name)
+{
+ int accesslevel = findByName(name).accesslevel;
+
+ return accesslevel;
+}
+
+/* Checks to see whether the user has the required permissions,
+ * for either changing the someones accesslevel or removing another player. */
+bool Automation::hasPermission(std::string user,
+ std::string player, int changeLevel)
+{
+ // level 5 players should not be able to remove others.
+ if (accessLevel(user) != 50 && accessLevel(player) < accessLevel(user)
+ && changeLevel <= accessLevel(user) && accessLevel(user) > 5 &&
+ findByName(user).guildName == findByName(player).guildName)
+ {
+ return true;
+ }
+ else
+ {
+ whisper(user, colorText("You do not have the correct "
+ "access level, for this operation."), 1);
+ return false;
+ }
+
+ return false;
+}
+
+/* Finds and a member by name. */
+member Automation::findByName(std::string name)
+{
+ member findme;
+ std::set<member>::iterator it;
+
+ for (it=guildMembers.begin(); it != guildMembers.end(); it++)
+ if (it->name == name)
+ findme = *it;
+
+ return findme;
+}
+
+/* Outputs a test message for testing purposes.*/
+void Automation::testMsg()
+{
+ for (int i=0;i < 20; i++){
+ std::string message = "testing " + toString(i);
+ addMessage(message,"global", "Info", 0);
+ }
+}
+
+std::string Automation::getMOTD(std::string guild)
+{
+ std::map<std::string, std::string>::iterator it;
+ it=guildMOTD.find(guild);
+
+ if (it != guildMOTD.end())
+ return it->second;
+ else
+ return "";
+}
+
+
+
+
diff --git a/src/automation.h b/src/automation.h
new file mode 100644
index 0000000..0f563fe
--- /dev/null
+++ b/src/automation.h
@@ -0,0 +1,77 @@
+/*
+ *
+ * Automation.h: The Ruined Place Chat Bot.
+ *
+ */
+
+#include <iostream>
+#include <string>
+#include <set>
+
+
+
+extern bool automation;
+
+struct member
+{
+ std::string name;
+ std::string guildName; /* Now suports more than one group */
+ int status; // 0 = offline, 1 = online
+ int accesslevel; // -1 = blocked, 0 = normal member, 10 = guildmaster, 20 = admin.
+ /* Note: blocked users do not have there online status updated, so don't recieve any messages.*/
+ int info; /* 0 = hide info messages, 1 = show info messages*/
+
+ bool operator<(const member &a) const
+ { return name < a.name; }
+};
+
+struct memberinvite
+{
+ std::string name;
+ std::string guildName;
+
+ bool operator<(const memberinvite &a) const
+ { return name < a.name; }
+};
+
+struct whispermsg
+{
+ std::string name;
+ std::string message;
+};
+
+class Automation
+{
+ public:
+
+ Automation();
+ ~Automation();
+ static Automation *getAutomationHandler();
+
+ void commandHandler(std::string message, std::string nick);
+ void logic();
+
+ void addMember(std::string name, std::string guildName, int access);
+ void removeMember(std::string name);
+ bool inGuild(std::string name);
+ void addMessage(std::string msg, std::string guildName, std::string sender, int p);
+ void updateOnline(std::set<std::string> &onlinePlayers);
+ int countOnline(std::string guildName);
+ int accessLevel(std::string name);
+ void saveMembers();
+ void loadMembers();
+ void whisper(std::string name, std::string msg, int priority);
+ void showOptions();
+ std::string colorText(std::string text);
+
+
+ private:
+ std::string getMOTD(std::string guild);
+ void testMsg();
+ void debugMsg(std::string msg);
+ member findByName(std::string name);
+ void clearMembers();
+ bool hasPermission(std::string user, std::string player, int changeLevel);
+};
+
+
diff --git a/src/game.cpp b/src/game.cpp
new file mode 100644
index 0000000..d933c2f
--- /dev/null
+++ b/src/game.cpp
@@ -0,0 +1,103 @@
+#include "game.h"
+
+#include <fstream>
+#include <sstream>
+#include <string>
+#include <iostream>
+
+#include "automation.h"
+#include "net/nethandler.h"
+#include "net/network.h"
+#include "onlinelist.h"
+
+std::string map_path;
+volatile int tick_time;
+volatile int cur_time;
+const int MAX_TIME = 10000;
+bool done = false;
+
+OnlineList *onlinelist;
+
+/**
+ * Advances game logic counter.
+ */
+Uint32 nextTick(Uint32 interval, void *param)
+{
+ tick_time++;
+ if (tick_time == MAX_TIME) tick_time = 0;
+ return interval;
+}
+
+int get_elapsed_time(int start_time)
+{
+ if (start_time <= tick_time) {
+ return (tick_time - start_time) * 10;
+ }
+ else {
+ return (tick_time + (MAX_TIME - start_time)) * 10;
+ }
+}
+
+Game::Game()
+{
+ // Initialize timers
+ tick_time = 0;
+ SDL_AddTimer(10, nextTick, NULL); // Logic counter
+ onlinelist = new OnlineList();
+}
+
+Game::~Game()
+{
+ delete onlinelist;
+}
+
+int stay_awake(void *data)
+{
+ /* Eathena seems to kick the client after 10 mins of inactivity.
+ A teenky hack to keep it alive.*/
+ while (!done)
+ {
+ NetHandler::getNetInstance()->sit();
+ std::cout << "I'm still here." << std::endl;
+ SDL_Delay(5 * 60 * 1000);
+ }
+}
+
+void Game::logic()
+{
+ done = false;
+ int gameTime = tick_time;
+
+ SDL_Thread *wakeywakey;
+
+
+ Network *mNetwork = NetHandler::getNetInstance()->getNetwork();
+ NetHandler::getNetInstance()->mapLoaded();
+ NetHandler::getNetInstance()->ping(tick_time);
+ //NetHandler::getNetInstance()->sit();
+ NetHandler::getNetInstance()->loadHandlers();
+ wakeywakey = SDL_CreateThread(stay_awake, NULL);
+
+ while (!done)
+ {
+ if (mNetwork->getState() == Network::ERROR_BROKE) //get out of this loop to allow a restart.
+ done = true;
+
+ mNetwork->flush();
+ mNetwork->dispatchMessages();
+
+ while (get_elapsed_time(gameTime) > 0)
+ {
+ cur_time = static_cast<int>(time(0));
+ onlinelist->logic();
+ Automation::getAutomationHandler()->logic();
+ ++gameTime;
+ }
+
+ gameTime = tick_time;
+
+ SDL_Delay(10); // Don't steal all the cpu time.
+ }
+
+ SDL_KillThread(wakeywakey);
+}
diff --git a/src/game.h b/src/game.h
new file mode 100644
index 0000000..e9cac14
--- /dev/null
+++ b/src/game.h
@@ -0,0 +1,37 @@
+/*
+ * File: game.h
+ * Author: dipesh
+ *
+ * Created on July 31, 2010, 6:27 PM
+ */
+
+#ifndef _GAME_H
+#define _GAME_H
+
+#include <iosfwd>
+#include <deque>
+
+
+//class MessageHandler;
+class Network;
+
+extern volatile int cur_time;
+extern std::string map_path;
+
+class Game
+{
+ public:
+ Game();
+ ~Game();
+
+ void logic();
+ protected:
+};
+ /**
+ * Returns elapsed time. (Warning: very unsafe function, it supposes the delay
+ * is always < 10 seconds)
+ */
+int get_elapsed_time(int start_time);
+
+#endif /* _GAME_H */
+
diff --git a/src/logindata.h b/src/logindata.h
new file mode 100644
index 0000000..62a04ff
--- /dev/null
+++ b/src/logindata.h
@@ -0,0 +1,42 @@
+/*
+ * The Mana World
+ * Copyright 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * The Mana World 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id: logindata.h 2184 2006-02-23 16:02:00Z der_doener $
+ */
+
+#ifndef _TMW_LOGINDATA_H
+#define _TMW_LOGINDATA_H
+
+struct LoginData
+{
+ std::string username;
+ std::string password;
+ std::string hostname;
+ short port;
+
+ int account_ID;
+ int session_ID1;
+ int session_ID2;
+ char sex;
+
+ bool remember;
+};
+
+#endif
diff --git a/src/main.cpp b/src/main.cpp
new file mode 100644
index 0000000..56f7815
--- /dev/null
+++ b/src/main.cpp
@@ -0,0 +1,153 @@
+/*
+ * File: main.cpp
+ * Author: dipesh
+ *
+ * Created on July 31, 2010, 6:04 PM
+ */
+
+#include <stdlib.h>
+#include <iostream>
+#include <string>
+#include <SDL.h>
+
+#include "logindata.h"
+#include "game.h"
+#include "main.h"
+#include "automation.h"
+
+#include "net/charserverhandler.h"
+#include "net/loginhandler.h"
+#include "net/maploginhandler.h"
+#include "net/messagein.h"
+#include "net/messageout.h"
+#include "net/network.h"
+#include "net/nethandler.h"
+#include "serverinfo.h"
+
+#if defined WIN32
+#include "Windows.h"
+#include "Winbase.h"
+#include "utils/specialfolder.h"
+#endif
+
+unsigned char state = LOGIN_STATE;
+unsigned char oldstate;
+std::string errorMessage;
+char n_server, n_character;
+
+class SERVER_INFO;
+SERVER_INFO **server_info;
+
+std::string main_username = "test";
+std::string main_pw = "test";
+std::string main_host = "127.0.0.1";
+int main_charno = 1; //character slot
+
+int main_port = 6901;
+
+int charID[3];
+int world;
+std::string char_name;
+std::string mLocalDataDir;
+
+LoginData loginData;
+
+void init_engine()
+{
+
+ if (SDL_Init(SDL_INIT_TIMER) < 0) {
+ std::cerr << "Could not initialize SDL: " <<
+ SDL_GetError() << std::endl;
+ exit(1);
+ }
+
+ atexit(SDL_Quit);
+ mLocalDataDir = ".";
+
+#if defined WIN32
+ mLocalDataDir = getSpecialFolderLocation(CSIDL_LOCAL_APPDATA);
+ mLocalDataDir += "/ManaGuild";
+#endif
+}
+
+int main(int argc, char **argv)
+{
+ Automation::getAutomationHandler()->loadMembers();
+
+ init_engine();
+ SDLNet_Init();
+ Network *network = NetHandler::getNetInstance()->getNetwork();
+ Game *game = new Game();
+
+ while (state != EXIT_STATE)
+ {
+ network->flush();
+ network->dispatchMessages();
+
+ if (network->getState() == Network::ERROR_BROKE)
+ {
+ state = ERROR_STATE;
+ errorMessage = "Got disconnected from server!";
+ }
+
+ if (state != oldstate)
+ {
+ oldstate = state;
+
+ switch (oldstate)
+ {
+ // Those states that don't cause a network disconnect
+ case ACCOUNT_STATE:
+ case CHAR_SELECT_STATE:
+ case GAME_STATE:
+ break;
+
+ default:
+ network->disconnect();
+ network->clearHandlers();
+ break;
+ }
+
+ switch (state)
+ {
+ case LOGIN_STATE:
+ state = ACCOUNT_STATE;
+ break;
+ case ACCOUNT_STATE:
+ loginData.hostname = main_host;
+ loginData.port = main_port;
+ loginData.password = main_pw;
+ loginData.username = main_username;
+ NetHandler::getNetInstance()->accountLogin(&loginData);
+ break;
+ case CHAR_SERVER_STATE:
+ {
+ SERVER_INFO *si = server_info[world];
+ loginData.hostname = iptostring(si->address);
+ loginData.port = si->port;
+ NetHandler::getNetInstance()->charLogin(&loginData);
+ break;
+ }
+ case CHAR_SELECT_STATE:
+ NetHandler::getNetInstance()->attemptCharSelect();
+ break;
+ case CONNECTING_STATE:
+ NetHandler::getNetInstance()->mapLogin(&loginData);
+ break;
+ case GAME_STATE:
+ game->logic();
+ break;
+ case ERROR_STATE:
+ state = EXIT_STATE; //LOGIN_STATE
+ break;
+ default:
+ state = EXIT_STATE;
+ break;
+ }
+ }
+ }
+
+ delete game;
+ return (EXIT_SUCCESS);
+}
+
diff --git a/src/main.h b/src/main.h
new file mode 100644
index 0000000..1b66278
--- /dev/null
+++ b/src/main.h
@@ -0,0 +1,40 @@
+/*
+ * File: man.h
+ * Author: dipesh
+ *
+ * Created on July 31, 2010, 6:04 PM
+ */
+
+#ifndef _MAIN_H
+#define _MAIN_H
+
+#include <iostream>
+#include <string>
+#include "serverinfo.h"
+
+extern SERVER_INFO **server_info;
+
+extern int charID[3];
+
+enum {
+ EXIT_STATE,
+ LOGIN_STATE,
+ ACCOUNT_STATE,
+ CHAR_SERVER_STATE,
+ CHAR_SELECT_STATE,
+ GAME_STATE,
+ ERROR_STATE,
+ CONNECTING_STATE
+};
+
+extern char n_server, n_character;
+extern unsigned char state;
+extern std::string errorMessage;
+extern std::string main_host;
+extern std::string char_name;
+extern int main_charno;
+extern int world;
+extern std::string mLocalDataDir;
+
+#endif /* _MAIN_H */
+
diff --git a/src/nbproject/Makefile-Debug.mk b/src/nbproject/Makefile-Debug.mk
new file mode 100644
index 0000000..d5830e6
--- /dev/null
+++ b/src/nbproject/Makefile-Debug.mk
@@ -0,0 +1,175 @@
+#
+# Generated Makefile - do not edit!
+#
+# Edit the Makefile in the project folder instead (../Makefile). Each target
+# has a -pre and a -post target defined where you can add customized code.
+#
+# This makefile implements configuration specific macros and targets.
+
+
+# Environment
+MKDIR=mkdir
+CP=cp
+CCADMIN=CCadmin
+RANLIB=ranlib
+CC=gcc
+CCC=g++
+CXX=g++
+FC=gfortran
+AS=as
+
+# Macros
+CND_PLATFORM=GNU-Linux-x86
+CND_CONF=Debug
+CND_DISTDIR=dist
+
+# Include project Makefile
+include Makefile
+
+# Object Directory
+OBJECTDIR=build/${CND_CONF}/${CND_PLATFORM}
+
+# Object Files
+OBJECTFILES= \
+ ${OBJECTDIR}/utils/stringutils.o \
+ ${OBJECTDIR}/net/maploginhandler.o \
+ ${OBJECTDIR}/game.o \
+ ${OBJECTDIR}/net/messageout.o \
+ ${OBJECTDIR}/onlinelist.o \
+ ${OBJECTDIR}/net/nethandler.o \
+ ${OBJECTDIR}/main.o \
+ ${OBJECTDIR}/net/messagein.o \
+ ${OBJECTDIR}/automation.o \
+ ${OBJECTDIR}/net/packet.o \
+ ${OBJECTDIR}/net/charserverhandler.o \
+ ${OBJECTDIR}/net/loginhandler.o \
+ ${OBJECTDIR}/utils/specialfolder.o \
+ ${OBJECTDIR}/net/network.o \
+ ${OBJECTDIR}/net/chathandler.o \
+ ${OBJECTDIR}/net/protocol.o \
+ ${OBJECTDIR}/net/messagehandler.o
+
+# C Compiler Flags
+CFLAGS=
+
+# CC Compiler Flags
+CCFLAGS=-pg
+CXXFLAGS=-pg
+
+# Fortran Compiler Flags
+FFLAGS=
+
+# Assembler Flags
+ASFLAGS=
+
+# Link Libraries and Options
+LDLIBSOPTIONS=-L/usr/lib -lSDL -lSDL_net -lpthread -lcurl
+
+# Build Targets
+.build-conf: ${BUILD_SUBPROJECTS}
+ ${MAKE} -f nbproject/Makefile-Debug.mk dist/Debug/GNU-Linux-x86/guild
+
+dist/Debug/GNU-Linux-x86/guild: ${OBJECTFILES}
+ ${MKDIR} -p dist/Debug/GNU-Linux-x86
+ ${LINK.cc} -o ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/guild ${OBJECTFILES} ${LDLIBSOPTIONS}
+
+${OBJECTDIR}/utils/stringutils.o: nbproject/Makefile-${CND_CONF}.mk utils/stringutils.cpp
+ ${MKDIR} -p ${OBJECTDIR}/utils
+ ${RM} $@.d
+ $(COMPILE.cc) -g -I/usr/include/SDL -MMD -MP -MF $@.d -o ${OBJECTDIR}/utils/stringutils.o utils/stringutils.cpp
+
+${OBJECTDIR}/net/maploginhandler.o: nbproject/Makefile-${CND_CONF}.mk net/maploginhandler.cpp
+ ${MKDIR} -p ${OBJECTDIR}/net
+ ${RM} $@.d
+ $(COMPILE.cc) -g -I/usr/include/SDL -MMD -MP -MF $@.d -o ${OBJECTDIR}/net/maploginhandler.o net/maploginhandler.cpp
+
+${OBJECTDIR}/game.o: nbproject/Makefile-${CND_CONF}.mk game.cpp
+ ${MKDIR} -p ${OBJECTDIR}
+ ${RM} $@.d
+ $(COMPILE.cc) -g -I/usr/include/SDL -MMD -MP -MF $@.d -o ${OBJECTDIR}/game.o game.cpp
+
+${OBJECTDIR}/net/messageout.o: nbproject/Makefile-${CND_CONF}.mk net/messageout.cpp
+ ${MKDIR} -p ${OBJECTDIR}/net
+ ${RM} $@.d
+ $(COMPILE.cc) -g -I/usr/include/SDL -MMD -MP -MF $@.d -o ${OBJECTDIR}/net/messageout.o net/messageout.cpp
+
+${OBJECTDIR}/onlinelist.o: nbproject/Makefile-${CND_CONF}.mk onlinelist.cpp
+ ${MKDIR} -p ${OBJECTDIR}
+ ${RM} $@.d
+ $(COMPILE.cc) -g -I/usr/include/SDL -MMD -MP -MF $@.d -o ${OBJECTDIR}/onlinelist.o onlinelist.cpp
+
+${OBJECTDIR}/net/nethandler.o: nbproject/Makefile-${CND_CONF}.mk net/nethandler.cpp
+ ${MKDIR} -p ${OBJECTDIR}/net
+ ${RM} $@.d
+ $(COMPILE.cc) -g -I/usr/include/SDL -MMD -MP -MF $@.d -o ${OBJECTDIR}/net/nethandler.o net/nethandler.cpp
+
+${OBJECTDIR}/main.o: nbproject/Makefile-${CND_CONF}.mk main.cpp
+ ${MKDIR} -p ${OBJECTDIR}
+ ${RM} $@.d
+ $(COMPILE.cc) -g -I/usr/include/SDL -MMD -MP -MF $@.d -o ${OBJECTDIR}/main.o main.cpp
+
+${OBJECTDIR}/net/messagein.o: nbproject/Makefile-${CND_CONF}.mk net/messagein.cpp
+ ${MKDIR} -p ${OBJECTDIR}/net
+ ${RM} $@.d
+ $(COMPILE.cc) -g -I/usr/include/SDL -MMD -MP -MF $@.d -o ${OBJECTDIR}/net/messagein.o net/messagein.cpp
+
+${OBJECTDIR}/automation.o: nbproject/Makefile-${CND_CONF}.mk automation.cpp
+ ${MKDIR} -p ${OBJECTDIR}
+ ${RM} $@.d
+ $(COMPILE.cc) -g -I/usr/include/SDL -MMD -MP -MF $@.d -o ${OBJECTDIR}/automation.o automation.cpp
+
+${OBJECTDIR}/net/packet.o: nbproject/Makefile-${CND_CONF}.mk net/packet.cpp
+ ${MKDIR} -p ${OBJECTDIR}/net
+ ${RM} $@.d
+ $(COMPILE.cc) -g -I/usr/include/SDL -MMD -MP -MF $@.d -o ${OBJECTDIR}/net/packet.o net/packet.cpp
+
+${OBJECTDIR}/net/charserverhandler.o: nbproject/Makefile-${CND_CONF}.mk net/charserverhandler.cpp
+ ${MKDIR} -p ${OBJECTDIR}/net
+ ${RM} $@.d
+ $(COMPILE.cc) -g -I/usr/include/SDL -MMD -MP -MF $@.d -o ${OBJECTDIR}/net/charserverhandler.o net/charserverhandler.cpp
+
+${OBJECTDIR}/net/loginhandler.o: nbproject/Makefile-${CND_CONF}.mk net/loginhandler.cpp
+ ${MKDIR} -p ${OBJECTDIR}/net
+ ${RM} $@.d
+ $(COMPILE.cc) -g -I/usr/include/SDL -MMD -MP -MF $@.d -o ${OBJECTDIR}/net/loginhandler.o net/loginhandler.cpp
+
+${OBJECTDIR}/utils/specialfolder.o: nbproject/Makefile-${CND_CONF}.mk utils/specialfolder.cpp
+ ${MKDIR} -p ${OBJECTDIR}/utils
+ ${RM} $@.d
+ $(COMPILE.cc) -g -I/usr/include/SDL -MMD -MP -MF $@.d -o ${OBJECTDIR}/utils/specialfolder.o utils/specialfolder.cpp
+
+${OBJECTDIR}/net/network.o: nbproject/Makefile-${CND_CONF}.mk net/network.cpp
+ ${MKDIR} -p ${OBJECTDIR}/net
+ ${RM} $@.d
+ $(COMPILE.cc) -g -I/usr/include/SDL -MMD -MP -MF $@.d -o ${OBJECTDIR}/net/network.o net/network.cpp
+
+${OBJECTDIR}/net/chathandler.o: nbproject/Makefile-${CND_CONF}.mk net/chathandler.cpp
+ ${MKDIR} -p ${OBJECTDIR}/net
+ ${RM} $@.d
+ $(COMPILE.cc) -g -I/usr/include/SDL -MMD -MP -MF $@.d -o ${OBJECTDIR}/net/chathandler.o net/chathandler.cpp
+
+${OBJECTDIR}/net/protocol.o: nbproject/Makefile-${CND_CONF}.mk net/protocol.cpp
+ ${MKDIR} -p ${OBJECTDIR}/net
+ ${RM} $@.d
+ $(COMPILE.cc) -g -I/usr/include/SDL -MMD -MP -MF $@.d -o ${OBJECTDIR}/net/protocol.o net/protocol.cpp
+
+${OBJECTDIR}/net/messagehandler.o: nbproject/Makefile-${CND_CONF}.mk net/messagehandler.cpp
+ ${MKDIR} -p ${OBJECTDIR}/net
+ ${RM} $@.d
+ $(COMPILE.cc) -g -I/usr/include/SDL -MMD -MP -MF $@.d -o ${OBJECTDIR}/net/messagehandler.o net/messagehandler.cpp
+
+# Subprojects
+.build-subprojects:
+
+# Clean Targets
+.clean-conf: ${CLEAN_SUBPROJECTS}
+ ${RM} -r build/Debug
+ ${RM} dist/Debug/GNU-Linux-x86/guild
+
+# Subprojects
+.clean-subprojects:
+
+# Enable dependency checking
+.dep.inc: .depcheck-impl
+
+include .dep.inc
diff --git a/src/nbproject/Makefile-Release.mk b/src/nbproject/Makefile-Release.mk
new file mode 100644
index 0000000..90d16af
--- /dev/null
+++ b/src/nbproject/Makefile-Release.mk
@@ -0,0 +1,176 @@
+#
+# Generated Makefile - do not edit!
+#
+# Edit the Makefile in the project folder instead (../Makefile). Each target
+# has a -pre and a -post target defined where you can add customized code.
+#
+# This makefile implements configuration specific macros and targets.
+
+
+# Environment
+MKDIR=mkdir
+CP=cp
+CCADMIN=CCadmin
+RANLIB=ranlib
+CC=gcc
+CCC=g++
+CXX=g++
+FC=gfortran
+AS=as
+
+# Macros
+CND_PLATFORM=GNU-Linux-x86
+CND_CONF=Release
+CND_DISTDIR=dist
+
+# Include project Makefile
+include Makefile
+
+# Object Directory
+OBJECTDIR=build/${CND_CONF}/${CND_PLATFORM}
+
+# Object Files
+OBJECTFILES= \
+ ${OBJECTDIR}/utils/stringutils.o \
+ ${OBJECTDIR}/net/maploginhandler.o \
+ ${OBJECTDIR}/game.o \
+ ${OBJECTDIR}/net/messageout.o \
+ ${OBJECTDIR}/onlinelist.o \
+ ${OBJECTDIR}/net/nethandler.o \
+ ${OBJECTDIR}/main.o \
+ ${OBJECTDIR}/net/messagein.o \
+ ${OBJECTDIR}/automation.o \
+ ${OBJECTDIR}/net/packet.o \
+ ${OBJECTDIR}/net/charserverhandler.o \
+ ${OBJECTDIR}/net/loginhandler.o \
+ ${OBJECTDIR}/utils/specialfolder.o \
+ ${OBJECTDIR}/net/network.o \
+ ${OBJECTDIR}/net/chathandler.o \
+ ${OBJECTDIR}/net/protocol.o \
+ ${OBJECTDIR}/net/messagehandler.o
+
+# C Compiler Flags
+CFLAGS=
+
+# CC Compiler Flags
+CCFLAGS=-march=i686
+CXXFLAGS=-march=i686
+
+# Fortran Compiler Flags
+FFLAGS=
+
+# Assembler Flags
+ASFLAGS=
+
+# Link Libraries and Options
+LDLIBSOPTIONS=-lSDL -lSDL_net -lcurl -lpthread
+
+# Build Targets
+.build-conf: ${BUILD_SUBPROJECTS}
+ ${MAKE} -f nbproject/Makefile-Release.mk dist/Release/GNU-Linux-x86/guild
+
+${OBJECTDIR}/utils/stringutils.o: nbproject/Makefile-${CND_CONF}.mk utils/stringutils.cpp
+ mkdir -p ${OBJECTDIR}/utils
+ rm -f $@.d
+ g++ -c -O2 -s -I/usr/include/SDL -MMD -MP -MF $@.d -o ${OBJECTDIR}/utils/stringutils.o utils/stringutils.cpp
+
+
+${OBJECTDIR}/net/maploginhandler.o: nbproject/Makefile-${CND_CONF}.mk net/maploginhandler.cpp
+ mkdir -p ${OBJECTDIR}/net
+ rm -f $@.d
+ g++ -c -O2 -s -I/usr/include/SDL -MMD -MP -MF $@.d -o ${OBJECTDIR}/net/maploginhandler.o net/maploginhandler.cpp
+
+${OBJECTDIR}/game.o: nbproject/Makefile-${CND_CONF}.mk game.cpp
+ mkdir -p ${OBJECTDIR}
+ rm -f $@.d
+ g++ -c -O2 -s -I/usr/include/SDL -MMD -MP -MF $@.d -o ${OBJECTDIR}/game.o game.cpp
+
+${OBJECTDIR}/net/messageout.o: nbproject/Makefile-${CND_CONF}.mk net/messageout.cpp
+ mkdir -p ${OBJECTDIR}/net
+ rm -f $@.d
+ g++ -c -O2 -s -I/usr/include/SDL -MMD -MP -MF $@.d -o ${OBJECTDIR}/net/messageout.o net/messageout.cpp
+
+${OBJECTDIR}/onlinelist.o: nbproject/Makefile-${CND_CONF}.mk onlinelist.cpp
+ mkdir -p ${OBJECTDIR}
+ rm -f $@.d
+ g++ -c -O2 -s -I/usr/include/SDL -I/usr/local/include -MMD -MP -MF $@.d -o ${OBJECTDIR}/onlinelist.o onlinelist.cpp
+
+${OBJECTDIR}/net/nethandler.o: nbproject/Makefile-${CND_CONF}.mk net/nethandler.cpp
+ mkdir -p ${OBJECTDIR}/net
+ rm -f $@.d
+ g++ -c -O2 -s -I/usr/include/SDL -MMD -MP -MF $@.d -o ${OBJECTDIR}/net/nethandler.o net/nethandler.cpp
+
+${OBJECTDIR}/main.o: nbproject/Makefile-${CND_CONF}.mk main.cpp
+ mkdir -p ${OBJECTDIR}
+ rm -f $@.d
+ g++ -c -O2 -s -I/usr/include/SDL -MMD -MP -MF $@.d -o ${OBJECTDIR}/main.o main.cpp
+
+${OBJECTDIR}/net/messagein.o: nbproject/Makefile-${CND_CONF}.mk net/messagein.cpp
+ mkdir -p ${OBJECTDIR}/net
+ rm -f $@.d
+ g++ -c -O2 -s -I/usr/include/SDL -MMD -MP -MF $@.d -o ${OBJECTDIR}/net/messagein.o net/messagein.cpp
+
+${OBJECTDIR}/automation.o: nbproject/Makefile-${CND_CONF}.mk automation.cpp
+ mkdir -p ${OBJECTDIR}
+ rm -f $@.d
+ g++ -c -O2 -s -I/usr/include/SDL -MMD -MP -MF $@.d -o ${OBJECTDIR}/automation.o automation.cpp
+
+${OBJECTDIR}/net/packet.o: nbproject/Makefile-${CND_CONF}.mk net/packet.cpp
+ mkdir -p ${OBJECTDIR}/net
+ rm -f $@.d
+ g++ -c -O2 -s -I/usr/include/SDL -MMD -MP -MF $@.d -o ${OBJECTDIR}/net/packet.o net/packet.cpp
+
+${OBJECTDIR}/net/charserverhandler.o: nbproject/Makefile-${CND_CONF}.mk net/charserverhandler.cpp
+ mkdir -p ${OBJECTDIR}/net
+ rm -f $@.d
+ g++ -c -O2 -s -I/usr/include/SDL -MMD -MP -MF $@.d -o ${OBJECTDIR}/net/charserverhandler.o net/charserverhandler.cpp
+
+${OBJECTDIR}/net/loginhandler.o: nbproject/Makefile-${CND_CONF}.mk net/loginhandler.cpp
+ mkdir -p ${OBJECTDIR}/net
+ rm -f $@.d
+ g++ -c -O2 -s -I/usr/include/SDL -MMD -MP -MF $@.d -o ${OBJECTDIR}/net/loginhandler.o net/loginhandler.cpp
+
+${OBJECTDIR}/utils/specialfolder.o: nbproject/Makefile-${CND_CONF}.mk utils/specialfolder.cpp
+ mkdir -p ${OBJECTDIR}/utils
+ rm -f $@.d
+ g++ -c -O2 -s -I/usr/include/SDL -MMD -MP -MF $@.d -o ${OBJECTDIR}/utils/specialfolder.o utils/specialfolder.cpp
+
+${OBJECTDIR}/net/network.o: nbproject/Makefile-${CND_CONF}.mk net/network.cpp
+ mkdir -p ${OBJECTDIR}/net
+ rm -f $@.d
+ g++ -c -O2 -s -I/usr/include/SDL -MMD -MP -MF $@.d -o ${OBJECTDIR}/net/network.o net/network.cpp
+
+${OBJECTDIR}/net/chathandler.o: nbproject/Makefile-${CND_CONF}.mk net/chathandler.cpp
+ mkdir -p ${OBJECTDIR}/net
+ rm -f $@.d
+ g++ -c -O2 -s -I/usr/include/SDL -MMD -MP -MF $@.d -o ${OBJECTDIR}/net/chathandler.o net/chathandler.cpp
+
+${OBJECTDIR}/net/protocol.o: nbproject/Makefile-${CND_CONF}.mk net/protocol.cpp
+ mkdir -p ${OBJECTDIR}/net
+ rm -f $@.d
+ g++ -c -O2 -s -I/usr/include/SDL -MMD -MP -MF $@.d -o ${OBJECTDIR}/net/protocol.o net/protocol.cpp
+
+${OBJECTDIR}/net/messagehandler.o: nbproject/Makefile-${CND_CONF}.mk net/messagehandler.cpp
+ mkdir -p ${OBJECTDIR}/net
+ rm -f $@.d
+ g++ -c -O2 -s -I/usr/include/SDL -MMD -MP -MF $@.d -o ${OBJECTDIR}/net/messagehandler.o net/messagehandler.cpp
+
+dist/Release/GNU-Linux-x86/guild: ${OBJECTFILES}
+ mkdir -p dist/Release/GNU-Linux-x86
+ ${LINK.cc} -L/usr/local/lib -o ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/guild ${OBJECTFILES} ${LDLIBSOPTIONS}
+
+# Subprojects
+.build-subprojects:
+
+# Clean Targets
+.clean-conf: ${CLEAN_SUBPROJECTS}
+ rm -f -r build/Release
+ rm -f dist/Release/GNU-Linux-x86/guild
+
+# Subprojects
+.clean-subprojects:
+
+# Enable dependency checking
+.dep.inc: .depcheck-impl
+
+include .dep.inc
diff --git a/src/nbproject/Makefile-impl.mk b/src/nbproject/Makefile-impl.mk
new file mode 100644
index 0000000..8ffd6a4
--- /dev/null
+++ b/src/nbproject/Makefile-impl.mk
@@ -0,0 +1,123 @@
+#
+# Generated Makefile - do not edit!
+#
+# Edit the Makefile in the project folder instead (../Makefile). Each target
+# has a pre- and a post- target defined where you can add customization code.
+#
+# This makefile implements macros and targets common to all configurations.
+#
+# NOCDDL
+
+
+# Building and Cleaning subprojects are done by default, but can be controlled with the SUB
+# macro. If SUB=no, subprojects will not be built or cleaned. The following macro
+# statements set BUILD_SUB-CONF and CLEAN_SUB-CONF to .build-reqprojects-conf
+# and .clean-reqprojects-conf unless SUB has the value 'no'
+SUB_no=NO
+SUBPROJECTS=${SUB_${SUB}}
+BUILD_SUBPROJECTS_=.build-subprojects
+BUILD_SUBPROJECTS_NO=
+BUILD_SUBPROJECTS=${BUILD_SUBPROJECTS_${SUBPROJECTS}}
+CLEAN_SUBPROJECTS_=.clean-subprojects
+CLEAN_SUBPROJECTS_NO=
+CLEAN_SUBPROJECTS=${CLEAN_SUBPROJECTS_${SUBPROJECTS}}
+
+
+# Project Name
+PROJECTNAME=guild
+
+# Active Configuration
+DEFAULTCONF=Debug
+CONF=${DEFAULTCONF}
+
+# All Configurations
+ALLCONFS=Debug Release
+
+
+# build
+.build-impl: .build-pre .validate-impl .depcheck-impl
+ @#echo "=> Running $@... Configuration=$(CONF)"
+ ${MAKE} -f nbproject/Makefile-${CONF}.mk SUBPROJECTS=${SUBPROJECTS} .build-conf
+
+
+# clean
+.clean-impl: .clean-pre .validate-impl .depcheck-impl
+ @#echo "=> Running $@... Configuration=$(CONF)"
+ ${MAKE} -f nbproject/Makefile-${CONF}.mk SUBPROJECTS=${SUBPROJECTS} .clean-conf
+
+
+# clobber
+.clobber-impl: .clobber-pre .depcheck-impl
+ @#echo "=> Running $@..."
+ for CONF in ${ALLCONFS}; \
+ do \
+ ${MAKE} -f nbproject/Makefile-$${CONF}.mk SUBPROJECTS=${SUBPROJECTS} .clean-conf; \
+ done
+
+# all
+.all-impl: .all-pre .depcheck-impl
+ @#echo "=> Running $@..."
+ for CONF in ${ALLCONFS}; \
+ do \
+ ${MAKE} -f nbproject/Makefile-$${CONF}.mk SUBPROJECTS=${SUBPROJECTS} .build-conf; \
+ done
+
+# dependency checking support
+.depcheck-impl:
+ @echo "# This code depends on make tool being used" >.dep.inc
+ @if [ -n "${MAKE_VERSION}" ]; then \
+ echo "DEPFILES=\$$(wildcard \$$(addsuffix .d, \$${OBJECTFILES}))" >>.dep.inc; \
+ echo "ifneq (\$${DEPFILES},)" >>.dep.inc; \
+ echo "include \$${DEPFILES}" >>.dep.inc; \
+ echo "endif" >>.dep.inc; \
+ else \
+ echo ".KEEP_STATE:" >>.dep.inc; \
+ echo ".KEEP_STATE_FILE:.make.state.\$${CONF}" >>.dep.inc; \
+ fi
+
+# configuration validation
+.validate-impl:
+ @if [ ! -f nbproject/Makefile-${CONF}.mk ]; \
+ then \
+ echo ""; \
+ echo "Error: can not find the makefile for configuration '${CONF}' in project ${PROJECTNAME}"; \
+ echo "See 'make help' for details."; \
+ echo "Current directory: " `pwd`; \
+ echo ""; \
+ fi
+ @if [ ! -f nbproject/Makefile-${CONF}.mk ]; \
+ then \
+ exit 1; \
+ fi
+
+
+# help
+.help-impl: .help-pre
+ @echo "This makefile supports the following configurations:"
+ @echo " ${ALLCONFS}"
+ @echo ""
+ @echo "and the following targets:"
+ @echo " build (default target)"
+ @echo " clean"
+ @echo " clobber"
+ @echo " all"
+ @echo " help"
+ @echo ""
+ @echo "Makefile Usage:"
+ @echo " make [CONF=<CONFIGURATION>] [SUB=no] build"
+ @echo " make [CONF=<CONFIGURATION>] [SUB=no] clean"
+ @echo " make [SUB=no] clobber"
+ @echo " make [SUB=no] all"
+ @echo " make help"
+ @echo ""
+ @echo "Target 'build' will build a specific configuration and, unless 'SUB=no',"
+ @echo " also build subprojects."
+ @echo "Target 'clean' will clean a specific configuration and, unless 'SUB=no',"
+ @echo " also clean subprojects."
+ @echo "Target 'clobber' will remove all built files from all configurations and,"
+ @echo " unless 'SUB=no', also from subprojects."
+ @echo "Target 'all' will will build all configurations and, unless 'SUB=no',"
+ @echo " also build subprojects."
+ @echo "Target 'help' prints this message."
+ @echo ""
+
diff --git a/src/nbproject/Makefile-variables.mk b/src/nbproject/Makefile-variables.mk
new file mode 100644
index 0000000..1d1cd46
--- /dev/null
+++ b/src/nbproject/Makefile-variables.mk
@@ -0,0 +1,24 @@
+#
+# Generated - do not edit!
+#
+# NOCDDL
+#
+CND_BASEDIR=`pwd`
+CND_BUILDDIR=build
+CND_DISTDIR=dist
+# Debug configuration
+CND_PLATFORM_Debug=GNU-Linux-x86
+CND_ARTIFACT_DIR_Debug=dist/Debug/GNU-Linux-x86
+CND_ARTIFACT_NAME_Debug=guild
+CND_ARTIFACT_PATH_Debug=dist/Debug/GNU-Linux-x86/guild
+CND_PACKAGE_DIR_Debug=dist/Debug/GNU-Linux-x86/package
+CND_PACKAGE_NAME_Debug=guild.tar
+CND_PACKAGE_PATH_Debug=dist/Debug/GNU-Linux-x86/package/guild.tar
+# Release configuration
+CND_PLATFORM_Release=GNU-Linux-x86
+CND_ARTIFACT_DIR_Release=dist/Release/GNU-Linux-x86
+CND_ARTIFACT_NAME_Release=guild
+CND_ARTIFACT_PATH_Release=dist/Release/GNU-Linux-x86/guild
+CND_PACKAGE_DIR_Release=dist/Release/GNU-Linux-x86/package
+CND_PACKAGE_NAME_Release=guild.tar
+CND_PACKAGE_PATH_Release=dist/Release/GNU-Linux-x86/package/guild.tar
diff --git a/src/nbproject/Package-Debug.bash b/src/nbproject/Package-Debug.bash
new file mode 100644
index 0000000..361cd54
--- /dev/null
+++ b/src/nbproject/Package-Debug.bash
@@ -0,0 +1,74 @@
+#!/bin/bash -x
+
+#
+# Generated - do not edit!
+#
+
+# Macros
+TOP=`pwd`
+CND_PLATFORM=GNU-Linux-x86
+CND_CONF=Debug
+CND_DISTDIR=dist
+TMPDIR=build/${CND_CONF}/${CND_PLATFORM}/tmp-packaging
+TMPDIRNAME=tmp-packaging
+OUTPUT_PATH=${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/guild
+OUTPUT_BASENAME=guild
+PACKAGE_TOP_DIR=guild/
+
+# Functions
+function checkReturnCode
+{
+ rc=$?
+ if [ $rc != 0 ]
+ then
+ exit $rc
+ fi
+}
+function makeDirectory
+# $1 directory path
+# $2 permission (optional)
+{
+ mkdir -p "$1"
+ checkReturnCode
+ if [ "$2" != "" ]
+ then
+ chmod $2 "$1"
+ checkReturnCode
+ fi
+}
+function copyFileToTmpDir
+# $1 from-file path
+# $2 to-file path
+# $3 permission
+{
+ cp "$1" "$2"
+ checkReturnCode
+ if [ "$3" != "" ]
+ then
+ chmod $3 "$2"
+ checkReturnCode
+ fi
+}
+
+# Setup
+cd "${TOP}"
+mkdir -p ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/package
+rm -rf ${TMPDIR}
+mkdir -p ${TMPDIR}
+
+# Copy files and create directories and links
+cd "${TOP}"
+makeDirectory ${TMPDIR}/guild/bin
+copyFileToTmpDir "${OUTPUT_PATH}" "${TMPDIR}/${PACKAGE_TOP_DIR}bin/${OUTPUT_BASENAME}" 0755
+
+
+# Generate tar file
+cd "${TOP}"
+rm -f ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/package/guild.tar
+cd ${TMPDIR}
+tar -vcf ../../../../${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/package/guild.tar *
+checkReturnCode
+
+# Cleanup
+cd "${TOP}"
+rm -rf ${TMPDIR}
diff --git a/src/nbproject/Package-Release.bash b/src/nbproject/Package-Release.bash
new file mode 100644
index 0000000..359438e
--- /dev/null
+++ b/src/nbproject/Package-Release.bash
@@ -0,0 +1,74 @@
+#!/bin/bash -x
+
+#
+# Generated - do not edit!
+#
+
+# Macros
+TOP=`pwd`
+CND_PLATFORM=GNU-Linux-x86
+CND_CONF=Release
+CND_DISTDIR=dist
+TMPDIR=build/${CND_CONF}/${CND_PLATFORM}/tmp-packaging
+TMPDIRNAME=tmp-packaging
+OUTPUT_PATH=${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/guild
+OUTPUT_BASENAME=guild
+PACKAGE_TOP_DIR=guild/
+
+# Functions
+function checkReturnCode
+{
+ rc=$?
+ if [ $rc != 0 ]
+ then
+ exit $rc
+ fi
+}
+function makeDirectory
+# $1 directory path
+# $2 permission (optional)
+{
+ mkdir -p "$1"
+ checkReturnCode
+ if [ "$2" != "" ]
+ then
+ chmod $2 "$1"
+ checkReturnCode
+ fi
+}
+function copyFileToTmpDir
+# $1 from-file path
+# $2 to-file path
+# $3 permission
+{
+ cp "$1" "$2"
+ checkReturnCode
+ if [ "$3" != "" ]
+ then
+ chmod $3 "$2"
+ checkReturnCode
+ fi
+}
+
+# Setup
+cd "${TOP}"
+mkdir -p ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/package
+rm -rf ${TMPDIR}
+mkdir -p ${TMPDIR}
+
+# Copy files and create directories and links
+cd "${TOP}"
+makeDirectory ${TMPDIR}/guild/bin
+copyFileToTmpDir "${OUTPUT_PATH}" "${TMPDIR}/${PACKAGE_TOP_DIR}bin/${OUTPUT_BASENAME}" 0755
+
+
+# Generate tar file
+cd "${TOP}"
+rm -f ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/package/guild.tar
+cd ${TMPDIR}
+tar -vcf ../../../../${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/package/guild.tar *
+checkReturnCode
+
+# Cleanup
+cd "${TOP}"
+rm -rf ${TMPDIR}
diff --git a/src/nbproject/configurations.xml b/src/nbproject/configurations.xml
new file mode 100644
index 0000000..d276a91
--- /dev/null
+++ b/src/nbproject/configurations.xml
@@ -0,0 +1,131 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configurationDescriptor version="62">
+ <logicalFolder name="root" displayName="root" projectFiles="true">
+ <logicalFolder name="HeaderFiles"
+ displayName="Header Files"
+ projectFiles="true">
+ <logicalFolder name="net" displayName="net" projectFiles="true">
+ <itemPath>net/charserverhandler.h</itemPath>
+ <itemPath>net/chathandler.h</itemPath>
+ <itemPath>net/loginhandler.h</itemPath>
+ <itemPath>net/maploginhandler.h</itemPath>
+ <itemPath>net/messagehandler.h</itemPath>
+ <itemPath>net/messagein.h</itemPath>
+ <itemPath>net/messageout.h</itemPath>
+ <itemPath>net/nethandler.h</itemPath>
+ <itemPath>net/network.h</itemPath>
+ <itemPath>net/packet.h</itemPath>
+ <itemPath>net/protocol.h</itemPath>
+ </logicalFolder>
+ <logicalFolder name="utils" displayName="utils" projectFiles="true">
+ <itemPath>utils/mutex.h</itemPath>
+ <itemPath>utils/specialfolder.h</itemPath>
+ <itemPath>utils/stringutils.h</itemPath>
+ </logicalFolder>
+ <itemPath>automation.h</itemPath>
+ <itemPath>game.h</itemPath>
+ <itemPath>logindata.h</itemPath>
+ <itemPath>main.h</itemPath>
+ <itemPath>onlinelist.h</itemPath>
+ <itemPath>serverinfo.h</itemPath>
+ </logicalFolder>
+ <logicalFolder name="ResourceFiles"
+ displayName="Resource Files"
+ projectFiles="true">
+ </logicalFolder>
+ <logicalFolder name="SourceFiles"
+ displayName="Source Files"
+ projectFiles="true">
+ <logicalFolder name="net" displayName="net" projectFiles="true">
+ <itemPath>net/charserverhandler.cpp</itemPath>
+ <itemPath>net/chathandler.cpp</itemPath>
+ <itemPath>net/loginhandler.cpp</itemPath>
+ <itemPath>net/maploginhandler.cpp</itemPath>
+ <itemPath>net/messagehandler.cpp</itemPath>
+ <itemPath>net/messagein.cpp</itemPath>
+ <itemPath>net/messageout.cpp</itemPath>
+ <itemPath>net/nethandler.cpp</itemPath>
+ <itemPath>net/network.cpp</itemPath>
+ <itemPath>net/packet.cpp</itemPath>
+ <itemPath>net/protocol.cpp</itemPath>
+ </logicalFolder>
+ <logicalFolder name="utils" displayName="utils" projectFiles="true">
+ <itemPath>utils/specialfolder.cpp</itemPath>
+ <itemPath>utils/stringutils.cpp</itemPath>
+ </logicalFolder>
+ <itemPath>automation.cpp</itemPath>
+ <itemPath>game.cpp</itemPath>
+ <itemPath>main.cpp</itemPath>
+ <itemPath>onlinelist.cpp</itemPath>
+ </logicalFolder>
+ <logicalFolder name="ExternalFiles"
+ displayName="Important Files"
+ projectFiles="false">
+ <itemPath>Makefile</itemPath>
+ </logicalFolder>
+ </logicalFolder>
+ <sourceRootList>
+ <Elem>net</Elem>
+ <Elem>utils</Elem>
+ </sourceRootList>
+ <projectmakefile>Makefile</projectmakefile>
+ <confs>
+ <conf name="Debug" type="1">
+ <toolsSet>
+ <developmentServer>localhost</developmentServer>
+ <compilerSet>GNU|GNU</compilerSet>
+ <platform>2</platform>
+ </toolsSet>
+ <compileType>
+ <ccTool>
+ <incDir>
+ <pElem>/usr/include/SDL</pElem>
+ </incDir>
+ <commandLine>-pg</commandLine>
+ </ccTool>
+ <linkerTool>
+ <linkerAddLib>
+ <pElem>/usr/lib</pElem>
+ </linkerAddLib>
+ <linkerLibItems>
+ <linkerLibLibItem>SDL</linkerLibLibItem>
+ <linkerLibLibItem>SDL_net</linkerLibLibItem>
+ <linkerLibLibItem>pthread</linkerLibLibItem>
+ <linkerLibLibItem>curl</linkerLibLibItem>
+ </linkerLibItems>
+ </linkerTool>
+ </compileType>
+ </conf>
+ <conf name="Release" type="1">
+ <toolsSet>
+ <developmentServer>localhost</developmentServer>
+ <compilerSet>GNU|GNU</compilerSet>
+ <platform>2</platform>
+ </toolsSet>
+ <compileType>
+ <cTool>
+ <developmentMode>5</developmentMode>
+ </cTool>
+ <ccTool>
+ <developmentMode>5</developmentMode>
+ <stripSymbols>true</stripSymbols>
+ <commandlineTool>g++</commandlineTool>
+ <incDir>
+ <pElem>/usr/include/SDL</pElem>
+ </incDir>
+ <commandLine>-march=i686</commandLine>
+ </ccTool>
+ <fortranCompilerTool>
+ <developmentMode>5</developmentMode>
+ </fortranCompilerTool>
+ <linkerTool>
+ <linkerLibItems>
+ <linkerLibLibItem>SDL</linkerLibLibItem>
+ <linkerLibLibItem>SDL_net</linkerLibLibItem>
+ <linkerLibLibItem>curl</linkerLibLibItem>
+ </linkerLibItems>
+ </linkerTool>
+ </compileType>
+ </conf>
+ </confs>
+</configurationDescriptor>
diff --git a/src/nbproject/private/configurations.xml b/src/nbproject/private/configurations.xml
new file mode 100644
index 0000000..ef9712c
--- /dev/null
+++ b/src/nbproject/private/configurations.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configurationDescriptor version="62">
+ <projectmakefile>Makefile</projectmakefile>
+ <defaultConf>0</defaultConf>
+ <confs>
+ <conf name="Debug" type="1">
+ <gdbdebugger version="2">
+ <gdb_command>gdb</gdb_command>
+ <array_repeat_threshold>10</array_repeat_threshold>
+ </gdbdebugger>
+ <gizmo_options version="3">
+ </gizmo_options>
+ <runprofile version="6">
+ <args></args>
+ <rundir></rundir>
+ <buildfirst>true</buildfirst>
+ <console-type>0</console-type>
+ <terminal-type>0</terminal-type>
+ <remove-instrumentation>0</remove-instrumentation>
+ <environment>
+ </environment>
+ </runprofile>
+ </conf>
+ <conf name="Release" type="1">
+ <gdbdebugger version="2">
+ <gdb_command>gdb</gdb_command>
+ <array_repeat_threshold>10</array_repeat_threshold>
+ </gdbdebugger>
+ <gizmo_options version="3">
+ </gizmo_options>
+ <runprofile version="6">
+ <args></args>
+ <rundir></rundir>
+ <buildfirst>true</buildfirst>
+ <console-type>0</console-type>
+ <terminal-type>0</terminal-type>
+ <remove-instrumentation>0</remove-instrumentation>
+ <environment>
+ </environment>
+ </runprofile>
+ </conf>
+ </confs>
+</configurationDescriptor>
diff --git a/src/nbproject/private/private.properties b/src/nbproject/private/private.properties
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/nbproject/private/private.properties
diff --git a/src/nbproject/private/private.xml b/src/nbproject/private/private.xml
new file mode 100644
index 0000000..c1f155a
--- /dev/null
+++ b/src/nbproject/private/private.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project-private xmlns="http://www.netbeans.org/ns/project-private/1">
+ <editor-bookmarks xmlns="http://www.netbeans.org/ns/editor-bookmarks/1"/>
+</project-private>
diff --git a/src/nbproject/project.properties b/src/nbproject/project.properties
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/nbproject/project.properties
diff --git a/src/nbproject/project.xml b/src/nbproject/project.xml
new file mode 100644
index 0000000..f6e48a3
--- /dev/null
+++ b/src/nbproject/project.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://www.netbeans.org/ns/project/1">
+ <type>org.netbeans.modules.cnd.makeproject</type>
+ <configuration>
+ <data xmlns="http://www.netbeans.org/ns/make-project/1">
+ <name>guild</name>
+ <make-project-type>0</make-project-type>
+ <c-extensions/>
+ <cpp-extensions>cpp</cpp-extensions>
+ <header-extensions>h</header-extensions>
+ <sourceEncoding>UTF-8</sourceEncoding>
+ <make-dep-projects/>
+ </data>
+ </configuration>
+</project>
diff --git a/src/net/charserverhandler.cpp b/src/net/charserverhandler.cpp
new file mode 100644
index 0000000..d500c0d
--- /dev/null
+++ b/src/net/charserverhandler.cpp
@@ -0,0 +1,166 @@
+/*
+ * The Mana World
+ * Copyright 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * The Mana World 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id: charserverhandler.cpp 2137 2006-02-04 16:54:35Z der_doener $
+ */
+
+#include "charserverhandler.h"
+
+#include "messagein.h"
+#include "network.h"
+#include "protocol.h"
+
+#include "../game.h"
+#include "../logindata.h"
+#include "../main.h"
+
+CharServerHandler::CharServerHandler()
+{
+ static const Uint16 _messages[] = {
+ 0x006b,
+ 0x006c,
+ 0x006d,
+ 0x0071,
+ 0x0081,
+ 0
+ };
+ handledMessages = _messages;
+}
+
+void CharServerHandler::handleMessage(MessageIn *msg)
+{
+ int slot;
+
+ /* logger->log("CharServerHandler: Packet ID: %x, Length: %d",
+ msg->getId(), msg->getLength());*/
+ switch (msg->getId())
+ {
+ case 0x006b:
+ {
+ int tmpCharID[3];
+ // Skip length word and an additional mysterious 20 bytes
+ msg->skip(2 + 20);
+
+ // Derive number of characters from message length
+ n_character = (msg->getLength() - 24) / 106;
+
+ for (int i = 0; i < n_character; i++)
+ {
+
+ tmpCharID[i] = msg->readInt32();
+ msg->readInt32(); //xp
+ msg->readInt32(); //gp
+ msg->readInt32(); //jobxp
+ msg->readInt32(); //joblvl
+ msg->skip(8); // unknown
+ msg->readInt32(); // option
+ msg->readInt32(); // karma
+ msg->readInt32(); // manner
+ msg->skip(2); // unknown
+ msg->readInt16(); //hp
+ msg->readInt16(); //maxhp
+ msg->readInt16(); //mp
+ msg->readInt16(); //maxmp
+ msg->readInt16(); // speed
+ msg->readInt16(); // class
+ msg->readInt16(); //hair
+ msg->readInt16(); //weapon
+ msg->readInt16(); //lvl
+ msg->readInt16(); // skill point
+ msg->readInt16(); // head bottom
+ msg->readInt16(); // shield
+ msg->readInt16(); // head option top
+ msg->readInt16(); // head option mid
+ msg->readInt16(); // hair color
+ msg->readInt16(); // unknown
+ std::string charname = msg->readString(24);
+ msg->readInt8(); //ATTR
+ msg->readInt8(); //ATTR
+ msg->readInt8(); //ATTR
+ msg->readInt8(); //ATTR
+ msg->readInt8(); //ATTR
+ msg->readInt8(); //ATTR
+ int slot = msg->readInt8(); // character slot
+ charID[slot] = tmpCharID[i]; /* Get the Character Id's, needed for map server.*/
+ msg->readInt8(); // unknown
+
+ if (slot == main_charno)
+ char_name = charname;
+
+ /* logger->log("CharServer: Player: %s (%d)",
+ charname.c_str(), slot);*/
+ }
+
+ state = CHAR_SELECT_STATE;
+ break;
+ }
+
+ case 0x006c:
+ switch (msg->readInt8()) {
+ case 0:
+ errorMessage = "Access denied";
+ break;
+ case 1:
+ errorMessage = "Cannot use this ID";
+ break;
+ default:
+ errorMessage = "Unknown failure to select character";
+ break;
+ }
+ break;
+
+ case 0x006d:
+ state = CONNECTING_STATE;
+ break;
+
+ case 0x0071:
+ {
+ msg->skip(4); // CharID, the same as the one we've already recieved.
+ map_path = msg->readString(16);
+ mLoginData->hostname = iptostring(msg->readInt32());
+ mLoginData->port = msg->readInt16();
+ /*logger->log("Map: Server: %s (%s:%d)",
+ map_path.c_str(),
+ mLoginData->hostname.c_str(),
+ mLoginData->port);*/
+
+ state = CONNECTING_STATE;
+ break;
+ }
+
+ case 0x0081:
+ switch (msg->readInt8()) {
+ case 1:
+ errorMessage = "Map server offline";
+ break;
+ case 3:
+ errorMessage = "Speed hack detected";
+ break;
+ case 8:
+ errorMessage = "Duplicated login";
+ break;
+ default:
+ errorMessage = "Unkown error with 0x0081";
+ break;
+ };
+ state = ERROR_STATE;
+ break;
+ }
+}
diff --git a/src/net/charserverhandler.cpp~ b/src/net/charserverhandler.cpp~
new file mode 100644
index 0000000..ea08c00
--- /dev/null
+++ b/src/net/charserverhandler.cpp~
@@ -0,0 +1,167 @@
+/*
+ * The Mana World
+ * Copyright 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * The Mana World 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id: charserverhandler.cpp 2137 2006-02-04 16:54:35Z der_doener $
+ */
+
+#include "charserverhandler.h"
+
+#include "messagein.h"
+#include "network.h"
+#include "protocol.h"
+
+#include "../game.h"
+#include "../log.h"
+#include "../logindata.h"
+#include "../main.h"
+
+CharServerHandler::CharServerHandler()
+{
+ static const Uint16 _messages[] = {
+ 0x006b,
+ 0x006c,
+ 0x006d,
+ 0x0071,
+ 0x0081,
+ 0
+ };
+ handledMessages = _messages;
+}
+
+void CharServerHandler::handleMessage(MessageIn *msg)
+{
+ int slot;
+
+ /* logger->log("CharServerHandler: Packet ID: %x, Length: %d",
+ msg->getId(), msg->getLength());*/
+ switch (msg->getId())
+ {
+ case 0x006b:
+ {
+ int tmpCharID[3];
+ // Skip length word and an additional mysterious 20 bytes
+ msg->skip(2 + 20);
+
+ // Derive number of characters from message length
+ n_character = (msg->getLength() - 24) / 106;
+
+ for (int i = 0; i < n_character; i++)
+ {
+
+ tmpCharID[i] = msg->readInt32();
+ msg->readInt32(); //xp
+ msg->readInt32(); //gp
+ msg->readInt32(); //jobxp
+ msg->readInt32(); //joblvl
+ msg->skip(8); // unknown
+ msg->readInt32(); // option
+ msg->readInt32(); // karma
+ msg->readInt32(); // manner
+ msg->skip(2); // unknown
+ msg->readInt16(); //hp
+ msg->readInt16(); //maxhp
+ msg->readInt16(); //mp
+ msg->readInt16(); //maxmp
+ msg->readInt16(); // speed
+ msg->readInt16(); // class
+ msg->readInt16(); //hair
+ msg->readInt16(); //weapon
+ msg->readInt16(); //lvl
+ msg->readInt16(); // skill point
+ msg->readInt16(); // head bottom
+ msg->readInt16(); // shield
+ msg->readInt16(); // head option top
+ msg->readInt16(); // head option mid
+ msg->readInt16(); // hair color
+ msg->readInt16(); // unknown
+ std::string charname = msg->readString(24);
+ msg->readInt8(); //ATTR
+ msg->readInt8(); //ATTR
+ msg->readInt8(); //ATTR
+ msg->readInt8(); //ATTR
+ msg->readInt8(); //ATTR
+ msg->readInt8(); //ATTR
+ int slot = msg->readInt8(); // character slot
+ charID[slot] = tmpCharID[i]; /* Get the Character Id's, needed for map server.*/
+ msg->readInt8(); // unknown
+
+ if (slot == main_charno)
+ char_name = charname;
+
+ /* logger->log("CharServer: Player: %s (%d)",
+ charname.c_str(), slot);*/
+ }
+
+ state = CHAR_SELECT_STATE;
+ break;
+ }
+
+ case 0x006c:
+ switch (msg->readInt8()) {
+ case 0:
+ errorMessage = "Access denied";
+ break;
+ case 1:
+ errorMessage = "Cannot use this ID";
+ break;
+ default:
+ errorMessage = "Unknown failure to select character";
+ break;
+ }
+ break;
+
+ case 0x006d:
+ state = CONNECTING_STATE;
+ break;
+
+ case 0x0071:
+ {
+ msg->skip(4); // CharID, the same as the one we've already recieved.
+ map_path = msg->readString(16);
+ mLoginData->hostname = iptostring(msg->readInt32());
+ mLoginData->port = msg->readInt16();
+ /*logger->log("Map: Server: %s (%s:%d)",
+ map_path.c_str(),
+ mLoginData->hostname.c_str(),
+ mLoginData->port);*/
+
+ state = CONNECTING_STATE;
+ break;
+ }
+
+ case 0x0081:
+ switch (msg->readInt8()) {
+ case 1:
+ errorMessage = "Map server offline";
+ break;
+ case 3:
+ errorMessage = "Speed hack detected";
+ break;
+ case 8:
+ errorMessage = "Duplicated login";
+ break;
+ default:
+ errorMessage = "Unkown error with 0x0081";
+ break;
+ };
+ state = ERROR_STATE;
+ break;
+ }
+}
diff --git a/src/net/charserverhandler.h b/src/net/charserverhandler.h
new file mode 100644
index 0000000..c6303a5
--- /dev/null
+++ b/src/net/charserverhandler.h
@@ -0,0 +1,52 @@
+/*
+ * The Mana World
+ * Copyright 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * The Mana World 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id: charserverhandler.h 2137 2006-02-04 16:54:35Z der_doener $
+ */
+
+#ifndef _TMW_NET_CHARSERVERHANDLER_H
+#define _TMW_NET_CHARSERVERHANDLER_H
+
+#include "messagehandler.h"
+
+//#include "../lockedarray.h"
+
+class LocalPlayer;
+class LoginData;
+
+class CharServerHandler : public MessageHandler
+{
+ public:
+ CharServerHandler();
+
+ void handleMessage(MessageIn *msg);
+
+ //void setCharInfo(LockedArray<LocalPlayer*> *charInfo) { mCharInfo = charInfo; };
+
+ void setLoginData(LoginData *loginData) { mLoginData = loginData; };
+
+ protected:
+ LoginData *mLoginData;
+ //LockedArray<LocalPlayer*> *mCharInfo;
+
+ //LocalPlayer* readPlayerData(MessageIn *msg, int &slot);
+};
+
+#endif
diff --git a/src/net/chathandler.cpp b/src/net/chathandler.cpp
new file mode 100644
index 0000000..19abc24
--- /dev/null
+++ b/src/net/chathandler.cpp
@@ -0,0 +1,146 @@
+/*
+ * The Mana World
+ * Copyright 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * The Mana World 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id: chathandler.cpp 2112 2006-01-22 13:31:13Z der_doener $
+ */
+
+#include "chathandler.h"
+
+#include <SDL_types.h>
+#include <string>
+#include <sstream>
+#include <iostream>
+
+#include "messagein.h"
+#include "protocol.h"
+#include "messageout.h"
+#include "../automation.h"
+#include "../game.h"
+#include "../utils/stringutils.h"
+#include "nethandler.h"
+
+ChatHandler::ChatHandler()
+{
+ static const Uint16 _messages[] = {
+ SMSG_BEING_CHAT,
+ SMSG_PLAYER_CHAT,
+ SMSG_WHISPER,
+ SMSG_WHISPER_RESPONSE,
+ SMSG_GM_CHAT,
+ 0
+ };
+ handledMessages = _messages;
+}
+
+void ChatHandler::handleMessage(MessageIn *msg)
+{
+ //Being *being;
+ std::string chatMsg;
+ std::stringstream ss;
+ Sint16 chatMsgLength;
+
+ switch (msg->getId())
+ {
+ // Received speech from being
+ case SMSG_BEING_CHAT:
+ {
+
+ chatMsgLength = msg->readInt16() - 8;
+ msg->readInt32();
+
+ if (chatMsgLength <= 0)
+ break;
+
+ chatMsg = msg->readString(chatMsgLength);
+
+ std::string::size_type pos = chatMsg.find(" : ", 0);
+ std::string sender_name = ((pos == std::string::npos)
+ ? ""
+ : chatMsg.substr(0, pos));
+
+ std::string mess = chatMsg.substr(pos+3);
+ // do something with chat
+ break;
+ }
+ case SMSG_WHISPER:
+ {
+ chatMsgLength = msg->readInt16() - 28;
+ std::string nick = msg->readString(24);
+
+ if (chatMsgLength <= 0)
+ break;
+
+ chatMsg = msg->readString(chatMsgLength);
+ Automation::getAutomationHandler()->commandHandler(chatMsg, nick);
+
+ break;
+ }
+ case SMSG_WHISPER_RESPONSE:
+ {
+ int type = msg->readInt8();
+ switch (type)
+ {
+ case 0x00:
+ break;
+ case 0x01:
+ //logger->log("Whisper could not be sent, user is offline.");
+ break;
+ case 0x02:
+ //logger->log("Whisper could not be sent, ignored by user.");
+ break;
+ default:
+ /*if (logger)
+ logger->log("Unkown Whisper Response.");*/
+ break;
+ }
+ break;
+ }
+ case SMSG_PLAYER_CHAT:
+ case SMSG_GM_CHAT:
+ {
+ chatMsgLength = msg->readInt16() - 4;
+
+ if (chatMsgLength <= 0)
+ {
+ break;
+ }
+
+ chatMsg = msg->readString(chatMsgLength);
+
+ if (msg->getId() == SMSG_PLAYER_CHAT)
+ {
+
+ std::string::size_type pos = chatMsg.find(" : ", 0);
+ if (pos != std::string::npos)
+ {
+ chatMsg.erase(0, pos + 3);
+ }
+ //player_node->setSpeech(chatMsg, SPEECH_TIME);
+ }
+ else
+ {
+ //chatWindow->chatLog(chatMsg, BY_GM);
+ }
+ break;
+ }
+
+
+ }
+}
diff --git a/src/net/chathandler.cpp~ b/src/net/chathandler.cpp~
new file mode 100644
index 0000000..cb4c32c
--- /dev/null
+++ b/src/net/chathandler.cpp~
@@ -0,0 +1,147 @@
+/*
+ * The Mana World
+ * Copyright 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * The Mana World 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id: chathandler.cpp 2112 2006-01-22 13:31:13Z der_doener $
+ */
+
+#include "chathandler.h"
+
+#include <SDL_types.h>
+#include <string>
+#include <sstream>
+#include <iostream>
+
+#include "messagein.h"
+#include "protocol.h"
+#include "messageout.h"
+#include "../automation.h"
+#include "../game.h"
+#include "../utils/stringutils.h"
+#include "../log.h"
+#include "nethandler.h"
+
+ChatHandler::ChatHandler()
+{
+ static const Uint16 _messages[] = {
+ SMSG_BEING_CHAT,
+ SMSG_PLAYER_CHAT,
+ SMSG_WHISPER,
+ SMSG_WHISPER_RESPONSE,
+ SMSG_GM_CHAT,
+ 0
+ };
+ handledMessages = _messages;
+}
+
+void ChatHandler::handleMessage(MessageIn *msg)
+{
+ //Being *being;
+ std::string chatMsg;
+ std::stringstream ss;
+ Sint16 chatMsgLength;
+
+ switch (msg->getId())
+ {
+ // Received speech from being
+ case SMSG_BEING_CHAT:
+ {
+
+ chatMsgLength = msg->readInt16() - 8;
+ msg->readInt32();
+
+ if (chatMsgLength <= 0)
+ break;
+
+ chatMsg = msg->readString(chatMsgLength);
+
+ std::string::size_type pos = chatMsg.find(" : ", 0);
+ std::string sender_name = ((pos == std::string::npos)
+ ? ""
+ : chatMsg.substr(0, pos));
+
+ std::string mess = chatMsg.substr(pos+3);
+ // do something with chat
+ break;
+ }
+ case SMSG_WHISPER:
+ {
+ chatMsgLength = msg->readInt16() - 28;
+ std::string nick = msg->readString(24);
+
+ if (chatMsgLength <= 0)
+ break;
+
+ chatMsg = msg->readString(chatMsgLength);
+ Automation::getAutomationHandler()->commandHandler(chatMsg, nick);
+
+ break;
+ }
+ case SMSG_WHISPER_RESPONSE:
+ {
+ int type = msg->readInt8();
+ switch (type)
+ {
+ case 0x00:
+ break;
+ case 0x01:
+ //logger->log("Whisper could not be sent, user is offline.");
+ break;
+ case 0x02:
+ //logger->log("Whisper could not be sent, ignored by user.");
+ break;
+ default:
+ /*if (logger)
+ logger->log("Unkown Whisper Response.");*/
+ break;
+ }
+ break;
+ }
+ case SMSG_PLAYER_CHAT:
+ case SMSG_GM_CHAT:
+ {
+ chatMsgLength = msg->readInt16() - 4;
+
+ if (chatMsgLength <= 0)
+ {
+ break;
+ }
+
+ chatMsg = msg->readString(chatMsgLength);
+
+ if (msg->getId() == SMSG_PLAYER_CHAT)
+ {
+
+ std::string::size_type pos = chatMsg.find(" : ", 0);
+ if (pos != std::string::npos)
+ {
+ chatMsg.erase(0, pos + 3);
+ }
+ //player_node->setSpeech(chatMsg, SPEECH_TIME);
+ }
+ else
+ {
+ //chatWindow->chatLog(chatMsg, BY_GM);
+ }
+ break;
+ }
+
+
+ }
+} \ No newline at end of file
diff --git a/src/net/chathandler.h b/src/net/chathandler.h
new file mode 100644
index 0000000..25874f0
--- /dev/null
+++ b/src/net/chathandler.h
@@ -0,0 +1,38 @@
+/*
+ * The Mana World
+ * Copyright 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * The Mana World 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id: chathandler.h 2112 2006-01-22 13:31:13Z der_doener $
+ */
+
+#ifndef _TMW_NET_CHATHANDLER_H
+#define _TMW_NET_CHATHANDLER_H
+
+#include "messagehandler.h"
+#include <string>
+
+class ChatHandler : public MessageHandler
+{
+ public:
+ ChatHandler();
+
+ void handleMessage(MessageIn *msg);
+};
+
+#endif
diff --git a/src/net/loginhandler.cpp b/src/net/loginhandler.cpp
new file mode 100644
index 0000000..b6f5b98
--- /dev/null
+++ b/src/net/loginhandler.cpp
@@ -0,0 +1,126 @@
+/*
+ * The Mana World
+ * Copyright 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * The Mana World 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id: loginhandler.cpp 2184 2006-02-23 16:02:00Z der_doener $
+ */
+
+#include <stdio.h>
+
+#include "loginhandler.h"
+
+#include "messagein.h"
+#include "network.h"
+#include "protocol.h"
+
+#include "../logindata.h"
+#include "../main.h"
+#include "../serverinfo.h"
+
+extern SERVER_INFO **server_info;
+
+LoginHandler::LoginHandler()
+{
+ static const Uint16 _messages[] = {
+ 0x0063,
+ 0x0069,
+ 0x006a,
+ 0
+ };
+ handledMessages = _messages;
+}
+
+void LoginHandler::handleMessage(MessageIn *msg)
+{
+ switch (msg->getId())
+ {
+ case 0x0063:
+ // This is the update host. The bot doesn't need it.
+ msg->skip(2);
+ msg->skip(msg->getLength() - 4);
+ break;
+
+ case 0x0069:
+ // Skip the length word
+ msg->skip(2);
+
+ n_server = (msg->getLength() - 47) / 32;
+ server_info = (SERVER_INFO**)malloc(sizeof(SERVER_INFO*) * n_server);
+
+ mLoginData->session_ID1 = msg->readInt32();
+ mLoginData->account_ID = msg->readInt32();
+ mLoginData->session_ID2 = msg->readInt32();
+ msg->skip(30); // unknown
+ mLoginData->sex = msg->readInt8();
+
+ for (int i = 0; i < n_server; i++)
+ {
+ server_info[i] = new SERVER_INFO;
+
+ server_info[i]->address = msg->readInt32();
+ server_info[i]->port = msg->readInt16();
+ server_info[i]->name = msg->readString(20);
+
+ if (server_info[i]->name == "The Mana World")
+ world = i;
+
+ server_info[i]->online_users = msg->readInt16();
+ msg->skip(4); // unknown
+
+ /*logger->log("Network: Server: %s (%s:%d)",
+ server_info[i]->name.c_str(),
+ iptostring(server_info[i]->address),
+ server_info[i]->port);*/
+ }
+ state = CHAR_SERVER_STATE;
+ break;
+
+ case 0x006a:
+ int loginError = msg->readInt8();
+ //logger->log("Login::error code: %i", loginError);
+ switch (loginError) {
+ case 0:
+ errorMessage = "Unregistered ID";
+ break;
+ case 1:
+ errorMessage = "Wrong password";
+ break;
+ case 2:
+ errorMessage = "Account expired";
+ break;
+ case 3:
+ errorMessage = "Rejected from server";
+ break;
+ case 4:
+ errorMessage = "You have been blocked by the GM Team";
+ break;
+ case 6:
+ errorMessage = "You have been banned for 5 minutes";
+ break;
+ case 9:
+ errorMessage = "This account is already logged in";
+ break;
+ default:
+ errorMessage = "Unknown error";
+ break;
+ }
+ state = ERROR_STATE;
+ break;
+ }
+}
diff --git a/src/net/loginhandler.cpp~ b/src/net/loginhandler.cpp~
new file mode 100644
index 0000000..070127e
--- /dev/null
+++ b/src/net/loginhandler.cpp~
@@ -0,0 +1,119 @@
+/*
+ * The Mana World
+ * Copyright 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * The Mana World 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id: loginhandler.cpp 2184 2006-02-23 16:02:00Z der_doener $
+ */
+
+#include "loginhandler.h"
+
+#include "messagein.h"
+#include "network.h"
+#include "protocol.h"
+
+#include "../log.h"
+#include "../logindata.h"
+#include "../main.h"
+#include "../serverinfo.h"
+
+extern SERVER_INFO **server_info;
+
+LoginHandler::LoginHandler()
+{
+ static const Uint16 _messages[] = {
+ 0x0069,
+ 0x006a,
+ 0
+ };
+ handledMessages = _messages;
+}
+
+void LoginHandler::handleMessage(MessageIn *msg)
+{
+ switch (msg->getId())
+ {
+ case 0x0069:
+ // Skip the length word
+ msg->skip(2);
+
+ n_server = (msg->getLength() - 47) / 32;
+ server_info = (SERVER_INFO**)malloc(sizeof(SERVER_INFO*) * n_server);
+
+ mLoginData->session_ID1 = msg->readInt32();
+ mLoginData->account_ID = msg->readInt32();
+ mLoginData->session_ID2 = msg->readInt32();
+ msg->skip(30); // unknown
+ mLoginData->sex = msg->readInt8();
+
+ for (int i = 0; i < n_server; i++)
+ {
+ server_info[i] = new SERVER_INFO;
+
+ server_info[i]->address = msg->readInt32();
+ server_info[i]->port = msg->readInt16();
+ server_info[i]->name = msg->readString(20);
+
+ if (server_info[i]->name == "The Mana World")
+ world = i;
+
+ server_info[i]->online_users = msg->readInt32();
+ msg->skip(2); // unknown
+
+ /*logger->log("Network: Server: %s (%s:%d)",
+ server_info[i]->name.c_str(),
+ iptostring(server_info[i]->address),
+ server_info[i]->port);*/
+ }
+ state = CHAR_SERVER_STATE;
+ break;
+
+ case 0x006a:
+ int loginError = msg->readInt8();
+ //logger->log("Login::error code: %i", loginError);
+
+ switch (loginError) {
+ case 0:
+ errorMessage = "Unregistered ID";
+ break;
+ case 1:
+ errorMessage = "Wrong password";
+ break;
+ case 2:
+ errorMessage = "Account expired";
+ break;
+ case 3:
+ errorMessage = "Rejected from server";
+ break;
+ case 4:
+ errorMessage = "You have been blocked by the GM Team";
+ break;
+ case 6:
+ errorMessage = "You have been banned for 5 minutes";
+ break;
+ case 9:
+ errorMessage = "This account is already logged in";
+ break;
+ default:
+ errorMessage = "Unknown error";
+ break;
+ }
+ state = ERROR_STATE;
+ break;
+ }
+}
diff --git a/src/net/loginhandler.h b/src/net/loginhandler.h
new file mode 100644
index 0000000..7a8feef
--- /dev/null
+++ b/src/net/loginhandler.h
@@ -0,0 +1,45 @@
+/*
+ * The Mana World
+ * Copyright 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * The Mana World 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id: loginhandler.h 2137 2006-02-04 16:54:35Z der_doener $
+ */
+
+#ifndef _TMW_NET_LOGINHANDLER_H
+#define _TMW_NET_LOGINHANDLER_H
+
+#include "messagehandler.h"
+#include "../serverinfo.h"
+
+struct LoginData;
+
+class LoginHandler : public MessageHandler
+{
+ public:
+ LoginHandler();
+
+ void handleMessage(MessageIn *msg);
+
+ void setLoginData(LoginData *loginData) { mLoginData = loginData; };
+
+ protected:
+ LoginData *mLoginData;
+};
+
+#endif
diff --git a/src/net/maploginhandler.cpp b/src/net/maploginhandler.cpp
new file mode 100644
index 0000000..1b0c4e7
--- /dev/null
+++ b/src/net/maploginhandler.cpp
@@ -0,0 +1,62 @@
+/*
+ * The Mana World
+ * Copyright 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * The Mana World 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id: maploginhandler.cpp 2112 2006-01-22 13:31:13Z der_doener $
+ */
+
+#include "maploginhandler.h"
+
+#include "messagein.h"
+#include "protocol.h"
+
+#include "../main.h"
+
+MapLoginHandler::MapLoginHandler()
+{
+ static const Uint16 _messages[] = {
+ SMSG_LOGIN_SUCCESS,
+ 0x0081,
+ 0
+ };
+ handledMessages = _messages;
+}
+
+void MapLoginHandler::handleMessage(MessageIn *msg)
+{
+ unsigned char direction;
+
+ switch (msg->getId())
+ {
+ case SMSG_LOGIN_SUCCESS:
+ msg->readInt32(); // server tick
+ unsigned short startX, startY;
+ msg->readCoordinates(startX, startY, direction);
+ msg->skip(2); // unknown
+ /*logger->log("Protocol: Player start position: (%d, %d), Direction: %d",
+ startX, startX, direction);*/
+ state = GAME_STATE;
+ break;
+
+ case 0x0081:
+ /*logger->log("Warning: Map server D/C");*/
+ state = ERROR_STATE;
+ break;
+ }
+}
diff --git a/src/net/maploginhandler.cpp~ b/src/net/maploginhandler.cpp~
new file mode 100644
index 0000000..1b0c4e7
--- /dev/null
+++ b/src/net/maploginhandler.cpp~
@@ -0,0 +1,62 @@
+/*
+ * The Mana World
+ * Copyright 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * The Mana World 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id: maploginhandler.cpp 2112 2006-01-22 13:31:13Z der_doener $
+ */
+
+#include "maploginhandler.h"
+
+#include "messagein.h"
+#include "protocol.h"
+
+#include "../main.h"
+
+MapLoginHandler::MapLoginHandler()
+{
+ static const Uint16 _messages[] = {
+ SMSG_LOGIN_SUCCESS,
+ 0x0081,
+ 0
+ };
+ handledMessages = _messages;
+}
+
+void MapLoginHandler::handleMessage(MessageIn *msg)
+{
+ unsigned char direction;
+
+ switch (msg->getId())
+ {
+ case SMSG_LOGIN_SUCCESS:
+ msg->readInt32(); // server tick
+ unsigned short startX, startY;
+ msg->readCoordinates(startX, startY, direction);
+ msg->skip(2); // unknown
+ /*logger->log("Protocol: Player start position: (%d, %d), Direction: %d",
+ startX, startX, direction);*/
+ state = GAME_STATE;
+ break;
+
+ case 0x0081:
+ /*logger->log("Warning: Map server D/C");*/
+ state = ERROR_STATE;
+ break;
+ }
+}
diff --git a/src/net/maploginhandler.h b/src/net/maploginhandler.h
new file mode 100644
index 0000000..6ff6bc0
--- /dev/null
+++ b/src/net/maploginhandler.h
@@ -0,0 +1,37 @@
+/*
+ * The Mana World
+ * Copyright 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * The Mana World 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id: maploginhandler.h 2112 2006-01-22 13:31:13Z der_doener $
+ */
+
+#ifndef _TMW_NET_MAPLOGINHANDLER_H
+#define _TMW_NET_MAPLOGINHANDLER_H
+
+#include "messagehandler.h"
+
+class MapLoginHandler : public MessageHandler
+{
+ public:
+ MapLoginHandler();
+
+ void handleMessage(MessageIn *msg);
+};
+
+#endif
diff --git a/src/net/messagehandler.cpp b/src/net/messagehandler.cpp
new file mode 100644
index 0000000..370a01a
--- /dev/null
+++ b/src/net/messagehandler.cpp
@@ -0,0 +1,45 @@
+/*
+ * The Mana World
+ * Copyright 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * The Mana World 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id: messagehandler.cpp 2112 2006-01-22 13:31:13Z der_doener $
+ */
+
+#include "messagehandler.h"
+
+#include <cassert>
+
+#include "network.h"
+
+MessageHandler::MessageHandler():
+ mNetwork(0)
+{
+}
+
+MessageHandler::~MessageHandler()
+{
+ if (mNetwork)
+ mNetwork->unregisterHandler(this);
+}
+
+void MessageHandler::setNetwork(Network *network)
+{
+ assert(!(network && mNetwork));
+ mNetwork = network;
+}
diff --git a/src/net/messagehandler.h b/src/net/messagehandler.h
new file mode 100644
index 0000000..90ffa48
--- /dev/null
+++ b/src/net/messagehandler.h
@@ -0,0 +1,48 @@
+/*
+ * The Mana World
+ * Copyright 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * The Mana World 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id: messagehandler.h 2112 2006-01-22 13:31:13Z der_doener $
+ */
+
+#ifndef _TMW_NET_MESSAGEHANDLER_H
+#define _TMW_NET_MESSAGEHANDLER_H
+
+#include <SDL_types.h>
+
+class MessageIn;
+class Network;
+
+class MessageHandler
+{
+ public:
+ const Uint16 *handledMessages;
+
+ MessageHandler();
+ virtual ~MessageHandler();
+
+ virtual void handleMessage(MessageIn *msg) =0;
+
+ void setNetwork(Network *network);
+
+ protected:
+ Network *mNetwork;
+};
+
+#endif
diff --git a/src/net/messagein.cpp b/src/net/messagein.cpp
new file mode 100644
index 0000000..192e857
--- /dev/null
+++ b/src/net/messagein.cpp
@@ -0,0 +1,198 @@
+/*
+ * The Mana World
+ * Copyright 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * The Mana World 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id: messagein.cpp 2158 2006-02-07 10:37:54Z der_doener $
+ */
+
+#include "messagein.h"
+
+#include <cassert>
+#include <SDL.h>
+#include <SDL_endian.h>
+
+#define MAKEWORD(low,high) \
+ ((unsigned short)(((unsigned char)(low)) | \
+ ((unsigned short)((unsigned char)(high))) << 8))
+
+
+MessageIn::MessageIn(const char *data, unsigned int length):
+ mData(data),
+ mLength(length),
+ mPos(0)
+{
+ // Read the message ID
+ mId = readInt16();
+}
+
+Sint8
+MessageIn::readInt8()
+{
+ assert(mPos < mLength);
+ return mData[mPos++];
+}
+
+Sint16
+MessageIn::readInt16()
+{
+ assert(mPos + 2 <= mLength);
+ mPos += 2;
+#if SDL_BYTEORDER == SDL_BIG_ENDIAN
+ return SDL_Swap16(*(Sint16*)(mData + (mPos - 2)));
+#else
+ return (*(Sint16*)(mData + (mPos - 2)));
+#endif
+}
+
+Sint32
+MessageIn::readInt32()
+{
+ assert(mPos + 4 <= mLength);
+ mPos += 4;
+#if SDL_BYTEORDER == SDL_BIG_ENDIAN
+ return SDL_Swap32(*(Sint32*)(mData + (mPos - 4)));
+#else
+ return (*(Sint32*)(mData + (mPos - 4)));
+#endif
+}
+
+void
+MessageIn::readCoordinates(Uint16 &x, Uint16 &y, Uint8 &direction)
+{
+ assert(mPos + 3 <= mLength);
+
+ const char *data = mData + mPos;
+ Sint16 temp;
+
+ temp = MAKEWORD(data[1] & 0x00c0, data[0] & 0x00ff);
+ x = temp >> 6;
+ temp = MAKEWORD(data[2] & 0x00f0, data[1] & 0x003f);
+ y = temp >> 4;
+
+ direction = data[2] & 0x000f;
+
+ // Translate from eAthena format
+ switch (direction)
+ {
+ case 0:
+ direction = 1;
+ break;
+ case 1:
+ direction = 3;
+ break;
+ case 2:
+ direction = 2;
+ break;
+ case 3:
+ direction = 6;
+ break;
+ case 4:
+ direction = 4;
+ break;
+ case 5:
+ direction = 12;
+ break;
+ case 6:
+ direction = 8;
+ break;
+ case 7:
+ direction = 9;
+ break;
+ default:
+ // OOPSIE! Impossible or unknown
+ direction = 0;
+ }
+
+ mPos += 3;
+}
+
+void
+MessageIn::readCoordinatePair(Uint16 &srcX, Uint16 &srcY,
+ Uint16 &dstX, Uint16 &dstY)
+{
+ assert(mPos + 5 <= mLength);
+
+ const char *data = mData + mPos;
+ Sint16 temp;
+
+ temp = MAKEWORD(data[3], data[2] & 0x000f);
+ dstX = temp >> 2;
+
+ dstY = MAKEWORD(data[4], data[3] & 0x0003);
+
+ temp = MAKEWORD(data[1], data[0]);
+ srcX = temp >> 6;
+
+ temp = MAKEWORD(data[2], data[1] & 0x003f);
+ srcY = temp >> 4;
+
+ mPos += 5;
+}
+
+void
+MessageIn::skip(unsigned int length)
+{
+ assert(mPos + length <= mLength);
+ mPos += length;
+}
+
+std::string
+MessageIn::readString(int length)
+{
+ int stringLength = 0;
+
+ // Get string length
+ if (length < 0) {
+ stringLength = readInt16();
+ } else {
+ stringLength = length;
+ }
+
+ // Make sure there is enough data available
+ assert(mPos + length <= mLength);
+
+ // Read the string
+ char *tmpString = new char[stringLength + 1];
+ memcpy(tmpString, (void*)&mData[mPos], stringLength);
+ tmpString[stringLength] = 0;
+ mPos += stringLength;
+
+ std::string read = tmpString;
+ delete[] tmpString;
+
+ return read;
+}
+
+Sint8& operator<<(Sint8 &lhs, MessageIn &msg)
+{
+ lhs = msg.readInt8();
+ return lhs;
+}
+
+Sint16& operator<<(Sint16 &lhs, MessageIn &msg)
+{
+ lhs = msg.readInt16();
+ return lhs;
+}
+
+Sint32& operator<<(Sint32 &lhs, MessageIn &msg)
+{
+ lhs = msg.readInt32();
+ return lhs;
+}
diff --git a/src/net/messagein.h b/src/net/messagein.h
new file mode 100644
index 0000000..0a6b8b8
--- /dev/null
+++ b/src/net/messagein.h
@@ -0,0 +1,97 @@
+/*
+ * The Mana World
+ * Copyright 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * The Mana World 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id: messagein.h 1879 2005-10-16 21:18:11Z der_doener $
+ */
+
+#ifndef _TMW_MESSAGEIN_
+#define _TMW_MESSAGEIN_
+
+#include <string>
+#include <SDL_types.h>
+
+/**
+ * Used for parsing an incoming message.
+ */
+class MessageIn
+{
+ friend Sint8& operator<<(Sint8 &lhs, MessageIn &msg);
+ friend Sint16& operator<<(Sint16 &lhs, MessageIn &msg);
+ friend Sint32& operator<<(Sint32 &lhs, MessageIn &msg);
+
+ public:
+ /**
+ * Constructor.
+ */
+ MessageIn(const char *data, unsigned int length);
+
+ /**
+ * Returns the message ID.
+ */
+ short
+ getId() { return mId; }
+
+ /**
+ * Returns the message length.
+ */
+ unsigned int
+ getLength() { return mLength; }
+
+ Sint8 readInt8(); /**< Reads a byte. */
+ Sint16 readInt16(); /**< Reads a short. */
+ Sint32 readInt32(); /**< Reads a long. */
+
+ /**
+ * Reads a special 3 byte block used by eAthena, containing x and y
+ * coordinates and direction.
+ */
+ void
+ readCoordinates(Uint16 &x, Uint16 &y, Uint8 &direction);
+
+ /**
+ * Reads a special 5 byte block used by eAthena, containing a source
+ * and destination coordinate pair.
+ */
+ void
+ readCoordinatePair(Uint16 &srcX, Uint16 &srcY,
+ Uint16 &dstX, Uint16 &dstY);
+
+ /**
+ * Skips a given number of bytes.
+ */
+ void
+ skip(unsigned int length);
+
+ /**
+ * Reads a string. If a length is not given (-1), it is assumed
+ * that the length of the string is stored in a short at the
+ * start of the string.
+ */
+ std::string
+ readString(int length = -1);
+
+ private:
+ const char* mData; /**< The message data. */
+ unsigned int mLength; /**< The length of the data. */
+ unsigned int mPos; /**< The position in the data. */
+ short mId; /**< The message ID. */
+};
+
+#endif
diff --git a/src/net/messageout.cpp b/src/net/messageout.cpp
new file mode 100644
index 0000000..b6a826c
--- /dev/null
+++ b/src/net/messageout.cpp
@@ -0,0 +1,116 @@
+/*
+ * The Mana World
+ * Copyright 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * The Mana World 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id: messageout.cpp 2112 2006-01-22 13:31:13Z der_doener $
+ */
+
+#include "messageout.h"
+
+#include <string>
+#include <SDL.h>
+#include <SDL_endian.h>
+
+#include "network.h"
+#include "packet.h"
+
+MessageOut::MessageOut(Network *network):
+ mNetwork(network),
+ mData(0),
+ mDataSize(0),
+ mPos(0)
+{
+ mData = mNetwork->mOutBuffer + mNetwork->mOutSize;
+}
+
+void MessageOut::writeInt8(Sint8 value)
+{
+ mData[mPos] = value;
+ mPos += sizeof(Sint8);
+ mNetwork->mOutSize+= sizeof(Sint8);
+}
+
+void MessageOut::writeInt16(Sint16 value)
+{
+#if SDL_BYTEORDER == SDL_BIG_ENDIAN
+ (*(Sint16 *)(mData + mPos)) = SDL_Swap16(value);
+#else
+ (*(Sint16 *)(mData + mPos)) = value;
+#endif
+ mPos += sizeof(Sint16);
+ mNetwork->mOutSize += sizeof(Sint16);
+}
+
+void MessageOut::writeInt32(Sint32 value)
+{
+#if SDL_BYTEORDER == SDL_BIG_ENDIAN
+ (*(Sint32 *)(mData + mPos)) = SDL_Swap32(value);
+#else
+ (*(Sint32 *)(mData + mPos)) = value;
+#endif
+ mPos += sizeof(Sint32);
+ mNetwork->mOutSize += sizeof(Sint32);
+}
+
+void MessageOut::writeString(const std::string &string, int length)
+{
+ std::string toWrite = string;
+
+ if (length < 0)
+ {
+ // Write the length at the start if not fixed
+ writeInt16(string.length());
+ }
+ else
+ {
+ // Make sure the length of the string is no longer than specified
+ toWrite = string.substr(0, length);
+ }
+
+ // Write the actual string
+ memcpy(&mData[mPos], (void*)toWrite.c_str(), toWrite.length());
+ mPos += toWrite.length();
+ mNetwork->mOutSize += toWrite.length();
+
+ // Pad remaining space with zeros
+ if (length > (int)toWrite.length())
+ {
+ memset(&mData[mPos], '\0', length - toWrite.length());
+ mPos += length - toWrite.length();
+ mNetwork->mOutSize += length - toWrite.length();
+ }
+}
+
+MessageOut& operator<<(MessageOut &msg, const Sint8 &rhs)
+{
+ msg.writeInt8(rhs);
+ return msg;
+}
+
+MessageOut& operator<<(MessageOut &msg, const Sint16 &rhs)
+{
+ msg.writeInt16(rhs);
+ return msg;
+}
+
+MessageOut& operator<<(MessageOut &msg, const Sint32 &rhs)
+{
+ msg.writeInt32(rhs);
+ return msg;
+}
diff --git a/src/net/messageout.h b/src/net/messageout.h
new file mode 100644
index 0000000..33deb1b
--- /dev/null
+++ b/src/net/messageout.h
@@ -0,0 +1,65 @@
+/*
+ * The Mana World
+ * Copyright 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * The Mana World 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id: messageout.h 2112 2006-01-22 13:31:13Z der_doener $
+ */
+
+#ifndef _TMW_MESSAGEOUT_
+#define _TMW_MESSAGEOUT_
+
+#include <iosfwd>
+#include <SDL_types.h>
+
+class Network;
+
+/**
+ * Used for building an outgoing message.
+ */
+class MessageOut
+{
+ friend MessageOut& operator<<(MessageOut &msg, const Sint8 &rhs);
+ friend MessageOut& operator<<(MessageOut &msg, const Sint16 &rhs);
+ friend MessageOut& operator<<(MessageOut &msg, const Sint32 &rhs);
+
+ public:
+ /**
+ * Constructor.
+ */
+ MessageOut(Network *network);
+
+ void writeInt8(Sint8 value); /**< Writes a byte. */
+ void writeInt16(Sint16 value); /**< Writes a short. */
+ void writeInt32(Sint32 value); /**< Writes a long. */
+
+ /**
+ * Writes a string. If a fixed length is not given (-1), it is stored
+ * as a short at the start of the string.
+ */
+ void writeString(const std::string &string, int length = -1);
+
+ private:
+ Network *mNetwork;
+
+ char *mData; /**< Data building up. */
+ unsigned int mDataSize; /**< Size of data. */
+ unsigned int mPos; /**< Position in the data. */
+};
+
+#endif
diff --git a/src/net/nethandler.cpp b/src/net/nethandler.cpp
new file mode 100644
index 0000000..8021e55
--- /dev/null
+++ b/src/net/nethandler.cpp
@@ -0,0 +1,182 @@
+#include "nethandler.h"
+#include "network.h"
+#include "protocol.h"
+#include "messageout.h"
+
+#include "loginhandler.h"
+#include "chathandler.h"
+#include "charserverhandler.h"
+#include "maploginhandler.h"
+
+#include "../main.h"
+#include "../game.h"
+
+static NetHandler *NetInstance = NULL;
+static Network *mNetwork = NULL;
+MessageHandler *mChatHandler = NULL;
+
+LoginHandler loginHandler;
+CharServerHandler charServerHandler;
+MapLoginHandler mapLoginHandler;
+
+NetHandler::NetHandler()
+{
+ NetInstance = this;
+}
+
+NetHandler::~NetHandler()
+{
+ delete mNetwork;
+
+ if (mChatHandler != NULL)
+ delete mChatHandler;
+
+ delete NetInstance;
+}
+
+void NetHandler::clean_up()
+{
+ delete mNetwork;
+
+ if (mChatHandler != NULL) // fix a crash caused by map server D/C
+ delete mChatHandler;
+
+ mNetwork = new Network();
+}
+
+NetHandler *NetHandler::getNetInstance()
+{
+ return NetInstance;
+}
+
+Network *NetHandler::getNetwork()
+{
+ if (mNetwork == NULL)
+ mNetwork = new Network();
+
+ return mNetwork;
+}
+
+void NetHandler::loadHandlers()
+{
+ mChatHandler = new ChatHandler();
+ mNetwork->registerHandler(mChatHandler);
+}
+
+// All code related to login, from main.cpp
+
+void NetHandler::accountLogin(LoginData *loginData)
+{
+ /*
+ logger->log("Trying to connect to account server...");
+ logger->log("Username is %s", loginData->username.c_str());*/
+ mNetwork->connect(loginData->hostname, loginData->port);
+ mNetwork->registerHandler(&loginHandler);
+ loginHandler.setLoginData(loginData);
+
+ // Send login infos
+ MessageOut outMsg(mNetwork);
+ outMsg.writeInt16(0x0064);
+ outMsg.writeInt32(9); // client version
+ outMsg.writeString(loginData->username, 24);
+ outMsg.writeString(loginData->password, 24);
+ outMsg.writeInt8(1 | 2); // flags
+}
+
+void NetHandler::charLogin(LoginData *loginData)
+{
+ /*logger->log("Trying to connect to char server...");
+
+ logger->log("Server: %s (%s:%d)",
+ server_info[0]->name.c_str(),
+ loginData->hostname.c_str(),
+ loginData->port);*/
+
+ mNetwork->connect(loginData->hostname, loginData->port);
+ mNetwork->registerHandler(&charServerHandler);
+ charServerHandler.setLoginData(loginData);
+
+ // Send login infos
+ MessageOut outMsg(mNetwork);
+ outMsg.writeInt16(0x0065);
+ outMsg.writeInt32(loginData->account_ID);
+ outMsg.writeInt32(loginData->session_ID1);
+ outMsg.writeInt32(loginData->session_ID2);
+ outMsg.writeInt16(1); // this should match MIN_CLIENT_VERSION in tmwa/src/char/char.hpp
+ outMsg.writeInt8(loginData->sex);
+
+ // We get 4 useless bytes before the real answer comes in
+ mNetwork->skip(4);
+}
+
+void NetHandler::mapLogin(LoginData *loginData)
+{
+ MessageOut outMsg(mNetwork);
+
+ /*logger->log("Trying to connect to map server...");
+ logger->log("Map: %s", map_path.c_str());*/
+
+ mNetwork->connect(loginData->hostname, loginData->port);
+ mNetwork->registerHandler(&mapLoginHandler);
+
+ // Send login infos
+ outMsg.writeInt16(0x0072);
+ outMsg.writeInt32(loginData->account_ID);
+ outMsg.writeInt32(charID[main_charno]);
+ outMsg.writeInt32(loginData->session_ID1);
+ outMsg.writeInt32(loginData->session_ID2);
+ outMsg.writeInt8(loginData->sex);
+
+ // We get 4 useless bytes before the real answer comes in
+ mNetwork->skip(4);
+}
+
+// add a few of the packets that need to be sent.
+void NetHandler::attemptCharSelect()
+{
+ /*logger->log("CharServer: Character Select: %s",
+ char_name.c_str());*/
+ // Request character selection
+ MessageOut outMsg(mNetwork);
+ outMsg.writeInt16(0x0066);
+ outMsg.writeInt8(main_charno);
+}
+
+void NetHandler::mapLoaded()
+{
+ MessageOut outMsg(mNetwork);
+ outMsg.writeInt16(CMSG_MAP_LOADED);
+}
+
+void NetHandler::privateMessage(std::string name, std::string msg)
+{
+ MessageOut outMsg(mNetwork);
+ outMsg.writeInt16(CMSG_CHAT_WHISPER);
+ outMsg.writeInt16(static_cast<short>(msg.length() + 28));
+ outMsg.writeString(name, 24);
+ outMsg.writeString(msg, static_cast<int>(msg.length()));
+}
+
+void NetHandler::publicMessage(std::string msg)
+{
+ std::string mes = std::string("guild") + " : " + msg;
+ MessageOut outMsg(mNetwork);
+ outMsg.writeInt16(CMSG_CHAT_MESSAGE);
+ outMsg.writeInt16(static_cast<short>(mes.length() + 4 + 1));
+ outMsg.writeString(mes, static_cast<int>(mes.length() + 1));
+}
+
+void NetHandler::sit()
+{
+ MessageOut outMsg(mNetwork);
+ outMsg.writeInt16(CMSG_PLAYER_CHANGE_ACT);
+ outMsg.writeInt32(0);
+ outMsg.writeInt8(2);
+}
+
+void NetHandler::ping(int tick)
+{
+ MessageOut outMsg(mNetwork);
+ outMsg.writeInt16(CMSG_CLIENT_PING);
+ outMsg.writeInt32(tick);
+}
diff --git a/src/net/nethandler.cpp~ b/src/net/nethandler.cpp~
new file mode 100644
index 0000000..d6f031e
--- /dev/null
+++ b/src/net/nethandler.cpp~
@@ -0,0 +1,183 @@
+#include "nethandler.h"
+#include "network.h"
+#include "protocol.h"
+#include "messageout.h"
+
+#include "loginhandler.h"
+#include "chathandler.h"
+#include "charserverhandler.h"
+#include "maploginhandler.h"
+
+#include "../log.h"
+#include "../main.h"
+#include "../game.h"
+
+static NetHandler *NetInstance = NULL;
+static Network *mNetwork = NULL;
+MessageHandler *mChatHandler = NULL;
+
+LoginHandler loginHandler;
+CharServerHandler charServerHandler;
+MapLoginHandler mapLoginHandler;
+
+NetHandler::NetHandler()
+{
+ NetInstance = this;
+}
+
+NetHandler::~NetHandler()
+{
+ delete mNetwork;
+
+ if (mChatHandler != NULL)
+ delete mChatHandler;
+
+ delete NetInstance;
+}
+
+void NetHandler::clean_up()
+{
+ delete mNetwork;
+
+ if (mChatHandler != NULL) // fix a crash caused by map server D/C
+ delete mChatHandler;
+
+ mNetwork = new Network();
+}
+
+NetHandler *NetHandler::getNetInstance()
+{
+ return NetInstance;
+}
+
+Network *NetHandler::getNetwork()
+{
+ if (mNetwork == NULL)
+ mNetwork = new Network();
+
+ return mNetwork;
+}
+
+void NetHandler::loadHandlers()
+{
+ mChatHandler = new ChatHandler();
+ mNetwork->registerHandler(mChatHandler);
+}
+
+// All code related to login, from main.cpp
+
+void NetHandler::accountLogin(LoginData *loginData)
+{
+ /*
+ logger->log("Trying to connect to account server...");
+ logger->log("Username is %s", loginData->username.c_str());*/
+ mNetwork->connect(loginData->hostname, loginData->port);
+ mNetwork->registerHandler(&loginHandler);
+ loginHandler.setLoginData(loginData);
+
+ // Send login infos
+ MessageOut outMsg(mNetwork);
+ outMsg.writeInt16(0x0064);
+ outMsg.writeInt32(0); // client version
+ outMsg.writeString(loginData->username, 24);
+ outMsg.writeString(loginData->password, 24);
+ outMsg.writeInt8(0); // unknown
+}
+
+void NetHandler::charLogin(LoginData *loginData)
+{
+ /*logger->log("Trying to connect to char server...");
+
+ logger->log("Server: %s (%s:%d)",
+ server_info[0]->name.c_str(),
+ loginData->hostname.c_str(),
+ loginData->port);*/
+
+ mNetwork->connect(loginData->hostname, loginData->port);
+ mNetwork->registerHandler(&charServerHandler);
+ charServerHandler.setLoginData(loginData);
+
+ // Send login infos
+ MessageOut outMsg(mNetwork);
+ outMsg.writeInt16(0x0065);
+ outMsg.writeInt32(loginData->account_ID);
+ outMsg.writeInt32(loginData->session_ID1);
+ outMsg.writeInt32(loginData->session_ID2);
+ outMsg.writeInt16(0); // unknown
+ outMsg.writeInt8(loginData->sex);
+
+ // We get 4 useless bytes before the real answer comes in
+ mNetwork->skip(4);
+}
+
+void NetHandler::mapLogin(LoginData *loginData)
+{
+ MessageOut outMsg(mNetwork);
+
+ /*logger->log("Trying to connect to map server...");
+ logger->log("Map: %s", map_path.c_str());*/
+
+ mNetwork->connect(loginData->hostname, loginData->port);
+ mNetwork->registerHandler(&mapLoginHandler);
+
+ // Send login infos
+ outMsg.writeInt16(0x0072);
+ outMsg.writeInt32(loginData->account_ID);
+ outMsg.writeInt32(charID[main_charno]);
+ outMsg.writeInt32(loginData->session_ID1);
+ outMsg.writeInt32(loginData->session_ID2);
+ outMsg.writeInt8(loginData->sex);
+
+ // We get 4 useless bytes before the real answer comes in
+ mNetwork->skip(4);
+}
+
+// add a few of the packets that need to be sent.
+void NetHandler::attemptCharSelect()
+{
+ /*logger->log("CharServer: Character Select: %s",
+ char_name.c_str());*/
+ // Request character selection
+ MessageOut outMsg(mNetwork);
+ outMsg.writeInt16(0x0066);
+ outMsg.writeInt8(main_charno);
+}
+
+void NetHandler::mapLoaded()
+{
+ MessageOut outMsg(mNetwork);
+ outMsg.writeInt16(CMSG_MAP_LOADED);
+}
+
+void NetHandler::privateMessage(std::string name, std::string msg)
+{
+ MessageOut outMsg(mNetwork);
+ outMsg.writeInt16(CMSG_CHAT_WHISPER);
+ outMsg.writeInt16(static_cast<short>(msg.length() + 28));
+ outMsg.writeString(name, 24);
+ outMsg.writeString(msg, static_cast<int>(msg.length()));
+}
+
+void NetHandler::publicMessage(std::string msg)
+{
+ std::string mes = std::string("guild") + " : " + msg;
+ MessageOut outMsg(mNetwork);
+ outMsg.writeInt16(CMSG_CHAT_MESSAGE);
+ outMsg.writeInt16(static_cast<short>(mes.length() + 4 + 1));
+ outMsg.writeString(mes, static_cast<int>(mes.length() + 1));
+}
+
+void NetHandler::sit()
+{
+ MessageOut outMsg(mNetwork);
+ outMsg.writeInt16(CMSG_PLAYER_CHANGE_ACT);
+ outMsg.writeInt32(0);
+ outMsg.writeInt8(2);
+}
+
+void NetHandler::ping(int tick)
+{
+ MessageOut outMsg(mNetwork);
+ outMsg.writeInt16(CMSG_CLIENT_PING);
+ outMsg.writeInt32(tick);
+} \ No newline at end of file
diff --git a/src/net/nethandler.h b/src/net/nethandler.h
new file mode 100644
index 0000000..41f523c
--- /dev/null
+++ b/src/net/nethandler.h
@@ -0,0 +1,33 @@
+#include "network.h"
+
+#include "loginhandler.h"
+#include "../logindata.h"
+
+class NetHandler
+{
+
+
+public:
+
+ NetHandler();
+ ~NetHandler();
+
+ static NetHandler *getNetInstance();
+
+ void loadHandlers();
+ Network *getNetwork();
+ void clean_up(); // for restart
+
+ void accountLogin(LoginData *loginData);
+ void charLogin(LoginData *loginData);
+ void mapLogin(LoginData *loginData);
+ void attemptCharSelect();
+
+ void mapLoaded();
+ void privateMessage(std::string name, std::string msg);
+ void publicMessage(std::string msg);
+ void ping(int tick);
+ void sit();
+private:
+
+};
diff --git a/src/net/network.cpp b/src/net/network.cpp
new file mode 100644
index 0000000..e4c6e65
--- /dev/null
+++ b/src/net/network.cpp
@@ -0,0 +1,442 @@
+/*
+ * The Mana World
+ * Copyright 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * The Mana World 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id: network.cpp 2187 2006-02-24 20:15:19Z der_doener $
+ */
+
+#include "network.h"
+
+#include "messagehandler.h"
+#include "messagein.h"
+
+#include "../main.h"
+
+/** Warning: buffers and other variables are shared,
+ so there can be only one connection active at a time */
+
+short packet_lengths[] = {
+ 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// #0x0040
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, -1, 55, 17, 3, 37, 46, -1, 23, -1, 3,108, 3, 2,
+ 3, 28, 19, 11, 3, -1, 9, 5, 54, 53, 58, 60, 41, 2, 6, 6,
+// #0x0080
+ 7, 3, 2, 2, 2, 5, 16, 12, 10, 7, 29, 23, -1, -1, -1, 0,
+ 7, 22, 28, 2, 6, 30, -1, -1, 3, -1, -1, 5, 9, 17, 17, 6,
+ 23, 6, 6, -1, -1, -1, -1, 8, 7, 6, 7, 4, 7, 0, -1, 6,
+ 8, 8, 3, 3, -1, 6, 6, -1, 7, 6, 2, 5, 6, 44, 5, 3,
+// #0x00C0
+ 7, 2, 6, 8, 6, 7, -1, -1, -1, -1, 3, 3, 6, 6, 2, 27,
+ 3, 4, 4, 2, -1, -1, 3, -1, 6, 14, 3, -1, 28, 29, -1, -1,
+ 30, 30, 26, 2, 6, 26, 3, 3, 8, 19, 5, 2, 3, 2, 2, 2,
+ 3, 2, 6, 8, 21, 8, 8, 2, 2, 26, 3, -1, 6, 27, 30, 10,
+// #0x0100
+ 2, 6, 6, 30, 79, 31, 10, 10, -1, -1, 4, 6, 6, 2, 11, -1,
+ 10, 39, 4, 10, 31, 35, 10, 18, 2, 13, 15, 20, 68, 2, 3, 16,
+ 6, 14, -1, -1, 21, 8, 8, 8, 8, 8, 2, 2, 3, 4, 2, -1,
+ 6, 86, 6, -1, -1, 7, -1, 6, 3, 16, 4, 4, 4, 6, 24, 26,
+// #0x0140
+ 22, 14, 6, 10, 23, 19, 6, 39, 8, 9, 6, 27, -1, 2, 6, 6,
+ 110, 6, -1, -1, -1, -1, -1, 6, -1, 54, 66, 54, 90, 42, 6, 42,
+ -1, -1, -1, -1, -1, 30, -1, 3, 14, 3, 30, 10, 43, 14,186,182,
+ 14, 30, 10, 3, -1, 6,106, -1, 4, 5, 4, -1, 6, 7, -1, -1,
+// #0x0180
+ 6, 3,106, 10, 10, 34, 0, 6, 8, 4, 4, 4, 29, -1, 10, 6,
+ 90, 86, 24, 6, 30,102, 9, 4, 8, 4, 14, 10, 4, 6, 2, 6,
+ 3, 3, 35, 5, 11, 26, -1, 4, 4, 6, 10, 12, 6, -1, 4, 4,
+ 11, 7, -1, 67, 12, 18,114, 6, 3, 6, 26, 26, 26, 26, 2, 3,
+// #0x01C0
+ 2, 14, 10, -1, 22, 22, 4, 2, 13, 97, 0, 9, 9, 29, 6, 28,
+ 8, 14, 10, 35, 6, 8, 4, 11, 54, 53, 60, 2, -1, 47, 33, 6,
+ 30, 8, 34, 14, 2, 6, 26, 2, 28, 81, 6, 10, 26, 2, -1, -1,
+ -1, -1, 20, 10, 32, 9, 34, 14, 2, 6, 48, 56, -1, 4, 5, 10,
+// #0x200
+ 26, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+const unsigned int BUFFER_SIZE = 65536;
+
+int networkThread(void *data)
+{
+ Network *network = static_cast<Network*>(data);
+
+ if (!network->realConnect())
+ return -1;
+
+ network->receive();
+
+ return 0;
+}
+
+Network::Network():
+ mAddress(), mPort(0),
+ mInBuffer(new char[BUFFER_SIZE]),
+ mOutBuffer(new char[BUFFER_SIZE]),
+ mInSize(0), mOutSize(0),
+ mToSkip(0),
+ mState(IDLE),
+ mWorkerThread(0)
+{
+ mMutex = SDL_CreateMutex();
+}
+
+Network::~Network()
+{
+ clearHandlers();
+
+ if (mState != IDLE && mState != ERROR_BROKE)
+ disconnect();
+
+ SDL_DestroyMutex(mMutex);
+
+ delete mInBuffer;
+ delete mOutBuffer;
+}
+
+bool Network::connect(const std::string &address, short port)
+{
+ if (mState != IDLE && mState != ERROR_BROKE)
+ {
+ //logger->log("Tried to connect an already connected socket!");
+ return false;
+ }
+
+ if (address.empty())
+ {
+ //logger->log("Empty address given to Network::connect()!");
+ mState = ERROR_BROKE;
+ return false;
+ }
+
+ //logger->log("Network::Connecting to %s:%i", address.c_str(), port);
+
+ mAddress = address;
+ mPort = port;
+
+ // Reset to sane values
+ mOutSize = 0;
+ mInSize = 0;
+ mToSkip = 0;
+
+ mState = CONNECTING;
+ mWorkerThread = SDL_CreateThread(networkThread, this);
+ if (!mWorkerThread)
+ {
+ //logger->log("Unable to create network worker thread");
+ mState = ERROR_BROKE;
+ return false;
+ }
+
+ return true;
+}
+
+void Network::disconnect()
+{
+ if (mState != CONNECTED && mState != CONNECTING)
+ return;
+
+ mState = IDLE;
+
+ if (mWorkerThread)
+ {
+ SDL_WaitThread(mWorkerThread, NULL);
+ mWorkerThread = NULL;
+ }
+ SDLNet_TCP_Close(mSocket);
+}
+
+void Network::registerHandler(MessageHandler *handler)
+{
+ const Uint16 *i = handler->handledMessages;
+
+ while(*i)
+ {
+ mMessageHandlers[*i] = handler;
+ i++;
+ }
+
+ handler->setNetwork(this);
+}
+
+void Network::unregisterHandler(MessageHandler *handler)
+{
+ for (const Uint16 *i = handler->handledMessages; *i; i++)
+ {
+ mMessageHandlers.erase(*i);
+ }
+
+ handler->setNetwork(0);
+}
+
+void Network::clearHandlers()
+{
+ MessageHandlerIterator i;
+ for (i = mMessageHandlers.begin(); i != mMessageHandlers.end(); i++)
+ {
+ i->second->setNetwork(0);
+ }
+ mMessageHandlers.clear();
+}
+
+void Network::dispatchMessages()
+{
+ while (messageReady())
+ {
+ MessageIn msg = getNextMessage();
+
+ MessageHandlerIterator iter = mMessageHandlers.find(msg.getId());
+
+ if (iter != mMessageHandlers.end())
+ iter->second->handleMessage(&msg);
+ /*else
+ logger->log("Unhandled packet: %x", msg.getId());*/
+
+ skip(msg.getLength());
+ }
+}
+
+void Network::flush()
+{
+ if (!mOutSize || mState != CONNECTED)
+ return;
+
+ int ret;
+
+
+ SDL_mutexP(mMutex);
+ ret = SDLNet_TCP_Send(mSocket, mOutBuffer, mOutSize);
+ if (ret < (int)mOutSize)
+ {
+ //logger->log("Error in SDLNet_TCP_Send(): %s", SDLNet_GetError());
+ mState = ERROR_BROKE;
+ }
+ mOutSize = 0;
+ SDL_mutexV(mMutex);
+}
+
+void Network::skip(int len)
+{
+ SDL_mutexP(mMutex);
+ mToSkip += len;
+ if (!mInSize)
+ {
+ SDL_mutexV(mMutex);
+ return;
+ }
+
+ if (mInSize >= mToSkip)
+ {
+ mInSize -= mToSkip;
+ memmove(mInBuffer, mInBuffer + mToSkip, mInSize);
+ mToSkip = 0;
+ }
+ else
+ {
+ mToSkip -= mInSize;
+ mInSize = 0;
+ }
+ SDL_mutexV(mMutex);
+}
+
+bool Network::messageReady()
+{
+ int len = -1;
+
+ SDL_mutexP(mMutex);
+ if (mInSize >= 2)
+ {
+ len = packet_lengths[readWord(0)];
+
+ if (len == -1 && mInSize > 4)
+ len = readWord(2);
+
+ }
+
+ bool ret = (mInSize >= static_cast<unsigned int>(len));
+ SDL_mutexV(mMutex);
+
+ return ret;
+}
+
+MessageIn Network::getNextMessage()
+{
+ while (!messageReady())
+ {
+ if (mState == ERROR_BROKE)
+ break;
+ }
+
+ SDL_mutexP(mMutex);
+ int msgId = readWord(0);
+ int len = packet_lengths[msgId];
+
+ if (len == -1)
+ len = readWord(2);
+
+#ifdef DEBUG
+ printf("Received packet 0x%x of length %d\n", msgId, length);
+#endif
+
+ MessageIn msg(mInBuffer, len);
+ SDL_mutexV(mMutex);
+
+ return msg;
+}
+
+bool Network::realConnect()
+{
+ IPaddress ipAddress;
+
+ if (SDLNet_ResolveHost(&ipAddress, mAddress.c_str(), mPort) == -1)
+ {
+ //logger->log("Error in SDLNet_ResolveHost(): %s", SDLNet_GetError());
+ mState = ERROR_BROKE;
+ return false;
+ }
+
+ mState = CONNECTING;
+
+ mSocket = SDLNet_TCP_Open(&ipAddress);
+ if (!mSocket)
+ {
+ //logger->log("Error in SDLNet_TCP_Open(): %s", SDLNet_GetError());
+ mState = ERROR_BROKE;
+ return false;
+ }
+
+ /*logger->log("Network::Started session with %s:%i",
+ iptostring(ipAddress.host), ipAddress.port);*/
+
+ mState = CONNECTED;
+
+ return true;
+}
+
+void Network::receive()
+{
+ SDLNet_SocketSet set;
+
+ if (!(set = SDLNet_AllocSocketSet(1)))
+ {
+ //logger->log("Error in SDLNet_AllocSocketSet(): %s", SDLNet_GetError());
+ mState = ERROR_BROKE;
+ return;
+ }
+
+ if (SDLNet_TCP_AddSocket(set, mSocket) == -1)
+ {
+ //logger->log("Error in SDLNet_AddSocket(): %s", SDLNet_GetError());
+ mState = ERROR_BROKE;
+ }
+
+ while (mState == CONNECTED)
+ {
+ // TODO Try to get this to block all the time while still being able
+ // to escape the loop
+ int numReady = SDLNet_CheckSockets(set, ((Uint32)500));
+ int ret;
+ switch (numReady)
+ {
+ case -1:
+ // logger->log("Error: SDLNet_CheckSockets");
+ // FALLTHROUGH
+ case 0:
+ break;
+
+ case 1:
+ // Receive data from the socket
+ SDL_mutexP(mMutex);
+ ret = SDLNet_TCP_Recv(mSocket, mInBuffer + mInSize, BUFFER_SIZE - mInSize);
+
+ if (!ret)
+ {
+ // We got disconnected
+ mState = ERROR_BROKE; //IDLE - changed to error to force a restart.
+ //logger->log("Disconnected.");
+ //state = LOGIN_STATE;
+ }
+ else if (ret < 0)
+ {
+ //logger->log("Error in SDLNet_TCP_Recv(): %s", SDLNet_GetError());
+ mState = ERROR_BROKE;
+ }
+ else {
+ mInSize += ret;
+ if (mToSkip)
+ {
+ if (mInSize >= mToSkip)
+ {
+ mInSize -= mToSkip;
+ memmove(mInBuffer, mInBuffer + mToSkip, mInSize);
+ mToSkip = 0;
+ }
+ else
+ {
+ mToSkip -= mInSize;
+ mInSize = 0;
+ }
+ }
+ }
+ SDL_mutexV(mMutex);
+ break;
+
+ default:
+ // more than one socket is ready..
+ // this should not happen since we only listen once socket.
+ //logger->log("Error in SDLNet_TCP_Recv(), %d sockets are ready : %s", numReady, SDLNet_GetError());
+ mState = ERROR_BROKE;
+ break;
+ }
+ }
+
+ if (SDLNet_TCP_DelSocket(set, mSocket) == -1)
+ {
+ //logger->log("Error in SDLNet_DelSocket(): %s", SDLNet_GetError());
+ }
+
+ SDLNet_FreeSocketSet(set);
+}
+
+char *iptostring(int address)
+{
+ static char asciiIP[16];
+
+ sprintf(asciiIP, "%i.%i.%i.%i",
+ (unsigned char)(address),
+ (unsigned char)(address >> 8),
+ (unsigned char)(address >> 16),
+ (unsigned char)(address >> 24));
+
+ return asciiIP;
+}
+
+Uint16 Network::readWord(int pos)
+{
+#if SDL_BYTEORDER == SDL_BIG_ENDIAN
+ return SDL_Swap16((*(Uint16*)(mInBuffer+(pos))));
+#else
+ return (*(Uint16*)(mInBuffer+(pos)));
+#endif
+}
diff --git a/src/net/network.cpp~ b/src/net/network.cpp~
new file mode 100644
index 0000000..fb531de
--- /dev/null
+++ b/src/net/network.cpp~
@@ -0,0 +1,443 @@
+/*
+ * The Mana World
+ * Copyright 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * The Mana World 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id: network.cpp 2187 2006-02-24 20:15:19Z der_doener $
+ */
+
+#include "network.h"
+
+#include "messagehandler.h"
+#include "messagein.h"
+
+#include "../main.h"
+#include "../log.h"
+
+/** Warning: buffers and other variables are shared,
+ so there can be only one connection active at a time */
+
+short packet_lengths[] = {
+ 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// #0x0040
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 55, 17, 3, 37, 46, -1, 23, -1, 3,108, 3, 2,
+ 3, 28, 19, 11, 3, -1, 9, 5, 54, 53, 58, 60, 41, 2, 6, 6,
+// #0x0080
+ 7, 3, 2, 2, 2, 5, 16, 12, 10, 7, 29, 23, -1, -1, -1, 0,
+ 7, 22, 28, 2, 6, 30, -1, -1, 3, -1, -1, 5, 9, 17, 17, 6,
+ 23, 6, 6, -1, -1, -1, -1, 8, 7, 6, 7, 4, 7, 0, -1, 6,
+ 8, 8, 3, 3, -1, 6, 6, -1, 7, 6, 2, 5, 6, 44, 5, 3,
+// #0x00C0
+ 7, 2, 6, 8, 6, 7, -1, -1, -1, -1, 3, 3, 6, 6, 2, 27,
+ 3, 4, 4, 2, -1, -1, 3, -1, 6, 14, 3, -1, 28, 29, -1, -1,
+ 30, 30, 26, 2, 6, 26, 3, 3, 8, 19, 5, 2, 3, 2, 2, 2,
+ 3, 2, 6, 8, 21, 8, 8, 2, 2, 26, 3, -1, 6, 27, 30, 10,
+// #0x0100
+ 2, 6, 6, 30, 79, 31, 10, 10, -1, -1, 4, 6, 6, 2, 11, -1,
+ 10, 39, 4, 10, 31, 35, 10, 18, 2, 13, 15, 20, 68, 2, 3, 16,
+ 6, 14, -1, -1, 21, 8, 8, 8, 8, 8, 2, 2, 3, 4, 2, -1,
+ 6, 86, 6, -1, -1, 7, -1, 6, 3, 16, 4, 4, 4, 6, 24, 26,
+// #0x0140
+ 22, 14, 6, 10, 23, 19, 6, 39, 8, 9, 6, 27, -1, 2, 6, 6,
+ 110, 6, -1, -1, -1, -1, -1, 6, -1, 54, 66, 54, 90, 42, 6, 42,
+ -1, -1, -1, -1, -1, 30, -1, 3, 14, 3, 30, 10, 43, 14,186,182,
+ 14, 30, 10, 3, -1, 6,106, -1, 4, 5, 4, -1, 6, 7, -1, -1,
+// #0x0180
+ 6, 3,106, 10, 10, 34, 0, 6, 8, 4, 4, 4, 29, -1, 10, 6,
+ 90, 86, 24, 6, 30,102, 9, 4, 8, 4, 14, 10, 4, 6, 2, 6,
+ 3, 3, 35, 5, 11, 26, -1, 4, 4, 6, 10, 12, 6, -1, 4, 4,
+ 11, 7, -1, 67, 12, 18,114, 6, 3, 6, 26, 26, 26, 26, 2, 3,
+// #0x01C0
+ 2, 14, 10, -1, 22, 22, 4, 2, 13, 97, 0, 9, 9, 29, 6, 28,
+ 8, 14, 10, 35, 6, 8, 4, 11, 54, 53, 60, 2, -1, 47, 33, 6,
+ 30, 8, 34, 14, 2, 6, 26, 2, 28, 81, 6, 10, 26, 2, -1, -1,
+ -1, -1, 20, 10, 32, 9, 34, 14, 2, 6, 48, 56, -1, 4, 5, 10,
+// #0x200
+ 26, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+const unsigned int BUFFER_SIZE = 65536;
+
+int networkThread(void *data)
+{
+ Network *network = static_cast<Network*>(data);
+
+ if (!network->realConnect())
+ return -1;
+
+ network->receive();
+
+ return 0;
+}
+
+Network::Network():
+ mAddress(), mPort(0),
+ mInBuffer(new char[BUFFER_SIZE]),
+ mOutBuffer(new char[BUFFER_SIZE]),
+ mInSize(0), mOutSize(0),
+ mToSkip(0),
+ mState(IDLE),
+ mWorkerThread(0)
+{
+ mMutex = SDL_CreateMutex();
+}
+
+Network::~Network()
+{
+ clearHandlers();
+
+ if (mState != IDLE && mState != ERROR_BROKE)
+ disconnect();
+
+ SDL_DestroyMutex(mMutex);
+
+ delete mInBuffer;
+ delete mOutBuffer;
+}
+
+bool Network::connect(const std::string &address, short port)
+{
+ if (mState != IDLE && mState != ERROR_BROKE)
+ {
+ //logger->log("Tried to connect an already connected socket!");
+ return false;
+ }
+
+ if (address.empty())
+ {
+ //logger->log("Empty address given to Network::connect()!");
+ mState = ERROR_BROKE;
+ return false;
+ }
+
+ //logger->log("Network::Connecting to %s:%i", address.c_str(), port);
+
+ mAddress = address;
+ mPort = port;
+
+ // Reset to sane values
+ mOutSize = 0;
+ mInSize = 0;
+ mToSkip = 0;
+
+ mState = CONNECTING;
+ mWorkerThread = SDL_CreateThread(networkThread, this);
+ if (!mWorkerThread)
+ {
+ //logger->log("Unable to create network worker thread");
+ mState = ERROR_BROKE;
+ return false;
+ }
+
+ return true;
+}
+
+void Network::disconnect()
+{
+ if (mState != CONNECTED && mState != CONNECTING)
+ return;
+
+ mState = IDLE;
+
+ if (mWorkerThread)
+ {
+ SDL_WaitThread(mWorkerThread, NULL);
+ mWorkerThread = NULL;
+ }
+ SDLNet_TCP_Close(mSocket);
+}
+
+void Network::registerHandler(MessageHandler *handler)
+{
+ const Uint16 *i = handler->handledMessages;
+
+ while(*i)
+ {
+ mMessageHandlers[*i] = handler;
+ i++;
+ }
+
+ handler->setNetwork(this);
+}
+
+void Network::unregisterHandler(MessageHandler *handler)
+{
+ for (const Uint16 *i = handler->handledMessages; *i; i++)
+ {
+ mMessageHandlers.erase(*i);
+ }
+
+ handler->setNetwork(0);
+}
+
+void Network::clearHandlers()
+{
+ MessageHandlerIterator i;
+ for (i = mMessageHandlers.begin(); i != mMessageHandlers.end(); i++)
+ {
+ i->second->setNetwork(0);
+ }
+ mMessageHandlers.clear();
+}
+
+void Network::dispatchMessages()
+{
+ while (messageReady())
+ {
+ MessageIn msg = getNextMessage();
+
+ MessageHandlerIterator iter = mMessageHandlers.find(msg.getId());
+
+ if (iter != mMessageHandlers.end())
+ iter->second->handleMessage(&msg);
+ /*else
+ logger->log("Unhandled packet: %x", msg.getId());*/
+
+ skip(msg.getLength());
+ }
+}
+
+void Network::flush()
+{
+ if (!mOutSize || mState != CONNECTED)
+ return;
+
+ int ret;
+
+
+ SDL_mutexP(mMutex);
+ ret = SDLNet_TCP_Send(mSocket, mOutBuffer, mOutSize);
+ if (ret < (int)mOutSize)
+ {
+ //logger->log("Error in SDLNet_TCP_Send(): %s", SDLNet_GetError());
+ mState = ERROR_BROKE;
+ }
+ mOutSize = 0;
+ SDL_mutexV(mMutex);
+}
+
+void Network::skip(int len)
+{
+ SDL_mutexP(mMutex);
+ mToSkip += len;
+ if (!mInSize)
+ {
+ SDL_mutexV(mMutex);
+ return;
+ }
+
+ if (mInSize >= mToSkip)
+ {
+ mInSize -= mToSkip;
+ memmove(mInBuffer, mInBuffer + mToSkip, mInSize);
+ mToSkip = 0;
+ }
+ else
+ {
+ mToSkip -= mInSize;
+ mInSize = 0;
+ }
+ SDL_mutexV(mMutex);
+}
+
+bool Network::messageReady()
+{
+ int len = -1;
+
+ SDL_mutexP(mMutex);
+ if (mInSize >= 2)
+ {
+ len = packet_lengths[readWord(0)];
+
+ if (len == -1 && mInSize > 4)
+ len = readWord(2);
+
+ }
+
+ bool ret = (mInSize >= static_cast<unsigned int>(len));
+ SDL_mutexV(mMutex);
+
+ return ret;
+}
+
+MessageIn Network::getNextMessage()
+{
+ while (!messageReady())
+ {
+ if (mState == ERROR_BROKE)
+ break;
+ }
+
+ SDL_mutexP(mMutex);
+ int msgId = readWord(0);
+ int len = packet_lengths[msgId];
+
+ if (len == -1)
+ len = readWord(2);
+
+#ifdef DEBUG
+ printf("Received packet 0x%x of length %d\n", msgId, length);
+#endif
+
+ MessageIn msg(mInBuffer, len);
+ SDL_mutexV(mMutex);
+
+ return msg;
+}
+
+bool Network::realConnect()
+{
+ IPaddress ipAddress;
+
+ if (SDLNet_ResolveHost(&ipAddress, mAddress.c_str(), mPort) == -1)
+ {
+ //logger->log("Error in SDLNet_ResolveHost(): %s", SDLNet_GetError());
+ mState = ERROR_BROKE;
+ return false;
+ }
+
+ mState = CONNECTING;
+
+ mSocket = SDLNet_TCP_Open(&ipAddress);
+ if (!mSocket)
+ {
+ //logger->log("Error in SDLNet_TCP_Open(): %s", SDLNet_GetError());
+ mState = ERROR_BROKE;
+ return false;
+ }
+
+ /*logger->log("Network::Started session with %s:%i",
+ iptostring(ipAddress.host), ipAddress.port);*/
+
+ mState = CONNECTED;
+
+ return true;
+}
+
+void Network::receive()
+{
+ SDLNet_SocketSet set;
+
+ if (!(set = SDLNet_AllocSocketSet(1)))
+ {
+ //logger->log("Error in SDLNet_AllocSocketSet(): %s", SDLNet_GetError());
+ mState = ERROR_BROKE;
+ return;
+ }
+
+ if (SDLNet_TCP_AddSocket(set, mSocket) == -1)
+ {
+ //logger->log("Error in SDLNet_AddSocket(): %s", SDLNet_GetError());
+ mState = ERROR_BROKE;
+ }
+
+ while (mState == CONNECTED)
+ {
+ // TODO Try to get this to block all the time while still being able
+ // to escape the loop
+ int numReady = SDLNet_CheckSockets(set, ((Uint32)500));
+ int ret;
+ switch (numReady)
+ {
+ case -1:
+ // logger->log("Error: SDLNet_CheckSockets");
+ // FALLTHROUGH
+ case 0:
+ break;
+
+ case 1:
+ // Receive data from the socket
+ SDL_mutexP(mMutex);
+ ret = SDLNet_TCP_Recv(mSocket, mInBuffer + mInSize, BUFFER_SIZE - mInSize);
+
+ if (!ret)
+ {
+ // We got disconnected
+ mState = ERROR_BROKE; //IDLE - changed to error to force a restart.
+ //logger->log("Disconnected.");
+ //state = LOGIN_STATE;
+ }
+ else if (ret < 0)
+ {
+ //logger->log("Error in SDLNet_TCP_Recv(): %s", SDLNet_GetError());
+ mState = ERROR_BROKE;
+ }
+ else {
+ mInSize += ret;
+ if (mToSkip)
+ {
+ if (mInSize >= mToSkip)
+ {
+ mInSize -= mToSkip;
+ memmove(mInBuffer, mInBuffer + mToSkip, mInSize);
+ mToSkip = 0;
+ }
+ else
+ {
+ mToSkip -= mInSize;
+ mInSize = 0;
+ }
+ }
+ }
+ SDL_mutexV(mMutex);
+ break;
+
+ default:
+ // more than one socket is ready..
+ // this should not happen since we only listen once socket.
+ //logger->log("Error in SDLNet_TCP_Recv(), %d sockets are ready : %s", numReady, SDLNet_GetError());
+ mState = ERROR_BROKE;
+ break;
+ }
+ }
+
+ if (SDLNet_TCP_DelSocket(set, mSocket) == -1)
+ {
+ //logger->log("Error in SDLNet_DelSocket(): %s", SDLNet_GetError());
+ }
+
+ SDLNet_FreeSocketSet(set);
+}
+
+char *iptostring(int address)
+{
+ static char asciiIP[16];
+
+ sprintf(asciiIP, "%i.%i.%i.%i",
+ (unsigned char)(address),
+ (unsigned char)(address >> 8),
+ (unsigned char)(address >> 16),
+ (unsigned char)(address >> 24));
+
+ return asciiIP;
+}
+
+Uint16 Network::readWord(int pos)
+{
+#if SDL_BYTEORDER == SDL_BIG_ENDIAN
+ return SDL_Swap16((*(Uint16*)(mInBuffer+(pos))));
+#else
+ return (*(Uint16*)(mInBuffer+(pos)));
+#endif
+}
diff --git a/src/net/network.h b/src/net/network.h
new file mode 100644
index 0000000..45a9838
--- /dev/null
+++ b/src/net/network.h
@@ -0,0 +1,103 @@
+/*
+ * The Mana World
+ * Copyright 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * The Mana World 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id: network.h 2187 2006-02-24 20:15:19Z der_doener $
+ */
+
+#ifndef _TMW_NETWORK_
+#define _TMW_NETWORK_
+
+#include <map>
+#include <SDL_net.h>
+#include <SDL_thread.h>
+#include <string>
+
+class MessageHandler;
+class MessageIn;
+
+class Network;
+
+class Network
+{
+ public:
+ friend int networkThread(void *data);
+ friend class MessageOut;
+
+ Network();
+ ~Network();
+
+ bool connect(const std::string &address, short port);
+ void disconnect();
+
+ void registerHandler(MessageHandler *handler);
+ void unregisterHandler(MessageHandler *handler);
+ void clearHandlers();
+
+ int getState() const { return mState; }
+ bool isConnected() const { return mState == CONNECTED; }
+
+ int getInSize() const { return mInSize; }
+
+ void skip(int len);
+
+ bool messageReady();
+ MessageIn getNextMessage();
+
+ void dispatchMessages();
+ void flush();
+
+ enum {
+ IDLE,
+ CONNECTED,
+ CONNECTING,
+ DATA,
+ ERROR_BROKE
+ };
+
+ protected:
+ Uint16 readWord(int pos);
+
+ TCPsocket mSocket;
+
+ std::string mAddress;
+ short mPort;
+
+ char *mInBuffer, *mOutBuffer;
+ unsigned int mInSize, mOutSize;
+
+ unsigned int mToSkip;
+
+ int mState;
+
+ SDL_Thread *mWorkerThread;
+ SDL_mutex *mMutex;
+
+ typedef std::map<Uint16, MessageHandler*> MessageHandlers;
+ typedef MessageHandlers::iterator MessageHandlerIterator;
+ MessageHandlers mMessageHandlers;
+
+ bool realConnect();
+ void receive();
+};
+
+/** Convert an address from int format to string */
+char *iptostring(int address);
+
+#endif
diff --git a/src/net/packet.cpp b/src/net/packet.cpp
new file mode 100644
index 0000000..53fb3ff
--- /dev/null
+++ b/src/net/packet.cpp
@@ -0,0 +1,40 @@
+/*
+ * The Mana World
+ * Copyright 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * The Mana World 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id: packet.cpp 1846 2005-10-09 03:34:45Z b_lindeijer $
+ */
+
+#include "packet.h"
+
+#include <cstring>
+
+Packet::Packet(const char *data, int length):
+ mLength(length)
+{
+ // Create a copy of the data
+ mData = new char[mLength];
+ memcpy(mData, data, mLength);
+}
+
+Packet::~Packet()
+{
+ // Clean up the data
+ delete[] mData;
+}
diff --git a/src/net/packet.h b/src/net/packet.h
new file mode 100644
index 0000000..5f4e8a2
--- /dev/null
+++ b/src/net/packet.h
@@ -0,0 +1,47 @@
+/*
+ * The Mana World
+ * Copyright 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * The Mana World 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id: packet.h 1846 2005-10-09 03:34:45Z b_lindeijer $
+ */
+
+#ifndef _TMW_PACKET_
+#define _TMW_PACKET_
+
+/**
+ * A packet wraps a certain amount of bytes for sending and receiving.
+ */
+class Packet
+{
+ public:
+ /**
+ * Constructor.
+ */
+ Packet(const char *data, int length);
+
+ /**
+ * Destructor.
+ */
+ ~Packet();
+
+ char *mData; /**< Packet data */
+ unsigned int mLength; /**< Length of data in bytes */
+};
+
+#endif
diff --git a/src/net/protocol.cpp b/src/net/protocol.cpp
new file mode 100644
index 0000000..791b7fe
--- /dev/null
+++ b/src/net/protocol.cpp
@@ -0,0 +1,79 @@
+/*
+ * The Mana World
+ * Copyright 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * The Mana World 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id: protocol.cpp 2158 2006-02-07 10:37:54Z der_doener $
+ */
+
+#include "protocol.h"
+
+#define LOBYTE(w) ((unsigned char)(w))
+#define HIBYTE(w) ((unsigned char)(((unsigned short)(w)) >> 8))
+
+void set_coordinates(char *data,
+ unsigned short x,
+ unsigned short y,
+ unsigned char direction)
+{
+ short temp;
+ temp = x;
+ temp <<= 6;
+ data[0] = 0;
+ data[1] = 1;
+ data[2] = 2;
+ data[0] = HIBYTE(temp);
+ data[1] = (unsigned char)(temp);
+ temp = y;
+ temp <<= 4;
+ data[1] |= HIBYTE(temp);
+ data[2] = LOBYTE(temp);
+
+ // Translate direction to eAthena format
+ switch (direction)
+ {
+ case 1:
+ direction = 0;
+ break;
+ case 3:
+ direction = 1;
+ break;
+ case 2:
+ direction = 2;
+ break;
+ case 6:
+ direction = 3;
+ break;
+ case 4:
+ direction = 4;
+ break;
+ case 12:
+ direction = 5;
+ break;
+ case 8:
+ direction = 6;
+ break;
+ case 9:
+ direction = 7;
+ break;
+ default:
+ // OOPSIE! Impossible or unknown
+ direction = (unsigned char)-1;
+ }
+ data[2] |= direction;
+}
diff --git a/src/net/protocol.h b/src/net/protocol.h
new file mode 100644
index 0000000..06b3df3
--- /dev/null
+++ b/src/net/protocol.h
@@ -0,0 +1,118 @@
+/*
+ * The Mana World
+ * Copyright 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * The Mana World 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id: protocol.h 2135 2006-02-03 13:53:50Z der_doener $
+ */
+
+#ifndef _TMW_PROTOCOL_
+#define _TMW_PROTOCOL_
+
+// Packets from server to client
+#define SMSG_SERVER_PING 0x007f /**< Contains server tick */
+#define SMSG_LOGIN_SUCCESS 0x0073 /**< Contains starting location */
+#define SMSG_QUEST_PLAYER_VARS 0x0215 /**< Quest Log info (ignored) */
+#define SMSG_PLAYER_UPDATE_1 0x01d8
+#define SMSG_PLAYER_UPDATE_2 0x01d9
+#define SMSG_PLAYER_MOVE 0x01da /**< A nearby player moves */
+#define SMSG_PLAYER_STAT_UPDATE_1 0x00b0
+#define SMSG_PLAYER_STAT_UPDATE_2 0x00b1
+#define SMSG_PLAYER_STAT_UPDATE_3 0x0141
+#define SMSG_PLAYER_STAT_UPDATE_4 0x00bc
+#define SMSG_PLAYER_STAT_UPDATE_5 0x00bd
+#define SMSG_PLAYER_STAT_UPDATE_6 0x00be
+#define SMSG_WHO_ANSWER 0x00c2
+#define SMSG_PLAYER_WARP 0x0091 /**< Warp player to map/location */
+#define SMSG_PLAYER_INVENTORY 0x01ee
+#define SMSG_PLAYER_INVENTORY_ADD 0x00a0
+#define SMSG_PLAYER_INVENTORY_REMOVE 0x00af
+#define SMSG_PLAYER_INVENTORY_USE 0x01c8
+#define SMSG_PLAYER_EQUIPMENT 0x00a4
+#define SMSG_PLAYER_EQUIP 0x00aa
+#define SMSG_PLAYER_UNEQUIP 0x00ac
+#define SMSG_PLAYER_ARROW_EQUIP 0x013c
+#define SMSG_PLAYER_ARROW_MESSAGE 0x013b
+#define SMSG_PLAYER_SKILLS 0x010f
+#define SMSG_SKILL_FAILED 0x0110
+#define SMSG_ITEM_USE_RESPONSE 0x00a8
+#define SMSG_ITEM_VISIBLE 0x009d /**< An item is on the floor */
+#define SMSG_ITEM_DROPPED 0x009e /**< An item is dropped */
+#define SMSG_ITEM_REMOVE 0x00a1 /**< An item disappers */
+#define SMSG_BEING_VISIBLE 0x0078
+#define SMSG_BEING_MOVE 0x007b /**< A nearby monster moves */
+#define SMSG_BEING_REMOVE 0x0080
+#define SMSG_BEING_CHANGE_LOOKS 0x00c3
+#define SMSG_BEING_LEVELUP 0x019b
+#define SMSG_BEING_EMOTION 0x00c0
+#define SMSG_BEING_ACTION 0x008a /**< Attack, sit, stand up, ... */
+#define SMSG_BEING_CHAT 0x008d /**< A being talks */
+#define SMSG_BEING_NAME_RESPONSE 0x0095 /**< Has to be requested */
+#define SMSG_NPC_MESSAGE 0x00b4
+#define SMSG_NPC_NEXT 0x00b5
+#define SMSG_NPC_CLOSE 0x00b6
+#define SMSG_NPC_CHOICE 0x00b7 /**< Display a choice */
+#define SMSG_NPC_BUY_SELL_CHOICE 0x00c4
+#define SMSG_NPC_BUY 0x00c6
+#define SMSG_NPC_SELL 0x00c7
+#define SMSG_NPC_BUY_RESPONSE 0x00ca
+#define SMSG_NPC_SELL_RESPONSE 0x00cb
+#define SMSG_PLAYER_CHAT 0x008e /**< Player talks */
+#define SMSG_WHISPER 0x0097 /**< Whisper Recieved */
+#define SMSG_WHISPER_RESPONSE 0x0098
+#define SMSG_GM_CHAT 0x009a /**< GM announce */
+#define SMSG_WALK_RESPONSE 0x0087
+#define SMSG_TRADE_REQUEST 0x00e5 /**< Receiving a request to trade */
+#define SMSG_TRADE_RESPONSE 0x00e7
+#define SMSG_TRADE_ITEM_ADD 0x00e9
+#define SMSG_TRADE_ITEM_ADD_RESPONSE 0x01b1 /**< Not standard eAthena! */
+#define SMSG_TRADE_OK 0x00ec
+#define SMSG_TRADE_CANCEL 0x00ee
+#define SMSG_TRADE_COMPLETE 0x00f0
+
+// Packets from client to server
+#define CMSG_CLIENT_PING 0x007e
+#define CMSG_TRADE_RESPONSE 0x00e6
+#define CMSG_ITEM_PICKUP 0x009f
+#define CMSG_MAP_LOADED 0x007d
+#define CMSG_NPC_BUY_REQUEST 0x00c8
+#define CMSG_NPC_BUY_SELL_REQUEST 0x00c5
+#define CMSG_CHAT_MESSAGE 0x008c
+#define CMSG_CHAT_WHISPER 0x0096
+#define CMSG_NPC_LIST_CHOICE 0x00b8
+#define CMSG_NPC_NEXT_REQUEST 0x00b9
+#define CMSG_NPC_SELL_REQUEST 0x00c9
+#define CMSG_SKILL_LEVELUP_REQUEST 0x0112
+#define CMSG_STAT_UPDATE_REQUEST 0x00bb
+#define CMSG_TRADE_ITEM_ADD_REQUEST 0x00e8
+#define CMSG_TRADE_CANCEL_REQUEST 0x00ed
+#define CMSG_TRADE_ADD_COMPLETE 0x00eb
+#define CMSG_TRADE_OK 0x00ef
+#define CMSG_NPC_TALK 0x0090
+#define CMSG_TRADE_REQUEST 0x00e4
+#define CMSG_PLAYER_INVENTORY_USE 0x00a7
+#define CMSG_PLAYER_INVENTORY_DROP 0x00a2
+#define CMSG_PLAYER_EQUIP 0x00a9
+#define CMSG_PLAYER_UNEQUIP 0x00ab
+#define CMSG_PLAYER_CHANGE_ACT 0x0089
+
+
+/** Encodes coords and direction in 3 bytes data */
+void set_coordinates(char *data, unsigned short x, unsigned short y, unsigned char direction);
+
+#endif
diff --git a/src/onlinelist.cpp b/src/onlinelist.cpp
new file mode 100644
index 0000000..1c326af
--- /dev/null
+++ b/src/onlinelist.cpp
@@ -0,0 +1,145 @@
+/*
+ * 4144's whoisonline code.
+ *
+ */
+
+#include "onlinelist.h"
+
+#include <iostream>
+#include <fstream>
+#include <SDL.h>
+#include <SDL_thread.h>
+#include <vector>
+#include <algorithm>
+
+#include "automation.h"
+#include "game.h"
+#include "main.h"
+#include "utils/stringutils.h"
+
+OnlineList::OnlineList():
+ mThread(NULL),
+ mDownloadStatus(UPDATE_LIST),
+ mDownloadComplete(true),
+ mAllowUpdate(true),
+ mOnlinePlayers()
+{
+ download();
+}
+
+OnlineList::~OnlineList()
+{
+ if (mThread && SDL_GetThreadID(mThread))
+ SDL_WaitThread(mThread, NULL);
+}
+
+
+int OnlineList::downloadThread(void *ptr)
+{
+ OnlineList *wio = reinterpret_cast<OnlineList *>(ptr);
+
+ std::string namelist = "online.txt";
+ std::ifstream listFile (namelist.c_str(), std::ifstream::in);
+
+ if (!wio->mAllowUpdate)
+ {
+ return 0;
+ }
+
+ if (listFile.is_open())
+ {
+ wio->mOnlinePlayers.clear();
+ const std::string gmText = "(GM)";
+ bool listStarted(false);
+
+ while (!listFile.eof())
+ {
+ std::string line;
+ getline(listFile, line);
+ if (!line.empty())
+ {
+ std::string lineStr = line;
+ utils_trim(lineStr);
+ std::string::size_type pos = lineStr.find(gmText, 0);
+ if (pos != std::string::npos && pos == lineStr.length() - gmText.length())
+ {
+ lineStr = lineStr.substr(0, pos-1);
+ utils_trim(lineStr);
+
+ }
+
+ if (listStarted == true)
+ {
+ size_t found = lineStr.find(" users are online."); //Dodgy hack!
+ if (found == std::string::npos)
+ wio->mOnlinePlayers.insert(lineStr);
+ }
+ else if (lineStr == "------------------------------")
+ listStarted = true;
+ }
+ }
+ listFile.close();
+ }
+ else
+ {
+ wio->mDownloadStatus = UPDATE_ERROR;
+ return 0;
+ }
+
+ wio->mDownloadComplete = true;
+ return 0;
+}
+
+void OnlineList::download()
+{
+ mDownloadComplete = true;
+ if (mThread && SDL_GetThreadID(mThread))
+ SDL_WaitThread(mThread, NULL);
+
+ mDownloadComplete = false;
+ mThread = SDL_CreateThread(OnlineList::downloadThread, this);
+
+ if (mThread == NULL)
+ mDownloadStatus = UPDATE_ERROR;
+}
+
+void OnlineList::logic()
+{
+
+ if (!mAllowUpdate)
+ return;
+
+ if (mUpdateTimer == 0)
+ mUpdateTimer = cur_time;
+
+ double timeDiff = difftime(cur_time, mUpdateTimer);
+ int timeLimit = 2; // Downloads the online list every 20 seconds.
+
+ if (timeDiff >= timeLimit && mDownloadStatus != UPDATE_LIST)
+ {
+ mUpdateTimer = 0;
+ mDownloadStatus = UPDATE_LIST;
+ download();
+ }
+
+ switch (mDownloadStatus)
+ {
+ case UPDATE_ERROR:
+ mDownloadStatus = UPDATE_COMPLETE;
+ break;
+ case UPDATE_LIST:
+ if (mDownloadComplete == true)
+ {
+ mDownloadStatus = UPDATE_COMPLETE;
+ mUpdateTimer = 0;
+
+ if (mOnlinePlayers.size() > 0)
+ Automation::getAutomationHandler()->updateOnline(mOnlinePlayers);
+
+ }
+ break;
+ default:
+ break;
+ }
+}
+
diff --git a/src/onlinelist.h b/src/onlinelist.h
new file mode 100644
index 0000000..4c4b5f3
--- /dev/null
+++ b/src/onlinelist.h
@@ -0,0 +1,86 @@
+/*
+ * File: onlinelist.h
+ * Author: dipesh
+ *
+ * Created on August 2, 2010, 1:12 AM
+ */
+
+#ifndef _ONLINELIST_H
+#define _ONLINELIST_H
+
+
+#include <string>
+#include <set>
+
+#include "utils/mutex.h"
+
+struct SDL_Thread;
+
+/**
+ * Update progress window GUI
+ *
+ * \ingroup GUI
+ */
+class OnlineList
+{
+ public:
+ /**
+ * Constructor.
+ */
+ OnlineList();
+
+ /**
+ * Destructor
+ */
+ ~OnlineList();
+
+ void logic();
+
+ std::set<std::string> &getOnlinePlayers()
+ { return mOnlinePlayers; }
+
+ void setAllowUpdate(bool n)
+ { mAllowUpdate = n; }
+
+private:
+ void download();
+
+ /**
+ * The thread function that download the files.
+ */
+ static int downloadThread(void *ptr);
+
+ enum DownloadStatus
+ {
+ UPDATE_ERROR = 0,
+ UPDATE_COMPLETE,
+ UPDATE_LIST
+ };
+
+ /** A thread that use libcurl to download updates. */
+ SDL_Thread *mThread;
+
+ /** Status of the current download. */
+ DownloadStatus mDownloadStatus;
+
+ /** Flag that show if current download is complete. */
+ bool mDownloadComplete;
+
+ /** Byte count currently downloaded in mMemoryBuffer. */
+ int mDownloadedBytes;
+
+ /** Buffer for files downloaded to memory. */
+ char *mMemoryBuffer;
+
+ /** Buffer to handler human readable error provided by curl. */
+ char *mCurlError;
+
+ time_t mUpdateTimer;
+ std::set<std::string> mOnlinePlayers;
+
+ bool mAllowUpdate;
+};
+
+#endif /* _ONLINELIST_H */
+
+
diff --git a/src/serverinfo.h b/src/serverinfo.h
new file mode 100644
index 0000000..e79bdf2
--- /dev/null
+++ b/src/serverinfo.h
@@ -0,0 +1,37 @@
+/*
+ * The Mana World
+ * Copyright 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * The Mana World 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id: serverinfo.h 1735 2005-09-13 22:56:29Z der_doener $
+ */
+
+#ifndef _TMW_SERVERINFO_
+#define _TMW_SERVERINFO_
+
+#include <string>
+
+struct SERVER_INFO
+{
+ int address;
+ short port;
+ std::string name;
+ short online_users;
+};
+
+#endif
diff --git a/src/utils/mutex.h b/src/utils/mutex.h
new file mode 100644
index 0000000..80569e2
--- /dev/null
+++ b/src/utils/mutex.h
@@ -0,0 +1,91 @@
+/*
+ * The Mana Client
+ * Copyright (C) 2008-2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 The Mana Developers
+ *
+ * This file is part of The Mana Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MUTEX_H
+#define MUTEX_H
+
+#include <SDL_thread.h>
+
+/**
+ * A mutex provides mutual exclusion of access to certain data that is
+ * accessed by multiple threads.
+ */
+class Mutex
+{
+public:
+ Mutex();
+ ~Mutex();
+
+ void lock();
+ void unlock();
+
+private:
+ Mutex(const Mutex&); // prevent copying
+ Mutex& operator=(const Mutex&);
+
+ SDL_mutex *mMutex;
+};
+
+/**
+ * A convenience class for locking a mutex.
+ */
+class MutexLocker
+{
+public:
+ MutexLocker(Mutex *mutex);
+ ~MutexLocker();
+
+private:
+ Mutex *mMutex;
+};
+
+
+inline Mutex::Mutex()
+{
+ mMutex = SDL_CreateMutex();
+}
+
+inline Mutex::~Mutex()
+{
+ SDL_DestroyMutex(mMutex);
+}
+
+inline void Mutex::lock()
+{
+}
+
+inline void Mutex::unlock()
+{
+}
+
+
+inline MutexLocker::MutexLocker(Mutex *mutex):
+ mMutex(mutex)
+{
+ mMutex->lock();
+}
+
+inline MutexLocker::~MutexLocker()
+{
+ mMutex->unlock();
+}
+
+#endif // MUTEX_H
diff --git a/src/utils/specialfolder.cpp b/src/utils/specialfolder.cpp
new file mode 100644
index 0000000..6460771
--- /dev/null
+++ b/src/utils/specialfolder.cpp
@@ -0,0 +1,78 @@
+/*
+ * The Mana Client
+ * Copyright (C) 2010 The Mana Developers
+ *
+ * This file is part of The Mana Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef WIN32
+#include "specialfolder.h"
+#include <windows.h>
+
+#ifdef _SPECIALFOLDERLOCATION_TEST_
+// compile with -D_SPECIALFOLDERLOCATION_TEST_ to get a standalone
+// binary for testing
+#include <iostream>
+#endif
+
+/*
+ * Retrieve the pathname of special folders on win32, or an empty string
+ * on error / if the folder does not exist.
+ * See http://msdn.microsoft.com/en-us/library/bb762494(VS.85).aspx for
+ * a list of folder ids
+ */
+std::string getSpecialFolderLocation(int folderId)
+{
+ std::string ret;
+ LPITEMIDLIST pItemIdList;
+ LPMALLOC pMalloc;
+ char szPath[_MAX_PATH];
+
+ // get the item ID list for folderId
+ HRESULT hr = SHGetSpecialFolderLocation(NULL, folderId, &pItemIdList);
+ if (hr != S_OK)
+ return ret;
+
+ // convert the ID list into a file system path
+ if (SHGetPathFromIDList(pItemIdList, szPath) == FALSE)
+ return ret;
+
+ // get the IMalloc pointer and free all resources we used
+ hr = SHGetMalloc(&pMalloc);
+ pMalloc->Free(pItemIdList);
+ pMalloc->Release();
+
+ ret = szPath;
+ return ret;
+}
+
+#ifdef _SPECIALFOLDERLOCATION_TEST_
+int main()
+{
+ std::cout << "APPDATA " << getSpecialFolderLocation(CSIDL_APPDATA)
+ << std::endl;
+ std::cout << "DESKTOP " << getSpecialFolderLocation(CSIDL_DESKTOP)
+ << std::endl;
+ std::cout << "LOCAL_APPDATA "
+ << getSpecialFolderLocation(CSIDL_LOCAL_APPDATA)
+ << std::endl;
+ std::cout << "MYPICTURES " << getSpecialFolderLocation(CSIDL_MYPICTURES)
+ << std::endl;
+ std::cout << "PERSONAL " << getSpecialFolderLocation(CSIDL_PERSONAL)
+ << std::endl;
+}
+#endif
+#endif
diff --git a/src/utils/specialfolder.h b/src/utils/specialfolder.h
new file mode 100644
index 0000000..c2c2e0b
--- /dev/null
+++ b/src/utils/specialfolder.h
@@ -0,0 +1,30 @@
+/*
+ * The Mana Client
+ * Copyright (C) 2010 The Mana Developers
+ *
+ * This file is part of The Mana Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _SPECIALFOLDER_H
+#define _SPECIALFOLDER_H
+
+#ifdef WIN32
+#include <shlobj.h>
+#include <string>
+std::string getSpecialFolderLocation(int folderId);
+#endif
+
+#endif
diff --git a/src/utils/stringutils.cpp b/src/utils/stringutils.cpp
new file mode 100644
index 0000000..c7f83c3
--- /dev/null
+++ b/src/utils/stringutils.cpp
@@ -0,0 +1,177 @@
+/*
+ * The Mana Client
+ * Copyright (C) 2007-2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 The Mana Developers
+ *
+ * This file is part of The Mana Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "stringutils.h"
+
+#include <string.h>
+#include <algorithm>
+#include <cstdarg>
+#include <cstdio>
+
+const int UTF8_MAX_SIZE = 10;
+
+std::string &utils_trim(std::string &str)
+{
+ std::string::size_type pos = str.find_last_not_of(' ');
+ if (pos != std::string::npos)
+ {
+ str.erase(pos + 1);
+ pos = str.find_first_not_of(' ');
+
+ if (pos != std::string::npos)
+ str.erase(0, pos);
+ }
+ else
+ {
+ // There is nothing else but whitespace in the string
+ str.clear();
+ }
+ return str;
+}
+
+std::string &toLower(std::string &str)
+{
+ std::transform(str.begin(), str.end(), str.begin(), tolower);
+ return str;
+}
+
+std::string &toUpper(std::string &str)
+{
+ std::transform(str.begin(), str.end(), str.begin(), toupper);
+ return str;
+}
+
+unsigned int atox(const std::string &str)
+{
+ unsigned int value;
+ sscanf(str.c_str(), "0x%06x", &value);
+
+ return value;
+}
+
+const char *ipToString(int address)
+{
+ static char asciiIP[16];
+
+ sprintf(asciiIP, "%i.%i.%i.%i",
+ (unsigned char)(address),
+ (unsigned char)(address >> 8),
+ (unsigned char)(address >> 16),
+ (unsigned char)(address >> 24));
+
+ return asciiIP;
+}
+
+std::string strprintf(char const *format, ...)
+{
+ char buf[256];
+ va_list(args);
+ va_start(args, format);
+ int nb = vsnprintf(buf, 256, format, args);
+ va_end(args);
+ if (nb < 256)
+ {
+ return buf;
+ }
+ // The static size was not big enough, try again with a dynamic allocation.
+ ++nb;
+ char *buf2 = new char[nb];
+ va_start(args, format);
+ vsnprintf(buf2, nb, format, args);
+ va_end(args);
+ std::string res(buf2);
+ delete [] buf2;
+ return res;
+}
+
+std::string &removeBadChars(std::string &str)
+{
+ std::string::size_type pos;
+ do
+ {
+ pos = str.find_first_of("@#[]");
+ if (pos != std::string::npos)
+ str.erase(pos, 1);
+ } while (pos != std::string::npos);
+
+ return str;
+}
+
+std::string removeColors(std::string msg)
+{
+ for (unsigned int f = 0; f < msg.length() - 2 && msg.length() > 2; f++)
+ {
+ while (msg.length() > f + 2 && msg.at(f) == '#' && msg.at(f + 1) == '#')
+ {
+ msg = msg.erase(f, 3);
+ }
+ }
+ return msg;
+}
+
+int compareStrI(const std::string &a, const std::string &b)
+{
+ std::string::const_iterator itA = a.begin();
+ std::string::const_iterator endA = a.end();
+ std::string::const_iterator itB = b.begin();
+ std::string::const_iterator endB = b.end();
+
+ for (; itA < endA, itB < endB; ++itA, ++itB)
+ {
+ int comp = tolower(*itA) - tolower(*itB);
+ if (comp)
+ return comp;
+ }
+
+ // Check string lengths
+ if (itA == endA && itB == endB)
+ return 0;
+ else if (itA == endA)
+ return -1;
+ else
+ return 1;
+}
+
+bool isWordSeparator(char chr)
+{
+ return (chr == ' ' || chr == ',' || chr == '.' || chr == '"');
+}
+
+const std::string findSameSubstring(const std::string &str1, const std::string &str2)
+{
+ int minLength = str1.length() > str2.length() ? str2.length() : str1.length();
+ for (int f = 0; f < minLength; f ++)
+ {
+ if (str1.at(f) != str2.at(f))
+ {
+ return str1.substr(0, f);
+ }
+ }
+ return str1.substr(0, minLength);
+}
+
+const char* getSafeUtf8String(std::string text)
+{
+ char* buf = new char[text.size() + UTF8_MAX_SIZE];
+ memcpy(buf, text.c_str(), text.size());
+ memset(buf + text.size(), 0, UTF8_MAX_SIZE);
+ return buf;
+}
diff --git a/src/utils/stringutils.h b/src/utils/stringutils.h
new file mode 100644
index 0000000..5f79f5b
--- /dev/null
+++ b/src/utils/stringutils.h
@@ -0,0 +1,142 @@
+/*
+ * The Mana Client
+ * Copyright (C) 2007-2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 The Mana Developers
+ *
+ * This file is part of The Mana Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef UTILS_STRINGUTILS_H
+#define UTILS_STRINGUTILS_H
+
+#include <string>
+#include <sstream>
+
+/**
+ * Trims spaces off the end and the beginning of the given string.
+ *
+ * @param str the string to trim spaces off
+ * @return a reference to the trimmed string
+ */
+std::string &utils_trim(std::string &str);
+
+/**
+ * Converts the given string to lower case.
+ *
+ * @param str the string to convert to lower case
+ * @return a reference to the given string converted to lower case
+ */
+std::string &toLower(std::string &str);
+
+/**
+ * Converts the given string to upper case.
+ *
+ * @param str the string to convert to upper case
+ * @return a reference to the given string converted to upper case
+ */
+std::string &toUpper(std::string &str);
+
+
+/**
+ * Converts an ascii hexidecimal string to an integer
+ *
+ * @param str the hex string to convert to an int
+ * @return the integer representation of the hex string
+ */
+unsigned int atox(const std::string &str);
+
+/**
+ * Converts the given value to a string using std::stringstream.
+ *
+ * @param arg the value to convert to a string
+ * @return the string representation of arg
+ */
+template<typename T> std::string toString(const T &arg)
+{
+ std::stringstream ss;
+ ss << arg;
+ return ss.str();
+}
+/**
+ * Converts the given value to a int using std::stringstream.
+ *
+ * @param arg the value to convert to a int
+ * @return the int representation of arg
+ */
+
+template<typename T> int toInt(const T &arg)
+{
+ std::stringstream ss(arg);
+ int out;
+ ss >> out;
+ return out;
+}
+
+/**
+ * Converts the given IP address to a string.
+ *
+ * The returned string is statically allocated, and shouldn't be freed. It is
+ * changed upon the next use of this method.
+ *
+ * @param address the address to convert to a string
+ * @return the string representation of the address
+ */
+const char *ipToString(int address);
+
+/**
+ * A safe version of sprintf that returns a std::string of the result.
+ */
+std::string strprintf(char const *, ...)
+#ifdef __GNUC__
+ /* This attribute is nice: it even works through gettext invokation. For
+ example, gcc will complain that strprintf(_("%s"), 42) is ill-formed. */
+ __attribute__((__format__(__printf__, 1, 2)))
+#endif
+;
+
+/**
+ * Removes bad characters from a string
+ *
+ * @param str the string to remove the bad chars from
+ * @return a reference to the string without bad chars
+ */
+std::string &removeBadChars(std::string &str);
+
+/**
+ * Removes colors from a string
+ *
+ * @param msg the string to remove the colors from
+ * @return string without colors
+ */
+std::string removeColors(std::string msg);
+
+/**
+ * Compares the two strings case-insensitively.
+ *
+ * @param a the first string in the comparison
+ * @param b the second string in the comparison
+ * @return 0 if the strings are equal, positive if the first is greater,
+ * negative if the second is greater
+ */
+int compareStrI(const std::string &a, const std::string &b);
+
+bool isWordSeparator(char chr);
+
+const std::string findSameSubstring(const std::string &str1, const std::string &str2);
+
+const char* getSafeUtf8String(std::string text);
+
+#endif // UTILS_STRINGUTILS_H