summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt98
-rw-r--r--src/Makefile.am39
-rw-r--r--src/animatedsprite.cpp6
-rw-r--r--src/animatedsprite.h1
-rw-r--r--src/being.cpp218
-rw-r--r--src/being.h49
-rw-r--r--src/beingmanager.cpp30
-rw-r--r--src/beingmanager.h8
-rw-r--r--src/configuration.cpp11
-rw-r--r--src/engine.cpp81
-rw-r--r--src/engine.h4
-rw-r--r--src/game.cpp60
-rw-r--r--src/game.h5
-rw-r--r--src/gui/browserbox.h1
-rw-r--r--src/gui/buddywindow.cpp2
-rw-r--r--src/gui/buy.cpp57
-rw-r--r--src/gui/buy.h7
-rw-r--r--src/gui/buysell.cpp2
-rw-r--r--src/gui/char_select.cpp88
-rw-r--r--src/gui/char_select.h12
-rw-r--r--src/gui/char_server.cpp125
-rw-r--r--src/gui/char_server.h68
-rw-r--r--src/gui/chat.cpp28
-rw-r--r--src/gui/chat.h4
-rw-r--r--src/gui/confirm_dialog.cpp2
-rw-r--r--src/gui/connection.cpp17
-rw-r--r--src/gui/connection.h2
-rw-r--r--src/gui/debugwindow.cpp2
-rw-r--r--src/gui/gui.cpp14
-rw-r--r--src/gui/help.cpp2
-rw-r--r--src/gui/inventorywindow.cpp2
-rw-r--r--src/gui/item_amount.cpp2
-rw-r--r--src/gui/login.cpp36
-rw-r--r--src/gui/login.h1
-rw-r--r--src/gui/menuwindow.cpp4
-rw-r--r--src/gui/newskill.cpp2
-rw-r--r--src/gui/npc_text.cpp2
-rw-r--r--src/gui/npclistdialog.cpp2
-rw-r--r--src/gui/ok_dialog.cpp2
-rw-r--r--src/gui/playerbox.cpp6
-rw-r--r--src/gui/playerbox.h8
-rw-r--r--src/gui/register.cpp59
-rw-r--r--src/gui/register.h5
-rw-r--r--src/gui/selectionlistener.h2
-rw-r--r--src/gui/sell.cpp76
-rw-r--r--src/gui/sell.h14
-rw-r--r--src/gui/serverdialog.cpp246
-rw-r--r--src/gui/serverdialog.h153
-rw-r--r--src/gui/setup.cpp2
-rw-r--r--src/gui/setup_audio.cpp2
-rw-r--r--src/gui/setup_video.cpp1
-rw-r--r--src/gui/setup_video.h2
-rw-r--r--src/gui/shop.cpp44
-rw-r--r--src/gui/shop.h37
-rw-r--r--src/gui/shoplistbox.cpp200
-rw-r--r--src/gui/shoplistbox.h124
-rw-r--r--src/gui/skill.cpp2
-rw-r--r--src/gui/status.cpp26
-rw-r--r--src/gui/status.h2
-rw-r--r--src/gui/trade.cpp47
-rw-r--r--src/gui/trade.h5
-rw-r--r--src/gui/updatewindow.cpp28
-rw-r--r--src/gui/updatewindow.h5
-rw-r--r--src/gui/vbox.cpp2
-rw-r--r--src/gui/widgets/dropdown.cpp191
-rw-r--r--src/gui/widgets/dropdown.h85
-rw-r--r--src/gui/window.cpp14
-rw-r--r--src/localplayer.cpp200
-rw-r--r--src/localplayer.h10
-rw-r--r--src/log.cpp9
-rw-r--r--src/log.h11
-rw-r--r--src/logindata.h2
-rw-r--r--src/main.cpp540
-rw-r--r--src/main.h44
-rw-r--r--src/map.cpp38
-rw-r--r--src/monster.cpp18
-rw-r--r--src/monster.h4
-rw-r--r--src/net/accountserver/account.cpp116
-rw-r--r--src/net/accountserver/account.h60
-rw-r--r--src/net/accountserver/accountserver.cpp68
-rw-r--r--src/net/accountserver/accountserver.h46
-rw-r--r--src/net/accountserver/internal.cpp34
-rw-r--r--src/net/accountserver/internal.h (renamed from src/net/maploginhandler.h)18
-rw-r--r--src/net/beinghandler.cpp352
-rw-r--r--src/net/beinghandler.h7
-rw-r--r--src/net/buysellhandler.cpp35
-rw-r--r--src/net/buysellhandler.h2
-rw-r--r--src/net/charserverhandler.cpp273
-rw-r--r--src/net/charserverhandler.h21
-rw-r--r--src/net/chathandler.cpp41
-rw-r--r--src/net/chathandler.h2
-rw-r--r--src/net/chatserver/chatserver.cpp116
-rw-r--r--src/net/chatserver/chatserver.h55
-rw-r--r--src/net/chatserver/internal.cpp34
-rw-r--r--src/net/chatserver/internal.h (renamed from src/net/packet.cpp)23
-rw-r--r--src/net/connection.cpp104
-rw-r--r--src/net/connection.h78
-rw-r--r--src/net/equipmenthandler.cpp47
-rw-r--r--src/net/equipmenthandler.h2
-rw-r--r--src/net/gameserver/gameserver.cpp42
-rw-r--r--src/net/gameserver/gameserver.h (renamed from src/net/packet.h)30
-rw-r--r--src/net/gameserver/internal.cpp34
-rw-r--r--src/net/gameserver/internal.h37
-rw-r--r--src/net/gameserver/player.cpp68
-rw-r--r--src/net/gameserver/player.h46
-rw-r--r--src/net/internal.cpp29
-rw-r--r--src/net/internal.h32
-rw-r--r--src/net/inventoryhandler.cpp61
-rw-r--r--src/net/inventoryhandler.h2
-rw-r--r--src/net/itemhandler.cpp17
-rw-r--r--src/net/itemhandler.h2
-rw-r--r--src/net/loginhandler.cpp131
-rw-r--r--src/net/loginhandler.h9
-rw-r--r--src/net/maploginhandler.cpp63
-rw-r--r--src/net/messagehandler.cpp14
-rw-r--r--src/net/messagehandler.h9
-rw-r--r--src/net/messagein.cpp174
-rw-r--r--src/net/messagein.h65
-rw-r--r--src/net/messageout.cpp103
-rw-r--r--src/net/messageout.h45
-rw-r--r--src/net/network.cpp447
-rw-r--r--src/net/network.h114
-rw-r--r--src/net/npchandler.cpp18
-rw-r--r--src/net/npchandler.h2
-rw-r--r--src/net/playerhandler.cpp197
-rw-r--r--src/net/playerhandler.h7
-rw-r--r--src/net/protocol.cpp79
-rw-r--r--src/net/protocol.h144
-rw-r--r--src/net/skillhandler.cpp34
-rw-r--r--src/net/skillhandler.h2
-rw-r--r--src/net/tradehandler.cpp29
-rw-r--r--src/net/tradehandler.h4
-rw-r--r--src/npc.cpp55
-rw-r--r--src/npc.h7
-rw-r--r--src/openglgraphics.cpp2
-rw-r--r--src/player.cpp84
-rw-r--r--src/player.h11
-rw-r--r--src/resources/image.h2
-rw-r--r--src/resources/openglsdlimageloader.cpp6
-rw-r--r--src/resources/resourcemanager.cpp13
-rw-r--r--src/sound.cpp2
-rw-r--r--src/tmw.rc8
142 files changed, 4056 insertions, 3118 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 3e4550c7..6a46aba4 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,8 +1,7 @@
FIND_PACKAGE(SDL REQUIRED)
FIND_PACKAGE(SDL_image REQUIRED)
FIND_PACKAGE(SDL_mixer REQUIRED)
-FIND_PACKAGE(SDL_net REQUIRED)
-
+FIND_PACKAGE(ENet REQUIRED)
FIND_PACKAGE(Libcurl REQUIRED)
FIND_PACKAGE(LibXml2 REQUIRED)
FIND_PACKAGE(PhysFS REQUIRED)
@@ -28,7 +27,7 @@ INCLUDE_DIRECTORIES(
${SDL_INCLUDE_DIR}
${SDLIMAGE_INCLUDE_DIR}
${SDLMIXER_INCLUDE_DIR}
- ${SDLNET_INCLUDE_DIR}
+ ${ENET_INCLUDE_DIR}
${PNG_INCLUDE_DIR}
${PHYSFS_INCLUDE_DIR}
${LIBCURL_INCLUDE_DIR}
@@ -38,6 +37,8 @@ INCLUDE_DIRECTORIES(
SET(SRCS
graphic/imagerect.h
+ gui/box.cpp
+ gui/box.h
gui/browserbox.cpp
gui/browserbox.h
gui/buddywindow.cpp
@@ -50,8 +51,6 @@ SET(SRCS
gui/buysell.h
gui/chargedialog.cpp
gui/chargedialog.h
- gui/char_server.cpp
- gui/char_server.h
gui/char_select.cpp
gui/char_select.h
gui/chat.cpp
@@ -74,14 +73,18 @@ SET(SRCS
gui/gccontainer.h
gui/gui.cpp
gui/gui.h
+ gui/hbox.cpp
+ gui/hbox.h
gui/help.cpp
gui/help.h
+ gui/inttextbox.cpp
+ gui/inttextbox.h
gui/inventorywindow.cpp
gui/inventorywindow.h
- gui/itemcontainer.cpp
- gui/itemcontainer.h
gui/item_amount.cpp
gui/item_amount.h
+ gui/itemcontainer.cpp
+ gui/itemcontainer.h
gui/linkhandler.h
gui/listbox.cpp
gui/listbox.h
@@ -118,6 +121,8 @@ SET(SRCS
gui/selectionlistener.h
gui/sell.cpp
gui/sell.h
+ gui/serverdialog.cpp
+ gui/serverdialog.h
gui/setup_audio.cpp
gui/setup_audio.h
gui/setup.cpp
@@ -143,38 +148,36 @@ SET(SRCS
gui/textfield.h
gui/trade.cpp
gui/trade.h
- gui/window.cpp
- gui/window.h
+ gui/updatewindow.cpp
+ gui/updatewindow.h
+ gui/vbox.cpp
+ gui/vbox.h
gui/windowcontainer.cpp
gui/windowcontainer.h
- gui/inttextbox.h
- gui/inttextbox.cpp
- gui/box.h
- gui/box.cpp
- gui/vbox.h
- gui/vbox.cpp
- gui/hbox.h
- gui/hbox.cpp
- gui/updatewindow.h
- gui/updatewindow.cpp
- net/beinghandler.h
+ gui/window.cpp
+ gui/window.h
+ gui/widgets/dropdown.cpp
+ gui/widgets/dropdown.h
net/beinghandler.cpp
- net/buysellhandler.h
+ net/beinghandler.h
net/buysellhandler.cpp
- net/charserverhandler.h
+ net/buysellhandler.h
net/charserverhandler.cpp
- net/chathandler.h
+ net/charserverhandler.h
net/chathandler.cpp
- net/equipmenthandler.h
+ net/chathandler.h
+ net/connection.cpp
+ net/connection.h
net/equipmenthandler.cpp
- net/inventoryhandler.h
+ net/equipmenthandler.h
+ net/internal.cpp
+ net/internal.h
net/inventoryhandler.cpp
- net/itemhandler.h
+ net/inventoryhandler.h
net/itemhandler.cpp
- net/loginhandler.h
+ net/itemhandler.h
net/loginhandler.cpp
- net/maploginhandler.cpp
- net/maploginhandler.h
+ net/loginhandler.h
net/messagehandler.cpp
net/messagehandler.h
net/messagein.cpp
@@ -185,44 +188,57 @@ SET(SRCS
net/network.h
net/npchandler.cpp
net/npchandler.h
- net/packet.cpp
- net/packet.h
net/playerhandler.cpp
net/playerhandler.h
- net/protocol.cpp
net/protocol.h
net/skillhandler.cpp
net/skillhandler.h
net/tradehandler.cpp
net/tradehandler.h
+ net/accountserver/account.cpp
+ net/accountserver/account.h
+ net/accountserver/accountserver.cpp
+ net/accountserver/accountserver.h
+ net/accountserver/internal.cpp
+ net/accountserver/internal.h
+ net/chatserver/chatserver.cpp
+ net/chatserver/chatserver.h
+ net/chatserver/internal.cpp
+ net/chatserver/internal.h
+ net/gameserver/gameserver.cpp
+ net/gameserver/gameserver.h
+ net/gameserver/internal.cpp
+ net/gameserver/internal.h
+ net/gameserver/player.cpp
+ net/gameserver/player.h
resources/ambientoverlay.cpp
resources/ambientoverlay.h
+ resources/buddylist.cpp
+ resources/buddylist.h
resources/image.cpp
resources/image.h
resources/imagewriter.cpp
resources/imagewriter.h
- resources/iteminfo.h
resources/iteminfo.cpp
+ resources/iteminfo.h
resources/itemmanager.cpp
resources/itemmanager.h
resources/mapreader.cpp
resources/mapreader.h
- resources/music.h
resources/music.cpp
- resources/openglsdlimageloader.h
+ resources/music.h
resources/openglsdlimageloader.cpp
+ resources/openglsdlimageloader.h
resources/resource.cpp
resources/resource.h
resources/resourcemanager.cpp
resources/resourcemanager.h
- resources/sdlimageloader.h
resources/sdlimageloader.cpp
- resources/soundeffect.h
+ resources/sdlimageloader.h
resources/soundeffect.cpp
- resources/spriteset.h
+ resources/soundeffect.h
resources/spriteset.cpp
- resources/buddylist.h
- resources/buddylist.cpp
+ resources/spriteset.h
utils/dtor.h
utils/tostring.h
animatedsprite.cpp
@@ -289,7 +305,7 @@ TARGET_LINK_LIBRARIES(tmw
${SDL_LIBRARY}
${SDLIMAGE_LIBRARY}
${SDLMIXER_LIBRARY}
- ${SDLNET_LIBRARY}
+ ${ENET_LIBRARIES}
${PNG_LIBRARIES}
${PHYSFS_LIBRARY}
${LIBCURL_LIBRARIES}
diff --git a/src/Makefile.am b/src/Makefile.am
index 7d37edf8..8ab16e32 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,5 +1,9 @@
+AUTOMAKE_OPTIONS = subdir-objects
+
bin_PROGRAMS = tmw
tmw_SOURCES = graphic/imagerect.h \
+ gui/widgets/dropdown.cpp \
+ gui/widgets/dropdown.h \
gui/browserbox.cpp \
gui/browserbox.h \
gui/buddywindow.cpp \
@@ -12,8 +16,6 @@ tmw_SOURCES = graphic/imagerect.h \
gui/buysell.h \
gui/chargedialog.cpp \
gui/chargedialog.h \
- gui/char_server.cpp \
- gui/char_server.h \
gui/char_select.cpp \
gui/char_select.h \
gui/chat.cpp \
@@ -80,6 +82,8 @@ tmw_SOURCES = graphic/imagerect.h \
gui/selectionlistener.h \
gui/sell.cpp \
gui/sell.h \
+ gui/serverdialog.cpp \
+ gui/serverdialog.h \
gui/setup_audio.cpp \
gui/setup_audio.h \
gui/setup.cpp \
@@ -91,8 +95,6 @@ tmw_SOURCES = graphic/imagerect.h \
gui/setup_video.h \
gui/shop.cpp \
gui/shop.h \
- gui/shoplistbox.cpp \
- gui/shoplistbox.h \
gui/skill.cpp \
gui/skill.h \
gui/slider.cpp \
@@ -129,6 +131,8 @@ tmw_SOURCES = graphic/imagerect.h \
net/charserverhandler.cpp \
net/chathandler.h \
net/chathandler.cpp \
+ net/connection.h \
+ net/connection.cpp \
net/equipmenthandler.h \
net/equipmenthandler.cpp \
net/inventoryhandler.h \
@@ -137,8 +141,6 @@ tmw_SOURCES = graphic/imagerect.h \
net/itemhandler.cpp \
net/loginhandler.h \
net/loginhandler.cpp \
- net/maploginhandler.cpp \
- net/maploginhandler.h \
net/messagehandler.cpp \
net/messagehandler.h \
net/messagein.cpp \
@@ -149,16 +151,29 @@ tmw_SOURCES = graphic/imagerect.h \
net/network.h \
net/npchandler.cpp \
net/npchandler.h \
- net/packet.cpp \
- net/packet.h \
net/playerhandler.cpp \
net/playerhandler.h \
- net/protocol.cpp \
net/protocol.h \
net/skillhandler.cpp \
net/skillhandler.h \
net/tradehandler.cpp \
net/tradehandler.h \
+ net/accountserver/account.cpp \
+ net/accountserver/account.h \
+ net/accountserver/accountserver.cpp \
+ net/accountserver/accountserver.h \
+ net/accountserver/internal.cpp \
+ net/accountserver/internal.h \
+ net/chatserver/chatserver.cpp \
+ net/chatserver/chatserver.h \
+ net/chatserver/internal.cpp \
+ net/chatserver/internal.h \
+ net/gameserver/gameserver.cpp \
+ net/gameserver/gameserver.h \
+ net/gameserver/internal.cpp \
+ net/gameserver/internal.h \
+ net/gameserver/player.cpp \
+ net/gameserver/player.h \
resources/ambientoverlay.cpp \
resources/ambientoverlay.h \
resources/image.cpp \
@@ -250,9 +265,3 @@ tmw_SOURCES = graphic/imagerect.h \
INCLUDES = \
$(all_includes) \
-DTMW_DATADIR=\""$(pkgdatadir)/"\"
-
-# the library search path.
-tmw_LDFLAGS = $(all_libraries) $(LIBSDL_RPATH) `pkg-config --libs libxml-2.0`
-tmw_CXXFLAGS = -Wall -Werror $(OPENGL_CFLAGS) $(LIBSDL_CFLAGS) `pkg-config --cflags libxml-2.0` $(CURL_CFLAGS)
-tmw_LDADD = $(LIBSDL_LIBS) -lguichan_sdl $(OPENGL_LIBS) $(CURL_LIBS)
-tmw_TARGET = tmw
diff --git a/src/animatedsprite.cpp b/src/animatedsprite.cpp
index e7439644..3815f04a 100644
--- a/src/animatedsprite.cpp
+++ b/src/animatedsprite.cpp
@@ -34,7 +34,8 @@ AnimatedSprite::AnimatedSprite(const std::string& animationFile, int variant):
mAction(NULL),
mDirection(DIRECTION_DOWN),
mLastTime(0),
- mSpeed(1.0f)
+ mSpeed(1.0f),
+ mAnimationFile(animationFile)
{
int size;
ResourceManager *resman = ResourceManager::getInstance();
@@ -278,7 +279,8 @@ AnimatedSprite::play(SpriteAction action)
if (i == mActions.end())
{
- logger->log("Warning: no action \"%u\" defined!", action);
+ //logger->log("Warning: no action %u defined for \"%s\"!",
+ // action, mAnimationFile.c_str());
mAction = NULL;
return;
}
diff --git a/src/animatedsprite.h b/src/animatedsprite.h
index e87a9885..bda612ab 100644
--- a/src/animatedsprite.h
+++ b/src/animatedsprite.h
@@ -175,6 +175,7 @@ class AnimatedSprite
SpriteDirection mDirection;
int mLastTime;
float mSpeed;
+ std::string mAnimationFile;
};
#endif
diff --git a/src/being.cpp b/src/being.cpp
index 47f9965c..fa24ad69 100644
--- a/src/being.cpp
+++ b/src/being.cpp
@@ -23,6 +23,8 @@
#include "being.h"
#include <algorithm>
+#include <cassert>
+#include <cmath>
#include "animatedsprite.h"
#include "equipment.h"
@@ -45,20 +47,21 @@ PATH_NODE::PATH_NODE(Uint16 iX, Uint16 iY):
{
}
-Being::Being(Uint32 id, Uint16 job, Map *map):
+Being::Being(Uint16 id, Uint16 job, Map *map):
mJob(job),
mX(0), mY(0), mDirection(DOWN),
- mAction(0),
+ mAction(STAND),
mWalkTime(0),
mEmotion(0), mEmotionTime(0),
mAttackSpeed(350),
mEquipment(new Equipment()),
mId(id),
+ mSex(2),
mWeapon(0),
mWalkSpeed(150),
+ mSpeedModifier(1024),
mMap(NULL),
mHairStyle(0), mHairColor(0),
- mSex(2),
mSpeechTime(0),
mDamageTime(0),
mShowSpeech(false), mShowDamage(false),
@@ -74,13 +77,157 @@ Being::~Being()
setMap(NULL);
}
-void
-Being::setDestination(Uint16 destX, Uint16 destY)
+void Being::adjustCourse(Uint16 srcX, Uint16 srcY, Uint16 dstX, Uint16 dstY)
{
- if (mMap)
+ if (!mMap || (mX == dstX && mY == dstY))
+ {
+ setPath(Path());
+ return;
+ }
+
+ if (mX / 32 == dstX / 32 && mY / 32 == dstY / 32)
{
- setPath(mMap->findPath(mX, mY, destX, destY));
+ // The being is already on the last tile of the path.
+ Path p;
+ p.push_back(PATH_NODE(dstX, dstY));
+ setPath(p);
+ return;
}
+
+ Path p1;
+ int p1_size, p1_length;
+ Uint16 *p1_dist;
+ int onPath = -1;
+ if (srcX / 32 == dstX / 32 && srcY / 32 == dstY / 32)
+ {
+ p1_dist = new Uint16[1];
+ p1_size = 1;
+ p1_dist[0] = 0;
+ p1_length = 0;
+ }
+ else
+ {
+ p1 = mMap->findPath(srcX / 32, srcY / 32, dstX / 32, dstY / 32);
+ if (p1.empty())
+ {
+ // No path? Better teleport.
+ mX = dstX;
+ mY = dstY;
+ setPath(p1);
+ return;
+ }
+ p1_size = p1.size();
+ p1_dist = new Uint16[p1_size];
+ int j = 0;
+ // Remove last tile so that it can be replaced by the exact destination.
+ p1.pop_back();
+ for (Path::iterator i = p1.begin(), i_end = p1.end(); i != i_end; ++i)
+ {
+ // Get distance from source to tile i.
+ p1_dist[j] = mMap->getMetaTile(i->x, i->y)->Gcost;
+ // Check if the being is already walking on the path.
+ if (i->x == mX / 32 && i->y == mY / 32)
+ {
+ onPath = j;
+ }
+ // Set intermediate steps to tile centers.
+ i->x = i->x * 32 + 16;
+ i->y = i->y * 32 + 16;
+ ++j;
+ }
+ p1_length = mMap->getMetaTile(dstX / 32, dstY / 32)->Gcost;
+ p1_dist[p1_size - 1] = p1_length;
+ }
+ p1.push_back(PATH_NODE(dstX, dstY));
+
+ if (mX / 32 == srcX / 32 && mY / 32 == srcY / 32)
+ {
+ // The being is at the start of the path.
+ setPath(p1);
+ delete[] p1_dist;
+ return;
+ }
+
+ if (onPath >= 0)
+ {
+ // The being is already on the path, but it needs to be slowed down.
+ for (int j = onPath; j >= 0; --j)
+ {
+ p1.pop_front();
+ }
+ int r = p1_length - p1_dist[onPath]; // remaining length
+ assert(r > 0);
+ setPath(p1, p1_length * 1024 / r);
+ delete[] p1_dist;
+ return;
+ }
+
+ Path bestPath;
+ int bestRating = -1, bestStart = 0, bestLength = 0;
+ int j = 0;
+
+ for (Path::iterator i = p1.begin(), i_end = p1.end(); i != i_end; ++i)
+ {
+ // Look if it is worth passing by tile i.
+ Path p2 = mMap->findPath(mX / 32, mY / 32, i->x / 32, i->y / 32);
+ if (!p2.empty())
+ {
+ int l1 = mMap->getMetaTile(i->x / 32, i->y / 32)->Gcost;
+ int l2 = p1_length - p1_dist[j];
+ int r = l1 + l2 / 2; // TODO: tune rating formula
+ assert(r > 0);
+ if (bestRating < 0 || r < bestRating)
+ {
+ bestPath.swap(p2);
+ bestRating = r;
+ bestStart = j;
+ bestLength = l1 + l2;
+ }
+ }
+ ++j;
+ }
+
+ if (bestRating < 0)
+ {
+ // Unable to reach the path? Better teleport.
+ mX = srcX;
+ mY = srcY;
+ setPath(p1);
+ delete[] p1_dist;
+ return;
+ }
+
+ bestPath.pop_back();
+ for (Path::iterator i = bestPath.begin(), i_end = bestPath.end(); i != i_end; ++i)
+ {
+ i->x = i->x * 32 + 16;
+ i->y = i->y * 32 + 16;
+ }
+
+ // Concatenate paths.
+ for (int j = bestStart; j > 0; --j)
+ {
+ p1.pop_front();
+ }
+ p1.splice(p1.begin(), bestPath);
+
+ assert(bestLength > 0);
+ setPath(p1, p1_length * 1024 / bestLength);
+ delete[] p1_dist;
+}
+
+void Being::adjustCourse(Uint16 srcX, Uint16 srcY)
+{
+ if (!mPath.empty())
+ {
+ adjustCourse(srcX, srcY, mPath.back().x, mPath.back().y);
+ }
+}
+
+void
+Being::setDestination(Uint16 destX, Uint16 destY)
+{
+ adjustCourse(mX, mY, destX, destY);
}
void
@@ -90,35 +237,29 @@ Being::clearPath()
}
void
-Being::setPath(const Path &path)
+Being::setPath(const Path &path, int mod)
{
mPath = path;
+ mSpeedModifier = mod >= 512 ? (mod <= 2048 ? mod : 2048) : 512; // TODO: tune bounds
if (mAction != WALK && mAction != DEAD)
{
- nextStep();
mWalkTime = tick_time;
+ mStepTime = 0;
+ nextStep();
}
}
void
Being::setHairColor(Uint16 color)
{
- mHairColor = color;
- if (mHairColor < 1 || mHairColor > NR_HAIR_COLORS + 1)
- {
- mHairColor = 1;
- }
+ mHairColor = (color < NR_HAIR_COLORS) ? color : 0;
}
void
Being::setHairStyle(Uint16 style)
{
- mHairStyle = style;
- if (mHairStyle < 1 || mHairStyle > NR_HAIR_STYLES)
- {
- mHairStyle = 1;
- }
+ mHairStyle = (style < NR_HAIR_STYLES) ? style : 0;
}
void
@@ -180,9 +321,6 @@ Being::setAction(Uint8 action)
else {
switch (getWeapon())
{
- case 3:
- currentAction = ACTION_ATTACK;
- break;
case 2:
currentAction = ACTION_ATTACK_BOW;
break;
@@ -292,15 +430,25 @@ Being::nextStep()
setDirection(dir);
+ mStepX = node.x - mX;
+ mStepY = node.y - mY;
mX = node.x;
mY = node.y;
setAction(WALK);
- mWalkTime += mWalkSpeed / 10;
+ mWalkTime += mStepTime / 10;
+ mStepTime = mWalkSpeed * (int)std::sqrt((double)mStepX * mStepX + (double)mStepY * mStepY) *
+ mSpeedModifier / (32 * 1024);
}
void
Being::logic()
{
+ // Determine whether the being should take another step
+ if (mAction == WALK && get_elapsed_time(mWalkTime) >= mStepTime)
+ {
+ nextStep();
+ }
+
// Determine whether speech should still be displayed
if (get_elapsed_time(mSpeechTime) > 5000)
{
@@ -314,8 +462,8 @@ Being::logic()
}
// Update pixel coordinates
- mPx = mX * 32 + getXOffset();
- mPy = mY * 32 + getYOffset();
+ mPx = mX - 16 + getXOffset();
+ mPy = mY - 16 + getYOffset();
if (mEmotion != 0)
{
@@ -417,17 +565,12 @@ Being::getType() const
void
Being::setWeaponById(Uint16 weapon)
{
- //TODO: Use an external file to map weapon IDs to weapon types
switch (weapon)
{
case 529: // iron arrows
case 1199: // arrows
break;
- case 623: //scythe
- setWeapon(3);
- break;
-
case 1200: // bow
case 530: // short bow
case 545: // forest bow
@@ -435,10 +578,6 @@ Being::setWeaponById(Uint16 weapon)
break;
case 521: // sharp knife
- /* UNCOMMENT TO TEST SHARP KNIFE AS SCYTHE
- * setWeapon(3)
- * break;
- */
case 522: // dagger
case 536: // short sword
case 1201: // knife
@@ -454,24 +593,23 @@ Being::setWeaponById(Uint16 weapon)
}
}
-int
-Being::getOffset(char pos, char neg) const
+int Being::getOffset(int step) const
{
// Check whether we're walking in the requested direction
- if (mAction != WALK || !(mDirection & (pos | neg))) {
+ if (mAction != WALK || step == 0) {
return 0;
}
- int offset = (get_elapsed_time(mWalkTime) * 32) / mWalkSpeed;
+ int offset = (get_elapsed_time(mWalkTime) * std::abs(step)) / mStepTime;
// We calculate the offset _from_ the _target_ location
- offset -= 32;
+ offset -= std::abs(step);
if (offset > 0) {
offset = 0;
}
// Going into negative direction? Invert the offset.
- if (mDirection & pos) {
+ if (step < 0) {
offset = -offset;
}
diff --git a/src/being.h b/src/being.h
index 42f37058..d8db9375 100644
--- a/src/being.h
+++ b/src/being.h
@@ -33,7 +33,7 @@
#include "map.h"
#include "animatedsprite.h"
-#define NR_HAIR_STYLES 7
+#define NR_HAIR_STYLES 8
#define NR_HAIR_COLORS 10
class AnimatedSprite;
@@ -98,11 +98,11 @@ class Being : public Sprite
static const char UP = 4;
static const char RIGHT = 8;
+ std::string mName; /**< Name of character */
Uint16 mJob; /**< Job (player job, npc, monster, ) */
- Uint16 mX, mY; /**< Tile coordinates */
+ Uint16 mX, mY; /**< Pixel coordinates (tile center) */
Uint8 mDirection; /**< Facing direction */
Uint8 mAction; /**< Action the being is performing */
- Uint8 mFrame;
Uint16 mWalkTime;
Uint8 mEmotion; /**< Currently showing emotion */
Uint8 mEmotionTime; /**< Time until emotion disappears */
@@ -112,7 +112,7 @@ class Being : public Sprite
/**
* Constructor.
*/
- Being(Uint32 id, Uint16 job, Map *map);
+ Being(Uint16 id, Uint16 job, Map *map);
/**
* Destructor.
@@ -127,7 +127,17 @@ class Being : public Sprite
/**
* Sets a new destination for this being to walk to.
*/
- virtual void setDestination(Uint16 destX, Uint16 destY);
+ void setDestination(Uint16 destX, Uint16 destY);
+
+ /**
+ * Adjusts course to expected stat point.
+ */
+ void adjustCourse(Uint16, Uint16);
+
+ /**
+ * Adjusts course to expected start and end points.
+ */
+ void adjustCourse(Uint16, Uint16, Uint16, Uint16);
/**
* Puts a "speech balloon" above this being for the specified amount
@@ -248,7 +258,7 @@ class Being : public Sprite
*
* @param weapon the picture id
*/
- virtual void
+ void
setWeapon(Uint16 weapon) { mWeapon = weapon; }
/**
@@ -274,14 +284,14 @@ class Being : public Sprite
/**
* Gets the sprite id.
*/
- Uint32
+ Uint16
getId() const { return mId; }
/**
* Sets the sprite id.
*/
void
- setId(Uint32 id) { mId = id; }
+ setId(Uint16 id) { mId = id; }
/**
* Sets the map the being is on
@@ -324,13 +334,13 @@ class Being : public Sprite
* Get the current X pixel offset.
*/
int
- getXOffset() const { return getOffset(LEFT, RIGHT); }
+ getXOffset() const { return getOffset(mStepX); }
/**
* Get the current Y pixel offset.
*/
int
- getYOffset() const { return getOffset(UP, DOWN); }
+ getYOffset() const { return getOffset(mStepY); }
std::auto_ptr<Equipment> mEquipment;
int mVisibleEquipment[6]; /**< Visible equipments */
@@ -340,13 +350,7 @@ class Being : public Sprite
* Sets the new path for this being.
*/
void
- setPath(const Path &path);
-
- /**
- * Calculates the offset in the given directions.
- * If walking in direction 'neg' the value is negated.
- */
- int getOffset(char pos, char neg) const;
+ setPath(const Path &path, int mod = 1024);
/**
* Returns the sprite direction of this being.
@@ -354,24 +358,29 @@ class Being : public Sprite
SpriteDirection
getSpriteDirection() const;
- Uint32 mId; /**< Unique sprite id */
+ Uint16 mId; /**< Unique being id */
+ Uint8 mSex; /**< Character's gender */
Uint16 mWeapon; /**< Weapon picture id */
Uint16 mWalkSpeed; /**< Walking speed */
+ Uint16 mSpeedModifier; /**< Modifier to keep course on sync (1024 = normal speed) */
Map *mMap; /**< Map on which this being resides */
- std::string mName; /**< Name of character */
SpriteIterator mSpriteIterator;
Path mPath;
std::string mSpeech;
std::string mDamage;
Uint16 mHairStyle, mHairColor;
- Uint8 mSex;
Uint32 mSpeechTime;
Uint32 mDamageTime;
bool mShowSpeech, mShowDamage;
Sint32 mPx, mPy; /**< Pixel coordinates */
std::vector<AnimatedSprite*> mSprites;
+
+ private:
+ Sint16 mStepX, mStepY;
+ Uint16 mStepTime;
+ int getOffset(int) const;
};
#endif
diff --git a/src/beingmanager.cpp b/src/beingmanager.cpp
index 027e08d3..923283b5 100644
--- a/src/beingmanager.cpp
+++ b/src/beingmanager.cpp
@@ -28,9 +28,6 @@
#include "npc.h"
#include "player.h"
-#include "net/messageout.h"
-#include "net/protocol.h"
-
#include "utils/dtor.h"
class FindBeingFunctor
@@ -39,8 +36,8 @@ class FindBeingFunctor
bool operator() (Being *being)
{
Uint16 other_y = y + ((being->getType() == Being::NPC) ? 1 : 0);
- return (being->mX == x &&
- (being->mY == y || being->mY == other_y) &&
+ return (being->mX / 32 == x &&
+ (being->mY / 32 == y || being->mY / 32 == other_y) &&
being->mAction != Being::MONSTER_DEAD &&
(type == Being::UNKNOWN || being->getType() == type));
}
@@ -49,11 +46,6 @@ class FindBeingFunctor
Being::Type type;
} beingFinder;
-BeingManager::BeingManager(Network *network):
- mNetwork(network)
-{
-}
-
void BeingManager::setMap(Map *map)
{
mMap = map;
@@ -67,19 +59,21 @@ void BeingManager::setPlayer(LocalPlayer *player)
mBeings.push_back(player);
}
-Being* BeingManager::createBeing(Uint32 id, Uint16 job)
+Being* BeingManager::createBeing(Uint16 id, Uint16 job)
{
Being *being;
if (job < 10)
{
being = new Player(id, job, mMap);
- MessageOut outMsg(mNetwork);
- outMsg.writeInt16(0x0094);
- outMsg.writeInt32(id);//readLong(2));
+ // XXX Convert for new server
+ /*
+ MessageOut outMsg(0x0094);
+ outMsg.writeLong(id);
+ */
}
else if (job >= 100 & job < 200)
- being = new NPC(id, job, mMap, mNetwork);
+ being = new NPC(id, job, mMap);
else if (job >= 1000 && job < 1200)
being = new Monster(id, job, mMap);
else
@@ -96,7 +90,7 @@ void BeingManager::destroyBeing(Being *being)
delete being;
}
-Being* BeingManager::findBeing(Uint32 id)
+Being* BeingManager::findBeing(Uint16 id)
{
for (BeingIterator i = mBeings.begin(); i != mBeings.end(); i++)
{
@@ -133,12 +127,12 @@ void BeingManager::logic()
being->logic();
- if (being->mAction == Being::MONSTER_DEAD && being->mFrame >= 20)
+ /*if (being->mAction == Being::MONSTER_DEAD && being->mFrame >= 20)
{
delete being;
i = mBeings.erase(i);
}
- else {
+ else*/ {
i++;
}
}
diff --git a/src/beingmanager.h b/src/beingmanager.h
index 152fb640..15a347de 100644
--- a/src/beingmanager.h
+++ b/src/beingmanager.h
@@ -28,7 +28,6 @@
class LocalPlayer;
class Map;
-class Network;
typedef std::list<Being*> Beings;
typedef Beings::iterator BeingIterator;
@@ -36,8 +35,6 @@ typedef Beings::iterator BeingIterator;
class BeingManager
{
public:
- BeingManager(Network *network);
-
/**
* Sets the map on which beings are created
*/
@@ -51,7 +48,7 @@ class BeingManager
/**
* Create a being and add it to the list of beings.
*/
- Being* createBeing(Uint32 id, Uint16 job);
+ Being* createBeing(Uint16 id, Uint16 job);
/**
* Remove a Being.
@@ -61,7 +58,7 @@ class BeingManager
/**
* Return a specific id Being.
*/
- Being* findBeing(Uint32 id);
+ Being* findBeing(Uint16 id);
/**
* Return a being at specific coordinates.
@@ -95,7 +92,6 @@ class BeingManager
protected:
Beings mBeings;
Map *mMap;
- Network *mNetwork;
};
extern BeingManager *beingManager;
diff --git a/src/configuration.cpp b/src/configuration.cpp
index 53f6785e..8bb0b8ca 100644
--- a/src/configuration.cpp
+++ b/src/configuration.cpp
@@ -79,6 +79,8 @@ void Configuration::write()
// Do not attempt to write to file that cannot be opened for writing
FILE *testFile = fopen(mConfigPath.c_str(), "w");
if (!testFile) {
+ logger->log("Configuration::write() couldn't open %s for writing",
+ mConfigPath.c_str());
return;
}
else {
@@ -87,8 +89,12 @@ void Configuration::write()
xmlTextWriterPtr writer = xmlNewTextWriterFilename(mConfigPath.c_str(), 0);
- if (!writer)
+ if (!writer) {
+ logger->log("Configuration::write() error while creating writer");
return;
+ }
+
+ logger->log("Configuration::write() writing configuration...");
xmlTextWriterSetIndent(writer, 1);
xmlTextWriterStartDocument(writer, NULL, NULL, NULL);
@@ -96,9 +102,6 @@ void Configuration::write()
for (OptionIterator i = mOptions.begin(); i != mOptions.end(); i++)
{
- logger->log("Configuration::write(%s, \"%s\")",
- i->first.c_str(), i->second.c_str());
-
xmlTextWriterStartElement(writer, BAD_CAST "option");
xmlTextWriterWriteAttribute(writer,
BAD_CAST "name", BAD_CAST i->first.c_str());
diff --git a/src/engine.cpp b/src/engine.cpp
index 868454d4..231313c4 100644
--- a/src/engine.cpp
+++ b/src/engine.cpp
@@ -34,16 +34,12 @@
#include "main.h"
#include "localplayer.h"
#include "log.h"
-#include "main.h"
#include "map.h"
#include "sound.h"
#include "gui/gui.h"
#include "gui/minimap.h"
-#include "net/messageout.h"
-#include "net/protocol.h"
-
#include "resources/itemmanager.h"
#include "resources/mapreader.h"
#include "resources/resourcemanager.h"
@@ -63,10 +59,9 @@ Spriteset *emotionset;
Spriteset *npcset;
std::vector<Spriteset *> weaponset;
-Engine::Engine(Network *network):
+Engine::Engine():
mShowDebugPath(false),
- mCurrentMap(NULL),
- mNetwork(network)
+ mCurrentMap(NULL)
{
// Load the sprite sets
ResourceManager *resman = ResourceManager::getInstance();
@@ -113,7 +108,7 @@ void Engine::changeMap(const std::string &mapPath)
beingManager->clear();
// Store full map path in global var
- map_path = "maps/" + mapPath.substr(0, mapPath.rfind(".")) + ".tmx.gz";
+ map_path = "maps/" + mapPath;
// Attempt to load the new map
Map *newMap = MapReader::readMap(map_path);
@@ -147,10 +142,6 @@ void Engine::changeMap(const std::string &mapPath)
}
mCurrentMap = newMap;
-
- // Send "map loaded"
- MessageOut outMsg(mNetwork);
- outMsg.writeInt16(CMSG_MAP_LOADED);
}
void Engine::logic()
@@ -161,20 +152,12 @@ void Engine::logic()
void Engine::draw(Graphics *graphics)
{
+ int midTileX = graphics->getWidth() / 2;
+ int midTileY = graphics->getHeight() / 2;
static int lastTick = tick_time;
- // Avoid freaking out when tick_time overflows
- if (tick_time < lastTick)
- {
- lastTick = tick_time;
- }
-
- // calculate viewpoint
- int midTileX = graphics->getWidth() / 32 / 2;
- int midTileY = graphics->getHeight() / 32 / 2;
-
- int player_x = (player_node->mX - midTileX) * 32 + player_node->getXOffset();
- int player_y = (player_node->mY - midTileY) * 32 + player_node->getYOffset();
+ int player_x = player_node->mX - midTileX + player_node->getXOffset();
+ int player_y = player_node->mY - midTileY + player_node->getYOffset();
scrollLaziness = (int)config.getValue("ScrollLaziness", 32);
scrollRadius = (int)config.getValue("ScrollRadius", 32);
@@ -183,7 +166,9 @@ void Engine::draw(Graphics *graphics)
scrollLaziness = 1; //avoids division by zero
//apply lazy scrolling
- while (lastTick < tick_time)
+ int nbTicks = get_elapsed_time(lastTick) / 10;
+ lastTick += nbTicks;
+ for (; nbTicks > 0; --nbTicks)
{
if (player_x > view_x + scrollRadius)
{
@@ -201,7 +186,6 @@ void Engine::draw(Graphics *graphics)
{
view_y += (player_y - view_y + scrollRadius) / scrollLaziness;
}
- lastTick++;
}
//auto center when player is off screen
@@ -222,29 +206,36 @@ void Engine::draw(Graphics *graphics)
if (view_y < 0) {
view_y = 0;
}
- if (view_x > (mCurrentMap->getWidth() - midTileX) * 32) {
- view_x = (mCurrentMap->getWidth() - midTileX) * 32;
+ if (view_x > mCurrentMap->getWidth() * 32 - midTileX) {
+ view_x = mCurrentMap->getWidth() * 32 - midTileX;
}
- if (view_y > (mCurrentMap->getHeight() - midTileY) * 32) {
- view_y = (mCurrentMap->getHeight() - midTileY) * 32;
+ if (view_y > mCurrentMap->getHeight() * 32 - midTileY) {
+ view_y = mCurrentMap->getHeight() * 32 - midTileY;
}
}
- camera_x = int(view_x + 16) / 32;
- camera_y = int(view_y + 16) / 32;
+ camera_x = (int)view_x;
+ camera_y = (int)view_y;
// Draw tiles and sprites
if (mCurrentMap != NULL)
{
- mCurrentMap->draw(graphics, (int)view_x, (int)view_y, 0);
- mCurrentMap->draw(graphics, (int)view_x, (int)view_y, 1);
- mCurrentMap->draw(graphics, (int)view_x, (int)view_y, 2);
+ mCurrentMap->draw(graphics, camera_x, camera_y, 0);
+ mCurrentMap->draw(graphics, camera_x, camera_y, 1);
+ mCurrentMap->draw(graphics, camera_x, camera_y, 2);
mCurrentMap->drawOverlay( graphics,
view_x,
view_y,
(int)config.getValue("OverlayDetail", 2)
);
}
+ else
+ {
+ // When no map is loaded, draw a replacement background
+ graphics->setColor(gcn::Color(128, 128, 128));
+ graphics->fillRectangle(gcn::Rectangle(0, 0,
+ graphics->getWidth(), graphics->getHeight()));
+ }
// Find a path from the player to the mouse, and draw it. This is for debug
// purposes.
@@ -254,18 +245,18 @@ void Engine::draw(Graphics *graphics)
int mouseX, mouseY;
SDL_GetMouseState(&mouseX, &mouseY);
- int mouseTileX = mouseX / 32 + camera_x;
- int mouseTileY = mouseY / 32 + camera_y;
+ int mouseTileX = (mouseX + camera_x) / 32;
+ int mouseTileY = (mouseY + camera_y) / 32;
Path debugPath = mCurrentMap->findPath(
- player_node->mX, player_node->mY,
+ player_node->mX / 32, player_node->mY / 32,
mouseTileX, mouseTileY);
graphics->setColor(gcn::Color(255, 0, 0));
for (PathIterator i = debugPath.begin(); i != debugPath.end(); i++)
{
- int squareX = i->x * 32 - int(view_x) + 12;
- int squareY = i->y * 32 - int(view_y) + 12;
+ int squareX = i->x * 32 - camera_x + 12;
+ int squareY = i->y * 32 - camera_y + 12;
graphics->fillRectangle(gcn::Rectangle(squareX, squareY, 8, 8));
graphics->drawText(
@@ -278,9 +269,9 @@ void Engine::draw(Graphics *graphics)
Beings &beings = beingManager->getAll();
for (BeingIterator i = beings.begin(); i != beings.end(); i++)
{
- (*i)->drawSpeech(graphics, -(int)view_x, -(int)view_y);
- (*i)->drawName(graphics, -(int)view_x, -(int)view_y);
- (*i)->drawEmotion(graphics, -(int)view_x, -(int)view_y);
+ (*i)->drawSpeech(graphics, -camera_x, -camera_y);
+ (*i)->drawName(graphics, -camera_x, -camera_y);
+ (*i)->drawEmotion(graphics, -camera_x, -camera_y);
}
// Draw target marker if needed
@@ -291,8 +282,8 @@ void Engine::draw(Graphics *graphics)
graphics->setColor(gcn::Color(255, 255, 255));
int dy = (target->getType() == Being::PLAYER) ? 90 : 52;
- graphics->drawText("[TARGET]", target->getPixelX() - (int)view_x + 15,
- target->getPixelY() - (int)view_y - dy, gcn::Graphics::CENTER);
+ graphics->drawText("[TARGET]", target->getPixelX() - camera_x + 15,
+ target->getPixelY() - camera_y - dy, gcn::Graphics::CENTER);
}
gui->draw();
diff --git a/src/engine.h b/src/engine.h
index 3ae380d6..e8ef7e33 100644
--- a/src/engine.h
+++ b/src/engine.h
@@ -30,7 +30,6 @@ extern int camera_x, camera_y;
class Graphics;
class Map;
-class Network;
/**
* Game engine that does the main drawing.
@@ -41,7 +40,7 @@ class Engine
/**
* Constructor.
*/
- Engine(Network *network);
+ Engine();
/**
* Destructor.
@@ -77,7 +76,6 @@ class Engine
bool mShowDebugPath;
Map *mCurrentMap;
- Network *mNetwork;
int scrollRadius;
int scrollLaziness;
diff --git a/src/game.cpp b/src/game.cpp
index b07c5c9a..5052f2ce 100644
--- a/src/game.cpp
+++ b/src/game.cpp
@@ -122,7 +122,7 @@ const int MAX_TIME = 10000;
*/
namespace {
struct ExitListener : public gcn::ActionListener {
- void action(const std::string& eventId, gcn::Widget* widget) {
+ void action(const std::string &eventId, gcn::Widget *widget) {
if (eventId == "yes") {
done = true;
}
@@ -164,15 +164,15 @@ int get_elapsed_time(int start_time)
/**
* Create all the various globally accessible gui windows
*/
-void createGuiWindows(Network *network)
+void createGuiWindows()
{
// Create dialogs
- chatWindow = new ChatWindow(network);
+ chatWindow = new ChatWindow;
menuWindow = new MenuWindow();
statusWindow = new StatusWindow(player_node);
miniStatusWindow = new MiniStatusWindow();
- buyDialog = new BuyDialog(network);
- sellDialog = new SellDialog(network);
+ buyDialog = new BuyDialog;
+ sellDialog = new SellDialog;
buySellDialog = new BuySellDialog();
inventoryWindow = new InventoryWindow();
npcTextDialog = new NpcTextDialog();
@@ -183,7 +183,7 @@ void createGuiWindows(Network *network)
minimap = new Minimap();
equipmentWindow = new EquipmentWindow(player_node->mEquipment.get());
chargeDialog = new ChargeDialog();
- tradeWindow = new TradeWindow(network);
+ tradeWindow = new TradeWindow;
//buddyWindow = new BuddyWindow();
helpWindow = new HelpWindow();
debugWindow = new DebugWindow();
@@ -252,8 +252,7 @@ void destroyGuiWindows()
delete debugWindow;
}
-Game::Game(Network *network):
- mNetwork(network),
+Game::Game():
mBeingHandler(new BeingHandler()),
mBuySellHandler(new BuySellHandler()),
mChatHandler(new ChatHandler()),
@@ -265,10 +264,10 @@ Game::Game(Network *network):
mSkillHandler(new SkillHandler()),
mTradeHandler(new TradeHandler())
{
- createGuiWindows(network);
- engine = new Engine(network);
+ createGuiWindows();
+ engine = new Engine;
- beingManager = new BeingManager(network);
+ beingManager = new BeingManager;
floorItemManager = new FloorItemManager();
// Initialize timers
@@ -282,8 +281,6 @@ Game::Game(Network *network):
// Initialize beings
beingManager->setPlayer(player_node);
- player_node->setNetwork(network);
- engine->changeMap(map_path);
Joystick::init();
// TODO: The user should be able to choose which one to use
@@ -293,16 +290,16 @@ Game::Game(Network *network):
joystick = new Joystick(0);
}
- network->registerHandler(mBeingHandler.get());
- network->registerHandler(mBuySellHandler.get());
- network->registerHandler(mChatHandler.get());
- network->registerHandler(mEquipmentHandler.get());
- network->registerHandler(mInventoryHandler.get());
- network->registerHandler(mItemHandler.get());
- network->registerHandler(mNpcHandler.get());
- network->registerHandler(mPlayerHandler.get());
- network->registerHandler(mSkillHandler.get());
- network->registerHandler(mTradeHandler.get());
+ Net::registerHandler(mBeingHandler.get());
+ Net::registerHandler(mBuySellHandler.get());
+ Net::registerHandler(mChatHandler.get());
+ Net::registerHandler(mEquipmentHandler.get());
+ Net::registerHandler(mInventoryHandler.get());
+ Net::registerHandler(mItemHandler.get());
+ Net::registerHandler(mNpcHandler.get());
+ Net::registerHandler(mPlayerHandler.get());
+ Net::registerHandler(mSkillHandler.get());
+ Net::registerHandler(mTradeHandler.get());
}
Game::~Game()
@@ -404,8 +401,7 @@ void Game::logic()
}
// Handle network stuff
- mNetwork->flush();
- mNetwork->dispatchMessages();
+ Net::flush();
}
}
@@ -509,14 +505,12 @@ void Game::handleInput()
case SDLK_z:
if (!chatWindow->isFocused())
{
- FloorItem *item = floorItemManager->findByCoordinates(
- player_node->mX, player_node->mY);
+ Uint16 x = player_node->mX / 32, y = player_node->mY / 32;
+ FloorItem *item = floorItemManager->findByCoordinates(x, y);
// If none below the player, try the tile in front of
// the player
if (!item) {
- Uint16 x = player_node->mX;
- Uint16 y = player_node->mY;
if (player_node->mDirection & Being::UP)
y--;
if (player_node->mDirection & Being::DOWN)
@@ -638,8 +632,7 @@ void Game::handleInput()
current_npc == 0 &&
!chatWindow->isFocused())
{
- Uint16 x = player_node->mX;
- Uint16 y = player_node->mY;
+ Uint16 x = player_node->mX / 32, y = player_node->mY / 32;
unsigned char Direction = 0;
// Translate pressed keys to movement and direction
@@ -691,7 +684,7 @@ void Game::handleInput()
if (player_node->mDirection & Being::RIGHT)
targetX++;
- // Attack priorioty is: Monster, Player, auto target
+ // Attack priority is: Monster, Player, auto target
target = beingManager->findBeing(
targetX, targetY, Being::MONSTER);
if (!target)
@@ -718,8 +711,7 @@ void Game::handleInput()
{
if (joystick->buttonPressed(1))
{
- FloorItem *item = floorItemManager->findByCoordinates(
- player_node->mX, player_node->mY);
+ FloorItem *item = floorItemManager->findByCoordinates(x, y);
if (item)
player_node->pickUp(item);
diff --git a/src/game.h b/src/game.h
index 2aaabf96..19a6054a 100644
--- a/src/game.h
+++ b/src/game.h
@@ -33,7 +33,6 @@
#define SPEECH_MAX_TIME 100
class MessageHandler;
-class Network;
extern std::string map_path;
extern volatile int fps;
@@ -42,7 +41,7 @@ extern volatile int tick_time;
class Game : public ConfigListener
{
public:
- Game(Network *network);
+ Game();
~Game();
void logic();
@@ -52,8 +51,6 @@ class Game : public ConfigListener
void optionChanged(const std::string &name);
private:
- Network *mNetwork;
-
/** Used to determine whether to draw the next frame. */
int mDrawTime;
diff --git a/src/gui/browserbox.h b/src/gui/browserbox.h
index 95b181ad..a2c9dd9b 100644
--- a/src/gui/browserbox.h
+++ b/src/gui/browserbox.h
@@ -31,6 +31,7 @@
#include <guichan/mouselistener.hpp>
#include "../guichanfwd.h"
+#include "../main.h"
class LinkHandler;
diff --git a/src/gui/buddywindow.cpp b/src/gui/buddywindow.cpp
index e4a96b67..145f0ad2 100644
--- a/src/gui/buddywindow.cpp
+++ b/src/gui/buddywindow.cpp
@@ -61,7 +61,7 @@ BuddyWindow::BuddyWindow():
add(cancel);
}
-void BuddyWindow::action(const std::string& eventId, gcn::Widget* widget)
+void BuddyWindow::action(const std::string &eventId, gcn::Widget *widget)
{
if (eventId == "Talk") {
int selected = mListbox->getSelected();
diff --git a/src/gui/buy.cpp b/src/gui/buy.cpp
index 0bf4c56d..73f696b7 100644
--- a/src/gui/buy.cpp
+++ b/src/gui/buy.cpp
@@ -26,28 +26,27 @@
#include <guichan/widgets/label.hpp>
#include "button.h"
+#include "listbox.h"
#include "scrollarea.h"
#include "shop.h"
#include "slider.h"
#include "../npc.h"
+#include "../resources/iteminfo.h"
#include "../resources/itemmanager.h"
-#include "../net/messageout.h"
-#include "../net/protocol.h"
-
#include "../utils/tostring.h"
-BuyDialog::BuyDialog(Network *network):
- Window("Buy"), mNetwork(network),
+BuyDialog::BuyDialog():
+ Window("Buy"),
mMoney(0), mAmountItems(0), mMaxItems(0)
{
mShopItems = new ShopItems;
- mShopItemList = new ShopListBox(mShopItems, mShopItems);
- mScrollArea = new ScrollArea(mShopItemList);
+ mItemList = new ListBox(mShopItems);
+ mScrollArea = new ScrollArea(mItemList);
mSlider = new Slider(1.0);
mQuantityLabel = new gcn::Label("0");
mMoneyLabel = new gcn::Label("Price : 0 GP / 0 GP");
@@ -61,7 +60,7 @@ BuyDialog::BuyDialog(Network *network):
setContentSize(260, 210);
mScrollArea->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
mScrollArea->setDimension(gcn::Rectangle(5, 5, 250, 110));
- mShopItemList->setDimension(gcn::Rectangle(5, 5, 238, 110));
+ mItemList->setDimension(gcn::Rectangle(5, 5, 238, 110));
mSlider->setDimension(gcn::Rectangle(5, 120, 200, 10));
mSlider->setEnabled(false);
@@ -85,11 +84,11 @@ BuyDialog::BuyDialog(Network *network):
mItemEffectLabel->setDimension(gcn::Rectangle(5, 150, 240, 14));
mItemDescLabel->setDimension(gcn::Rectangle(5, 169, 240, 14));
- mShopItemList->setEventId("item");
+ mItemList->setEventId("item");
mSlider->setEventId("slider");
- mShopItemList->addActionListener(this);
- mShopItemList->addSelectionListener(this);
+ mItemList->addActionListener(this);
+ mItemList->addSelectionListener(this);
mSlider->addActionListener(this);
add(mScrollArea);
@@ -114,7 +113,6 @@ BuyDialog::~BuyDialog()
void BuyDialog::setMoney(int amount)
{
mMoney = amount;
- mShopItemList->setPlayersMoney(amount);
mMoneyLabel->setCaption("Price : 0 GP / " + toString(mMoney) + " GP");
mMoneyLabel->adjustSize();
}
@@ -127,7 +125,7 @@ void BuyDialog::reset()
mAmountItems = 0;
// Reset Previous Selected Items to prevent failing asserts
- mShopItemList->setSelected(-1);
+ mItemList->setSelected(-1);
mIncreaseButton->setEnabled(false);
mDecreaseButton->setEnabled(false);
mQuantityLabel->setCaption("0");
@@ -140,13 +138,20 @@ void BuyDialog::reset()
void BuyDialog::addItem(short id, int price)
{
- mShopItems->addItem(id, price);
- mShopItemList->adjustSize();
+ ITEM_SHOP item_shop;
+
+ item_shop.name = itemDb->getItemInfo(id).getName() + " "
+ + toString(price) + " GP";
+ item_shop.price = price;
+ item_shop.id = id;
+
+ mShopItems->push_back(item_shop);
+ mItemList->adjustSize();
}
-void BuyDialog::action(const std::string& eventId, gcn::Widget* widget)
+void BuyDialog::action(const std::string &eventId, gcn::Widget *widget)
{
- int selectedItem = mShopItemList->getSelected();
+ int selectedItem = mItemList->getSelected();
if (eventId == "item")
{
@@ -164,7 +169,7 @@ void BuyDialog::action(const std::string& eventId, gcn::Widget* widget)
// If no item was selected, none can be bought, otherwise
// calculate how many the player can afford
- mMaxItems = (mShopItemList->getSelected() == -1) ? 0 :
+ mMaxItems = (mItemList->getSelected() == -1) ? 0 :
mMoney / mShopItems->at(selectedItem).price;
// When at least one item can be bought, enable the slider and the
@@ -179,7 +184,7 @@ void BuyDialog::action(const std::string& eventId, gcn::Widget* widget)
}
// The following actions require a valid selection
- if (selectedItem < 0 || selectedItem >= int(mShopItems->getNumberOfElements()))
+ if (selectedItem < 0 || selectedItem >= int(mShopItems->size()))
{
return;
}
@@ -219,11 +224,13 @@ void BuyDialog::action(const std::string& eventId, gcn::Widget* widget)
else if (eventId == "buy" && (mAmountItems > 0 &&
mAmountItems <= mMaxItems))
{
- MessageOut outMsg(mNetwork);
- outMsg.writeInt16(CMSG_NPC_BUY_REQUEST);
- outMsg.writeInt16(8);
- outMsg.writeInt16(mAmountItems);
- outMsg.writeInt16(mShopItems->at(selectedItem).id);
+ // XXX Convert for new server
+ /*
+ MessageOut outMsg(CMSG_NPC_BUY_REQUEST);
+ outMsg.writeShort(8);
+ outMsg.writeShort(mAmountItems);
+ outMsg.writeShort(mShopItems->at(selectedItem).id);
+ */
// update money !
mMoney -= mAmountItems * mShopItems->at(selectedItem).price;
@@ -262,7 +269,7 @@ void BuyDialog::action(const std::string& eventId, gcn::Widget* widget)
void BuyDialog::selectionChanged(const SelectionEvent &event)
{
- int selectedItem = mShopItemList->getSelected();
+ int selectedItem = mItemList->getSelected();
if (selectedItem > -1)
{
diff --git a/src/gui/buy.h b/src/gui/buy.h
index 2af6cfe8..f5c163e1 100644
--- a/src/gui/buy.h
+++ b/src/gui/buy.h
@@ -28,11 +28,9 @@
#include "window.h"
#include "selectionlistener.h"
-#include "shoplistbox.h"
#include "../guichanfwd.h"
-class Network;
class ShopItems;
class ListBox;
@@ -49,7 +47,7 @@ class BuyDialog : public Window, public gcn::ActionListener, SelectionListener
*
* @see Window::Window
*/
- BuyDialog(Network *network);
+ BuyDialog();
/**
* Destructor
@@ -94,12 +92,11 @@ class BuyDialog : public Window, public gcn::ActionListener, SelectionListener
std::string getElementAt(int i);
private:
- Network *mNetwork;
gcn::Button *mBuyButton;
gcn::Button *mQuitButton;
gcn::Button *mIncreaseButton;
gcn::Button *mDecreaseButton;
- ShopListBox *mShopItemList;
+ ListBox *mItemList;
gcn::ScrollArea *mScrollArea;
gcn::Label *mItemDescLabel;
gcn::Label *mItemEffectLabel;
diff --git a/src/gui/buysell.cpp b/src/gui/buysell.cpp
index e2e0e686..4bbbb2ff 100644
--- a/src/gui/buysell.cpp
+++ b/src/gui/buysell.cpp
@@ -52,7 +52,7 @@ BuySellDialog::BuySellDialog():
requestFocus();
}
-void BuySellDialog::action(const std::string& eventId, gcn::Widget* widget)
+void BuySellDialog::action(const std::string &eventId, gcn::Widget *widget)
{
if (eventId == "Buy") {
current_npc->buy();
diff --git a/src/gui/char_select.cpp b/src/gui/char_select.cpp
index fa4c0241..d825db31 100644
--- a/src/gui/char_select.cpp
+++ b/src/gui/char_select.cpp
@@ -37,7 +37,7 @@
#include "../localplayer.h"
#include "../main.h"
-#include "../net/messageout.h"
+#include "../net/accountserver/account.h"
#include "../utils/tostring.h"
@@ -48,7 +48,7 @@ class CharDeleteConfirm : public ConfirmDialog
{
public:
CharDeleteConfirm(CharSelectDialog *master);
- void action(const std::string& eventId, gcn::Widget* widget);
+ void action(const std::string &eventId, gcn::Widget *widget);
private:
CharSelectDialog *master;
};
@@ -60,7 +60,7 @@ CharDeleteConfirm::CharDeleteConfirm(CharSelectDialog *m):
{
}
-void CharDeleteConfirm::action(const std::string& eventId, gcn::Widget* widget)
+void CharDeleteConfirm::action(const std::string &eventId, gcn::Widget *widget)
{
//ConfirmDialog::action(eventId);
if (eventId == "yes") {
@@ -69,11 +69,9 @@ void CharDeleteConfirm::action(const std::string& eventId, gcn::Widget* widget)
ConfirmDialog::action(eventId, widget);
}
-CharSelectDialog::CharSelectDialog(Network *network,
- LockedArray<LocalPlayer*> *charInfo,
- unsigned char sex):
- Window("Select Character"), mNetwork(network),
- mCharInfo(charInfo), mSex(sex), mCharSelected(false)
+CharSelectDialog::CharSelectDialog(LockedArray<LocalPlayer*> *charInfo):
+ Window("Select Character"),
+ mCharInfo(charInfo), mCharSelected(false)
{
mSelectButton = new Button("Ok", "ok", this);
mCancelButton = new Button("Cancel", "cancel", this);
@@ -84,9 +82,8 @@ CharSelectDialog::CharSelectDialog(Network *network,
mNameLabel = new gcn::Label("Name");
mLevelLabel = new gcn::Label("Level");
- mJobLevelLabel = new gcn::Label("Job Level");
mMoneyLabel = new gcn::Label("Money");
- mPlayerBox = new PlayerBox(sex);
+ mPlayerBox = new PlayerBox(0);
int w = 195;
int h = 220;
@@ -94,7 +91,6 @@ CharSelectDialog::CharSelectDialog(Network *network,
mPlayerBox->setDimension(gcn::Rectangle(5, 5, w - 10, 90));
mNameLabel->setDimension(gcn::Rectangle(10, 100, 128, 16));
mLevelLabel->setDimension(gcn::Rectangle(10, 116, 128, 16));
- mJobLevelLabel->setDimension(gcn::Rectangle(10, 132, 128, 16));
mMoneyLabel->setDimension(gcn::Rectangle(10, 148, 128, 16));
mPreviousButton->setPosition(5, 170);
mNextButton->setPosition(mPreviousButton->getWidth() + 10, 170);
@@ -118,7 +114,6 @@ CharSelectDialog::CharSelectDialog(Network *network,
add(mNextButton);
add(mNameLabel);
add(mLevelLabel);
- add(mJobLevelLabel);
add(mMoneyLabel);
mSelectButton->requestFocus();
@@ -126,7 +121,7 @@ CharSelectDialog::CharSelectDialog(Network *network,
updatePlayerInfo();
}
-void CharSelectDialog::action(const std::string& eventId, gcn::Widget* widget)
+void CharSelectDialog::action(const std::string &eventId, gcn::Widget *widget)
{
if (eventId == "ok" && n_character > 0)
{
@@ -137,11 +132,12 @@ void CharSelectDialog::action(const std::string& eventId, gcn::Widget* widget)
mPreviousButton->setEnabled(false);
mNextButton->setEnabled(false);
mCharSelected = true;
- attemptCharSelect();
+ Net::AccountServer::Account::selectCharacter(mCharInfo->getPos());
+ mCharInfo->lock();
}
else if (eventId == "cancel")
{
- state = EXIT_STATE;
+ state = STATE_EXIT;
}
else if (eventId == "new")
{
@@ -149,7 +145,7 @@ void CharSelectDialog::action(const std::string& eventId, gcn::Widget* widget)
{
// Start new character dialog
mCharInfo->lock();
- new CharCreateDialog(this, mCharInfo->getPos(), mNetwork, mSex);
+ new CharCreateDialog(this, mCharInfo->getPos());
mCharInfo->unlock();
}
}
@@ -178,21 +174,20 @@ void CharSelectDialog::updatePlayerInfo()
if (pi) {
mNameLabel->setCaption(pi->getName());
mLevelLabel->setCaption("Lvl: " + toString(pi->mLevel));
- mJobLevelLabel->setCaption("Job Lvl: " + toString(pi->mJobLevel));
- mMoneyLabel->setCaption("Gold: " + toString(pi->mGp));
+ mMoneyLabel->setCaption("Money: " + toString(pi->mMoney));
if (!mCharSelected)
{
mNewCharButton->setEnabled(false);
mDelCharButton->setEnabled(true);
mSelectButton->setEnabled(true);
}
- mPlayerBox->mHairStyle = pi->getHairStyle() - 1;
- mPlayerBox->mHairColor = pi->getHairColor() - 1;
+ mPlayerBox->mHairStyle = pi->getHairStyle();
+ mPlayerBox->mHairColor = pi->getHairColor();
+ mPlayerBox->mSex = pi->getSex();
mPlayerBox->mShowPlayer = true;
} else {
mNameLabel->setCaption("Name");
mLevelLabel->setCaption("Level");
- mJobLevelLabel->setCaption("Job Level");
mMoneyLabel->setCaption("Money");
mNewCharButton->setEnabled(true);
mDelCharButton->setEnabled(false);
@@ -206,20 +201,7 @@ void CharSelectDialog::updatePlayerInfo()
void CharSelectDialog::attemptCharDelete()
{
- // Request character deletion
- MessageOut outMsg(mNetwork);
- outMsg.writeInt16(0x0068);
- outMsg.writeInt32(mCharInfo->getEntry()->mCharId);
- outMsg.writeString("a@a.com", 40);
- mCharInfo->lock();
-}
-
-void CharSelectDialog::attemptCharSelect()
-{
- // Request character selection
- MessageOut outMsg(mNetwork);
- outMsg.writeInt16(0x0066);
- outMsg.writeInt8(mCharInfo->getPos());
+ Net::AccountServer::Account::deleteCharacter(mCharInfo->getPos());
mCharInfo->lock();
}
@@ -255,9 +237,8 @@ std::string CharSelectDialog::getName()
return mNameLabel->getCaption();
}
-CharCreateDialog::CharCreateDialog(Window *parent, int slot, Network *network,
- unsigned char sex):
- Window("Create Character", true, parent), mNetwork(network), mSlot(slot)
+CharCreateDialog::CharCreateDialog(Window *parent, int slot):
+ Window("Create Character", true, parent), mSlot(slot)
{
mNameField = new TextField("");
mNameLabel = new gcn::Label("Name:");
@@ -269,7 +250,7 @@ CharCreateDialog::CharCreateDialog(Window *parent, int slot, Network *network,
mHairStyleLabel = new gcn::Label("Hair Style:");
mCreateButton = new Button("Create", "create", this);
mCancelButton = new Button("Cancel", "cancel", this);
- mPlayerBox = new PlayerBox(sex);
+ mPlayerBox = new PlayerBox(0);
mPlayerBox->mShowPlayer = true;
mNameField->setEventId("create");
@@ -311,13 +292,21 @@ CharCreateDialog::CharCreateDialog(Window *parent, int slot, Network *network,
setLocationRelativeTo(getParent());
}
-void CharCreateDialog::action(const std::string& eventId, gcn::Widget* widget)
+void CharCreateDialog::action(const std::string &eventId, gcn::Widget *widget)
{
if (eventId == "create") {
if (getName().length() >= 4) {
// Attempt to create the character
mCreateButton->setEnabled(false);
- attemptCharCreate();
+ Net::AccountServer::Account::createCharacter(
+ getName(), mPlayerBox->mHairStyle, mPlayerBox->mHairColor,
+ 0, // gender
+ 10, // STR
+ 10, // AGI
+ 10, // VIT
+ 10, // INT
+ 10, // DEX
+ 10); // LUK
scheduleDelete();
}
else {
@@ -349,20 +338,3 @@ std::string CharCreateDialog::getName()
{
return mNameField->getText();
}
-
-void CharCreateDialog::attemptCharCreate()
-{
- // Send character infos
- MessageOut outMsg(mNetwork);
- outMsg.writeInt16(0x0067);
- outMsg.writeString(getName(), 24);
- outMsg.writeInt8(5);
- outMsg.writeInt8(5);
- outMsg.writeInt8(5);
- outMsg.writeInt8(5);
- outMsg.writeInt8(5);
- outMsg.writeInt8(5);
- outMsg.writeInt8(mSlot);
- outMsg.writeInt16(mPlayerBox->mHairColor + 1);
- outMsg.writeInt16(mPlayerBox->mHairStyle + 1);
-}
diff --git a/src/gui/char_select.h b/src/gui/char_select.h
index 0a1b5eac..6d9d1a83 100644
--- a/src/gui/char_select.h
+++ b/src/gui/char_select.h
@@ -32,7 +32,6 @@
#include <guichan/actionlistener.hpp>
class LocalPlayer;
-class Network;
class PlayerBox;
/**
@@ -47,9 +46,7 @@ class CharSelectDialog : public Window, public gcn::ActionListener
/**
* Constructor.
*/
- CharSelectDialog(Network *network,
- LockedArray<LocalPlayer*> *charInfo,
- unsigned char sex);
+ CharSelectDialog(LockedArray<LocalPlayer*> *charInfo);
void action(const std::string& eventId, gcn::Widget* widget);
@@ -65,7 +62,6 @@ class CharSelectDialog : public Window, public gcn::ActionListener
std::string getName();
private:
- Network *mNetwork;
LockedArray<LocalPlayer*> *mCharInfo;
gcn::Button *mSelectButton;
@@ -77,12 +73,10 @@ class CharSelectDialog : public Window, public gcn::ActionListener
gcn::Label *mNameLabel;
gcn::Label *mLevelLabel;
- gcn::Label *mJobLevelLabel;
gcn::Label *mMoneyLabel;
PlayerBox *mPlayerBox;
- unsigned char mSex;
bool mCharSelected;
/**
@@ -107,15 +101,13 @@ class CharCreateDialog : public Window, public gcn::ActionListener
/**
* Constructor.
*/
- CharCreateDialog(Window *parent, int slot, Network *network,
- unsigned char sex);
+ CharCreateDialog(Window *parent, int slot);
void action(const std::string& eventId, gcn::Widget* widget);
std::string getName();
private:
- Network *mNetwork;
gcn::TextField *mNameField;
gcn::Label *mNameLabel;
gcn::Button *mNextHairColorButton;
diff --git a/src/gui/char_server.cpp b/src/gui/char_server.cpp
deleted file mode 100644
index 87ed9c17..00000000
--- a/src/gui/char_server.cpp
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * 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$
- */
-
-#include "char_server.h"
-
-#include "button.h"
-#include "listbox.h"
-#include "scrollarea.h"
-
-#include "../logindata.h"
-#include "../main.h"
-#include "../serverinfo.h"
-
-#include "../net/network.h" // TODO this is just for iptostring, move that?
-
-#include "../utils/tostring.h"
-
-extern SERVER_INFO **server_info;
-
-/**
- * The list model for the server list.
- */
-class ServerListModel : public gcn::ListModel {
- public:
- virtual ~ServerListModel() {};
-
- int getNumberOfElements();
- std::string getElementAt(int i);
-};
-
-ServerSelectDialog::ServerSelectDialog(LoginData *loginData):
- Window("Select Server"), mLoginData(loginData)
-{
- mServerListModel = new ServerListModel();
- mServerList = new ListBox(mServerListModel);
- ScrollArea *mScrollArea = new ScrollArea(mServerList);
- mOkButton = new Button("OK", "ok", this);
- Button *mCancelButton = new Button("Cancel", "cancel", this);
-
- setContentSize(200, 100);
-
- mCancelButton->setPosition(
- 200 - mCancelButton->getWidth() - 5,
- 100 - mCancelButton->getHeight() - 5);
- mOkButton->setPosition(
- mCancelButton->getX() - mOkButton->getWidth() - 5,
- 100 - mOkButton->getHeight() - 5);
- mScrollArea->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
- mScrollArea->setDimension(gcn::Rectangle(
- 5, 5, 200 - 2 * 5,
- 100 - 3 * 5 - mCancelButton->getHeight() -
- mScrollArea->getBorderSize()));
-
- mServerList->setEventId("ok");
-
- //mServerList->addActionListener(this);
-
- add(mScrollArea);
- add(mOkButton);
- add(mCancelButton);
-
- if (n_server == 0) {
- // Disable Ok button
- mOkButton->setEnabled(false);
- } else {
- // Select first server
- mServerList->setSelected(1);
- }
-
- mOkButton->requestFocus();
- setLocationRelativeTo(getParent());
-}
-
-ServerSelectDialog::~ServerSelectDialog()
-{
- delete mServerListModel;
-}
-
-void
-ServerSelectDialog::action(const std::string& eventId, gcn::Widget* widget)
-{
- if (eventId == "ok") {
- mOkButton->setEnabled(false);
- const SERVER_INFO *si = server_info[mServerList->getSelected()];
- mLoginData->hostname = iptostring(si->address);
- mLoginData->port = si->port;
- state = CHAR_CONNECT_STATE;
- }
- else if (eventId == "cancel") {
- state = LOGIN_STATE;
- }
-}
-
-int
-ServerListModel::getNumberOfElements()
-{
- return n_server;
-}
-
-std::string
-ServerListModel::getElementAt(int i)
-{
- const SERVER_INFO *si = server_info[i];
- return si->name + " (" + toString(si->online_users) + ")";
-}
diff --git a/src/gui/char_server.h b/src/gui/char_server.h
deleted file mode 100644
index 3dd66566..00000000
--- a/src/gui/char_server.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * 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$
- */
-
-#ifndef _CHAR_SEL_SERVER_H
-#define _CHAR_SEL_SERVER_H
-
-#include <guichan/actionlistener.hpp>
-#include <guichan/listmodel.hpp>
-
-#include "window.h"
-
-#include "../guichanfwd.h"
-
-class LoginData;
-class ServerListModel;
-
-/**
- * The server select dialog.
- *
- * \ingroup Interface
- */
-class ServerSelectDialog : public Window, public gcn::ActionListener {
- public:
- /**
- * Constructor
- *
- * @see Window::Window
- */
- ServerSelectDialog(LoginData *loginData);
-
- /**
- * Destructor.
- */
- ~ServerSelectDialog();
-
- /**
- * Called when receiving actions from the widgets.
- */
- void action(const std::string& eventId, gcn::Widget* widget);
-
- private:
- LoginData *mLoginData;
- ServerListModel *mServerListModel;
- gcn::ListBox *mServerList;
- gcn::Button *mOkButton;
-};
-
-#endif
diff --git a/src/gui/chat.cpp b/src/gui/chat.cpp
index f188b90e..3dc252ab 100644
--- a/src/gui/chat.cpp
+++ b/src/gui/chat.cpp
@@ -36,12 +36,12 @@
#include "../game.h"
#include "../localplayer.h"
-#include "../net/messageout.h"
-#include "../net/protocol.h"
+#include "../net/chatserver/chatserver.h"
-ChatWindow::ChatWindow(Network *network):
+#include "../net/gameserver/player.h"
+
+ChatWindow::ChatWindow():
Window(""),
- mNetwork(network),
mTmpVisible(false)
{
setWindowName("Chat");
@@ -180,7 +180,7 @@ ChatWindow::chatLog(CHATSKILL act)
}
void
-ChatWindow::action(const std::string& eventId, gcn::Widget* widget)
+ChatWindow::action(const std::string &eventId, gcn::Widget *widget)
{
if (eventId == "chatinput")
{
@@ -249,20 +249,12 @@ ChatWindow::chatSend(const std::string &nick, std::string msg)
// Prepare ordinary message
if (msg.substr(0, 1) != "/") {
- msg = nick + " : " + msg;
-
- MessageOut outMsg(mNetwork);
- outMsg.writeInt16(CMSG_CHAT_MESSAGE);
- outMsg.writeInt16(msg.length() + 4);
- outMsg.writeString(msg, msg.length());
+ Net::GameServer::Player::say(msg);
}
else if (msg.substr(0, IS_ANNOUNCE_LENGTH) == IS_ANNOUNCE)
{
msg.erase(0, IS_ANNOUNCE_LENGTH);
- MessageOut outMsg(mNetwork);
- outMsg.writeInt16(0x0099);
- outMsg.writeInt16(msg.length() + 4);
- outMsg.writeString(msg, msg.length());
+ Net::ChatServer::announce(msg);
}
else if (msg.substr(0, IS_HELP_LENGTH) == IS_HELP)
{
@@ -278,8 +270,10 @@ ChatWindow::chatSend(const std::string &nick, std::string msg)
}
else if (msg.substr(0, IS_WHO_LENGTH) == IS_WHO)
{
- MessageOut outMsg(mNetwork);
- outMsg.writeInt16(0x00c1);
+ // XXX Convert for new server
+ /*
+ MessageOut outMsg(0x00c1);
+ */
}
else
{
diff --git a/src/gui/chat.h b/src/gui/chat.h
index 20841873..a0a3d1ec 100644
--- a/src/gui/chat.h
+++ b/src/gui/chat.h
@@ -35,7 +35,6 @@
#include "../guichanfwd.h"
class BrowserBox;
-class Network;
class ScrollArea;
#define BY_GM 0 // those should be self-explanatory =)
@@ -116,7 +115,7 @@ class ChatWindow : public Window, public gcn::ActionListener,
/**
* Constructor.
*/
- ChatWindow(Network *network);
+ ChatWindow();
/**
* Logic (updates components' size)
@@ -188,7 +187,6 @@ class ChatWindow : public Window, public gcn::ActionListener,
void setVisible(bool visible);
private:
- Network *mNetwork;
bool mTmpVisible;
/** One item in the chat log */
diff --git a/src/gui/confirm_dialog.cpp b/src/gui/confirm_dialog.cpp
index 3bd15589..ed2f8680 100644
--- a/src/gui/confirm_dialog.cpp
+++ b/src/gui/confirm_dialog.cpp
@@ -64,7 +64,7 @@ ConfirmDialog::ConfirmDialog(const std::string &title, const std::string &msg,
yesButton->requestFocus();
}
-void ConfirmDialog::action(const std::string& eventId, gcn::Widget* widget)
+void ConfirmDialog::action(const std::string &eventId, gcn::Widget *widget)
{
// Proxy button events to our listeners
ActionListenerIterator i;
diff --git a/src/gui/connection.cpp b/src/gui/connection.cpp
index 8da36f20..1e0034fb 100644
--- a/src/gui/connection.cpp
+++ b/src/gui/connection.cpp
@@ -35,16 +35,25 @@
namespace {
struct ConnectionActionListener : public gcn::ActionListener
{
- void action(const std::string& eventId, gcn::Widget* widget) { state = EXIT_STATE; }
- } listener;
+ ConnectionActionListener(unsigned char previousState):
+ mPreviousState(previousState) {};
+
+ void action(const std::string &eventId, gcn::Widget *widget) {
+ state = mPreviousState;
+ }
+
+ unsigned char mPreviousState;
+ };
}
-ConnectionDialog::ConnectionDialog():
+ConnectionDialog::ConnectionDialog(unsigned char previousState):
Window("Info"), mProgress(0)
{
setContentSize(200, 100);
- Button *cancelButton = new Button("Cancel", "cancelButton", &listener);
+ ConnectionActionListener *connectionListener = new ConnectionActionListener(previousState);
+
+ Button *cancelButton = new Button("Cancel", "cancelButton", connectionListener);
mProgressBar = new ProgressBar(0.0, 200 - 10, 20, 128, 128, 128);
gcn::Label *label = new gcn::Label("Connecting...");
diff --git a/src/gui/connection.h b/src/gui/connection.h
index 7a072d2e..4b3187f6 100644
--- a/src/gui/connection.h
+++ b/src/gui/connection.h
@@ -41,7 +41,7 @@ class ConnectionDialog : public Window
*
* @see Window::Window
*/
- ConnectionDialog();
+ ConnectionDialog(unsigned char previousState);
void logic();
diff --git a/src/gui/debugwindow.cpp b/src/gui/debugwindow.cpp
index 2f788d05..d467d4d3 100644
--- a/src/gui/debugwindow.cpp
+++ b/src/gui/debugwindow.cpp
@@ -98,7 +98,7 @@ DebugWindow::logic()
}
void
-DebugWindow::action(const std::string& eventId, gcn::Widget* widget)
+DebugWindow::action(const std::string &eventId, gcn::Widget *widget)
{
if (eventId == "close")
{
diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp
index b7f64274..38b17781 100644
--- a/src/gui/gui.cpp
+++ b/src/gui/gui.cpp
@@ -55,6 +55,9 @@
#include "../resources/image.h"
#include "../resources/resourcemanager.h"
#include "../resources/sdlimageloader.h"
+#ifdef USE_OPENGL
+#include "../resources/openglsdlimageloader.h"
+#endif
// Guichan stuff
Gui *gui;
@@ -233,7 +236,7 @@ Gui::mousePress(int mx, int my, int button)
// Mouse pressed on window container (basically, the map)
// Are we in-game yet?
- if (state != GAME_STATE)
+ if (state != STATE_GAME)
return;
// Check if we are alive and kickin'
@@ -244,8 +247,8 @@ Gui::mousePress(int mx, int my, int button)
if (current_npc)
return;
- int tilex = mx / 32 + camera_x;
- int tiley = my / 32 + camera_y;
+ int tilex = (mx + camera_x) / 32;
+ int tiley = (my + camera_y) / 32;
// Right click might open a popup
if (button == gcn::MouseInput::RIGHT)
@@ -307,13 +310,14 @@ Gui::mousePress(int mx, int my, int button)
player_node->pickUp(item);
}
// Just walk around
- else if (engine->getCurrentMap()->getWalk(tilex, tiley))
+ else if (engine->getCurrentMap() &&
+ engine->getCurrentMap()->getWalk(tilex, tiley))
{
// XXX XXX XXX REALLY UGLY!
Uint8 *keys = SDL_GetKeyState(NULL);
if (!(keys[SDLK_LSHIFT] || keys[SDLK_RSHIFT]))
{
- player_node->setDestination(tilex, tiley);
+ player_node->setDestination(mx + camera_x, my + camera_y);
player_node->stopAttack();
}
}
diff --git a/src/gui/help.cpp b/src/gui/help.cpp
index 2b9b649a..e7429b29 100644
--- a/src/gui/help.cpp
+++ b/src/gui/help.cpp
@@ -54,7 +54,7 @@ HelpWindow::HelpWindow():
setLocationRelativeTo(getParent());
}
-void HelpWindow::action(const std::string& eventId, gcn::Widget* widget)
+void HelpWindow::action(const std::string &eventId, gcn::Widget *widget)
{
if (eventId == "close")
{
diff --git a/src/gui/inventorywindow.cpp b/src/gui/inventorywindow.cpp
index eb85220b..452b7c16 100644
--- a/src/gui/inventorywindow.cpp
+++ b/src/gui/inventorywindow.cpp
@@ -98,7 +98,7 @@ void InventoryWindow::logic()
mWeightLabel->adjustSize();
}
-void InventoryWindow::action(const std::string& eventId, gcn::Widget* widget)
+void InventoryWindow::action(const std::string &eventId, gcn::Widget *widget)
{
Item *item = mItems->getItem();
diff --git a/src/gui/item_amount.cpp b/src/gui/item_amount.cpp
index 3f8daddd..30c899a8 100644
--- a/src/gui/item_amount.cpp
+++ b/src/gui/item_amount.cpp
@@ -94,7 +94,7 @@ void ItemAmountWindow::resetAmount()
mItemAmountTextBox->setInt(1);
}
-void ItemAmountWindow::action(const std::string& eventId, gcn::Widget* widget)
+void ItemAmountWindow::action(const std::string &eventId, gcn::Widget *widget)
{
int amount = mItemAmountTextBox->getInt();
diff --git a/src/gui/login.cpp b/src/gui/login.cpp
index 675de078..1d9b6e1e 100644
--- a/src/gui/login.cpp
+++ b/src/gui/login.cpp
@@ -43,7 +43,7 @@ WrongDataNoticeListener::setTarget(gcn::TextField *textField)
}
void
-WrongDataNoticeListener::action(const std::string& eventId, gcn::Widget* widget)
+WrongDataNoticeListener::action(const std::string &eventId, gcn::Widget *widget)
{
if (eventId == "ok")
{
@@ -59,53 +59,43 @@ LoginDialog::LoginDialog(LoginData *loginData):
{
gcn::Label *userLabel = new gcn::Label("Name:");
gcn::Label *passLabel = new gcn::Label("Password:");
- gcn::Label *serverLabel = new gcn::Label("Server:");
mUserField = new TextField(mLoginData->username);
mPassField = new PasswordField(mLoginData->password);
- mServerField = new TextField(mLoginData->hostname);
mKeepCheck = new CheckBox("Keep", mLoginData->remember);
mOkButton = new Button("OK", "ok", this);
mCancelButton = new Button("Cancel", "cancel", this);
mRegisterButton = new Button("Register", "register", this);
- setContentSize(200, 100);
+ setContentSize(200, 91);
userLabel->setPosition(5, 5);
passLabel->setPosition(5, 14 + userLabel->getHeight());
- serverLabel->setPosition(
- 5, 23 + userLabel->getHeight() + passLabel->getHeight());
mUserField->setPosition(65, 5);
mPassField->setPosition(65, 14 + userLabel->getHeight());
- mServerField->setPosition(
- 65, 23 + userLabel->getHeight() + passLabel->getHeight());
mUserField->setWidth(130);
mPassField->setWidth(130);
- mServerField->setWidth(130);
- mKeepCheck->setPosition(4, 77);
+ mKeepCheck->setPosition(4, 68);
mCancelButton->setPosition(
200 - mCancelButton->getWidth() - 5,
- 100 - mCancelButton->getHeight() - 5);
+ 91 - mCancelButton->getHeight() - 5);
mOkButton->setPosition(
mCancelButton->getX() - mOkButton->getWidth() - 5,
- 100 - mOkButton->getHeight() - 5);
- mRegisterButton->setPosition(mKeepCheck->getX() + mKeepCheck->getWidth() + 10,
- 100 - mRegisterButton->getHeight() - 5);
+ 91 - mOkButton->getHeight() - 5);
+ mRegisterButton->setPosition(
+ mKeepCheck->getX() + mKeepCheck->getWidth() + 10,
+ 91 - mRegisterButton->getHeight() - 5);
mUserField->setEventId("ok");
mPassField->setEventId("ok");
- mServerField->setEventId("ok");
mUserField->addActionListener(this);
mPassField->addActionListener(this);
- mServerField->addActionListener(this);
mKeepCheck->addActionListener(this);
add(userLabel);
add(passLabel);
- add(serverLabel);
add(mUserField);
add(mPassField);
- add(mServerField);
add(mKeepCheck);
add(mOkButton);
add(mCancelButton);
@@ -128,7 +118,7 @@ LoginDialog::~LoginDialog()
}
void
-LoginDialog::action(const std::string& eventId, gcn::Widget* widget)
+LoginDialog::action(const std::string &eventId, gcn::Widget *widget)
{
if (eventId == "ok")
{
@@ -141,24 +131,22 @@ LoginDialog::action(const std::string& eventId, gcn::Widget* widget)
}
else
{
- mLoginData->hostname = mServerField->getText();
mLoginData->username = mUserField->getText();
mLoginData->password = mPassField->getText();
mLoginData->remember = mKeepCheck->isMarked();
mOkButton->setEnabled(false);
- //mCancelButton->setEnabled(false);
mRegisterButton->setEnabled(false);
- state = ACCOUNT_STATE;
+ state = STATE_LOGIN_ATTEMPT;
}
}
else if (eventId == "cancel")
{
- state = EXIT_STATE;
+ state = STATE_EXIT;
}
else if (eventId == "register")
{
- state = REGISTER_STATE;
+ state = STATE_REGISTER;
}
}
diff --git a/src/gui/login.h b/src/gui/login.h
index 7218dca8..6d510da7 100644
--- a/src/gui/login.h
+++ b/src/gui/login.h
@@ -70,7 +70,6 @@ class LoginDialog : public Window, public gcn::ActionListener {
private:
gcn::TextField *mUserField;
gcn::TextField *mPassField;
- gcn::TextField *mServerField;
gcn::CheckBox *mKeepCheck;
gcn::Button *mOkButton;
gcn::Button *mCancelButton;
diff --git a/src/gui/menuwindow.cpp b/src/gui/menuwindow.cpp
index 701d9366..a1b342f0 100644
--- a/src/gui/menuwindow.cpp
+++ b/src/gui/menuwindow.cpp
@@ -39,7 +39,7 @@ namespace {
/**
* Called when receiving actions from widget.
*/
- void action(const std::string& eventId, gcn::Widget* widget);
+ void action(const std::string &eventId, gcn::Widget *widget);
} listener;
}
@@ -75,7 +75,7 @@ void MenuWindow::draw(gcn::Graphics *graphics)
}
-void MenuWindowListener::action(const std::string& eventId, gcn::Widget* widget)
+void MenuWindowListener::action(const std::string &eventId, gcn::Widget *widget)
{
Window *window = NULL;
if (eventId == "Status")
diff --git a/src/gui/newskill.cpp b/src/gui/newskill.cpp
index 59cdd9db..7f5de543 100644
--- a/src/gui/newskill.cpp
+++ b/src/gui/newskill.cpp
@@ -121,7 +121,7 @@ NewSkillDialog::NewSkillDialog():
setLocationRelativeTo(getParent());
}
-void NewSkillDialog::action(const std::string& eventId, gcn::Widget* widget)
+void NewSkillDialog::action(const std::string &eventId, gcn::Widget *widget)
{
int osp = startPoint;
if (eventId == "close")
diff --git a/src/gui/npc_text.cpp b/src/gui/npc_text.cpp
index 6b647032..5b7ca439 100644
--- a/src/gui/npc_text.cpp
+++ b/src/gui/npc_text.cpp
@@ -67,7 +67,7 @@ NpcTextDialog::addText(const std::string &text)
}
void
-NpcTextDialog::action(const std::string& eventId, gcn::Widget* widget)
+NpcTextDialog::action(const std::string &eventId, gcn::Widget *widget)
{
if (eventId == "ok")
{
diff --git a/src/gui/npclistdialog.cpp b/src/gui/npclistdialog.cpp
index 895ef1f9..d1c3ddcb 100644
--- a/src/gui/npclistdialog.cpp
+++ b/src/gui/npclistdialog.cpp
@@ -91,7 +91,7 @@ NpcListDialog::reset()
}
void
-NpcListDialog::action(const std::string& eventId, gcn::Widget* widget)
+NpcListDialog::action(const std::string &eventId, gcn::Widget *widget)
{
int choice = 0;
diff --git a/src/gui/ok_dialog.cpp b/src/gui/ok_dialog.cpp
index e527339e..906fd61f 100644
--- a/src/gui/ok_dialog.cpp
+++ b/src/gui/ok_dialog.cpp
@@ -54,7 +54,7 @@ OkDialog::OkDialog(const std::string &title, const std::string &msg,
okButton->requestFocus();
}
-void OkDialog::action(const std::string& eventId, gcn::Widget* widget)
+void OkDialog::action(const std::string &eventId, gcn::Widget *widget)
{
// Proxy button events to our listeners
ActionListenerIterator i;
diff --git a/src/gui/playerbox.cpp b/src/gui/playerbox.cpp
index 0a155573..46cd7e85 100644
--- a/src/gui/playerbox.cpp
+++ b/src/gui/playerbox.cpp
@@ -94,13 +94,13 @@ void PlayerBox::draw(gcn::Graphics *graphics)
playerset[mSex]->get(0), 23, 12);
// Draw his hair
- if (mHairColor >= 0 && mHairStyle >= 0 &&
- mHairColor < NR_HAIR_COLORS && mHairStyle < NR_HAIR_STYLES)
+ if (mHairStyle > 0 && mHairColor < NR_HAIR_COLORS &&
+ mHairStyle < NR_HAIR_STYLES)
{
int hf = 5 * mHairColor;
if (hf >= 0 && hf < (int)hairset[mHairStyle]->size()) {
dynamic_cast<Graphics*>(graphics)->drawImage(
- hairset[mHairStyle]->get(hf), 35, 7);
+ hairset[mHairStyle - 1]->get(hf), 35, 7);
}
}
}
diff --git a/src/gui/playerbox.h b/src/gui/playerbox.h
index 79f7c2aa..ec04eaf6 100644
--- a/src/gui/playerbox.h
+++ b/src/gui/playerbox.h
@@ -57,10 +57,10 @@ class PlayerBox : public gcn::ScrollArea
*/
void drawBorder(gcn::Graphics *graphics);
- int mHairColor; /**< The hair color index */
- int mHairStyle; /**< The hair style index */
- unsigned char mSex; /**< Sex */
- bool mShowPlayer; /**< Wether to show the player or not */
+ unsigned char mHairColor; /**< The hair color index */
+ unsigned char mHairStyle; /**< The hair style index */
+ unsigned char mSex; /**< Sex */
+ bool mShowPlayer; /**< Wether to show the player or not */
private:
static int instances;
diff --git a/src/gui/register.cpp b/src/gui/register.cpp
index 1c1f0a26..7cef62a2 100644
--- a/src/gui/register.cpp
+++ b/src/gui/register.cpp
@@ -44,24 +44,21 @@
RegisterDialog::RegisterDialog(LoginData *loginData):
Window("Register"),
mWrongDataNoticeListener(new WrongDataNoticeListener()),
- mWrongRegisterNotice(0),
mLoginData(loginData)
{
gcn::Label *userLabel = new gcn::Label("Name:");
gcn::Label *passwordLabel = new gcn::Label("Password:");
gcn::Label *confirmLabel = new gcn::Label("Confirm:");
- gcn::Label *serverLabel = new gcn::Label("Server:");
+ gcn::Label *emailLabel = new gcn::Label("Email:");
mUserField = new TextField("player");
mPasswordField = new PasswordField();
mConfirmField = new PasswordField();
- mServerField = new TextField();
- mMaleButton = new RadioButton("Male", "sex", true);
- mFemaleButton = new RadioButton("Female", "sex", false);
+ mEmailField = new TextField();
mRegisterButton = new Button("Register", "register", this);
mCancelButton = new Button("Cancel", "cancel", this);
- int width = 200;
- int height = 150;
+ const int width = 200;
+ const int height = 130;
setContentSize(width, height);
mUserField->setPosition(65, 5);
@@ -72,55 +69,49 @@ RegisterDialog::RegisterDialog(LoginData *loginData):
mConfirmField->setPosition(
65, mPasswordField->getY() + mPasswordField->getHeight() + 7);
mConfirmField->setWidth(130);
- mServerField->setPosition(
- 65, 23 + mConfirmField->getY() + mConfirmField->getHeight() + 7);
- mServerField->setWidth(130);
+ mEmailField->setPosition(
+ 65, mConfirmField->getY() + mConfirmField->getHeight() + 7);
+ mEmailField->setWidth(130);
userLabel->setPosition(5, mUserField->getY() + 1);
passwordLabel->setPosition(5, mPasswordField->getY() + 1);
confirmLabel->setPosition(5, mConfirmField->getY() + 1);
- serverLabel->setPosition(5, mServerField->getY() + 1);
+ emailLabel->setPosition(5, mEmailField->getY() + 1);
- mFemaleButton->setPosition(width - mFemaleButton->getWidth() - 10,
- mConfirmField->getY() + mConfirmField->getHeight() + 7);
- mMaleButton->setPosition(mFemaleButton->getX() - mMaleButton->getWidth() - 5,
- mFemaleButton->getY());
-
- mRegisterButton->setPosition(5, height - mRegisterButton->getHeight() - 5);
- mCancelButton->setPosition(10 + mRegisterButton->getWidth(),
- mRegisterButton->getY());
+ mCancelButton->setPosition(
+ width - 5 - mCancelButton->getWidth(),
+ height - 5 - mCancelButton->getHeight());
+ mRegisterButton->setPosition(
+ mCancelButton->getX() - 5 - mRegisterButton->getWidth(),
+ mCancelButton->getY());
add(userLabel);
add(passwordLabel);
- add(serverLabel);
+ add(emailLabel);
add(confirmLabel);
add(mUserField);
add(mPasswordField);
add(mConfirmField);
- add(mServerField);
- add(mMaleButton);
- add(mFemaleButton);
+ add(mEmailField);
add(mRegisterButton);
add(mCancelButton);
setLocationRelativeTo(getParent());
mUserField->requestFocus();
mUserField->setCaretPosition(mUserField->getText().length());
-
- mServerField->setText(config.getValue("host", ""));
}
RegisterDialog::~RegisterDialog()
{
- delete mWrongRegisterNotice;
+ delete mWrongDataNoticeListener;
}
void
-RegisterDialog::action(const std::string& eventId, gcn::Widget* widget)
+RegisterDialog::action(const std::string &eventId, gcn::Widget *widget)
{
if (eventId == "cancel")
{
- state = EXIT_STATE;
+ state = STATE_LOGIN;
}
else if (eventId == "register")
{
@@ -176,6 +167,8 @@ RegisterDialog::action(const std::string& eventId, gcn::Widget* widget)
error = 2;
}
+ // TODO: Check if a valid email address was given
+
if (error > 0)
{
if (error == 1)
@@ -189,22 +182,20 @@ RegisterDialog::action(const std::string& eventId, gcn::Widget* widget)
mConfirmField->setText("");
}
- delete mWrongRegisterNotice;
- mWrongRegisterNotice = new OkDialog("Error", errorMsg.str());
- mWrongRegisterNotice->addActionListener(mWrongDataNoticeListener);
+ OkDialog *dlg = new OkDialog("Error", errorMsg.str());
+ dlg->addActionListener(mWrongDataNoticeListener);
}
else
{
// No errors detected, register the new user.
mRegisterButton->setEnabled(false);
- mLoginData->hostname = config.getValue("host", "animesites.de");
mLoginData->port = (short)config.getValue("port", 0);
mLoginData->username = mUserField->getText();
mLoginData->password = mPasswordField->getText();
- mLoginData->username += mFemaleButton->isMarked() ? "_F" : "_M";
+ mLoginData->email = mEmailField->getText();
- state = ACCOUNT_STATE;
+ state = STATE_REGISTER_ATTEMPT;
}
}
}
diff --git a/src/gui/register.h b/src/gui/register.h
index 5d3f6cd5..4c98788f 100644
--- a/src/gui/register.h
+++ b/src/gui/register.h
@@ -65,15 +65,12 @@ class RegisterDialog : public Window, public gcn::ActionListener {
gcn::TextField *mUserField;
gcn::TextField *mPasswordField;
gcn::TextField *mConfirmField;
- gcn::TextField *mServerField;
+ gcn::TextField *mEmailField;
gcn::Button *mRegisterButton;
gcn::Button *mCancelButton;
- gcn::RadioButton *mMaleButton;
- gcn::RadioButton *mFemaleButton;
WrongDataNoticeListener *mWrongDataNoticeListener;
- OkDialog *mWrongRegisterNotice;
LoginData *mLoginData;
};
diff --git a/src/gui/selectionlistener.h b/src/gui/selectionlistener.h
index b39672b5..a2fc6533 100644
--- a/src/gui/selectionlistener.h
+++ b/src/gui/selectionlistener.h
@@ -18,7 +18,7 @@
* 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$
+ * $Id: selectionlistener.h 2651 2006-09-03 16:47:48Z b_lindeijer $
*/
#ifndef _TMW_SELECTIONLISTENER_H__
diff --git a/src/gui/sell.cpp b/src/gui/sell.cpp
index 7f50c1e4..9c25aced 100644
--- a/src/gui/sell.cpp
+++ b/src/gui/sell.cpp
@@ -28,7 +28,7 @@
#include <guichan/widgets/label.hpp>
#include "button.h"
-#include "shoplistbox.h"
+#include "listbox.h"
#include "scrollarea.h"
#include "shop.h"
#include "slider.h"
@@ -39,23 +39,19 @@
#include "../resources/iteminfo.h"
#include "../resources/itemmanager.h"
-#include "../net/messageout.h"
-#include "../net/protocol.h"
-
#include "../utils/tostring.h"
-SellDialog::SellDialog(Network *network):
+SellDialog::SellDialog():
Window("Sell"),
- mNetwork(network),
mMaxItems(0), mAmountItems(0)
{
mShopItems = new ShopItems();
- mShopItemList = new ShopListBox(mShopItems, mShopItems);
- ScrollArea *scrollArea = new ScrollArea(mShopItemList);
+ mItemList = new ListBox(mShopItems);
+ ScrollArea *scrollArea = new ScrollArea(mItemList);
mSlider = new Slider(1.0);
mQuantityLabel = new gcn::Label("0");
- mMoneyLabel = new gcn::Label("Money: 0 GP / Total: 0 GP");
+ mMoneyLabel = new gcn::Label("Price: 0");
mItemDescLabel = new gcn::Label("Description:");
mItemEffectLabel = new gcn::Label("Effect:");
mIncreaseButton = new Button("+", "+", this);
@@ -67,7 +63,7 @@ SellDialog::SellDialog(Network *network):
setContentSize(260, 210);
scrollArea->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
scrollArea->setDimension(gcn::Rectangle(5, 5, 250, 110));
- mShopItemList->setDimension(gcn::Rectangle(5, 5, 238, 110));
+ mItemList->setDimension(gcn::Rectangle(5, 5, 238, 110));
mSlider->setDimension(gcn::Rectangle(5, 120, 200, 10));
mSlider->setEnabled(false);
@@ -91,13 +87,11 @@ SellDialog::SellDialog(Network *network):
quitButton->setPosition(208, 186);
- mShopItemList->setEventId("item");
+ mItemList->setEventId("item");
mSlider->setEventId("mSlider");
- mShopItemList->setPriceCheck(false);
-
- mShopItemList->addActionListener(this);
- mShopItemList->addSelectionListener(this);
+ mItemList->addActionListener(this);
+ mItemList->addSelectionListener(this);
mSlider->addActionListener(this);
add(scrollArea);
@@ -127,14 +121,13 @@ void SellDialog::reset()
mQuantityLabel->setCaption("0");
mQuantityLabel->adjustSize();
- mMoneyLabel->setCaption("Money: 0 GP / Total: "
- + toString(mPlayerMoney) + " GP");
+ mMoneyLabel->setCaption("Price: 0");
mMoneyLabel->adjustSize();
mItemDescLabel->setCaption("");
mItemEffectLabel->setCaption("");
// Reset Previous Selected Items to prevent failing asserts
- mShopItemList->setSelected(-1);
+ mItemList->setSelected(-1);
mIncreaseButton->setEnabled(false);
mDecreaseButton->setEnabled(false);
}
@@ -151,15 +144,14 @@ void SellDialog::addItem(Item *item, int price)
item_shop.index = item->getInvIndex();
item_shop.id = item->getId();
item_shop.quantity = item->getQuantity();
- item_shop.image = item->getInfo().getImage();
mShopItems->push_back(item_shop);
- mShopItemList->adjustSize();
+ mItemList->adjustSize();
}
-void SellDialog::action(const std::string& eventId, gcn::Widget* widget)
+void SellDialog::action(const std::string &eventId, gcn::Widget *widget)
{
- int selectedItem = mShopItemList->getSelected();
+ int selectedItem = mItemList->getSelected();
if (eventId == "item")
{
@@ -168,22 +160,19 @@ void SellDialog::action(const std::string& eventId, gcn::Widget* widget)
mDecreaseButton->setEnabled(false);
mSellButton->setEnabled(false);
+ mQuantityLabel->setCaption("0");
mQuantityLabel->adjustSize();
- mMoneyLabel->setCaption("Money: 0 GP / Total: "
- + toString(mPlayerMoney) + " GP");
+ mMoneyLabel->setCaption("Price: 0");
mMoneyLabel->adjustSize();
if (selectedItem > -1) {
mSlider->setEnabled(true);
mIncreaseButton->setEnabled(true);
mMaxItems = mShopItems->at(selectedItem).quantity;
- mQuantityLabel->setCaption("0 / " + toString(mMaxItems));
} else {
mSlider->setEnabled(false);
mIncreaseButton->setEnabled(false);
- mQuantityLabel->setCaption("0");
}
- mQuantityLabel->adjustSize();
}
else if (eventId == "quit")
{
@@ -192,7 +181,7 @@ void SellDialog::action(const std::string& eventId, gcn::Widget* widget)
}
// The following actions require a valid item selection
- if (selectedItem == -1 || selectedItem >= int(mShopItems->getNumberOfElements())) {
+ if (selectedItem == -1 || selectedItem >= int(mShopItems->size())) {
return;
}
@@ -226,23 +215,23 @@ void SellDialog::action(const std::string& eventId, gcn::Widget* widget)
// Attempt sell
assert(mAmountItems > 0 && mAmountItems <= mMaxItems);
- MessageOut outMsg(mNetwork);
- outMsg.writeInt16(CMSG_NPC_SELL_REQUEST);
- outMsg.writeInt16(8);
- outMsg.writeInt16(mShopItems->at(selectedItem).index);
- outMsg.writeInt16(mAmountItems);
+ // XXX Convert for new server
+ /*
+ MessageOut outMsg(CMSG_NPC_SELL_REQUEST);
+ outMsg.writeShort(8);
+ outMsg.writeShort(mShopItems->at(selectedItem).index);
+ outMsg.writeShort(mAmountItems);
+ */
mMaxItems -= mAmountItems;
- mShopItems->getShop()->at(selectedItem).quantity = mMaxItems;
mAmountItems = 0;
mSlider->setValue(0);
mSlider->setEnabled(mMaxItems != 0);
// All were sold
if (!mMaxItems) {
-
- mShopItemList->setSelected(-1);
- mShopItems->getShop()->erase(mShopItems->getShop()->begin() + selectedItem);
+ mItemList->setSelected(-1);
+ mShopItems->erase(mShopItems->begin() + selectedItem);
}
// Update only when there are items left, the entry doesn't exist
@@ -254,12 +243,11 @@ void SellDialog::action(const std::string& eventId, gcn::Widget* widget)
if (updateButtonsAndLabels)
{
// Update labels
- mQuantityLabel->setCaption(toString(mAmountItems) + " / " + toString(mMaxItems));
+ mQuantityLabel->setCaption(toString(mAmountItems));
mQuantityLabel->adjustSize();
int price = mAmountItems * mShopItems->at(selectedItem).price;
- mMoneyLabel->setCaption("Money: " + toString(price) + " GP / Total: "
- + toString(price + mPlayerMoney) + " GP");
+ mMoneyLabel->setCaption("Price: " + toString(price));
mMoneyLabel->adjustSize();
// Update Buttons
@@ -271,7 +259,7 @@ void SellDialog::action(const std::string& eventId, gcn::Widget* widget)
void SellDialog::selectionChanged(const SelectionEvent &event)
{
- int selectedItem = mShopItemList->getSelected();
+ int selectedItem = mItemList->getSelected();
if (selectedItem > -1)
{
@@ -287,9 +275,3 @@ void SellDialog::selectionChanged(const SelectionEvent &event)
mItemEffectLabel->setCaption("Effect");
}
}
-
-void SellDialog::setMoney(int amount)
-{
- mPlayerMoney = amount;
- mShopItemList->setPlayersMoney(amount);
-}
diff --git a/src/gui/sell.h b/src/gui/sell.h
index f27a9751..69f8b089 100644
--- a/src/gui/sell.h
+++ b/src/gui/sell.h
@@ -32,9 +32,8 @@
#include "../guichanfwd.h"
class Item;
-class Network;
class ShopItems;
-class ShopListBox;
+class ListBox;
/**
* The sell dialog.
@@ -49,7 +48,7 @@ class SellDialog : public Window, gcn::ActionListener, SelectionListener
*
* @see Window::Window
*/
- SellDialog(Network *network);
+ SellDialog();
/**
* Destructor
@@ -78,17 +77,11 @@ class SellDialog : public Window, gcn::ActionListener, SelectionListener
*/
void selectionChanged(const SelectionEvent &event);
- /**
- * Gives Player's Money amount
- */
- void setMoney(int amount);
-
private:
- Network *mNetwork;
gcn::Button *mSellButton;
gcn::Button *mIncreaseButton;
gcn::Button *mDecreaseButton;
- ShopListBox *mShopItemList;
+ ListBox *mItemList;
gcn::Label *mMoneyLabel;
gcn::Label *mItemDescLabel;
gcn::Label *mItemEffectLabel;
@@ -96,7 +89,6 @@ class SellDialog : public Window, gcn::ActionListener, SelectionListener
gcn::Slider *mSlider;
ShopItems *mShopItems;
- int mPlayerMoney;
int mMaxItems;
int mAmountItems;
diff --git a/src/gui/serverdialog.cpp b/src/gui/serverdialog.cpp
new file mode 100644
index 00000000..39abd5ed
--- /dev/null
+++ b/src/gui/serverdialog.cpp
@@ -0,0 +1,246 @@
+/*
+ * 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: login.cpp 2550 2006-08-20 00:56:23Z b_lindeijer $
+ */
+
+#include "serverdialog.h"
+
+#include <iostream>
+#include <string>
+
+#include <guichan/widgets/label.hpp>
+
+#include "button.h"
+#include "listbox.h"
+#include "ok_dialog.h"
+#include "scrollarea.h"
+#include "textfield.h"
+
+#include "../configuration.h"
+#include "../log.h"
+#include "../logindata.h"
+#include "../main.h"
+
+#include "../utils/tostring.h"
+
+const short MAX_SERVERLIST = 5;
+
+void
+DropDownListener::action(const std::string &eventId, gcn::Widget *widget)
+{
+ if (eventId == "ok")
+ {
+ // Reset the text fields and give back the server dialog.
+ mServerNameField->setText("");
+ mServerNameField->setCaretPosition(0);
+ mServerPortField->setText("");
+ mServerPortField->setCaretPosition(0);
+
+ mServerNameField->requestFocus();
+ }
+ else if (eventId == "changeSelection")
+ {
+ // Change the textField Values according to new selection
+ if (currentSelectedIndex != mServersListBox->getSelected())
+ {
+ Server myServer;
+ myServer = mServersListModel->getServer(mServersListBox->getSelected());
+ mServerNameField->setText(myServer.serverName);
+ mServerPortField->setText(toString(myServer.port));
+ currentSelectedIndex = mServersListBox->getSelected();
+ }
+ }
+}
+
+int ServersListModel::getNumberOfElements()
+{
+ return servers.size();
+}
+
+std::string ServersListModel::getElementAt(int elementIndex)
+{
+ std::string myServer = "";
+ myServer = servers.at(elementIndex).serverName;
+ myServer += ":";
+ myServer += toString(servers.at(elementIndex).port);
+ return myServer;
+}
+
+void ServersListModel::addFirstElement(Server server)
+{
+ // Equivalent to push_front
+ std::vector<Server>::iterator MyIterator = servers.begin();
+ servers.insert(MyIterator, 1, server);
+}
+
+void ServersListModel::addElement(Server server)
+{
+ servers.push_back(server);
+}
+
+ServerDialog::ServerDialog(LoginData *loginData):
+ Window("Choose your Mana World Server"), mLoginData(loginData)
+{
+ gcn::Label *serverLabel = new gcn::Label("Server:");
+ gcn::Label *portLabel = new gcn::Label("Port:");
+ mServerNameField = new TextField(mLoginData->hostname);
+ mPortField = new TextField(toString(mLoginData->port));
+
+ // Add the most used servers from config
+ mMostUsedServersListModel = new ServersListModel();
+ Server currentServer;
+ std::string currentConfig = "";
+ for (int i=0; i<=MAX_SERVERLIST; i++)
+ {
+ currentServer.serverName = "";
+ currentServer.port = 0;
+
+ currentConfig = "MostUsedServerName" + toString(i);
+ currentServer.serverName = config.getValue(currentConfig, "");
+
+ currentConfig = "MostUsedServerPort" + toString(i);
+ currentServer.port = (short)atoi(config.getValue(currentConfig, "").c_str());
+ if (!currentServer.serverName.empty() || currentServer.port != 0)
+ {
+ mMostUsedServersListModel->addElement(currentServer);
+ }
+ }
+
+ mMostUsedServersListBox = new ListBox(NULL);
+ mMostUsedServersListBox->setListModel(mMostUsedServersListModel);
+ mMostUsedServersScrollArea = new ScrollArea();
+ mMostUsedServersDropDown = new DropDown(mMostUsedServersListModel,
+ mMostUsedServersScrollArea, mMostUsedServersListBox);
+
+ mDropDownListener = new DropDownListener(mServerNameField, mPortField,
+ mMostUsedServersListModel, mMostUsedServersListBox);
+
+ mOkButton = new Button("OK", "ok", this);
+ mCancelButton = new Button("Cancel", "cancel", this);
+
+ setContentSize(200, 100);
+
+ serverLabel->setPosition(10, 5);
+ portLabel->setPosition(10, 14 + serverLabel->getHeight());
+
+ mServerNameField->setPosition(60, 5);
+ mPortField->setPosition(60, 14 + serverLabel->getHeight());
+ mServerNameField->setWidth(130);
+ mPortField->setWidth(130);
+
+ mMostUsedServersDropDown->setPosition(10, 10 +
+ portLabel->getY() + portLabel->getHeight());
+ mMostUsedServersDropDown->setWidth(180);
+
+ mCancelButton->setPosition(
+ 200 - mCancelButton->getWidth() - 5,
+ 100 - mCancelButton->getHeight() - 5);
+ mOkButton->setPosition(
+ mCancelButton->getX() - mOkButton->getWidth() - 5,
+ 100 - mOkButton->getHeight() - 5);
+
+ mServerNameField->setEventId("ok");
+ mPortField->setEventId("ok");
+ mMostUsedServersDropDown->setEventId("changeSelection");
+
+ mServerNameField->addActionListener(this);
+ mPortField->addActionListener(this);
+ mMostUsedServersDropDown->addActionListener(mDropDownListener);
+
+ add(serverLabel);
+ add(portLabel);
+ add(mServerNameField);
+ add(mPortField);
+ add(mMostUsedServersDropDown);
+ add(mOkButton);
+ add(mCancelButton);
+
+ setLocationRelativeTo(getParent());
+
+ if (mServerNameField->getText().empty()) {
+ mServerNameField->requestFocus();
+ } else {
+ if (mPortField->getText().empty()) {
+ mPortField->requestFocus();
+ } else {
+ mOkButton->requestFocus();
+ }
+ }
+}
+
+ServerDialog::~ServerDialog()
+{
+ delete mDropDownListener;
+}
+
+void
+ServerDialog::action(const std::string &eventId, gcn::Widget *widget)
+{
+ if (eventId == "ok")
+ {
+ // Check login
+ if (mServerNameField->getText().empty() || mPortField->getText().empty())
+ {
+ OkDialog *dlg = new OkDialog("Error", "Enter the chosen server.");
+ dlg->addActionListener(mDropDownListener);
+ }
+ else
+ {
+ mLoginData->hostname = mServerNameField->getText();
+ mLoginData->port = (short) atoi(mPortField->getText().c_str());
+ mOkButton->setEnabled(false);
+ mCancelButton->setEnabled(false);
+
+ // First, look if the entry is a new one.
+ Server currentServer;
+ bool newEntry = true;
+ for (int i = 0; i < mMostUsedServersListModel->getNumberOfElements(); i++)
+ {
+ currentServer = mMostUsedServersListModel->getServer(i);
+ if (currentServer.serverName == mLoginData->hostname &&
+ currentServer.port == mLoginData->port)
+ newEntry = false;
+ }
+ // Then, add it to config if it's really new
+ currentServer.serverName = mLoginData->hostname;
+ currentServer.port = mLoginData->port;
+ if (newEntry)
+ mMostUsedServersListModel->addFirstElement(currentServer);
+ // Write the entry in config
+ std::string currentConfig = "";
+ for (int i = 0; i < mMostUsedServersListModel->getNumberOfElements(); i++)
+ {
+ currentServer = mMostUsedServersListModel->getServer(i);
+
+ currentConfig = "MostUsedServerName" + toString(i);
+ config.setValue(currentConfig, currentServer.serverName);
+
+ currentConfig = "MostUsedServerPort" + toString(i);
+ config.setValue(currentConfig, toString(currentServer.port));
+ }
+ state = STATE_CONNECT_ACCOUNT;
+ }
+ }
+ else if (eventId == "cancel")
+ {
+ state = STATE_EXIT;
+ }
+}
diff --git a/src/gui/serverdialog.h b/src/gui/serverdialog.h
new file mode 100644
index 00000000..5b265c17
--- /dev/null
+++ b/src/gui/serverdialog.h
@@ -0,0 +1,153 @@
+/*
+ * 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: login.h 2486 2006-07-30 14:33:28Z b_lindeijer $
+ */
+
+#ifndef _TMW_SERVERDIALOG_H
+#define _TMW_SERVERDIALOG_H
+
+#include <iosfwd>
+#include <vector>
+
+#include <guichan/actionlistener.hpp>
+#include <guichan/listmodel.hpp>
+#include "./widgets/dropdown.h"
+
+#include "login.h"
+#include "window.h"
+
+#include "../guichanfwd.h"
+
+#include "../net/network.h"
+
+class LoginData;
+
+/**
+ * A server structure to keep pairs of servers and ports.
+ */
+struct Server {
+ Server():
+ serverName(""),
+ port(0) {};
+
+ std::string serverName;
+ short port;
+};
+
+/**
+ * Server and Port List Model
+ */
+class ServersListModel : public gcn::ListModel
+{
+ public:
+ /**
+ * Used to get number of line in the list
+ */
+ int getNumberOfElements();
+ /**
+ * Used to get an element from the list
+ */
+ std::string getElementAt(int elementIndex);
+ /**
+ * Used to get the corresponding Server struct
+ */
+ Server getServer(int elementIndex) { return servers[elementIndex]; };
+ /**
+ * Add an Element at the end of the server list
+ */
+ void addElement(Server server);
+ /**
+ * Add an Element at the beginning of the server list
+ */
+ void addFirstElement(Server server);
+
+ private:
+ std::vector<Server> servers;
+};
+
+/**
+ * Listener used for handling the DropDown in the server Dialog.
+ */
+class DropDownListener : public gcn::ActionListener
+{
+ public:
+ DropDownListener(gcn::TextField *serverNameField,
+ gcn::TextField *serverPortField,
+ ServersListModel *serversListModel,
+ gcn::ListBox *serversListBox):
+ currentSelectedIndex(0),
+ mServerNameField(serverNameField),
+ mServerPortField(serverPortField),
+ mServersListModel(serversListModel),
+ mServersListBox(serversListBox) {};
+ void action(const std::string& eventId,
+ gcn::Widget* widget);
+ private:
+ short currentSelectedIndex;
+ gcn::TextField *mServerNameField;
+ gcn::TextField *mServerPortField;
+ ServersListModel *mServersListModel;
+ gcn::ListBox *mServersListBox;
+};
+
+
+/**
+ * The server choice dialog.
+ *
+ * \ingroup Interface
+ */
+class ServerDialog : public Window, public gcn::ActionListener
+{
+ public:
+ /**
+ * Constructor
+ *
+ * @see Window::Window
+ */
+ ServerDialog(LoginData *loginData);
+
+ /**
+ * Destructor
+ */
+ ~ServerDialog();
+
+ /**
+ * Called when receiving actions from the widgets.
+ */
+ void action(const std::string& eventId, gcn::Widget* widget);
+
+ private:
+ gcn::TextField *mServerNameField;
+ gcn::TextField *mPortField;
+ gcn::Button *mOkButton;
+ gcn::Button *mCancelButton;
+
+ DropDown *mMostUsedServersDropDown;
+ gcn::ListBox *mMostUsedServersListBox;
+ gcn::ScrollArea *mMostUsedServersScrollArea;
+ ServersListModel *mMostUsedServersListModel;
+
+ DropDownListener *mDropDownListener;
+
+ LoginData *mLoginData;
+};
+
+#endif
diff --git a/src/gui/setup.cpp b/src/gui/setup.cpp
index 7deb39ff..78b10498 100644
--- a/src/gui/setup.cpp
+++ b/src/gui/setup.cpp
@@ -85,7 +85,7 @@ Setup::~Setup()
for_each(mTabs.begin(), mTabs.end(), make_dtor(mTabs));
}
-void Setup::action(const std::string& event, gcn::Widget* widget)
+void Setup::action(const std::string& event, gcn::Widget *widget)
{
if (event == "Apply")
{
diff --git a/src/gui/setup_audio.cpp b/src/gui/setup_audio.cpp
index ac5771ad..db88ff64 100644
--- a/src/gui/setup_audio.cpp
+++ b/src/gui/setup_audio.cpp
@@ -108,7 +108,7 @@ void Setup_Audio::cancel()
config.setValue("musicVolume", mMusicVolume);
}
-void Setup_Audio::action(const std::string& event, gcn::Widget* widget)
+void Setup_Audio::action(const std::string& event, gcn::Widget *widget)
{
if (event == "sfx")
{
diff --git a/src/gui/setup_video.cpp b/src/gui/setup_video.cpp
index 22d0520e..7a4aae03 100644
--- a/src/gui/setup_video.cpp
+++ b/src/gui/setup_video.cpp
@@ -42,6 +42,7 @@
#include "../configuration.h"
#include "../graphics.h"
#include "../log.h"
+#include "../main.h"
#include "../utils/tostring.h"
diff --git a/src/gui/setup_video.h b/src/gui/setup_video.h
index df6dc85e..482d1c65 100644
--- a/src/gui/setup_video.h
+++ b/src/gui/setup_video.h
@@ -44,7 +44,7 @@ class Setup_Video : public SetupTab, public gcn::ActionListener,
void action(const std::string &eventId, gcn::Widget *widget);
/** Called when key is pressed */
- void keyPress(const gcn::Key &key);
+ void keyPress(const gcn::Key& key);
private:
bool mFullScreenEnabled;
diff --git a/src/gui/shop.cpp b/src/gui/shop.cpp
index 3f30732a..3706cdf8 100644
--- a/src/gui/shop.cpp
+++ b/src/gui/shop.cpp
@@ -22,53 +22,13 @@
*/
#include "shop.h"
-#include "../utils/tostring.h"
-#include "../resources/itemmanager.h"
-
-ShopItems::~ShopItems()
-{
- clear();
-}
int ShopItems::getNumberOfElements()
{
- return mItemsShop.size();
+ return size();
}
std::string ShopItems::getElementAt(int i)
{
- return mItemsShop.at(i).name;
-}
-
-void ShopItems::addItem(short id, int price)
-{
- ITEM_SHOP item_shop;
-
- item_shop.name = itemDb->getItemInfo(id).getName()
- + " " + toString(price) + " GP";
- item_shop.price = price;
- item_shop.id = id;
- item_shop.image = itemDb->getItemInfo(id).getImage();
-
- mItemsShop.push_back(item_shop);
-}
-
-ITEM_SHOP ShopItems::at(int i)
-{
- return mItemsShop.at(i);
-}
-
-void ShopItems::push_back(ITEM_SHOP item_shop)
-{
- mItemsShop.push_back(item_shop);
-}
-
-void ShopItems::clear()
-{
- mItemsShop.clear();
-}
-
-std::vector<ITEM_SHOP>* ShopItems::getShop()
-{
- return &mItemsShop;
+ return at(i).name;
}
diff --git a/src/gui/shop.h b/src/gui/shop.h
index de452b5c..fb1f33fd 100644
--- a/src/gui/shop.h
+++ b/src/gui/shop.h
@@ -28,34 +28,22 @@
#include <vector>
#include <guichan/listmodel.hpp>
-#include "../resources/image.h"
struct ITEM_SHOP {
- short id;
std::string name;
- Image *image;
int price;
+ short id;
int index;
int quantity;
};
-class ShopItems : public gcn::ListModel
+class ShopItems : public std::vector<ITEM_SHOP>, public gcn::ListModel
{
public:
/**
* Destructor
*/
- ~ShopItems();
-
- /**
- * Adds an item and its associated picture
- */
- void addItem(short id, int price);
-
- /**
- * Convenience function for adding items
- */
- void push_back(ITEM_SHOP item_shop);
+ virtual ~ShopItems() {};
/**
* Returns the number of items in the shop.
@@ -66,25 +54,6 @@ class ShopItems : public gcn::ListModel
* Returns the name of item number i in the shop.
*/
std::string getElementAt(int i);
-
- /**
- * Returns the item number i in the shop.
- */
- ITEM_SHOP at(int i);
-
- /**
- * Clear the vector.
- */
- void clear();
-
- /**
- * Direct access to the vector
- */
- std::vector<ITEM_SHOP>* getShop();
-
- private:
- std::vector<ITEM_SHOP> mItemsShop;
-
};
#endif
diff --git a/src/gui/shoplistbox.cpp b/src/gui/shoplistbox.cpp
deleted file mode 100644
index 61abff35..00000000
--- a/src/gui/shoplistbox.cpp
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * 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: listbox.cpp 2655 2006-09-03 21:25:02Z b_lindeijer $
- */
-
-#include "shoplistbox.h"
-
-#include "selectionlistener.h"
-
-#include <guichan/font.hpp>
-#include <guichan/graphics.hpp>
-#include <guichan/listmodel.hpp>
-#include <guichan/mouseinput.hpp>
-#include <guichan/imagefont.hpp>
-#include <guichan/basiccontainer.hpp>
-
-#include "../graphics.h"
-
-const int ITEM_SPRITE_HEIGHT = 32;
-
-ShopListBox::ShopListBox(gcn::ListModel *listModel):
- gcn::ListBox(listModel),
- mMousePressed(false),
- mPlayerMoney(0)
-{
- mRowHeight = getFont()->getHeight();
- mPriceCheck = true;
-}
-
-ShopListBox::ShopListBox(gcn::ListModel *listModel, ShopItems *shopListModel):
- gcn::ListBox(listModel),
- mMousePressed(false),
- mPlayerMoney(0),
- mShopItems(shopListModel)
-{
- mRowHeight = (getFont()->getHeight() > ITEM_SPRITE_HEIGHT ?
- getFont()->getHeight() : ITEM_SPRITE_HEIGHT);
- mPriceCheck = true;
-}
-
-
-void ShopListBox::setPlayersMoney(int money)
-{
- mPlayerMoney = money;
-}
-
-void ShopListBox::draw(gcn::Graphics *graphics)
-{
- if (mListModel == NULL) {
- return;
- }
-
- graphics->setFont(getFont());
-
- // Draw the list elements
- for (int i = 0, y = 0; i < mListModel->getNumberOfElements(); ++i, y += mRowHeight)
- {
- graphics->setColor(gcn::Color(0xffffff));
- if (mShopItems != NULL)
- {
- if(mPlayerMoney < mShopItems->at(i).price && mPriceCheck)
- {
- graphics->setColor(gcn::Color(0x919191));
- }
- }
- graphics->fillRectangle(gcn::Rectangle(0, y, getWidth(), mRowHeight));
- if (mShopItems)
- dynamic_cast<Graphics*>(graphics)->drawImage(mShopItems->at(i).image, 1, y);
- graphics->drawText(mListModel->getElementAt(i), ITEM_SPRITE_HEIGHT, y);
- }
-
- // Draw rectangle below the selected list element and the list element
- // not shown.
- if (mSelected >= 0) {
- graphics->setColor(gcn::Color(110, 160, 255));
- graphics->fillRectangle(gcn::Rectangle(0, mRowHeight * mSelected,
- getWidth(), mRowHeight));
- if (mShopItems)
- dynamic_cast<Graphics*>(graphics)->drawImage(
- mShopItems->at(mSelected).image, 1, mRowHeight * mSelected);
- graphics->drawText(mListModel->getElementAt(mSelected),
- ITEM_SPRITE_HEIGHT, mRowHeight * mSelected);
- }
-}
-
-void ShopListBox::setSelected(int selected)
-{
- gcn::ListBox::setSelected(selected);
- if (mListModel != NULL)
- {
- gcn::BasicContainer *par = getParent();
- if (par == NULL)
- {
- return;
- }
-
- gcn::Rectangle scroll;
-
- if (mSelected < 0)
- {
- scroll.y = 0;
- }
- else
- {
- scroll.y = mRowHeight * mSelected;
- }
-
- scroll.height = mRowHeight;
- par->showWidgetPart(this, scroll);
- }
- fireSelectionChangedEvent();
-}
-
-void ShopListBox::mousePress(int x, int y, int button)
-{
-
- bool enoughMoney = false;
- if (button == gcn::MouseInput::LEFT && hasMouse())
- {
- if (mShopItems)
- {
- if(mPlayerMoney >= mShopItems->at(y / mRowHeight).price)
- enoughMoney = true;
- }
- else // Old Behaviour
- enoughMoney = true;
-
- if (!mPriceCheck)
- enoughMoney = true;
-
- if (enoughMoney)
- {
- setSelected(y / mRowHeight);
- generateAction();
- mMousePressed = true;
- }
- }
-}
-
-void ShopListBox::mouseRelease(int x, int y, int button)
-{
- gcn::ListBox::mouseRelease(x, y, button);
-
- mMousePressed = false;
-}
-
-void ShopListBox::mouseMotion(int x, int y)
-{
- gcn::ListBox::mouseMotion(x, y);
-
- // Pretend mouse is pressed continuously while dragged. Causes list
- // selection to be updated as is default in many GUIs.
- if (mMousePressed)
- {
- mousePress(x, y, gcn::MouseInput::LEFT);
- }
-}
-
-void ShopListBox::fireSelectionChangedEvent()
-{
- SelectionEvent event(this);
- SelectionListeners::iterator i_end = mListeners.end();
- SelectionListeners::iterator i;
-
- for (i = mListeners.begin(); i != i_end; ++i)
- {
- (*i)->selectionChanged(event);
- }
-}
-
-void ShopListBox::adjustSize()
-{
- if (mListModel != NULL)
- {
- setHeight(mRowHeight * mListModel->getNumberOfElements());
- }
-}
-
-void ShopListBox::setPriceCheck(bool check)
-{
- mPriceCheck = check;
-}
diff --git a/src/gui/shoplistbox.h b/src/gui/shoplistbox.h
deleted file mode 100644
index 2dff8977..00000000
--- a/src/gui/shoplistbox.h
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * 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: listbox.h 2655 2006-09-03 21:25:02Z b_lindeijer $
- */
-
-#ifndef _TMW_LISTBOX_H
-#define _TMW_LISTBOX_H
-
-#include <guichan/widgets/listbox.hpp>
-#include "shop.h"
-
-class SelectionListener;
-
-/**
- * A list box, meant to be used inside a scroll area. Same as the Guichan list
- * box except this one doesn't have a background, instead completely relying
- * on the scroll area. It also adds selection listener functionality.
- *
- * \ingroup GUI
- */
-class ShopListBox : public gcn::ListBox
-{
- public:
- /**
- * Constructor.
- */
- ShopListBox(gcn::ListModel *listModel);
-
- /**
- * Constructor with shopitems
- */
- ShopListBox(gcn::ListModel *listModel, ShopItems *shopListModel);
-
- /**
- * Draws the list box.
- */
- void draw(gcn::Graphics *graphics);
-
- void mousePress(int x, int y, int button);
- void mouseRelease(int x, int y, int button);
- void mouseMotion(int x, int y);
-
- /**
- * Adds a listener to the list that's notified each time a change to
- * the selection occurs.
- */
- void addSelectionListener(SelectionListener *listener)
- {
- mListeners.push_back(listener);
- }
-
- /**
- * Removes a listener from the list that's notified each time a change
- * to the selection occurs.
- */
- void removeSelectionListener(SelectionListener *listener)
- {
- mListeners.remove(listener);
- }
-
- /**
- * Sets the index of the selected element.
- */
- void setSelected(int selected);
-
- /**
- * gives information about the current player's money
- */
- void setPlayersMoney(int money);
-
- /**
- * Adjust List draw size
- */
- void adjustSize();
-
- /**
- * Set on/off the disabling of too expensive items.
- * (Good for selling mode.)
- */
- void setPriceCheck(bool check);
-
- private:
- /**
- * Sends out selection events to the list of selection listeners.
- */
- void fireSelectionChangedEvent();
-
- bool mMousePressed; /**< Keeps track of mouse pressed status. */
-
- std::list<SelectionListener*> mListeners;
-
- int mPlayerMoney;
-
- /**
- * Keeps another pointer to the same listModel, permitting to
- * use the ShopItems specific functions.
- */
- ShopItems *mShopItems;
-
- int mRowHeight; /**< Row Height */
-
- bool mPriceCheck;
-
-};
-
-#endif
diff --git a/src/gui/skill.cpp b/src/gui/skill.cpp
index e824f2f0..4f552fd7 100644
--- a/src/gui/skill.cpp
+++ b/src/gui/skill.cpp
@@ -103,7 +103,7 @@ SkillDialog::~SkillDialog()
cleanList();
}
-void SkillDialog::action(const std::string& eventId, gcn::Widget* widget)
+void SkillDialog::action(const std::string &eventId, gcn::Widget *widget)
{
if (eventId == "inc")
{
diff --git a/src/gui/status.cpp b/src/gui/status.cpp
index 0f149403..b53e0942 100644
--- a/src/gui/status.cpp
+++ b/src/gui/status.cpp
@@ -48,7 +48,7 @@ StatusWindow::StatusWindow(LocalPlayer *player):
// ----------------------
mLvlLabel = new gcn::Label("Level:");
- mGpLabel = new gcn::Label("Money:");
+ mMoneyLabel = new gcn::Label("Money:");
mHpLabel = new gcn::Label("HP:");
mHpBar = new ProgressBar(1.0f, 80, 15, 0, 171, 34);
@@ -71,7 +71,7 @@ StatusWindow::StatusWindow(LocalPlayer *player):
mLvlLabel->setPosition(x, y);
x += mLvlLabel->getWidth() + 40;
- mGpLabel->setPosition(x, y);
+ mMoneyLabel->setPosition(x, y);
y += mLvlLabel->getHeight() + 5; // Next Row
x = 5;
@@ -100,7 +100,7 @@ StatusWindow::StatusWindow(LocalPlayer *player):
mJobValueLabel->setPosition(290, y);
add(mLvlLabel);
- add(mGpLabel);
+ add(mMoneyLabel);
add(mHpLabel);
add(mHpValueLabel);
add(mMpLabel);
@@ -227,8 +227,8 @@ void StatusWindow::update()
mLvlLabel->setCaption("Level: " + toString(mPlayer->mLevel));
mLvlLabel->adjustSize();
- mGpLabel->setCaption("Money: " + toString(mPlayer->mGp) + " GP");
- mGpLabel->adjustSize();
+ mMoneyLabel->setCaption("Money: " + toString(mPlayer->mMoney) + " GP");
+ mMoneyLabel->adjustSize();
mJobXpLabel->setCaption("Job: " + toString(mPlayer->mJobLevel));
mJobXpLabel->adjustSize();
@@ -334,7 +334,7 @@ void StatusWindow::update()
mStatsReflexPoints->adjustSize();
// Update Second column widgets position
- mGpLabel->setPosition(mLvlLabel->getX() + mLvlLabel->getWidth() + 20,
+ mMoneyLabel->setPosition(mLvlLabel->getX() + mLvlLabel->getWidth() + 20,
mLvlLabel->getY());
mXpLabel->setPosition(
@@ -361,34 +361,34 @@ void StatusWindow::draw(gcn::Graphics *g)
Window::draw(g);
}
-void StatusWindow::action(const std::string& eventId, gcn::Widget* widget)
+void StatusWindow::action(const std::string &eventId, gcn::Widget *widget)
{
// Stats Part
if (eventId.length() == 3)
{
if (eventId == "STR")
{
- player_node->raiseAttribute(LocalPlayer::STR);
+ mPlayer->raiseAttribute(LocalPlayer::STR);
}
if (eventId == "AGI")
{
- player_node->raiseAttribute(LocalPlayer::AGI);
+ mPlayer->raiseAttribute(LocalPlayer::AGI);
}
if (eventId == "VIT")
{
- player_node->raiseAttribute(LocalPlayer::VIT);
+ mPlayer->raiseAttribute(LocalPlayer::VIT);
}
if (eventId == "INT")
{
- player_node->raiseAttribute(LocalPlayer::INT);
+ mPlayer->raiseAttribute(LocalPlayer::INT);
}
if (eventId == "DEX")
{
- player_node->raiseAttribute(LocalPlayer::DEX);
+ mPlayer->raiseAttribute(LocalPlayer::DEX);
}
if (eventId == "LUK")
{
- player_node->raiseAttribute(LocalPlayer::LUK);
+ mPlayer->raiseAttribute(LocalPlayer::LUK);
}
}
}
diff --git a/src/gui/status.h b/src/gui/status.h
index 6b963d24..fe2140e3 100644
--- a/src/gui/status.h
+++ b/src/gui/status.h
@@ -69,7 +69,7 @@ class StatusWindow : public Window, public gcn::ActionListener {
/**
* Status Part
*/
- gcn::Label *mLvlLabel, *mGpLabel, *mHpLabel, *mHpValueLabel;
+ gcn::Label *mLvlLabel, *mMoneyLabel, *mHpLabel, *mHpValueLabel;
gcn::Label *mMpLabel, *mMpValueLabel;
gcn::Label *mXpLabel, *mXpValueLabel, *mJobXpLabel, *mJobValueLabel;
ProgressBar *mHpBar, *mMpBar;
diff --git a/src/gui/trade.cpp b/src/gui/trade.cpp
index 5352b23d..2ac56ae5 100644
--- a/src/gui/trade.cpp
+++ b/src/gui/trade.cpp
@@ -38,16 +38,12 @@
#include "../inventory.h"
#include "../item.h"
-#include "../net/messageout.h"
-#include "../net/protocol.h"
-
#include "../resources/iteminfo.h"
#include "../utils/tostring.h"
-TradeWindow::TradeWindow(Network *network):
+TradeWindow::TradeWindow():
Window("Trade: You"),
- mNetwork(network),
mMyInventory(new Inventory()),
mPartnerInventory(new Inventory())
{
@@ -217,10 +213,12 @@ void TradeWindow::receivedOk(bool own)
void TradeWindow::tradeItem(Item *item, int quantity)
{
- MessageOut outMsg(mNetwork);
- outMsg.writeInt16(CMSG_TRADE_ITEM_ADD_REQUEST);
- outMsg.writeInt16(item->getInvIndex());
- outMsg.writeInt32(quantity);
+ // XXX Convert for new server
+ /*
+ MessageOut outMsg(CMSG_TRADE_ITEM_ADD_REQUEST);
+ outMsg.writeShort(item->getInvIndex());
+ outMsg.writeLong(quantity);
+ */
}
void TradeWindow::selectionChanged(const SelectionEvent &event)
@@ -258,7 +256,7 @@ void TradeWindow::selectionChanged(const SelectionEvent &event)
}
}
-void TradeWindow::action(const std::string& eventId, gcn::Widget* widget)
+void TradeWindow::action(const std::string &eventId, gcn::Widget *widget)
{
Item *item = inventoryWindow->getItem();
@@ -290,8 +288,10 @@ void TradeWindow::action(const std::string& eventId, gcn::Widget* widget)
}
else if (eventId == "cancel")
{
- MessageOut outMsg(mNetwork);
- outMsg.writeInt16(CMSG_TRADE_CANCEL_REQUEST);
+ // XXX Convert for new server
+ /*
+ MessageOut outMsg(CMSG_TRADE_CANCEL_REQUEST);
+ */
}
else if (eventId == "ok")
{
@@ -301,20 +301,27 @@ void TradeWindow::action(const std::string& eventId, gcn::Widget* widget)
{
mMoneyField->setText(toString(tempInt));
- MessageOut outMsg(mNetwork);
- outMsg.writeInt16(CMSG_TRADE_ITEM_ADD_REQUEST);
- outMsg.writeInt16(0);
- outMsg.writeInt32(tempInt);
+ // XXX Convert for new server
+ /*
+ MessageOut outMsg(CMSG_TRADE_ITEM_ADD_REQUEST);
+ outMsg.writeShort(0);
+ outMsg.writeLong(tempInt);
+ */
} else {
mMoneyField->setText("");
}
mMoneyField->setEnabled(false);
- MessageOut outMsg(mNetwork);
- outMsg.writeInt16(CMSG_TRADE_ADD_COMPLETE);
+
+ // XXX Convert for new server
+ /*
+ MessageOut outMsg(CMSG_TRADE_ADD_COMPLETE);
+ */
}
else if (eventId == "trade")
{
- MessageOut outMsg(mNetwork);
- outMsg.writeInt16(CMSG_TRADE_OK);
+ // XXX Convert for new server
+ /*
+ MessageOut outMsg(CMSG_TRADE_OK);
+ */
}
}
diff --git a/src/gui/trade.h b/src/gui/trade.h
index 339fc4e3..ebd05a52 100644
--- a/src/gui/trade.h
+++ b/src/gui/trade.h
@@ -36,7 +36,6 @@
class Inventory;
class Item;
class ItemContainer;
-class Network;
class ScrollArea;
/**
@@ -50,7 +49,7 @@ class TradeWindow : public Window, gcn::ActionListener, SelectionListener
/**
* Constructor.
*/
- TradeWindow(Network *network);
+ TradeWindow();
/**
* Destructor.
@@ -115,8 +114,6 @@ class TradeWindow : public Window, gcn::ActionListener, SelectionListener
void action(const std::string &eventId, gcn::Widget *widget);
private:
- Network *mNetwork;
-
typedef std::auto_ptr<Inventory> InventoryPtr;
InventoryPtr mMyInventory;
InventoryPtr mPartnerInventory;
diff --git a/src/gui/updatewindow.cpp b/src/gui/updatewindow.cpp
index 89d1793e..510e10ba 100644
--- a/src/gui/updatewindow.cpp
+++ b/src/gui/updatewindow.cpp
@@ -86,8 +86,7 @@ UpdaterWindow::UpdaterWindow():
mCancelButton->requestFocus();
setLocationRelativeTo(getParent());
- mUpdateHost =
- config.getValue("updatehost", "http://updates.themanaworld.org");
+ mUpdateHost = config.getValue("updatehost", "themanaworld.org/files");
mBasePath = config.getValue("homeDir", ".");
// Try to download the updates list
@@ -130,7 +129,7 @@ void UpdaterWindow::enable()
mPlayButton->requestFocus();
}
-void UpdaterWindow::action(const std::string& eventId, gcn::Widget* widget)
+void UpdaterWindow::action(const std::string &eventId, gcn::Widget *widget)
{
if (eventId == "cancel")
{
@@ -139,7 +138,7 @@ void UpdaterWindow::action(const std::string& eventId, gcn::Widget* widget)
// Skip the updating process
if (mDownloadStatus == UPDATE_COMPLETE)
{
- state = EXIT_STATE;
+ state = STATE_EXIT;
}
else
{
@@ -148,7 +147,7 @@ void UpdaterWindow::action(const std::string& eventId, gcn::Widget* widget)
}
else if (eventId == "play")
{
- state = LOGIN_STATE;
+ state = STATE_LOGIN;
}
}
@@ -182,12 +181,6 @@ void UpdaterWindow::loadNews()
setVisible(true);
}
-void UpdaterWindow::addRow(const std::string &row)
-{
- mBrowserBox->addRow(row);
- mScrollArea->setVerticalScrollAmount(mScrollArea->getVerticalMaxScroll());
-}
-
int UpdaterWindow::updateProgress(void *ptr,
double dt, double dn, double ut, double un)
{
@@ -201,7 +194,7 @@ int UpdaterWindow::updateProgress(void *ptr,
uw->mCurrentFile + " (" + toString((int)progress * 100) + "%)");
uw->setProgress(progress);
- if (state != UPDATE_STATE || uw->mDownloadStatus == UPDATE_ERROR)
+ if (state != STATE_UPDATE || uw->mDownloadStatus == UPDATE_ERROR)
{
// If the action was canceled return an error code to stop the mThread
return -1;
@@ -343,11 +336,12 @@ void UpdaterWindow::logic()
}
mThread = NULL;
}
- addRow("");
- addRow("##1 The update process is incomplete.");
- addRow("##1 It is strongly recommended that");
- addRow("##1 you try again later");
- addRow(mCurlError);
+ mBrowserBox->addRow("");
+ mBrowserBox->addRow("##1 The update process is incomplete.");
+ mBrowserBox->addRow("##1 It is strongly recommended that");
+ mBrowserBox->addRow("##1 you try again later");
+ mBrowserBox->addRow(mCurlError);
+ mScrollArea->setVerticalScrollAmount(mScrollArea->getVerticalMaxScroll());
mDownloadStatus = UPDATE_COMPLETE;
break;
case UPDATE_NEWS:
diff --git a/src/gui/updatewindow.h b/src/gui/updatewindow.h
index 5016036d..16442656 100644
--- a/src/gui/updatewindow.h
+++ b/src/gui/updatewindow.h
@@ -81,11 +81,6 @@ class UpdaterWindow : public Window, public gcn::ActionListener
void action(const std::string& eventId, gcn::Widget* widget);
- /**
- * Add a row to the message field.
- */
- void addRow(const std::string &row);
-
void logic();
int updateState;
diff --git a/src/gui/vbox.cpp b/src/gui/vbox.cpp
index eb838ead..b503508e 100644
--- a/src/gui/vbox.cpp
+++ b/src/gui/vbox.cpp
@@ -25,7 +25,7 @@
void VBox::draw(gcn::Graphics *graphics)
{
- if (mWidgets.size() == 0)
+ if (mWidgets.empty())
{
return;
}
diff --git a/src/gui/widgets/dropdown.cpp b/src/gui/widgets/dropdown.cpp
new file mode 100644
index 00000000..34c6b93a
--- /dev/null
+++ b/src/gui/widgets/dropdown.cpp
@@ -0,0 +1,191 @@
+/*
+ * 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$
+ */
+
+#include "dropdown.h"
+
+#include "../../graphics.h"
+
+#include "../../graphic/imagerect.h"
+
+#include "../../resources/image.h"
+#include "../../resources/resourcemanager.h"
+
+#include "../../utils/dtor.h"
+
+int DropDown::instances = 0;
+Image *DropDown::buttons[2][2];
+ImageRect DropDown::skin;
+
+DropDown::DropDown(gcn::ListModel *listModel,
+ gcn::ScrollArea *scrollArea,
+ gcn::ListBox *listBox):
+ gcn::DropDown::DropDown(listModel,
+ scrollArea, listBox)
+{
+ setBorderSize(2);
+
+ // Initialize graphics
+ if (instances == 0)
+ {
+ // Load the background skin
+ ResourceManager *resman = ResourceManager::getInstance();
+
+ // Get the button skin
+ buttons[1][0] =
+ resman->getImage("graphics/gui/vscroll_up_default.png");
+ buttons[0][0] =
+ resman->getImage("graphics/gui/vscroll_down_default.png");
+ buttons[1][1] =
+ resman->getImage("graphics/gui/vscroll_up_pressed.png");
+ buttons[0][1] =
+ resman->getImage("graphics/gui/vscroll_down_pressed.png");
+
+ // get the border skin
+ Image *boxBorder = resman->getImage("graphics/gui/deepbox.png");
+ int gridx[4] = {0, 3, 28, 31};
+ int gridy[4] = {0, 3, 28, 31};
+ int a = 0, x, y;
+
+ for (y = 0; y < 3; y++) {
+ for (x = 0; x < 3; x++) {
+ skin.grid[a] = boxBorder->getSubImage(
+ gridx[x], gridy[y],
+ gridx[x + 1] - gridx[x] + 1,
+ gridy[y + 1] - gridy[y] + 1);
+ a++;
+ }
+ }
+
+ boxBorder->decRef();
+ }
+
+ instances++;
+}
+
+DropDown::~DropDown()
+{
+ instances--;
+ // Free images memory
+ if (instances == 0)
+ {
+ buttons[0][0]->decRef();
+ buttons[0][1]->decRef();
+ buttons[1][0]->decRef();
+ buttons[1][1]->decRef();
+
+ for_each(skin.grid, skin.grid + 9, dtor<Image*>());
+ }
+}
+
+void DropDown::draw(gcn::Graphics* graphics)
+{
+ int h;
+
+ if (mDroppedDown)
+ {
+ h = mOldH;
+ }
+ else
+ {
+ h = getHeight();
+ }
+
+ int alpha = getBaseColor().a;
+ gcn::Color faceColor = getBaseColor();
+ faceColor.a = alpha;
+ gcn::Color highlightColor = faceColor + 0x303030;
+ highlightColor.a = alpha;
+ gcn::Color shadowColor = faceColor - 0x303030;
+ shadowColor.a = alpha;
+
+
+ graphics->setColor(getBackgroundColor());
+ graphics->fillRectangle(gcn::Rectangle(0, 0, getWidth(), h));
+
+ graphics->setColor(getForegroundColor());
+ graphics->setFont(getFont());
+
+ if (mListBox->getListModel() && mListBox->getSelected() >= 0)
+ {
+ graphics->drawText(mListBox->getListModel()->getElementAt(mListBox->getSelected()), 1, 0);
+ }
+
+ if (isFocused())
+ {
+ graphics->setColor(highlightColor);
+ graphics->drawRectangle(gcn::Rectangle(0, 0, getWidth() - h, h));
+ }
+
+ drawButton(graphics);
+
+ if (mDroppedDown)
+ {
+ drawChildren(graphics);
+
+ // Draw two lines separating the ListBox with se selected
+ // element view.
+ graphics->setColor(highlightColor);
+ graphics->drawLine(0, h, getWidth(), h);
+ graphics->setColor(shadowColor);
+ graphics->drawLine(0, h + 1,getWidth(),h + 1);
+ }
+}
+
+void DropDown::drawBorder(gcn::Graphics *graphics)
+{
+ int w, h, bs;
+ bs = getBorderSize();
+ w = getWidth() + bs * 2;
+ h = getHeight() + bs * 2;
+
+ dynamic_cast<Graphics*>(graphics)->drawImageRect(0, 0, w, h, skin);
+}
+
+void DropDown::drawButton(gcn::Graphics *graphics)
+{
+
+ unsigned short state = 0;
+ unsigned short dir = 0;
+ gcn::Rectangle dim;
+
+ if (mPushed)
+ state = 1;
+
+ if (mDroppedDown)
+ dir = 1;
+
+ int height;
+ if (mDroppedDown)
+ {
+ height = mOldH;
+ }
+ else
+ {
+ height = getHeight();
+ }
+ int x = getWidth() - height;
+ int y = 0;
+
+ dynamic_cast<Graphics*>(graphics)->drawImage(
+ buttons[dir][state], x, y + 1);
+}
diff --git a/src/gui/widgets/dropdown.h b/src/gui/widgets/dropdown.h
new file mode 100644
index 00000000..37e754af
--- /dev/null
+++ b/src/gui/widgets/dropdown.h
@@ -0,0 +1,85 @@
+/*
+ * 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$
+ */
+
+#ifndef DROPDOWN_H
+#define DROPDOWN_H
+
+#include <iosfwd>
+
+#include <guichan/widgets/dropdown.hpp>
+#include "../scrollarea.h"
+#include "../listbox.h"
+
+class Image;
+class ImageRect;
+
+ /**
+ * A drop down box from which you can select different values. It is one of
+ * the most complicated Widgets you will find in Guichan. For drawing the
+ * DroppedDown box it uses one ScrollArea and one ListBox. It also uses an
+ * internal FocusHandler to handle the focus of the internal ScollArea and
+ * ListBox. DropDown uses a ListModel to handle the list. To be able to use
+ * DropDown you must give DropDown an implemented ListModel which represents
+ * your list.
+ */
+class DropDown : public gcn::DropDown
+{
+ public:
+ /**
+ * Contructor.
+ *
+ * @param listModel the ListModel to use.
+ * @param scrollArea the ScrollArea to use.
+ * @param listBox the listBox to use.
+ * @see ListModel, ScrollArea, ListBox.
+ */
+ DropDown(gcn::ListModel *listModel = NULL,
+ gcn::ScrollArea *scrollArea = NULL,
+ gcn::ListBox *listBox = NULL);
+
+ /**
+ * Destructor.
+ */
+ ~DropDown();
+
+ void draw(gcn::Graphics* graphics);
+
+ void drawBorder(gcn::Graphics* graphics);
+
+
+ protected:
+ /**
+ * Draws the button with the little down arrow.
+ *
+ * @param graphics a Graphics object to draw with.
+ */
+ void drawButton(gcn::Graphics *graphics);
+
+ // Add own Images.
+ static int instances;
+ static Image *buttons[2][2];
+ static ImageRect skin;
+};
+
+#endif // end DROPDOWN_H
+
diff --git a/src/gui/window.cpp b/src/gui/window.cpp
index fe23c775..c7860021 100644
--- a/src/gui/window.cpp
+++ b/src/gui/window.cpp
@@ -196,7 +196,7 @@ void Window::setContentHeight(int height)
resizeToContent();
}
-void Window::setLocationRelativeTo(gcn::Widget* widget)
+void Window::setLocationRelativeTo(gcn::Widget *widget)
{
int wx, wy;
int x, y;
@@ -249,16 +249,18 @@ void Window::setSticky(bool sticky)
mSticky = sticky;
}
-bool Window::isSticky() {
+bool Window::isSticky()
+{
return mSticky;
}
-void Window::setVisible(bool visible) {
- if(isSticky())
+void Window::setVisible(bool visible)
+{
+ if (isSticky())
{
gcn::Window::setVisible(true);
- }
- else
+ }
+ else
{
gcn::Window::setVisible(visible);
}
diff --git a/src/localplayer.cpp b/src/localplayer.cpp
index 802da92f..6898dfb7 100644
--- a/src/localplayer.cpp
+++ b/src/localplayer.cpp
@@ -31,13 +31,13 @@
#include "main.h"
#include "sound.h"
-#include "net/messageout.h"
-#include "net/protocol.h"
+#include "net/gameserver/player.h"
LocalPlayer *player_node = NULL;
-LocalPlayer::LocalPlayer(Uint32 id, Uint16 job, Map *map):
- Player(id, job, map),
+LocalPlayer::LocalPlayer():
+ Player(65535, 0, NULL),
+ mLevel(1),
mInventory(new Inventory()),
mTarget(NULL), mPickUpTarget(NULL),
mTrading(false), mLastAction(-1)
@@ -50,26 +50,9 @@ LocalPlayer::~LocalPlayer()
void LocalPlayer::logic()
{
- switch (mAction) {
- case WALK:
- mFrame = (get_elapsed_time(mWalkTime) * 6) / mWalkSpeed;
- if (mFrame >= 6) {
- nextStep();
- }
- break;
-
- case ATTACK:
- int frames = 4;
- if (getWeapon() == 2)
- {
- frames = 5;
- }
- mFrame = (get_elapsed_time(mWalkTime) * frames) / mAttackSpeed;
- if (mFrame >= frames) {
- nextStep();
- attack();
- }
- break;
+ if (mAction == ATTACK && get_elapsed_time(mWalkTime) >= mAttackSpeed)
+ {
+ attack();
}
// Actions are allowed once per second
@@ -115,10 +98,10 @@ Item* LocalPlayer::getInvItem(int index)
void LocalPlayer::equipItem(Item *item)
{
- MessageOut outMsg(mNetwork);
- outMsg.writeInt16(CMSG_PLAYER_EQUIP);
- outMsg.writeInt16(item->getInvIndex());
- outMsg.writeInt16(0);
+ // XXX What's itemId and slot exactly? Same as eAthena?
+ /*
+ Net::GameServer::Player::equip(itemId, slot));
+ */
}
void LocalPlayer::unequipItem(Item *item)
@@ -126,9 +109,11 @@ void LocalPlayer::unequipItem(Item *item)
if (!item)
return;
- MessageOut outMsg(mNetwork);
- outMsg.writeInt16(CMSG_PLAYER_UNEQUIP);
- outMsg.writeInt16(item->getInvIndex());
+ // XXX Convert for new server
+ /*
+ MessageOut outMsg(CMSG_PLAYER_UNEQUIP);
+ outMsg.writeShort(item->getInvIndex());
+ */
// Tidy equipment directly to avoid weapon still shown bug, by instance
mEquipment->removeEquipment(item);
@@ -136,34 +121,39 @@ void LocalPlayer::unequipItem(Item *item)
void LocalPlayer::useItem(Item *item)
{
- MessageOut outMsg(mNetwork);
- outMsg.writeInt16(CMSG_PLAYER_INVENTORY_USE);
- outMsg.writeInt16(item->getInvIndex());
- outMsg.writeInt32(item->getId());
+ // XXX Convert for new server
+ /*
+ MessageOut outMsg(CMSG_PLAYER_INVENTORY_USE);
+ outMsg.writeShort(item->getInvIndex());
+ outMsg.writeLong(item->getId());
// Note: id is dest of item, usually player_node->account_ID ??
+ */
}
void LocalPlayer::dropItem(Item *item, int quantity)
{
- // TODO: Fix wrong coordinates of drops, serverside?
- MessageOut outMsg(mNetwork);
- outMsg.writeInt16(CMSG_PLAYER_INVENTORY_DROP);
- outMsg.writeInt16(item->getInvIndex());
- outMsg.writeInt16(quantity);
+ // XXX Convert for new server
+ /*
+ MessageOut outMsg(CMSG_PLAYER_INVENTORY_DROP);
+ outMsg.writeShort(item->getInvIndex());
+ outMsg.writeShort(quantity);
+ */
}
void LocalPlayer::pickUp(FloorItem *item)
{
- int dx = item->getX() - mX;
- int dy = item->getY() - mY;
+ int dx = item->getX() - mX / 32;
+ int dy = item->getY() - mY / 32;
if (dx * dx + dy * dy < 4) {
- MessageOut outMsg(mNetwork);
- outMsg.writeInt16(CMSG_ITEM_PICKUP);
- outMsg.writeInt32(item->getId());
+ // XXX Convert for new server
+ /*
+ MessageOut outMsg(CMSG_ITEM_PICKUP);
+ outMsg.writeLong(item->getId());
+ */
mPickUpTarget = NULL;
} else {
- setDestination(item->getX(), item->getY());
+ setDestination(item->getX() * 32 + 16, item->getY() * 32 + 16);
mPickUpTarget = item;
stopAttack();
}
@@ -181,28 +171,28 @@ void LocalPlayer::walk(unsigned char dir)
return;
}
- Sint16 dx = 0, dy = 0;
+ int dx = 0, dy = 0;
if (dir & UP)
- dy--;
+ dy -= 32;
if (dir & DOWN)
- dy++;
+ dy += 32;
if (dir & LEFT)
- dx--;
+ dx -= 32;
if (dir & RIGHT)
- dx++;
+ dx += 32;
// Prevent skipping corners over colliding tiles
- if (dx && mMap->tileCollides(mX + dx, mY))
- dx = 0;
- if (dy && mMap->tileCollides(mX, mY + dy))
- dy = 0;
+ if (dx && mMap->tileCollides((mX + dx) / 32, mY / 32))
+ dx = 16 - mX % 32;
+ if (dy && mMap->tileCollides(mX / 32, (mY + dy) / 32))
+ dy = 16 - mY % 32;
// Choose a straight direction when diagonal target is blocked
- if (dx && dy && !mMap->getWalk(mX + dx, mY + dy))
- dx = 0;
+ if (dx && dy && !mMap->getWalk((mX + dx) / 32, (mY + dy) / 32))
+ dx = 16 - mX % 32;
// Walk to where the player can actually go
- if ((dx || dy) && mMap->getWalk(mX + dx, mY + dy))
+ if ((dx || dy) && mMap->getWalk((mX + dx) / 32, (mY + dy) / 32))
{
setDestination(mX + dx, mY + dy);
}
@@ -218,11 +208,15 @@ void LocalPlayer::walk(unsigned char dir)
void LocalPlayer::setDestination(Uint16 x, Uint16 y)
{
- char temp[3];
- MessageOut outMsg(mNetwork);
- set_coordinates(temp, x, y, mDirection);
- outMsg.writeInt16(0x0085);
- outMsg.writeString(temp, 3);
+ // Fix coordinates so that the player does not seem to dig into walls.
+ int tx = x / 32, ty = y / 32, fx = x % 32, fy = y % 32;
+ if (fx != 16 && !mMap->getWalk(tx + fx / 16 * 2 - 1, ty)) fx = 16;
+ if (fy != 16 && !mMap->getWalk(tx, ty + fy / 16 * 2 - 1)) fy = 16;
+ if (fx != 16 && fy != 16 && !mMap->getWalk(tx + fx / 16 * 2 - 1, ty + fy / 16 * 2 - 1)) fx = 16;
+ x = tx * 32 + fx;
+ y = ty * 32 + fy;
+
+ Net::GameServer::Player::walk(x, y);
mPickUpTarget = NULL;
@@ -231,36 +225,38 @@ void LocalPlayer::setDestination(Uint16 x, Uint16 y)
void LocalPlayer::raiseAttribute(Attribute attr)
{
- MessageOut outMsg(mNetwork);
- outMsg.writeInt16(CMSG_STAT_UPDATE_REQUEST);
+ // XXX Convert for new server
+ /*
+ MessageOut outMsg(CMSG_STAT_UPDATE_REQUEST);
switch (attr)
{
case STR:
- outMsg.writeInt16(0x000d);
+ outMsg.writeShort(0x000d);
break;
case AGI:
- outMsg.writeInt16(0x000e);
+ outMsg.writeShort(0x000e);
break;
case VIT:
- outMsg.writeInt16(0x000f);
+ outMsg.writeShort(0x000f);
break;
case INT:
- outMsg.writeInt16(0x0010);
+ outMsg.writeShort(0x0010);
break;
case DEX:
- outMsg.writeInt16(0x0011);
+ outMsg.writeShort(0x0011);
break;
case LUK:
- outMsg.writeInt16(0x0012);
+ outMsg.writeShort(0x0012);
break;
}
- outMsg.writeInt8(1);
+ outMsg.writeByte(1);
+ */
}
void LocalPlayer::raiseSkill(Uint16 skillId)
@@ -268,9 +264,11 @@ void LocalPlayer::raiseSkill(Uint16 skillId)
if (mSkillPoint <= 0)
return;
- MessageOut outMsg(mNetwork);
- outMsg.writeInt16(CMSG_SKILL_LEVELUP_REQUEST);
- outMsg.writeInt16(skillId);
+ // XXX Convert for new server
+ /*
+ MessageOut outMsg(CMSG_SKILL_LEVELUP_REQUEST);
+ outMsg.writeShort(skillId);
+ */
}
void LocalPlayer::toggleSit()
@@ -287,10 +285,12 @@ void LocalPlayer::toggleSit()
default: return;
}
- MessageOut outMsg(mNetwork);
- outMsg.writeInt16(0x0089);
- outMsg.writeInt32(0);
- outMsg.writeInt8(type);
+ // XXX Convert for new server
+ /*
+ MessageOut outMsg(0x0089);
+ outMsg.writeLong(0);
+ outMsg.writeByte(type);
+ */
}
void LocalPlayer::emote(Uint8 emotion)
@@ -299,9 +299,11 @@ void LocalPlayer::emote(Uint8 emotion)
return;
mLastAction = tick_time;
- MessageOut outMsg(mNetwork);
- outMsg.writeInt16(0x00bf);
- outMsg.writeInt8(emotion);
+ // XXX Convert for new server
+ /*
+ MessageOut outMsg(0x00bf);
+ outMsg.writeByte(emotion);
+ */
}
void LocalPlayer::tradeReply(bool accept)
@@ -309,16 +311,20 @@ void LocalPlayer::tradeReply(bool accept)
if (!accept)
mTrading = false;
- MessageOut outMsg(mNetwork);
- outMsg.writeInt16(CMSG_TRADE_RESPONSE);
- outMsg.writeInt8(accept ? 3 : 4);
+ // XXX Convert for new server
+ /*
+ MessageOut outMsg(CMSG_TRADE_RESPONSE);
+ outMsg.writeByte(accept ? 3 : 4);
+ */
}
void LocalPlayer::trade(Being *being) const
{
- MessageOut outMsg(mNetwork);
- outMsg.writeInt16(CMSG_TRADE_REQUEST);
- outMsg.writeInt32(being->getId());
+ // XXX Convert for new server
+ /*
+ MessageOut outMsg(CMSG_TRADE_REQUEST);
+ outMsg.writeLong(being->getId());
+ */
}
bool LocalPlayer::tradeRequestOk() const
@@ -368,10 +374,12 @@ void LocalPlayer::attack(Being *target, bool keep)
else
sound.playSfx("sfx/fist-swish.ogg");
- MessageOut outMsg(mNetwork);
- outMsg.writeInt16(0x0089);
- outMsg.writeInt32(target->getId());
- outMsg.writeInt8(0);
+ // XXX Convert for new server
+ /*
+ MessageOut outMsg(0x0089);
+ outMsg.writeLong(target->getId());
+ outMsg.writeByte(0);
+ */
}
void LocalPlayer::stopAttack()
@@ -386,7 +394,9 @@ Being* LocalPlayer::getTarget() const
void LocalPlayer::revive()
{
- MessageOut outMsg(mNetwork);
- outMsg.writeInt16(0x00b2);
- outMsg.writeInt8(0);
+ // XXX Convert for new server
+ /*
+ MessageOut outMsg(0x00b2);
+ outMsg.writeByte(0);
+ */
}
diff --git a/src/localplayer.h b/src/localplayer.h
index a3fe91f7..dbf2a147 100644
--- a/src/localplayer.h
+++ b/src/localplayer.h
@@ -34,7 +34,6 @@
class FloorItem;
class Inventory;
class Item;
-class Network;
class LocalPlayer : public Player
{
@@ -43,12 +42,10 @@ class LocalPlayer : public Player
STR = 0, AGI, VIT, INT, DEX, LUK
};
- LocalPlayer(Uint32 id, Uint16 job, Map *map);
+ LocalPlayer();
virtual ~LocalPlayer();
- void setNetwork(Network *network) { mNetwork = network; }
-
virtual void logic();
virtual void nextStep();
@@ -115,7 +112,7 @@ class LocalPlayer : public Player
/**
* Sets a new destination for this being to walk to.
*/
- virtual void setDestination(Uint16 x, Uint16 y);
+ void setDestination(Uint16 x, Uint16 y);
void raiseAttribute(Attribute attr);
void raiseSkill(Uint16 skillId);
@@ -132,7 +129,7 @@ class LocalPlayer : public Player
Uint32 mJobLevel;
Uint32 mXpForNextLevel, mJobXpForNextLevel;
Uint16 mHp, mMaxHp, mMp, mMaxMp;
- Uint32 mGp;
+ Uint32 mMoney;
Uint32 mTotalWeight, mMaxWeight;
@@ -150,7 +147,6 @@ class LocalPlayer : public Player
std::auto_ptr<Inventory> mInventory;
protected:
- Network *mNetwork;
Being *mTarget;
FloorItem *mPickUpTarget;
diff --git a/src/log.cpp b/src/log.cpp
index 3d101d29..07eb55f7 100644
--- a/src/log.cpp
+++ b/src/log.cpp
@@ -31,6 +31,10 @@
#include <iostream>
#include <sstream>
+Logger::Logger():
+ mLogToStandardOut(false)
+{
+}
Logger::~Logger()
{
@@ -85,6 +89,11 @@ void Logger::log(const char *log_text, ...)
mLogFile << timeStr.str() << buf << std::endl;
+ if (mLogToStandardOut)
+ {
+ std::cout << timeStr.str() << buf << std::endl;
+ }
+
// Delete temporary buffer
delete[] buf;
}
diff --git a/src/log.h b/src/log.h
index 4876a9aa..36328527 100644
--- a/src/log.h
+++ b/src/log.h
@@ -32,6 +32,11 @@ class Logger
{
public:
/**
+ * Constructor.
+ */
+ Logger();
+
+ /**
* Destructor, closes log file.
*/
~Logger();
@@ -42,6 +47,11 @@ class Logger
void setLogFile(const std::string &logFilename);
/**
+ * Sets whether the log should be written to standard output.
+ */
+ void setLogToStandardOut(bool value) { mLogToStandardOut = value; }
+
+ /**
* Enters a message in the log. The message will be timestamped.
*/
void log(const char *log_text, ...);
@@ -54,6 +64,7 @@ class Logger
private:
std::ofstream mLogFile;
+ bool mLogToStandardOut;
};
extern Logger *logger;
diff --git a/src/logindata.h b/src/logindata.h
index f4fcd1b1..70b80bb7 100644
--- a/src/logindata.h
+++ b/src/logindata.h
@@ -29,12 +29,12 @@ struct LoginData
std::string username;
std::string password;
std::string hostname;
+ std::string email;
short port;
int account_ID;
int session_ID1;
int session_ID2;
- char sex;
bool remember;
};
diff --git a/src/main.cpp b/src/main.cpp
index 13fc09f4..c1919bc0 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -55,10 +55,10 @@
#endif
#include "sound.h"
-#include "gui/char_server.h"
#include "gui/char_select.h"
#include "gui/connection.h"
#include "gui/gui.h"
+#include "gui/serverdialog.h"
#include "gui/login.h"
#include "gui/ok_dialog.h"
#include "gui/register.h"
@@ -66,11 +66,16 @@
#include "gui/textfield.h"
#include "net/charserverhandler.h"
+#include "net/connection.h"
#include "net/loginhandler.h"
-#include "net/maploginhandler.h"
-#include "net/messageout.h"
#include "net/network.h"
+#include "net/accountserver/accountserver.h"
+
+#include "net/chatserver/chatserver.h"
+
+#include "net/gameserver/gameserver.h"
+
#include "resources/image.h"
#include "resources/resourcemanager.h"
#include "resources/spriteset.h"
@@ -79,18 +84,16 @@
#include "utils/tostring.h"
// Account infos
-char n_server, n_character;
+char n_character;
+std::string token;
std::vector<Spriteset *> hairset;
Spriteset *playerset[2];
Graphics *graphics;
-// TODO Anyone knows a good location for this? Or a way to make it non-global?
-class SERVER_INFO;
-SERVER_INFO **server_info;
-
unsigned char state;
std::string errorMessage;
+std::string homeDir;
unsigned char screen_mode;
Sound sound;
@@ -99,10 +102,16 @@ Music *bgm;
Configuration config; /**< Xml file configuration reader */
Logger *logger; /**< Log object */
+Net::Connection *accountServerConnection = 0;
+Net::Connection *gameServerConnection = 0;
+Net::Connection *chatServerConnection = 0;
+
namespace {
struct ErrorListener : public gcn::ActionListener
{
- void action(const std::string& eventId, gcn::Widget* widget) { state = LOGIN_STATE; }
+ void action(const std::string &eventId, gcn::Widget *widget) {
+ state = STATE_CHOOSE_SERVER;
+ }
} errorListener;
}
@@ -118,37 +127,28 @@ struct Options
Options():
printHelp(false),
skipUpdate(false),
- chooseDefault(false)
+ chooseDefault(false),
+ serverPort(0)
{};
bool printHelp;
bool skipUpdate;
bool chooseDefault;
- std::string username;
- std::string password;
std::string playername;
+ std::string password;
std::string configPath;
+
+ std::string serverName;
+ short serverPort;
};
/**
- * Do all initialization stuff
+ * Initializes the home directory. On UNIX and FreeBSD, ~/.tmw is used. On
+ * Windows and other systems we use the current working directory.
*/
-void init_engine(const Options &options)
+void initHomeDir()
{
- // Initialize SDL
- if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) < 0) {
- std::cerr << "Could not initialize SDL: " <<
- SDL_GetError() << std::endl;
- exit(1);
- }
- atexit(SDL_Quit);
-
- SDL_EnableUNICODE(1);
- SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
-
- std::string homeDir = "";
#if !(defined __USE_UNIX98 || defined __FreeBSD__)
- // In Windows and other systems we currently store data next to executable.
homeDir = ".";
#else
homeDir = std::string(PHYSFS_getUserDir()) + "/.tmw";
@@ -163,38 +163,16 @@ void init_engine(const Options &options)
exit(1);
}
#endif
+}
- // Set log file
- logger->setLogFile(homeDir + std::string("/tmw.log"));
-
- ResourceManager *resman = ResourceManager::getInstance();
-
- if (!resman->setWriteDir(homeDir)) {
- std::cout << homeDir
- << " couldn't be set as home directory! Exitting."
- << std::endl;
- exit(1);
- }
-
- // Add the user's homedir to PhysicsFS search path
- resman->addToSearchPath(homeDir, false);
- // Creating and checking the updates folder existence and rights.
- if (!resman->isDirectory("/updates")) {
- if (!resman->mkdir("/updates")) {
- std::cout << homeDir << "/updates "
- << "can't be made, but it doesn't exist! Exitting."
- << std::endl;
- exit(1);
- }
- }
-
- // Add the main data directory to our PhysicsFS search path
- resman->addToSearchPath("data", true);
- resman->addToSearchPath(TMW_DATADIR "data", true);
-
+/**
+ * Initialize configuration.
+ */
+void initConfiguration(const Options &options)
+{
// Fill configuration with defaults
config.setValue("host", "animesites.de");
- config.setValue("port", 6901);
+ config.setValue("port", 9601);
config.setValue("hwaccel", 0);
#if (defined __APPLE__ || defined WIN32) && defined USE_OPENGL
config.setValue("opengl", 1);
@@ -207,13 +185,13 @@ void init_engine(const Options &options)
config.setValue("remember", 1);
config.setValue("sfxVolume", 100);
config.setValue("musicVolume", 60);
- config.setValue("fpslimit", 60);
- config.setValue("updatehost", "http://updates.themanaworld.org");
+ config.setValue("fpslimit", 0);
+ config.setValue("updatehost", "http://themanaworld.org/files");
config.setValue("customcursor", 1);
config.setValue("homeDir", homeDir);
- // Checking if the configuration file exists... otherwise creates it with
- // default options !
+ // Checking if the configuration file exists... otherwise create it with
+ // default options.
FILE *tmwFile = 0;
std::string configPath = options.configPath;
if (configPath == "") {
@@ -228,15 +206,57 @@ void init_engine(const Options &options)
}
if (tmwFile == NULL) {
std::cout << "Can't create " << configPath << ". "
- "Using Defaults." << std::endl;
+ << "Using Defaults." << std::endl;
} else {
fclose(tmwFile);
config.init(configPath);
}
+}
+
+/**
+ * Do all initialization stuff.
+ */
+void init_engine()
+{
+ // Initialize SDL
+ if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) < 0) {
+ std::cerr << "Could not initialize SDL: " <<
+ SDL_GetError() << std::endl;
+ exit(1);
+ }
+ atexit(SDL_Quit);
+
+ SDL_EnableUNICODE(1);
+ SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
SDL_WM_SetCaption("The Mana World", NULL);
SDL_WM_SetIcon(IMG_Load(TMW_DATADIR "data/icons/tmw-icon.png"), NULL);
+ ResourceManager *resman = ResourceManager::getInstance();
+
+ if (!resman->setWriteDir(homeDir)) {
+ std::cout << homeDir
+ << " couldn't be set as home directory! Exitting."
+ << std::endl;
+ exit(1);
+ }
+
+ // Add the user's homedir to PhysicsFS search path
+ resman->addToSearchPath(homeDir, false);
+ // Creating and checking the updates folder existence and rights.
+ if (!resman->isDirectory("/updates")) {
+ if (!resman->mkdir("/updates")) {
+ std::cout << homeDir << "/updates "
+ << "can't be made, but it doesn't exist! Exitting."
+ << std::endl;
+ exit(1);
+ }
+ }
+
+ // Add the main data directory to our PhysicsFS search path
+ resman->addToSearchPath("data", true);
+ resman->addToSearchPath(TMW_DATADIR "data", true);
+
#ifdef USE_OPENGL
bool useOpenGL = (config.getValue("opengl", 0) == 1);
@@ -250,8 +270,8 @@ void init_engine(const Options &options)
graphics = new Graphics();
#endif
- int width = (int)config.getValue("screenwidth", 800);
- int height = (int)config.getValue("screenheight", 600);
+ int width = (int)config.getValue("screenwidth", defaultScreenWidth);
+ int height = (int)config.getValue("screenheight", defaultScreenHeight);
int bpp = 0;
bool fullscreen = ((int)config.getValue("screen", 0) == 1);
bool hwaccel = ((int)config.getValue("hwaccel", 0) == 1);
@@ -259,8 +279,9 @@ void init_engine(const Options &options)
// Try to set the desired video mode
if (!graphics->setVideoMode(width, height, bpp, fullscreen, hwaccel))
{
- std::cerr << "Couldn't set " << width << "x" << height << "x" <<
- bpp << " video mode: " << SDL_GetError() << std::endl;
+ std::cerr << "Couldn't set "
+ << width << "x" << height << "x" << bpp << " video mode: "
+ << SDL_GetError() << std::endl;
exit(1);
}
@@ -275,7 +296,7 @@ void init_engine(const Options &options)
if (!playerset[1]) logger->error("Couldn't load female player spriteset!");
- for (int i=0; i < NR_HAIR_STYLES; i++)
+ for (int i = 0; i < NR_HAIR_STYLES - 1; i++)
{
Spriteset *tmp = ResourceManager::getInstance()->getSpriteset(
"graphics/sprites/hairstyle" + toString(i + 1) + ".png",
@@ -288,18 +309,19 @@ void init_engine(const Options &options)
}
gui = new Gui(graphics);
- state = UPDATE_STATE; /**< Initial game state */
+ state = STATE_CHOOSE_SERVER; /**< Initial game state */
// Initialize sound engine
try {
if (config.getValue("sound", 0) == 1) {
sound.init();
}
- sound.setSfxVolume((int)config.getValue("sfxVolume", 100));
- sound.setMusicVolume((int)config.getValue("musicVolume", 60));
+ sound.setSfxVolume((int)config.getValue("sfxVolume", defaultSfxVolume));
+ sound.setMusicVolume((int)config.getValue("musicVolume",
+ defaultMusicVolume));
}
catch (const char *err) {
- state = ERROR_STATE;
+ state = STATE_ERROR;
errorMessage = err;
logger->log("Warning: %s", err);
}
@@ -326,27 +348,27 @@ void exit_engine()
sound.close();
ResourceManager::deleteInstance();
- delete logger;
}
void printHelp()
{
- std::cout
- << "tmw" << std::endl << std::endl
- << "Options: " << std::endl
- << " -h --help : Display this help" << std::endl
- << " -u --skipupdate : Skip the update process" << std::endl
- << " -U --username : Login with this username" << std::endl
- << " -P --password : Login with this password" << std::endl
- << " -D --default : Bypass the login process with default settings" << std::endl
- << " -p --playername : Login with this player" << std::endl
- << " -C --configfile : Configuration file to use"
- << std::endl;
+ std::cout <<
+ "tmw\n\n"
+ "Options:\n"
+ " -h --help : Display this help\n"
+ " -u --skipupdate : Skip the update process\n"
+ " -U --username : Login with this username\n"
+ " -P --password : Login with this password\n"
+ " -D --default : Bypass the login process with default settings\n"
+ " -s --server : Login Server name or IP\n"
+ " -o --port : Login Server Port\n"
+ " -p --playername : Login with this player\n"
+ " -C --configfile : Configuration file to use\n";
}
void parseOptions(int argc, char *argv[], Options &options)
{
- const char *optstring = "huU:P:Dp:C:";
+ const char *optstring = "huU:P:Dp:s:o:C:";
const struct option long_options[] = {
{ "help", no_argument, 0, 'h' },
@@ -354,6 +376,8 @@ void parseOptions(int argc, char *argv[], Options &options)
{ "username", required_argument, 0, 'U' },
{ "password", required_argument, 0, 'P' },
{ "default", no_argument, 0, 'D' },
+ { "server", required_argument, 0, 's' },
+ { "port", required_argument, 0, 'o' },
{ "playername", required_argument, 0, 'p' },
{ "configfile", required_argument, 0, 'C' },
{ 0 }
@@ -375,7 +399,7 @@ void parseOptions(int argc, char *argv[], Options &options)
options.skipUpdate = true;
break;
case 'U':
- options.username = optarg;
+ options.playername = optarg;
break;
case 'P':
options.password = optarg;
@@ -383,6 +407,12 @@ void parseOptions(int argc, char *argv[], Options &options)
case 'D':
options.chooseDefault = true;
break;
+ case 's':
+ options.serverName = optarg;
+ break;
+ case 'o':
+ options.serverPort = (short)atoi(optarg);
+ break;
case 'p':
options.playername = optarg;
break;
@@ -414,24 +444,20 @@ CharServerHandler charServerHandler;
LoginData loginData;
LoginHandler loginHandler;
LockedArray<LocalPlayer*> charInfo(MAX_SLOT + 1);
-MapLoginHandler mapLoginHandler;
// TODO Find some nice place for these functions
-void accountLogin(Network *network, LoginData *loginData)
+void accountLogin(LoginData *loginData)
{
- logger->log("Trying to connect to account server...");
logger->log("Username is %s", loginData->username.c_str());
- network->connect(loginData->hostname, loginData->port);
- network->registerHandler(&loginHandler);
- loginHandler.setLoginData(loginData);
+
+ Net::registerHandler(&loginHandler);
+
+ charServerHandler.setCharInfo(&charInfo);
+ Net::registerHandler(&charServerHandler);
// Send login infos
- MessageOut outMsg(network);
- outMsg.writeInt16(0x0064);
- outMsg.writeInt32(0); // client version
- outMsg.writeString(loginData->username, 24);
- outMsg.writeString(loginData->password, 24);
- outMsg.writeInt8(0); // unknown
+ Net::AccountServer::login(accountServerConnection, 0,
+ loginData->username, loginData->password);
// Clear the password, avoids auto login when returning to login
loginData->password = "";
@@ -445,51 +471,34 @@ void accountLogin(Network *network, LoginData *loginData)
config.setValue("remember", loginData->remember);
}
-void charLogin(Network *network, LoginData *loginData)
+void accountRegister(LoginData *loginData)
{
- logger->log("Trying to connect to char server...");
- network->connect(loginData->hostname, loginData->port);
- network->registerHandler(&charServerHandler);
+ logger->log("Username is %s", loginData->username.c_str());
+
+ Net::registerHandler(&loginHandler);
+
charServerHandler.setCharInfo(&charInfo);
- charServerHandler.setLoginData(loginData);
+ Net::registerHandler(&charServerHandler);
- // Send login infos
- MessageOut outMsg(network);
- 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
- network->skip(4);
+ Net::AccountServer::registerAccount(accountServerConnection, 0,
+ loginData->username, loginData->password, loginData->email);
}
-void mapLogin(Network *network, LoginData *loginData)
+void xmlNullLogger(void *ctx, const char *msg, ...)
{
- logger->log("Memorizing selected character %s",
- player_node->getName().c_str());
- config.setValue("lastCharacter", player_node->getName());
-
- MessageOut outMsg(network);
-
- logger->log("Trying to connect to map server...");
- logger->log("Map: %s", map_path.c_str());
+ // Does nothing, that's the whole point of it
+}
- network->connect(loginData->hostname, loginData->port);
- network->registerHandler(&mapLoginHandler);
+// Initialize libxml2 and check for potential ABI mismatches between
+// compiled version and the shared library actually used.
+void initXML()
+{
+ logger->log("Initializing libxml2...");
+ xmlInitParser();
+ LIBXML_TEST_VERSION;
- // Send login infos
- outMsg.writeInt16(0x0072);
- outMsg.writeInt32(loginData->account_ID);
- outMsg.writeInt32(player_node->mCharId);
- 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
- network->skip(4);
+ // Suppress libxml2 error messages
+ xmlSetGenericErrorFunc(NULL, xmlNullLogger);
}
/** Main */
@@ -498,42 +507,35 @@ int main(int argc, char *argv[])
#ifdef PACKAGE_VERSION
std::cout << "The Mana World v" << PACKAGE_VERSION << std::endl;
#endif
- logger = new Logger();
+ // Parse command line options
Options options;
-
parseOptions(argc, argv, options);
-
if (options.printHelp)
{
printHelp();
return 0;
}
- // Initialize libxml2 and check for potential ABI mismatches between
- // compiled version and the shared library actually used.
- xmlInitParser();
- LIBXML_TEST_VERSION;
-
- // Redirect libxml errors to /dev/null
- FILE *nullFile = fopen("/dev/null", "w");
- xmlSetGenericErrorFunc(nullFile, NULL);
-
// Initialize PhysicsFS
PHYSFS_init(argv[0]);
- init_engine(options);
+ initHomeDir();
+ // Configure logger
+ logger = new Logger();
+ logger->setLogFile(homeDir + std::string("/tmw.log"));
+ logger->setLogToStandardOut(config.getValue("logToStandardOut", 0));
- SDL_Event event;
+ initXML();
+ initConfiguration(options);
- if (options.skipUpdate && state != ERROR_STATE) {
- state = LOGIN_STATE;
- }
- else {
- state = UPDATE_STATE;
- }
- unsigned int oldstate = !state; // We start with a status change.
+ // Log the tmw version
+#ifdef PACKAGE_VERSION
+ logger->log("The Mana World v%s", PACKAGE_VERSION);
+#endif
+
+ init_engine();
Window *currentDialog = NULL;
Image *login_wallpaper = NULL;
@@ -541,7 +543,22 @@ int main(int argc, char *argv[])
sound.playMusic(TMW_DATADIR "data/music/Magick - Real.ogg");
- loginData.username = options.username;
+ // Server choice
+ if (options.serverName.empty()) {
+ loginData.hostname = config.getValue("MostUsedServerName0",
+ defaultAccountServerName.c_str());
+ }
+ else {
+ loginData.hostname = options.serverName;
+ }
+ if (options.serverPort == 0) {
+ loginData.port = (short)config.getValue("MostUsedServerPort0",
+ defaultAccountServerPort);
+ } else {
+ loginData.port = options.serverPort;
+ }
+
+ loginData.username = options.playername;
if (loginData.username.empty()) {
if (config.getValue("remember", 0)) {
loginData.username = config.getValue("username", "");
@@ -550,24 +567,29 @@ int main(int argc, char *argv[])
if (!options.password.empty()) {
loginData.password = options.password;
}
- loginData.hostname = config.getValue("host", "animesites.de");
- loginData.port = (short)config.getValue("port", 0);
+
loginData.remember = config.getValue("remember", 0);
- SDLNet_Init();
- Network *network = new Network();
- while (state != EXIT_STATE)
+ Net::initialize();
+ accountServerConnection = Net::getConnection();
+ gameServerConnection = Net::getConnection();
+ chatServerConnection = Net::getConnection();
+
+ unsigned int oldstate = !state; // We start with a status change.
+
+ SDL_Event event;
+ while (state != STATE_EXIT)
{
// Handle SDL events
while (SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_QUIT:
- state = EXIT_STATE;
+ state = STATE_EXIT;
break;
case SDL_KEYDOWN:
if (event.key.keysym.sym == SDLK_ESCAPE)
- state = EXIT_STATE;
+ state = STATE_EXIT;
break;
}
@@ -575,13 +597,15 @@ int main(int argc, char *argv[])
}
gui->logic();
- network->flush();
- network->dispatchMessages();
+ Net::flush();
- if (network->getState() == Network::ERROR)
+ if (state > STATE_CONNECT_ACCOUNT && state < STATE_GAME)
{
- state = ERROR_STATE;
- errorMessage = "Got disconnected from server!";
+ if (!accountServerConnection->isConnected())
+ {
+ state = STATE_ERROR;
+ errorMessage = "Got disconnected from account server!";
+ }
}
if (!login_wallpaper)
@@ -602,65 +626,103 @@ int main(int argc, char *argv[])
gui->draw();
graphics->updateScreen();
+ // TODO: Add connect timeout to go back to choose server
+ if (state == STATE_CONNECT_ACCOUNT &&
+ accountServerConnection->isConnected())
+ {
+ if (options.skipUpdate) {
+ state = STATE_LOGIN;
+ } else {
+ state = STATE_UPDATE;
+ }
+ }
+ else if (state == STATE_CONNECT_GAME &&
+ gameServerConnection->isConnected() &&
+ chatServerConnection->isConnected())
+ {
+ accountServerConnection->disconnect();
+ Net::clearHandlers();
+ state = STATE_GAME;
+ }
+
if (state != oldstate) {
- switch (oldstate)
+ // Load updates after exiting the update state
+ if (oldstate == STATE_UPDATE)
{
- case UPDATE_STATE:
- loadUpdates();
- // Reload the wallpaper in case that it was updated
- login_wallpaper->decRef();
- login_wallpaper = ResourceManager::getInstance()->
- getImage("graphics/images/login_wallpaper.png");
- break;
-
- // Those states don't cause a network disconnect
- case ACCOUNT_STATE:
- case CHAR_CONNECT_STATE:
- case CONNECTING_STATE:
- break;
-
- default:
- network->disconnect();
- network->clearHandlers();
- break;
+ loadUpdates();
+ // Reload the wallpaper in case that it was updated
+ login_wallpaper->decRef();
+ login_wallpaper = ResourceManager::getInstance()->
+ getImage("graphics/images/login_wallpaper.png");
}
oldstate = state;
- if (currentDialog && state != ACCOUNT_STATE &&
- state != CHAR_CONNECT_STATE) {
+ // Get rid of the dialog of the previous state
+ if (currentDialog) {
delete currentDialog;
currentDialog = NULL;
}
switch (state) {
- case LOGIN_STATE:
- logger->log("State: LOGIN");
- if (!loginData.password.empty()) {
- state = ACCOUNT_STATE;
+ case STATE_CHOOSE_SERVER:
+ logger->log("State: CHOOSE_SERVER");
+
+ // Allow changing this using a server choice dialog
+ // We show the dialog box only if the command-line options
+ // weren't set.
+ if (options.serverName.empty() && options.serverPort == 0) {
+ currentDialog = new ServerDialog(&loginData);
} else {
- currentDialog = new LoginDialog(&loginData);
+ state = STATE_CONNECT_ACCOUNT;
+
+ // Reset options so that cancelling or connect timeout
+ // will show the server dialog
+ options.serverName = "";
+ options.serverPort = 0;
}
break;
- case REGISTER_STATE:
+ case STATE_CONNECT_ACCOUNT:
+ logger->log("State: CONNECT_ACCOUNT");
+ logger->log("Trying to connect to account server...");
+ accountServerConnection->connect(loginData.hostname,
+ loginData.port);
+ currentDialog = new ConnectionDialog(STATE_CHOOSE_SERVER);
+ break;
+
+ case STATE_UPDATE:
+ logger->log("State: UPDATE");
+ // TODO: Revive later
+ //currentDialog = new UpdaterWindow();
+ state = STATE_LOGIN;
+ break;
+
+ case STATE_LOGIN:
+ logger->log("State: LOGIN");
+ currentDialog = new LoginDialog(&loginData);
+ // TODO: Restore autologin
+ //if (!loginData.password.empty()) {
+ // accountLogin(&loginData);
+ //}
+ break;
+
+ case STATE_LOGIN_ATTEMPT:
+ accountLogin(&loginData);
+ break;
+
+ case STATE_REGISTER:
logger->log("State: REGISTER");
currentDialog = new RegisterDialog(&loginData);
break;
- case CHAR_SERVER_STATE:
- logger->log("State: CHAR_SERVER");
- currentDialog = new ServerSelectDialog(&loginData);
- if (options.chooseDefault || options.playername != "") {
- ((ServerSelectDialog*)currentDialog)->action("ok",
- NULL);
- }
+ case STATE_REGISTER_ATTEMPT:
+ accountRegister(&loginData);
break;
- case CHAR_SELECT_STATE:
+ case STATE_CHAR_SELECT:
logger->log("State: CHAR_SELECT");
- currentDialog = new CharSelectDialog(network, &charInfo,
- 1 - loginData.sex);
+ currentDialog = new CharSelectDialog(&charInfo);
if (((CharSelectDialog*)currentDialog)->
selectByName(options.playername))
@@ -673,66 +735,56 @@ int main(int argc, char *argv[])
((CharSelectDialog*)currentDialog)->action("ok", NULL);
break;
- case GAME_STATE:
- sound.fadeOutMusic(1000);
-
- currentDialog = NULL;
- login_wallpaper->decRef();
- login_wallpaper = NULL;
-
- logger->log("State: GAME");
- game = new Game(network);
- game->logic();
- delete game;
- state = EXIT_STATE;
- break;
-
- case UPDATE_STATE:
- logger->log("State: UPDATE");
- currentDialog = new UpdaterWindow();
- break;
-
- case ERROR_STATE:
+ case STATE_ERROR:
logger->log("State: ERROR");
currentDialog = new OkDialog("Error", errorMessage);
currentDialog->addActionListener(&errorListener);
currentDialog = NULL; // OkDialog deletes itself
- network->disconnect();
- network->clearHandlers();
+ gameServerConnection->disconnect();
+ chatServerConnection->disconnect();
+ Net::clearHandlers();
break;
- case CONNECTING_STATE:
- logger->log("State: CONNECTING");
- mapLogin(network, &loginData);
- currentDialog = new ConnectionDialog();
+ case STATE_CONNECT_GAME:
+ logger->log("State: CONNECT_GAME");
+ currentDialog = new ConnectionDialog(STATE_CHAR_SELECT);
break;
- case CHAR_CONNECT_STATE:
- printf("Char: %i\n", loginData.sex);
- charLogin(network, &loginData);
- break;
+ case STATE_GAME:
+ logger->log("Memorizing selected character %s",
+ player_node->getName().c_str());
+ config.setValue("lastCharacter", player_node->getName());
- case ACCOUNT_STATE:
- printf("Account: %i\n", loginData.sex);
- accountLogin(network, &loginData);
+ Net::GameServer::connect(gameServerConnection, token);
+ Net::ChatServer::connect(chatServerConnection, token);
+ sound.fadeOutMusic(1000);
+
+ currentDialog = NULL;
+ login_wallpaper->decRef();
+ login_wallpaper = NULL;
+
+ logger->log("State: GAME");
+ game = new Game;
+ game->logic();
+ delete game;
+ state = STATE_EXIT;
break;
default:
- state = EXIT_STATE;
+ state = STATE_EXIT;
break;
}
}
}
- delete network;
- SDLNet_Quit();
+ delete accountServerConnection;
+ delete gameServerConnection;
+ delete chatServerConnection;
+ Net::finalize();
- if (nullFile)
- {
- fclose(nullFile);
- }
logger->log("State: EXIT");
exit_engine();
PHYSFS_deinit();
+ delete logger;
return 0;
}
diff --git a/src/main.h b/src/main.h
index 4aa3fc13..b68a4e4d 100644
--- a/src/main.h
+++ b/src/main.h
@@ -37,21 +37,22 @@
#define TMW_DATADIR ""
#endif
-
+/*
+ * Client different States
+ */
enum {
- EXIT_STATE,
- LOGIN_STATE,
- ACCOUNT_STATE,
- REGISTER_STATE,
- CHAR_CONNECT_STATE,
- CHAR_SERVER_STATE,
- CHAR_SELECT_STATE,
- CHAR_NEW_STATE,
- CHAR_DEL_STATE,
- GAME_STATE,
- ERROR_STATE,
- UPDATE_STATE,
- CONNECTING_STATE
+ STATE_CHOOSE_SERVER,
+ STATE_CONNECT_ACCOUNT,
+ STATE_UPDATE,
+ STATE_LOGIN,
+ STATE_LOGIN_ATTEMPT,
+ STATE_REGISTER,
+ STATE_REGISTER_ATTEMPT,
+ STATE_CHAR_SELECT,
+ STATE_ERROR,
+ STATE_CONNECT_GAME,
+ STATE_GAME,
+ STATE_EXIT
};
/* length definitions for several char[]s in order
@@ -65,7 +66,20 @@ enum {
LEN_MIN_PASSWORD = 4
};
-extern char n_server, n_character;
+// Default game values
+// -------------------
+// Screen
+const short defaultScreenWidth = 800;
+const short defaultScreenHeight = 600;
+// Sound
+const short defaultSfxVolume = 100;
+const short defaultMusicVolume = 60;
+// Account Server Name and port
+const std::string defaultAccountServerName = "animesites.de";
+const short defaultAccountServerPort = 9601;
+
+extern char n_character;
+extern std::string token;
extern unsigned char state;
extern std::string errorMessage;
diff --git a/src/map.cpp b/src/map.cpp
index 05dea951..1cdc1077 100644
--- a/src/map.cpp
+++ b/src/map.cpp
@@ -287,14 +287,16 @@ Map::getWalk(int x, int y)
return false;
}
+ /*
// Check for collision with a being
Beings &beings = beingManager->getAll();
for (BeingIterator i = beings.begin(); i != beings.end(); i++) {
// job 45 is a portal, they don't collide
- if ((*i)->mX == x && (*i)->mY == y && (*i)->mJob != 45) {
+ if ((*i)->mX / 32 == x && (*i)->mY / 32 == y && (*i)->mJob != 45) {
return false;
}
}
+ */
return true;
}
@@ -342,6 +344,8 @@ Map::removeSprite(SpriteIterator iterator)
mSprites.erase(iterator);
}
+static int const basicCost = 100;
+
Path
Map::findPath(int startX, int startY, int destX, int destY)
{
@@ -419,13 +423,27 @@ Map::findPath(int startX, int startY, int destX, int destY)
}
}
- // Calculate G cost for this route, 10 for moving straight and
- // 14 for moving diagonal
- int Gcost = curr.tile->Gcost + ((dx == 0 || dy == 0) ? 10 : 14);
+ // Calculate G cost for this route, ~sqrt(2) for moving diagonal
+ int Gcost = curr.tile->Gcost +
+ (dx == 0 || dy == 0 ? basicCost : basicCost * 362 / 256);
+
+ /* Demote an arbitrary direction to speed pathfinding by
+ adding a defect (TODO: change depending on the desired
+ visual effect, e.g. a cross-product defect toward
+ destination).
+ Important: as long as the total defect along any path is
+ less than the basicCost, the pathfinder will still find one
+ of the shortest paths! */
+ if (dx == 0 || dy == 0)
+ {
+ // Demote horizontal and vertical directions, so that two
+ // consecutive directions cannot have the same Fcost.
+ ++Gcost;
+ }
// Skip if Gcost becomes too much
// Warning: probably not entirely accurate
- if (Gcost > 200)
+ if (Gcost > 20 * basicCost)
{
continue;
}
@@ -433,8 +451,14 @@ Map::findPath(int startX, int startY, int destX, int destY)
if (newTile->whichList != mOnOpenList)
{
// Found a new tile (not on open nor on closed list)
- // Update Hcost of the new tile using Manhatten distance
- newTile->Hcost = 10 * (abs(x - destX) + abs(y - destY));
+
+ /* Update Hcost of the new tile. The pathfinder does not
+ work reliably if the heuristic cost is higher than the
+ real cost. In particular, using Manhattan distance is
+ forbidden here. */
+ int dx = std::abs(x - destX), dy = std::abs(y - destY);
+ newTile->Hcost = std::abs(dx - dy) * basicCost +
+ std::min(dx, dy) * (basicCost * 362 / 256);
// Set the current tile as the parent of the new tile
newTile->parentX = curr.x;
diff --git a/src/monster.cpp b/src/monster.cpp
index 8a7e2f32..a4317e5e 100644
--- a/src/monster.cpp
+++ b/src/monster.cpp
@@ -29,28 +29,12 @@
#include "utils/tostring.h"
-Monster::Monster(Uint32 id, Uint16 job, Map *map):
+Monster::Monster(Uint16 id, Uint16 job, Map *map):
Being(id, job, map)
{
mSprites[BASE_SPRITE] = new AnimatedSprite("graphics/sprites/monster" + toString(job - 1002) + ".xml", 0);
}
-void
-Monster::logic()
-{
- if (mAction != STAND)
- {
- mFrame = (get_elapsed_time(mWalkTime) * 4) / mWalkSpeed;
-
- if (mFrame >= 4 && mAction != MONSTER_DEAD)
- {
- nextStep();
- }
- }
-
- Being::logic();
-}
-
Being::Type
Monster::getType() const
{
diff --git a/src/monster.h b/src/monster.h
index 4a82a461..0314a035 100644
--- a/src/monster.h
+++ b/src/monster.h
@@ -29,9 +29,7 @@
class Monster : public Being
{
public:
- Monster(Uint32 id, Uint16 job, Map *map);
-
- virtual void logic();
+ Monster(Uint16 id, Uint16 job, Map *map);
virtual Type getType() const;
};
diff --git a/src/net/accountserver/account.cpp b/src/net/accountserver/account.cpp
new file mode 100644
index 00000000..385cd77a
--- /dev/null
+++ b/src/net/accountserver/account.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$
+ */
+
+#include "account.h"
+
+#include "internal.h"
+
+#include "../connection.h"
+#include "../messageout.h"
+#include "../protocol.h"
+
+void Net::AccountServer::Account::createCharacter(
+ const std::string &name, char hairColor, char hairStyle, char gender,
+ short strength, short agility, short vitality,
+ short intelligence, short dexterity, short luck)
+{
+ MessageOut msg(PAMSG_CHAR_CREATE);
+
+ msg.writeString(name);
+ msg.writeByte(hairStyle);
+ msg.writeByte(hairColor);
+ msg.writeByte(gender);
+ msg.writeShort(strength);
+ msg.writeShort(agility);
+ msg.writeShort(vitality);
+ msg.writeShort(intelligence);
+ msg.writeShort(dexterity);
+ msg.writeShort(luck);
+
+ Net::AccountServer::connection->send(msg);
+}
+
+void Net::AccountServer::Account::deleteCharacter(char slot)
+{
+ MessageOut msg(PAMSG_CHAR_DELETE);
+
+ msg.writeByte(slot);
+
+ Net::AccountServer::connection->send(msg);
+}
+
+void Net::AccountServer::Account::selectCharacter(char slot)
+{
+ MessageOut msg(PAMSG_CHAR_SELECT);
+
+ msg.writeByte(slot);
+
+ Net::AccountServer::connection->send(msg);
+}
+
+void Net::AccountServer::Account::unregister()
+{
+ MessageOut msg(PAMSG_UNREGISTER);
+ Net::AccountServer::connection->send(msg);
+}
+
+void Net::AccountServer::Account::changeEmail(const std::string &email)
+{
+ MessageOut msg(PAMSG_EMAIL_CHANGE);
+
+ msg.writeString(email);
+
+ Net::AccountServer::connection->send(msg);
+}
+
+void Net::AccountServer::Account::getEmail()
+{
+ MessageOut msg(PAMSG_EMAIL_GET);
+
+ Net::AccountServer::connection->send(msg);
+}
+
+void Net::AccountServer::Account::changePassword(
+ const std::string &oldPassword, const std::string &newPassword)
+{
+ MessageOut msg(PAMSG_PASSWORD_CHANGE);
+
+ msg.writeString(oldPassword);
+ msg.writeString(newPassword);
+
+ Net::AccountServer::connection->send(msg);
+}
+
+void Net::AccountServer::Account::enterWorld()
+{
+ MessageOut msg(PAMSG_ENTER_WORLD);
+
+ Net::AccountServer::connection->send(msg);
+}
+
+void Net::AccountServer::Account::enterChat()
+{
+ MessageOut msg(PAMSG_ENTER_CHAT);
+
+ Net::AccountServer::connection->send(msg);
+}
diff --git a/src/net/accountserver/account.h b/src/net/accountserver/account.h
new file mode 100644
index 00000000..8e46eaa5
--- /dev/null
+++ b/src/net/accountserver/account.h
@@ -0,0 +1,60 @@
+/*
+ * 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$
+ */
+
+#ifndef _TMW_NET_ACCOUNTSERVER_CHARACTER_H
+#define _TMW_NET_ACCOUNTSERVER_CHARACTER_H
+
+#include <iosfwd>
+
+namespace Net
+{
+ namespace AccountServer
+ {
+ namespace Account
+ {
+ void createCharacter(const std::string &name,
+ char hairColor, char hairStyle, char gender,
+ short strength, short agility, short vitality,
+ short intelligence, short dexterity, short luck);
+
+ void deleteCharacter(char slot);
+
+ void selectCharacter(char slot);
+
+ void unregister();
+
+ void changeEmail(const std::string &email);
+
+ void getEmail();
+
+ void changePassword(const std::string &oldPassowrd,
+ const std::string &newPassword);
+
+ void enterWorld();
+
+ void enterChat();
+ }
+ }
+}
+
+#endif
diff --git a/src/net/accountserver/accountserver.cpp b/src/net/accountserver/accountserver.cpp
new file mode 100644
index 00000000..8fde6d5e
--- /dev/null
+++ b/src/net/accountserver/accountserver.cpp
@@ -0,0 +1,68 @@
+/*
+ * 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$
+ */
+
+#include "accountserver.h"
+
+#include "internal.h"
+
+#include "../connection.h"
+#include "../messageout.h"
+#include "../protocol.h"
+
+void Net::AccountServer::login(Net::Connection *connection, int version,
+ const std::string &username, const std::string &password)
+{
+ Net::AccountServer::connection = connection;
+
+ MessageOut msg(PAMSG_LOGIN);
+
+ msg.writeLong(version);
+ msg.writeString(username);
+ msg.writeString(password);
+
+ Net::AccountServer::connection->send(msg);
+}
+
+void Net::AccountServer::registerAccount(Net::Connection *connection,
+ int version, const std::string &username, const std::string &password,
+ const std::string &email)
+{
+ Net::AccountServer::connection = connection;
+
+ MessageOut msg(PAMSG_REGISTER);
+
+ msg.writeLong(version); // client version
+ msg.writeString(username);
+ msg.writeString(password);
+ msg.writeString(email);
+
+ Net::AccountServer::connection->send(msg);
+}
+
+void Net::AccountServer::logout()
+{
+ MessageOut msg(PAMSG_LOGOUT);
+ Net::AccountServer::connection->send(msg);
+
+ Net::AccountServer::connection = 0;
+}
diff --git a/src/net/accountserver/accountserver.h b/src/net/accountserver/accountserver.h
new file mode 100644
index 00000000..c05b5317
--- /dev/null
+++ b/src/net/accountserver/accountserver.h
@@ -0,0 +1,46 @@
+/*
+ * 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$
+ */
+
+#ifndef _TMW_NET_ACCOUNTSERVER_ACCOUNTSERVER_H
+#define _TMW_NET_ACCOUNTSERVER_ACCOUNTSERVER_H
+
+#include <iosfwd>
+
+namespace Net
+{
+ class Connection;
+
+ namespace AccountServer
+ {
+ void login(Net::Connection *connection, int version,
+ const std::string &username, const std::string &password);
+
+ void registerAccount(Net::Connection *connection, int version,
+ const std::string &username, const std::string &password,
+ const std::string &email);
+
+ void logout();
+ }
+}
+
+#endif
diff --git a/src/net/accountserver/internal.cpp b/src/net/accountserver/internal.cpp
new file mode 100644
index 00000000..28a9695e
--- /dev/null
+++ b/src/net/accountserver/internal.cpp
@@ -0,0 +1,34 @@
+/*
+ * 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$
+ */
+
+#include "internal.h"
+
+namespace Net
+{
+ class Connection;
+
+ namespace AccountServer
+ {
+ Connection *connection = 0;
+ }
+}
diff --git a/src/net/maploginhandler.h b/src/net/accountserver/internal.h
index fe597549..8af5ec04 100644
--- a/src/net/maploginhandler.h
+++ b/src/net/accountserver/internal.h
@@ -21,17 +21,17 @@
* $Id$
*/
-#ifndef _TMW_NET_MAPLOGINHANDLER_H
-#define _TMW_NET_MAPLOGINHANDLER_H
+#ifndef _TMW_NET_ACCOUNTSERVER_INTERNAL_H
+#define _TMW_NET_ACCOUNTSERVER_INTERNAL_H
-#include "messagehandler.h"
-
-class MapLoginHandler : public MessageHandler
+namespace Net
{
- public:
- MapLoginHandler();
+ class Connection;
- void handleMessage(MessageIn *msg);
-};
+ namespace AccountServer
+ {
+ extern Connection *connection;
+ }
+}
#endif
diff --git a/src/net/beinghandler.cpp b/src/net/beinghandler.cpp
index cd5653fc..2d68dd28 100644
--- a/src/net/beinghandler.cpp
+++ b/src/net/beinghandler.cpp
@@ -41,42 +41,60 @@ const int EMOTION_TIME = 150; /**< Duration of emotion icon */
BeingHandler::BeingHandler()
{
static const Uint16 _messages[] = {
- SMSG_BEING_VISIBLE,
- SMSG_BEING_MOVE,
- SMSG_BEING_REMOVE,
- SMSG_BEING_ACTION,
- SMSG_BEING_LEVELUP,
- SMSG_BEING_EMOTION,
- SMSG_BEING_CHANGE_LOOKS,
- SMSG_BEING_NAME_RESPONSE,
- SMSG_PLAYER_UPDATE_1,
- SMSG_PLAYER_UPDATE_2,
- SMSG_PLAYER_MOVE,
- 0x0119,
+ //SMSG_BEING_VISIBLE,
+ //SMSG_BEING_MOVE,
+ //SMSG_BEING_REMOVE,
+ //SMSG_BEING_ACTION,
+ //SMSG_BEING_LEVELUP,
+ //SMSG_BEING_EMOTION,
+ //SMSG_BEING_CHANGE_LOOKS,
+ //SMSG_BEING_NAME_RESPONSE,
+ //SMSG_PLAYER_UPDATE_1,
+ //SMSG_PLAYER_UPDATE_2,
+ //SMSG_PLAYER_MOVE,
+ //0x0119,
+ GPMSG_BEING_ENTER,
+ GPMSG_BEING_LEAVE,
+ GPMSG_BEINGS_MOVE,
0
};
handledMessages = _messages;
}
-void BeingHandler::handleMessage(MessageIn *msg)
+void BeingHandler::handleMessage(MessageIn &msg)
{
+ /*
Uint32 id;
Uint16 job, speed;
Sint16 param1;
Sint8 type;
Being *srcBeing, *dstBeing;
+ */
- switch (msg->getId())
+ switch (msg.getId())
{
+ case GPMSG_BEING_ENTER:
+ handleBeingEnterMessage(msg);
+ break;
+
+ case GPMSG_BEING_LEAVE:
+ handleBeingLeaveMessage(msg);
+ break;
+
+ case GPMSG_BEINGS_MOVE:
+ handleBeingsMoveMessage(msg);
+ break;
+
+ /*
case SMSG_BEING_VISIBLE:
case SMSG_BEING_MOVE:
// Information about a being in range
- id = msg->readInt32();
- speed = msg->readInt16();
- msg->readInt16(); // unknown
- msg->readInt16(); // unknown
- msg->readInt16(); // option
- job = msg->readInt16(); // class
+ id = msg.readLong();
+ speed = msg.readShort();
+ msg.readShort(); // unknown
+ msg.readShort(); // unknown
+ msg.readShort(); // option
+ job = msg.readShort(); // class
dstBeing = beingManager->findBeing(id);
@@ -91,7 +109,7 @@ void BeingHandler::handleMessage(MessageIn *msg)
dstBeing = beingManager->createBeing(id, job);
}
- else if (msg->getId() == 0x0078)
+ else if (msg.getId() == 0x0078)
{
dstBeing->clearPath();
dstBeing->mFrame = 0;
@@ -104,57 +122,56 @@ void BeingHandler::handleMessage(MessageIn *msg)
dstBeing->setWalkSpeed(speed);
dstBeing->mJob = job;
- dstBeing->setHairStyle(msg->readInt16());
- dstBeing->setWeapon(msg->readInt16());
- dstBeing->setVisibleEquipment(3, msg->readInt16()); // head bottom
+ dstBeing->setHairStyle(msg.readShort());
+ dstBeing->setWeapon(msg.readShort());
+ dstBeing->setVisibleEquipment(3, msg.readShort()); // head bottom
- if (msg->getId() == SMSG_BEING_MOVE)
+ if (msg.getId() == SMSG_BEING_MOVE)
{
- msg->readInt32(); // server tick
+ msg.readLong(); // server tick
}
- msg->readInt16(); // shield
- dstBeing->setVisibleEquipment(4, msg->readInt16()); // head top
- dstBeing->setVisibleEquipment(5, msg->readInt16()); // head mid
- dstBeing->setHairColor(msg->readInt16());
- msg->readInt16(); // unknown
- msg->readInt16(); // head dir
- msg->readInt16(); // guild
- msg->readInt16(); // unknown
- msg->readInt16(); // unknown
- msg->readInt16(); // manner
- msg->readInt16(); // karma
- msg->readInt8(); // unknown
- dstBeing->setSex(1 - msg->readInt8()); // sex
-
- if (msg->getId() == SMSG_BEING_MOVE)
+ msg.readShort(); // shield
+ dstBeing->setVisibleEquipment(4, msg.readShort()); // head top
+ dstBeing->setVisibleEquipment(5, msg.readShort()); // head mid
+ dstBeing->setHairColor(msg.readShort());
+ msg.readShort(); // unknown
+ msg.readShort(); // head dir
+ msg.readShort(); // guild
+ msg.readShort(); // unknown
+ msg.readShort(); // unknown
+ msg.readShort(); // manner
+ msg.readShort(); // karma
+ msg.readByte(); // unknown
+ dstBeing->setSex(1 - msg.readByte()); // sex
+
+ if (msg.getId() == SMSG_BEING_MOVE)
{
- Uint16 srcX, srcY, dstX, dstY;
- msg->readCoordinatePair(srcX, srcY, dstX, dstY);
- dstBeing->setAction(Being::STAND);
- dstBeing->mX = srcX;
- dstBeing->mY = srcY;
- dstBeing->setDestination(dstX, dstY);
+ //Uint16 srcX, srcY, dstX, dstY;
+ //msg.readCoordinatePair(srcX, srcY, dstX, dstY);
+ //dstBeing->setAction(Being::STAND);
+ //dstBeing->mX = srcX;
+ //dstBeing->mY = srcY;
+ //dstBeing->setDestination(dstX, dstY);
}
else
{
- msg->readCoordinates(dstBeing->mX, dstBeing->mY,
- dstBeing->mDirection);
+ //msg.readCoordinates(dstBeing->mX, dstBeing->mY, dstBeing->mDirection);
}
- msg->readInt8(); // unknown
- msg->readInt8(); // unknown
- msg->readInt8(); // unknown / sit
+ msg.readByte(); // unknown
+ msg.readByte(); // unknown
+ msg.readByte(); // unknown / sit
break;
case SMSG_BEING_REMOVE:
// A being should be removed or has died
- dstBeing = beingManager->findBeing(msg->readInt32());
+ dstBeing = beingManager->findBeing(msg.readLong());
if (!dstBeing)
break;
- if (msg->readInt8() == 1)
+ if (msg.readByte() == 1)
{
// Death
switch (dstBeing->getType())
@@ -182,15 +199,15 @@ void BeingHandler::handleMessage(MessageIn *msg)
break;
case SMSG_BEING_ACTION:
- srcBeing = beingManager->findBeing(msg->readInt32());
- dstBeing = beingManager->findBeing(msg->readInt32());
- msg->readInt32(); // server tick
- msg->readInt32(); // src speed
- msg->readInt32(); // dst speed
- param1 = msg->readInt16();
- msg->readInt16(); // param 2
- type = msg->readInt8();
- msg->readInt16(); // param 3
+ srcBeing = beingManager->findBeing(msg.readLong());
+ dstBeing = beingManager->findBeing(msg.readLong());
+ msg.readLong(); // server tick
+ msg.readLong(); // src speed
+ msg.readLong(); // dst speed
+ param1 = msg.readShort();
+ msg.readShort(); // param 2
+ type = msg.readByte();
+ msg.readShort(); // param 3
switch (type)
{
@@ -231,63 +248,63 @@ void BeingHandler::handleMessage(MessageIn *msg)
break;
case SMSG_BEING_LEVELUP:
- if ((Uint32)msg->readInt32() == player_node->getId()) {
+ if ((Uint32) msg.readLong() == player_node->getId()) {
logger->log("Level up");
sound.playSfx("sfx/levelup.ogg");
} else {
logger->log("Someone else went level up");
}
- msg->readInt32(); // type
+ msg.readLong(); // type
break;
case SMSG_BEING_EMOTION:
- if (!(dstBeing = beingManager->findBeing(msg->readInt32())))
+ if (!(dstBeing = beingManager->findBeing(msg.readLong())))
{
break;
}
- dstBeing->mEmotion = msg->readInt8();
+ dstBeing->mEmotion = msg.readByte();
dstBeing->mEmotionTime = EMOTION_TIME;
break;
case SMSG_BEING_CHANGE_LOOKS:
{
- if (!(dstBeing = beingManager->findBeing(msg->readInt32())))
+ if (!(dstBeing = beingManager->findBeing(msg.readLong())))
{
break;
}
-
- int type = msg->readInt8();
+
+ int type = msg.readByte();
switch (type) {
case 1:
- dstBeing->setHairStyle(msg->readInt8());
+ dstBeing->setHairStyle(msg.readByte());
break;
case 2:
- dstBeing->setWeapon(msg->readInt8());
+ dstBeing->setWeapon(msg.readByte());
break;
case 3:
case 4:
case 5:
// Equip/unequip head 3. Bottom 4. Top 5. Middle
- dstBeing->setVisibleEquipment(type, msg->readInt8());
+ dstBeing->setVisibleEquipment(type, msg.readByte());
// First 3 slots of mVisibleEquipments are reserved for
// later use, probably accessories.
break;
case 6:
- dstBeing->setHairColor(msg->readInt8());
+ dstBeing->setHairColor(msg.readByte());
break;
default:
- printf("c3: %i\n", msg->readInt8()); // unsupported
+ printf("c3: %i\n", msg.readByte()); // unsupported
break;
}
}
break;
case SMSG_BEING_NAME_RESPONSE:
- if ((dstBeing = beingManager->findBeing(msg->readInt32())))
+ if ((dstBeing = beingManager->findBeing(msg.readLong())))
{
- dstBeing->setName(msg->readString(24));
+ dstBeing->setName(msg.readString(24));
}
break;
@@ -295,12 +312,12 @@ void BeingHandler::handleMessage(MessageIn *msg)
case SMSG_PLAYER_UPDATE_2:
case SMSG_PLAYER_MOVE:
// An update about a player, potentially including movement.
- id = msg->readInt32();
- speed = msg->readInt16();
- msg->readInt16(); // option 1
- msg->readInt16(); // option 2
- msg->readInt16(); // option
- job = msg->readInt16();
+ id = msg.readLong();
+ speed = msg.readShort();
+ msg.readShort(); // option 1
+ msg.readShort(); // option 2
+ msg.readShort(); // option
+ job = msg.readShort();
dstBeing = beingManager->findBeing(id);
@@ -311,58 +328,57 @@ void BeingHandler::handleMessage(MessageIn *msg)
dstBeing->setWalkSpeed(speed);
dstBeing->mJob = job;
- dstBeing->setHairStyle(msg->readInt16());
- dstBeing->setWeaponById(msg->readInt16()); // item id 1
- msg->readInt16(); // item id 2
- dstBeing->setVisibleEquipment(3, msg->readInt16()); // head bottom
+ dstBeing->setHairStyle(msg.readShort());
+ dstBeing->setWeaponById(msg.readShort()); // item id 1
+ msg.readShort(); // item id 2
+ dstBeing->setVisibleEquipment(3, msg.readShort()); // head bottom
- if (msg->getId() == SMSG_PLAYER_MOVE)
+ if (msg.getId() == SMSG_PLAYER_MOVE)
{
- msg->readInt32(); // server tick
+ msg.readLong(); // server tick
}
- dstBeing->setVisibleEquipment(4, msg->readInt16()); // head top
- dstBeing->setVisibleEquipment(5, msg->readInt16()); // head mid
- dstBeing->setHairColor(msg->readInt16());
- msg->readInt16(); // unknown
- msg->readInt16(); // head dir
- msg->readInt32(); // guild
- msg->readInt32(); // emblem
- msg->readInt16(); // manner
- msg->readInt8(); // karma
- dstBeing->setSex(1 - msg->readInt8()); // sex
-
- if (msg->getId() == SMSG_PLAYER_MOVE)
+ dstBeing->setVisibleEquipment(4, msg.readShort()); // head top
+ dstBeing->setVisibleEquipment(5, msg.readShort()); // head mid
+ dstBeing->setHairColor(msg.readShort());
+ msg.readShort(); // unknown
+ msg.readShort(); // head dir
+ msg.readLong(); // guild
+ msg.readLong(); // emblem
+ msg.readShort(); // manner
+ msg.readByte(); // karma
+ dstBeing->setSex(1 - msg.readByte()); // sex
+
+ if (msg.getId() == SMSG_PLAYER_MOVE)
{
- Uint16 srcX, srcY, dstX, dstY;
- msg->readCoordinatePair(srcX, srcY, dstX, dstY);
- dstBeing->mX = srcX;
- dstBeing->mY = srcY;
- dstBeing->setDestination(dstX, dstY);
+ //Uint16 srcX, srcY, dstX, dstY;
+ //msg.readCoordinatePair(srcX, srcY, dstX, dstY);
+ //dstBeing->mX = srcX;
+ //dstBeing->mY = srcY;
+ //dstBeing->setDestination(dstX, dstY);
}
else
{
- msg->readCoordinates(dstBeing->mX, dstBeing->mY,
- dstBeing->mDirection);
+ //msg.readCoordinates(dstBeing->mX, dstBeing->mY, dstBeing->mDirection);
}
- msg->readInt8(); // unknown
- msg->readInt8(); // unknown
+ msg.readByte(); // unknown
+ msg.readByte(); // unknown
- if (msg->getId() == SMSG_PLAYER_UPDATE_1)
+ if (msg.getId() == SMSG_PLAYER_UPDATE_1)
{
- if (msg->readInt8() == 2)
+ if (msg.readByte() == 2)
{
dstBeing->setAction(Being::SIT);
}
}
- else if (msg->getId() == SMSG_PLAYER_MOVE)
+ else if (msg.getId() == SMSG_PLAYER_MOVE)
{
- msg->readInt8(); // unknown
+ msg.readByte(); // unknown
}
- msg->readInt8(); // Lv
- msg->readInt8(); // unknown
+ msg.readByte(); // Lv
+ msg.readByte(); // unknown
dstBeing->mWalkTime = tick_time;
dstBeing->mFrame = 0;
@@ -370,9 +386,107 @@ void BeingHandler::handleMessage(MessageIn *msg)
case 0x0119:
// Change in players look
- printf("0x0119 %i %i %i %x %i\n", msg->readInt32(),
- msg->readInt16(), msg->readInt16(), msg->readInt16(),
- msg->readInt8());
+ printf("0x0119 %li %i %i %x %i\n", msg.readLong(),
+ msg.readShort(), msg.readShort(), msg.readShort(),
+ msg.readByte());
break;
+ */
+ }
+}
+
+void
+BeingHandler::handleBeingEnterMessage(MessageIn &msg)
+{
+ int type = msg.readByte(); // type
+ int id = msg.readShort();
+
+ switch (type) {
+ case OBJECT_PLAYER:
+ {
+ std::string name = msg.readString();
+ Being *being;
+ if (player_node->getName() == name)
+ {
+ being = player_node;
+ being->setId(id);
+ }
+ else
+ {
+ being = beingManager->createBeing(id, 0);
+ being->setName(name);
+ }
+ being->setHairStyle(msg.readByte());
+ being->setHairColor(msg.readByte());
+ being->setSex(msg.readByte());
+ } break;
+ case OBJECT_MONSTER:
+ {
+ int monsterId = msg.readShort();
+ Being *being;
+ being = beingManager->createBeing(id, 1002 + monsterId);
+ being->setWalkSpeed(150); // TODO
+ } break;
+ }
+}
+
+void BeingHandler::handleBeingLeaveMessage(MessageIn &msg)
+{
+ Being *being = beingManager->findBeing(msg.readShort());
+ if (!being) return;
+ if (being == player_node->getTarget())
+ {
+ player_node->stopAttack();
+ }
+ beingManager->destroyBeing(being);
+}
+
+void BeingHandler::handleBeingsMoveMessage(MessageIn &msg)
+{
+ while (msg.getUnreadLength())
+ {
+ Uint16 id = msg.readShort();
+ Uint8 flags = msg.readByte();
+ Being *being = beingManager->findBeing(id);
+ int sx = 0, sy = 0, dx = 0, dy = 0;
+ if (flags & MOVING_POSITION)
+ {
+ Uint16 sx2, sy2;
+ msg.readCoordinates(sx2, sy2);
+ sx = sx2 * 32 + 16;
+ sy = sy2 * 32 + 16;
+ }
+ if (flags & MOVING_DESTINATION)
+ {
+ dx = msg.readShort();
+ dy = msg.readShort();
+ if (!(flags & MOVING_POSITION))
+ {
+ sx = dx;
+ sy = dy;
+ }
+ }
+ if (!being || !(flags & (MOVING_POSITION | MOVING_DESTINATION)))
+ {
+ continue;
+ }
+ if (abs(being->mX - sx) + abs(being->mY - sy) > 4 * 32)
+ {
+ // Too large a desynchronization.
+ being->mX = sx;
+ being->mY = sy;
+ being->setDestination(dx, dy);
+ }
+ else if (!(flags & MOVING_POSITION))
+ {
+ being->setDestination(dx, dy);
+ }
+ else if (!(flags & MOVING_DESTINATION))
+ {
+ being->adjustCourse(sx, sy);
+ }
+ else
+ {
+ being->adjustCourse(sx, sy, dx, dy);
+ }
}
}
diff --git a/src/net/beinghandler.h b/src/net/beinghandler.h
index 03012f39..59539ffe 100644
--- a/src/net/beinghandler.h
+++ b/src/net/beinghandler.h
@@ -31,7 +31,12 @@ class BeingHandler : public MessageHandler
public:
BeingHandler();
- void handleMessage(MessageIn *msg);
+ void handleMessage(MessageIn &msg);
+
+ private:
+ void handleBeingEnterMessage(MessageIn &msg);
+ void handleBeingLeaveMessage(MessageIn &msg);
+ void handleBeingsMoveMessage(MessageIn &msg);
};
#endif
diff --git a/src/net/buysellhandler.cpp b/src/net/buysellhandler.cpp
index d7f063a7..173c59d2 100644
--- a/src/net/buysellhandler.cpp
+++ b/src/net/buysellhandler.cpp
@@ -54,10 +54,10 @@ BuySellHandler::BuySellHandler()
handledMessages = _messages;
}
-void BuySellHandler::handleMessage(MessageIn *msg)
+void BuySellHandler::handleMessage(MessageIn &msg)
{
int n_items;
- switch (msg->getId())
+ switch (msg.getId())
{
case SMSG_NPC_BUY_SELL_CHOICE:
buyDialog->setVisible(false);
@@ -65,39 +65,38 @@ void BuySellHandler::handleMessage(MessageIn *msg)
sellDialog->setVisible(false);
sellDialog->reset();
buySellDialog->setVisible(true);
- current_npc = dynamic_cast<NPC*>(beingManager->findBeing(msg->readInt32()));
+ current_npc = dynamic_cast<NPC*>(beingManager->findBeing(msg.readLong()));
break;
case SMSG_NPC_BUY:
- msg->readInt16(); // length
- n_items = (msg->getLength() - 4) / 11;
+ msg.readShort(); // length
+ n_items = (msg.getLength() - 4) / 11;
buyDialog->reset();
- buyDialog->setMoney(player_node->mGp);
+ buyDialog->setMoney(player_node->mMoney);
buyDialog->setVisible(true);
for (int k = 0; k < n_items; k++)
{
- Sint32 value = msg->readInt32();
- msg->readInt32(); // DCvalue
- msg->readInt8(); // type
- Sint16 itemId = msg->readInt16();
+ Sint32 value = msg.readLong();
+ msg.readLong(); // DCvalue
+ msg.readByte(); // type
+ Sint16 itemId = msg.readShort();
buyDialog->addItem(itemId, value);
}
break;
case SMSG_NPC_SELL:
- msg->readInt16(); // length
- n_items = (msg->getLength() - 4) / 10;
+ msg.readShort(); // length
+ n_items = (msg.getLength() - 4) / 10;
if (n_items > 0) {
- sellDialog->setMoney(player_node->mGp);
sellDialog->reset();
sellDialog->setVisible(true);
for (int k = 0; k < n_items; k++)
{
- Sint16 index = msg->readInt16();
- Sint32 value = msg->readInt32();
- msg->readInt32(); // OCvalue
+ Sint16 index = msg.readShort();
+ Sint32 value = msg.readLong();
+ msg.readLong(); // OCvalue
Item *item = player_node->getInvItem(index);
if (item && !(item->isEquipped())) {
@@ -112,7 +111,7 @@ void BuySellHandler::handleMessage(MessageIn *msg)
break;
case SMSG_NPC_BUY_RESPONSE:
- if (msg->readInt8() == 0) {
+ if (msg.readByte() == 0) {
chatWindow->chatLog("Thanks for buying", BY_SERVER);
} else {
chatWindow->chatLog("Unable to buy", BY_SERVER);
@@ -120,7 +119,7 @@ void BuySellHandler::handleMessage(MessageIn *msg)
break;
case SMSG_NPC_SELL_RESPONSE:
- if (msg->readInt8() == 0) {
+ if (msg.readByte() == 0) {
chatWindow->chatLog("Thanks for selling", BY_SERVER);
} else {
chatWindow->chatLog("Unable to sell", BY_SERVER);
diff --git a/src/net/buysellhandler.h b/src/net/buysellhandler.h
index 673aaac1..e242d373 100644
--- a/src/net/buysellhandler.h
+++ b/src/net/buysellhandler.h
@@ -31,7 +31,7 @@ class BuySellHandler : public MessageHandler
public:
BuySellHandler();
- void handleMessage(MessageIn *msg);
+ void handleMessage(MessageIn &msg);
};
#endif
diff --git a/src/net/charserverhandler.cpp b/src/net/charserverhandler.cpp
index 06ec78c1..f715b434 100644
--- a/src/net/charserverhandler.cpp
+++ b/src/net/charserverhandler.cpp
@@ -23,9 +23,9 @@
#include "charserverhandler.h"
-#include "messagein.h"
-#include "network.h"
+#include "connection.h"
#include "protocol.h"
+#include "messagein.h"
#include "../game.h"
#include "../localplayer.h"
@@ -35,66 +35,67 @@
#include "../gui/ok_dialog.h"
+extern Net::Connection *gameServerConnection;
+extern Net::Connection *chatServerConnection;
+
CharServerHandler::CharServerHandler()
{
static const Uint16 _messages[] = {
- 0x006b,
- 0x006c,
- 0x006d,
- 0x006e,
- 0x006f,
- 0x0070,
- 0x0071,
- 0x0081,
+ APMSG_CHAR_CREATE_RESPONSE,
+ APMSG_CHAR_DELETE_RESPONSE,
+ APMSG_CHAR_INFO,
+ APMSG_CHAR_SELECT_RESPONSE,
0
};
handledMessages = _messages;
}
-void CharServerHandler::handleMessage(MessageIn *msg)
+void
+CharServerHandler::handleMessage(MessageIn &msg)
{
int slot;
LocalPlayer *tempPlayer;
- logger->log("CharServerHandler: Packet ID: %x, Length: %d",
- msg->getId(), msg->getLength());
- switch (msg->getId())
+ switch (msg.getId())
{
- case 0x006b:
- // 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;
+ case APMSG_CHAR_CREATE_RESPONSE:
+ handleCharCreateResponse(msg);
+ break;
- for (int i = 0; i < n_character; i++)
+ case APMSG_CHAR_DELETE_RESPONSE:
+ {
+ int errMsg = msg.readByte();
+ // Character deletion successful
+ if (errMsg == ERRMSG_OK)
{
- tempPlayer = readPlayerData(msg, slot);
- mCharInfo->select(slot);
- mCharInfo->setEntry(tempPlayer);
- logger->log("CharServer: Player: %s (%d)",
- tempPlayer->getName().c_str(), slot);
+ delete mCharInfo->getEntry();
+ mCharInfo->setEntry(0);
+ mCharInfo->unlock();
+ n_character--;
+ new OkDialog("Info", "Player deleted");
}
-
- 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;
+ // Character deletion failed
+ else
+ {
+ std::string message = "";
+ switch (errMsg)
+ {
+ case ERRMSG_NO_LOGIN:
+ message = "Not logged in";
+ break;
+ case ERRMSG_INVALID_ARGUMENT:
+ message = "Selection out of range";
+ break;
+ default:
+ message = "Unknown error";
+ }
+ mCharInfo->unlock();
+ new OkDialog("Error", message);
}
- mCharInfo->unlock();
+ }
break;
- case 0x006d:
+ case APMSG_CHAR_INFO:
tempPlayer = readPlayerData(msg, slot);
mCharInfo->unlock();
mCharInfo->select(slot);
@@ -102,107 +103,111 @@ void CharServerHandler::handleMessage(MessageIn *msg)
n_character++;
break;
- case 0x006e:
- new OkDialog("Error", "Failed to create character");
- break;
-
- case 0x006f:
- delete mCharInfo->getEntry();
- mCharInfo->setEntry(0);
- mCharInfo->unlock();
- n_character--;
- new OkDialog("Info", "Player deleted");
+ case APMSG_CHAR_SELECT_RESPONSE:
+ handleCharSelectResponse(msg);
break;
+ }
+}
- case 0x0070:
- mCharInfo->unlock();
- new OkDialog("Error", "Failed to delete character.");
- break;
+void
+CharServerHandler::handleCharCreateResponse(MessageIn &msg)
+{
+ int errMsg = msg.readByte();
- case 0x0071:
- player_node = mCharInfo->getEntry();
- msg->skip(4); // CharID, must be the same as player_node->charID
- map_path = msg->readString(16);
- mLoginData->hostname = iptostring(msg->readInt32());
- mLoginData->port = msg->readInt16();
- mCharInfo->unlock();
- mCharInfo->select(0);
- // Clear unselected players infos
- do
- {
- LocalPlayer *tmp = mCharInfo->getEntry();
- if (tmp != player_node)
- delete tmp;
- mCharInfo->next();
- } while (mCharInfo->getPos());
+ // Character creation failed
+ if (errMsg != ERRMSG_OK)
+ {
+ std::string message = "";
+ switch (errMsg)
+ {
+ case ERRMSG_NO_LOGIN:
+ message = "Not logged in";
+ break;
+ case CREATE_TOO_MUCH_CHARACTERS:
+ message = "No empty slot";
+ break;
+ case ERRMSG_INVALID_ARGUMENT:
+ message = "Invalid name";
+ break;
+ case CREATE_EXISTS_NAME:
+ message = "Character's name already exists";
+ break;
+ case CREATE_INVALID_HAIRSTYLE:
+ message = "Invalid hairstyle";
+ break;
+ case CREATE_INVALID_HAIRCOLOR:
+ message = "Invalid hair color";
+ break;
+ case CREATE_INVALID_GENDER:
+ message = "Invalid gender";
+ break;
+ case CREATE_RAW_STATS_TOO_HIGH:
+ message = "Character's stats are too high";
+ break;
+ case CREATE_RAW_STATS_TOO_LOW:
+ message = "Character's stats are too low";
+ break;
+ case CREATE_RAW_STATS_INVALID_DIFF:
+ message = "Character's stats difference is too high";
+ break;
+ case CREATE_RAW_STATS_EQUAL_TO_ZERO:
+ message = "One stat is zero";
+ break;
+ default:
+ message = "Unknown error";
+ break;
+ }
+ new OkDialog("Error", message);
+ }
+}
- state = CONNECTING_STATE;
- break;
+void
+CharServerHandler::handleCharSelectResponse(MessageIn &msg)
+{
+ int errMsg = msg.readByte();
- 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;
- }
- mCharInfo->unlock();
- state = ERROR_STATE;
- break;
+ if (errMsg == ERRMSG_OK)
+ {
+ token = msg.readString(32);
+ std::string gameServer = msg.readString();
+ unsigned short gameServerPort = msg.readShort();
+ std::string chatServer = msg.readString();
+ unsigned short chatServerPort = msg.readShort();
+
+ logger->log("Game server: %s:%d", gameServer.c_str(), gameServerPort);
+ logger->log("Chat server: %s:%d", chatServer.c_str(), chatServerPort);
+
+ gameServerConnection->connect(gameServer, gameServerPort);
+ chatServerConnection->connect(chatServer, chatServerPort);
+
+ // Keep the selected character and delete the others
+ player_node = mCharInfo->getEntry();
+ mCharInfo->unlock();
+ mCharInfo->select(0);
+ do {
+ LocalPlayer *tmp = mCharInfo->getEntry();
+ if (tmp != player_node)
+ delete tmp;
+ mCharInfo->next();
+ } while (mCharInfo->getPos());
+
+ state = STATE_CONNECT_GAME;
}
}
-LocalPlayer* CharServerHandler::readPlayerData(MessageIn *msg, int &slot)
+LocalPlayer*
+CharServerHandler::readPlayerData(MessageIn &msg, int &slot)
{
- LocalPlayer *tempPlayer = new LocalPlayer(mLoginData->account_ID, 0, NULL);
- tempPlayer->setSex(1 - mLoginData->sex);
-
- tempPlayer->mCharId = msg->readInt32();
- tempPlayer->mTotalWeight = 0;
- tempPlayer->mMaxWeight = 0;
- tempPlayer->mLastAttackTime = 0;
- tempPlayer->mXp = msg->readInt32();
- tempPlayer->mGp = msg->readInt32();
- tempPlayer->mJobXp = msg->readInt32();
- tempPlayer->mJobLevel = msg->readInt32();
- msg->skip(8); // unknown
- msg->readInt32(); // option
- msg->readInt32(); // karma
- msg->readInt32(); // manner
- msg->skip(2); // unknown
- tempPlayer->mHp = msg->readInt16();
- tempPlayer->mMaxHp = msg->readInt16();
- tempPlayer->mMp = msg->readInt16();
- tempPlayer->mMaxMp = msg->readInt16();
- msg->readInt16(); // speed
- msg->readInt16(); // class
- tempPlayer->setHairStyle(msg->readInt16());
- Uint16 weapon = msg->readInt16();
- if (weapon == 11)
- weapon = 2;
- tempPlayer->setWeapon(weapon);
- tempPlayer->mLevel = msg->readInt16();
- msg->readInt16(); // skill point
- tempPlayer->setVisibleEquipment(3, msg->readInt16()); // head bottom
- msg->readInt16(); // shield
- tempPlayer->setVisibleEquipment(4, msg->readInt16()); // head option top
- tempPlayer->setVisibleEquipment(5, msg->readInt16()); // head option mid
- tempPlayer->setHairColor(msg->readInt16());
- msg->readInt16(); // unknown
- tempPlayer->setName(msg->readString(24));
+ LocalPlayer *tempPlayer = new LocalPlayer;
+ slot = msg.readByte(); // character slot
+ tempPlayer->mName = msg.readString();
+ tempPlayer->setSex(msg.readByte());
+ tempPlayer->setHairStyle(msg.readByte());
+ tempPlayer->setHairColor(msg.readByte());
+ tempPlayer->mLevel = msg.readByte();
+ tempPlayer->mMoney = msg.readShort();
for (int i = 0; i < 6; i++) {
- tempPlayer->mAttr[i] = msg->readInt8();
+ tempPlayer->mAttr[i] = msg.readByte();
}
- slot = msg->readInt8(); // character slot
- msg->readInt8(); // unknown
-
return tempPlayer;
}
diff --git a/src/net/charserverhandler.h b/src/net/charserverhandler.h
index 16d2c361..342641d7 100644
--- a/src/net/charserverhandler.h
+++ b/src/net/charserverhandler.h
@@ -36,17 +36,26 @@ class CharServerHandler : public MessageHandler
public:
CharServerHandler();
- void handleMessage(MessageIn *msg);
+ void
+ handleMessage(MessageIn &msg);
- void setCharInfo(LockedArray<LocalPlayer*> *charInfo) { mCharInfo = charInfo; };
-
- void setLoginData(LoginData *loginData) { mLoginData = loginData; };
+ void
+ setCharInfo(LockedArray<LocalPlayer*> *charInfo)
+ {
+ mCharInfo = charInfo;
+ }
protected:
- LoginData *mLoginData;
+ void
+ handleCharCreateResponse(MessageIn &msg);
+
+ void
+ handleCharSelectResponse(MessageIn &msg);
+
LockedArray<LocalPlayer*> *mCharInfo;
- LocalPlayer* readPlayerData(MessageIn *msg, int &slot);
+ LocalPlayer*
+ readPlayerData(MessageIn &msg, int &slot);
};
#endif
diff --git a/src/net/chathandler.cpp b/src/net/chathandler.cpp
index 9095a4e1..f765f0f4 100644
--- a/src/net/chathandler.cpp
+++ b/src/net/chathandler.cpp
@@ -42,35 +42,53 @@ extern Being *player_node;
ChatHandler::ChatHandler()
{
static const Uint16 _messages[] = {
+ GPMSG_SAY,
+ /*
SMSG_BEING_CHAT,
SMSG_PLAYER_CHAT,
SMSG_GM_CHAT,
SMSG_WHO_ANSWER,
0x10c, // MVP
+ */
0
};
handledMessages = _messages;
}
-void ChatHandler::handleMessage(MessageIn *msg)
+void ChatHandler::handleMessage(MessageIn &msg)
{
Being *being;
std::string chatMsg;
- Sint16 chatMsgLength;
+ //Sint16 chatMsgLength;
- switch (msg->getId())
+ switch (msg.getId())
{
+ case GPMSG_SAY:
+ being = beingManager->findBeing(msg.readShort());
+ chatMsg = msg.readString();
+ if (being)
+ {
+ chatWindow->chatLog(being->getName() + " : " + chatMsg, being == player_node ? BY_PLAYER : BY_OTHER);
+ being->setSpeech(chatMsg, SPEECH_TIME);
+ }
+ else
+ {
+ chatWindow->chatLog("John Doe : " + chatMsg, BY_OTHER);
+ }
+ break;
+
+ /*
// Received speech from being
case SMSG_BEING_CHAT:
- chatMsgLength = msg->readInt16() - 8;
- being = beingManager->findBeing(msg->readInt32());
+ chatMsgLength = msg.readShort() - 8;
+ being = beingManager->findBeing(msg.readLong());
if (!being || chatMsgLength <= 0)
{
break;
}
- chatMsg = msg->readString(chatMsgLength);
+ chatMsg = msg.readString(chatMsgLength);
chatWindow->chatLog(chatMsg, BY_OTHER);
chatMsg.erase(0, chatMsg.find(" : ", 0) + 3);
being->setSpeech(chatMsg, SPEECH_TIME);
@@ -78,16 +96,16 @@ void ChatHandler::handleMessage(MessageIn *msg)
case SMSG_PLAYER_CHAT:
case SMSG_GM_CHAT:
- chatMsgLength = msg->readInt16() - 4;
+ chatMsgLength = msg.readShort() - 4;
if (chatMsgLength <= 0)
{
break;
}
- chatMsg = msg->readString(chatMsgLength);
+ chatMsg = msg.readString(chatMsgLength);
- if (msg->getId() == SMSG_PLAYER_CHAT)
+ if (msg.getId() == SMSG_PLAYER_CHAT)
{
chatWindow->chatLog(chatMsg, BY_PLAYER);
@@ -105,14 +123,15 @@ void ChatHandler::handleMessage(MessageIn *msg)
break;
case SMSG_WHO_ANSWER:
- chatWindow->chatLog("Online users: " + toString(msg->readInt32()),
+ chatWindow->chatLog("Online users: " + toString(msg.readLong()),
BY_SERVER);
break;
case 0x010c:
// Display MVP player
- msg->readInt32(); // id
+ msg.readLong(); // id
chatWindow->chatLog("MVP player", BY_SERVER);
break;
+ */
}
}
diff --git a/src/net/chathandler.h b/src/net/chathandler.h
index eed19206..e9db3575 100644
--- a/src/net/chathandler.h
+++ b/src/net/chathandler.h
@@ -31,7 +31,7 @@ class ChatHandler : public MessageHandler
public:
ChatHandler();
- void handleMessage(MessageIn *msg);
+ void handleMessage(MessageIn &msg);
};
#endif
diff --git a/src/net/chatserver/chatserver.cpp b/src/net/chatserver/chatserver.cpp
new file mode 100644
index 00000000..e6a3331d
--- /dev/null
+++ b/src/net/chatserver/chatserver.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$
+ */
+
+#include "chatserver.h"
+
+#include "internal.h"
+
+#include "../connection.h"
+#include "../messageout.h"
+#include "../protocol.h"
+
+using Net::ChatServer::connection;
+
+void Net::ChatServer::connect(Net::Connection *connection,
+ const std::string &token)
+{
+ Net::ChatServer::connection = connection;
+
+ MessageOut msg(PCMSG_CONNECT);
+
+ msg.writeString(token, 32);
+
+ connection->send(msg);
+}
+
+void Net::ChatServer::chat(short channel, const std::string &text)
+{
+ MessageOut msg(PCMSG_CHAT);
+
+ msg.writeString(text);
+ msg.writeShort(channel);
+
+ connection->send(msg);
+}
+
+void Net::ChatServer::announce(const std::string &text)
+{
+ MessageOut msg(PCMSG_ANNOUNCE);
+
+ msg.writeString(text);
+
+ connection->send(msg);
+}
+
+void Net::ChatServer::privMsg(const std::string &recipient,
+ const std::string &text)
+{
+ MessageOut msg(PCMSG_PRIVMSG);
+
+ msg.writeString(recipient);
+ msg.writeString(text);
+
+ connection->send(msg);
+}
+
+void Net::ChatServer::registerChannel(const std::string &name,
+ const std::string &annoucement, const std::string &password,
+ char isPrivate)
+{
+ MessageOut msg(PCMSG_REGISTER_CHANNEL);
+
+ msg.writeByte(isPrivate);
+ msg.writeString(name);
+ msg.writeString(annoucement);
+ msg.writeString(password);
+
+ connection->send(msg);
+}
+
+void Net::ChatServer::unregisterChannel(short channel)
+{
+ MessageOut msg(PCMSG_UNREGISTER_CHANNEL);
+
+ msg.writeShort(channel);
+
+ connection->send(msg);
+}
+
+void Net::ChatServer::enterChannel(short channel, const std::string &password)
+{
+ MessageOut msg(PCMSG_ENTER_CHANNEL);
+
+ msg.writeShort(channel);
+ msg.writeString(password);
+
+ connection->send(msg);
+}
+
+void Net::ChatServer::quitChannel(short channel)
+{
+ MessageOut msg(PCMSG_QUIT_CHANNEL);
+
+ msg.writeShort(channel);
+
+ connection->send(msg);
+}
diff --git a/src/net/chatserver/chatserver.h b/src/net/chatserver/chatserver.h
new file mode 100644
index 00000000..93fe17c4
--- /dev/null
+++ b/src/net/chatserver/chatserver.h
@@ -0,0 +1,55 @@
+/*
+ * 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$
+ */
+
+#ifndef _TMW_NET_CHATSERVER_CHATSERVER_H
+#define _TMW_NET_CHATSERVER_CHATSERVER_H
+
+#include <iosfwd>
+
+namespace Net
+{
+ class Connection;
+
+ namespace ChatServer
+ {
+ void connect(Net::Connection *connection, const std::string &token);
+
+ void chat(short channel, const std::string &text);
+
+ void announce(const std::string &text);
+
+ void privMsg(const std::string &recipient, const std::string &text);
+
+ void registerChannel(const std::string &name,
+ const std::string &announcement, const std::string &password,
+ char isPrivate);
+
+ void unregisterChannel(short channel);
+
+ void enterChannel(short channel, const std::string &password);
+
+ void quitChannel(short channel);
+ }
+}
+
+#endif
diff --git a/src/net/chatserver/internal.cpp b/src/net/chatserver/internal.cpp
new file mode 100644
index 00000000..c1f7a3f7
--- /dev/null
+++ b/src/net/chatserver/internal.cpp
@@ -0,0 +1,34 @@
+/*
+ * 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$
+ */
+
+#include "internal.h"
+
+namespace Net
+{
+ class Connection;
+
+ namespace ChatServer
+ {
+ Connection *connection = 0;
+ }
+}
diff --git a/src/net/packet.cpp b/src/net/chatserver/internal.h
index e77ac117..7579972b 100644
--- a/src/net/packet.cpp
+++ b/src/net/chatserver/internal.h
@@ -21,20 +21,17 @@
* $Id$
*/
-#include "packet.h"
+#ifndef _TMW_NET_CHATSERVER_INTERNAL_H
+#define _TMW_NET_CHATSERVER_INTERNAL_H
-#include <cstring>
-
-Packet::Packet(const char *data, int length):
- mLength(length)
+namespace Net
{
- // Create a copy of the data
- mData = new char[mLength];
- memcpy(mData, data, mLength);
-}
+ class Connection;
-Packet::~Packet()
-{
- // Clean up the data
- delete[] mData;
+ namespace ChatServer
+ {
+ extern Connection *connection;
+ }
}
+
+#endif
diff --git a/src/net/connection.cpp b/src/net/connection.cpp
new file mode 100644
index 00000000..a17bc727
--- /dev/null
+++ b/src/net/connection.cpp
@@ -0,0 +1,104 @@
+/*
+ * 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$
+ */
+
+#include "connection.h"
+
+#include <string>
+
+#include "internal.h"
+#include "messageout.h"
+
+#include "../log.h"
+
+Net::Connection::Connection(ENetHost *client):
+ mConnection(0), mClient(client)
+{
+ Net::connections++;
+}
+
+Net::Connection::~Connection()
+{
+ Net::connections--;
+}
+
+bool Net::Connection::connect(const std::string &address, short port)
+{
+ logger->log("Net::Connection::connect(%s, %i)", address.c_str(), port);
+
+ if (address.empty())
+ {
+ logger->log("Net::Connection::connect() got empty address!");
+ mState = ERROR;
+ return false;
+ }
+
+ ENetAddress enetAddress;
+
+ enet_address_set_host(&enetAddress, address.c_str());
+ enetAddress.port = port;
+
+ // Initiate the connection, allocating channel 0.
+ mConnection = enet_host_connect(mClient, &enetAddress, 1);
+
+ if (!mConnection)
+ {
+ logger->log("Unable to initiate connection to the server.");
+ mState = ERROR;
+ return false;
+ }
+
+ return true;
+}
+
+void Net::Connection::disconnect()
+{
+ if (!mConnection)
+ return;
+
+ enet_peer_disconnect(mConnection, 0);
+ enet_host_flush(mClient);
+ enet_peer_reset(mConnection);
+
+ mConnection = 0;
+}
+
+bool Net::Connection::isConnected()
+{
+ return mConnection && mConnection->state == ENET_PEER_STATE_CONNECTED;
+}
+
+void Net::Connection::send(const MessageOut &msg)
+{
+ if (!isConnected())
+ {
+ logger->log("Warning: cannot send message to not connected server!");
+ return;
+ }
+
+ logger->log("Sending message of size %d...", msg.getDataSize());
+
+ ENetPacket *packet = enet_packet_create(msg.getData(),
+ msg.getDataSize(),
+ ENET_PACKET_FLAG_RELIABLE);
+ enet_peer_send(mConnection, 0, packet);
+}
diff --git a/src/net/connection.h b/src/net/connection.h
new file mode 100644
index 00000000..179367c6
--- /dev/null
+++ b/src/net/connection.h
@@ -0,0 +1,78 @@
+/*
+ * 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$
+ */
+
+#ifndef _TMW_NET_CONNECTION_H
+#define _TMW_NET_CONNECTION_H
+
+#include <iosfwd>
+
+#include <enet/enet.h>
+
+class MessageOut;
+
+namespace Net
+{
+ class Connection
+ {
+ public:
+ enum State {
+ OK, ERROR
+ };
+
+ ~Connection();
+
+ /**
+ * Connects to the given server with the specified address and port.
+ * This method is non-blocking, use isConnected to check whether the
+ * server is connected.
+ */
+ bool connect(const std::string &address, short port);
+
+ /**
+ * Disconnects from the given server.
+ */
+ void disconnect();
+
+ State getState() { return mState; }
+
+ /**
+ * Returns whether the server is connected.
+ */
+ bool isConnected();
+
+ /**
+ * Sends a message.
+ */
+ void send(const MessageOut &msg);
+
+ private:
+ friend Connection *Net::getConnection();
+ Connection(ENetHost *client);
+
+ ENetPeer *mConnection;
+ ENetHost *mClient;
+ State mState;
+ };
+}
+
+#endif
diff --git a/src/net/equipmenthandler.cpp b/src/net/equipmenthandler.cpp
index 01760eeb..1c0fd4ca 100644
--- a/src/net/equipmenthandler.cpp
+++ b/src/net/equipmenthandler.cpp
@@ -48,7 +48,7 @@ EquipmentHandler::EquipmentHandler()
handledMessages = _messages;
}
-void EquipmentHandler::handleMessage(MessageIn *msg)
+void EquipmentHandler::handleMessage(MessageIn &msg)
{
Sint32 itemCount;
Sint16 index, equipPoint, itemId;
@@ -57,23 +57,22 @@ void EquipmentHandler::handleMessage(MessageIn *msg)
Being *being;
Item *item;
- switch (msg->getId())
+ switch (msg.getId())
{
case SMSG_PLAYER_EQUIPMENT:
- msg->readInt16(); // length
- itemCount = (msg->getLength() - 4) / 20;
+ msg.readShort(); // length
+ itemCount = (msg.getLength() - 4) / 20;
for (int loop = 0; loop < itemCount; loop++)
{
- index = msg->readInt16();
- itemId = msg->readInt16();
- msg->readInt8(); // type
- msg->readInt8(); // identify flag
- msg->readInt16(); // equip type
- equipPoint = msg->readInt16();
- msg->readInt8(); // attribute
- msg->readInt8(); // refine
- msg->skip(8); // card
+ index = msg.readShort();
+ itemId = msg.readShort();
+ msg.readByte(); // type
+ msg.readByte(); // identify flag
+ msg.readShort(); // equip type
+ equipPoint = msg.readShort();
+ msg.readByte(); // attribute
+ msg.readByte(); // refine
player_node->addInvItem(index, itemId, 1, true);
@@ -93,9 +92,9 @@ void EquipmentHandler::handleMessage(MessageIn *msg)
break;
case SMSG_PLAYER_EQUIP:
- index = msg->readInt16();
- equipPoint = msg->readInt16();
- type = msg->readInt8();
+ index = msg.readShort();
+ equipPoint = msg.readShort();
+ type = msg.readByte();
logger->log("Equipping: %i %i %i", index, equipPoint, type);
@@ -129,10 +128,10 @@ void EquipmentHandler::handleMessage(MessageIn *msg)
case 0x01d7:
// Equipment related
- being = beingManager->findBeing(msg->readInt32());
- msg->readInt8(); // equip point
- itemId = msg->readInt16();
- msg->readInt16(); // item id 2
+ being = beingManager->findBeing(msg.readLong());
+ msg.readByte(); // equip point
+ itemId = msg.readShort();
+ msg.readShort(); // item id 2
if (!being)
break;
@@ -141,9 +140,9 @@ void EquipmentHandler::handleMessage(MessageIn *msg)
break;
case SMSG_PLAYER_UNEQUIP:
- index = msg->readInt16();
- equipPoint = msg->readInt16();
- type = msg->readInt8();
+ index = msg.readShort();
+ equipPoint = msg.readShort();
+ type = msg.readByte();
if (!type) {
chatWindow->chatLog("Unable to unequip.", BY_SERVER);
@@ -193,7 +192,7 @@ void EquipmentHandler::handleMessage(MessageIn *msg)
break;
case SMSG_PLAYER_ARROW_EQUIP:
- itemId = msg->readInt16();
+ itemId = msg.readShort();
if (itemId <= 1)
break;
diff --git a/src/net/equipmenthandler.h b/src/net/equipmenthandler.h
index 656f7a73..c9c65d67 100644
--- a/src/net/equipmenthandler.h
+++ b/src/net/equipmenthandler.h
@@ -31,7 +31,7 @@ class EquipmentHandler : public MessageHandler
public:
EquipmentHandler();
- void handleMessage(MessageIn *msg);
+ void handleMessage(MessageIn &msg);
};
#endif
diff --git a/src/net/gameserver/gameserver.cpp b/src/net/gameserver/gameserver.cpp
new file mode 100644
index 00000000..04e5bb08
--- /dev/null
+++ b/src/net/gameserver/gameserver.cpp
@@ -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$
+ */
+
+#include "gameserver.h"
+
+#include "internal.h"
+
+#include "../connection.h"
+#include "../messageout.h"
+#include "../protocol.h"
+
+void Net::GameServer::connect(Net::Connection *connection,
+ const std::string &token)
+{
+ Net::GameServer::connection = connection;
+
+ MessageOut msg(PGMSG_CONNECT);
+
+ msg.writeString(token, 32);
+
+ Net::GameServer::connection->send(msg);
+}
diff --git a/src/net/packet.h b/src/net/gameserver/gameserver.h
index 84d16d5e..ee49d7e3 100644
--- a/src/net/packet.h
+++ b/src/net/gameserver/gameserver.h
@@ -21,27 +21,19 @@
* $Id$
*/
-#ifndef _TMW_PACKET_
-#define _TMW_PACKET_
+#ifndef _TMW_NET_GAMESERVER_GAMESERVER_H
+#define _TMW_NET_GAMESERVER_GAMESERVER_H
-/**
- * A packet wraps a certain amount of bytes for sending and receiving.
- */
-class Packet
-{
- public:
- /**
- * Constructor.
- */
- Packet(const char *data, int length);
+#include <iosfwd>
- /**
- * Destructor.
- */
- ~Packet();
+namespace Net
+{
+ class Connection;
- char *mData; /**< Packet data */
- unsigned int mLength; /**< Length of data in bytes */
-};
+ namespace GameServer
+ {
+ void connect(Net::Connection *connection, const std::string &token);
+ }
+}
#endif
diff --git a/src/net/gameserver/internal.cpp b/src/net/gameserver/internal.cpp
new file mode 100644
index 00000000..328b4863
--- /dev/null
+++ b/src/net/gameserver/internal.cpp
@@ -0,0 +1,34 @@
+/*
+ * 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$
+ */
+
+#include "internal.h"
+
+namespace Net
+{
+ class Connection;
+
+ namespace GameServer
+ {
+ Connection *connection = 0;
+ }
+}
diff --git a/src/net/gameserver/internal.h b/src/net/gameserver/internal.h
new file mode 100644
index 00000000..567e15d2
--- /dev/null
+++ b/src/net/gameserver/internal.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$
+ */
+
+#ifndef _TMW_NET_GAMESERVER_INTERNAL_H
+#define _TMW_NET_GAMESERVER_INTERNAL_H
+
+namespace Net
+{
+ class Connection;
+
+ namespace GameServer
+ {
+ extern Connection *connection;
+ }
+}
+
+#endif
diff --git a/src/net/gameserver/player.cpp b/src/net/gameserver/player.cpp
new file mode 100644
index 00000000..1f27276a
--- /dev/null
+++ b/src/net/gameserver/player.cpp
@@ -0,0 +1,68 @@
+/*
+ * 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$
+ */
+
+#include "player.h"
+
+#include "internal.h"
+
+#include "../connection.h"
+#include "../messageout.h"
+#include "../protocol.h"
+
+void Net::GameServer::Player::say(const std::string &text)
+{
+ MessageOut msg(PGMSG_SAY);
+
+ msg.writeString(text);
+
+ Net::GameServer::connection->send(msg);
+}
+
+void Net::GameServer::Player::walk(short x, short y)
+{
+ MessageOut msg(PGMSG_WALK);
+
+ msg.writeShort(x);
+ msg.writeShort(y);
+
+ Net::GameServer::connection->send(msg);
+}
+
+void Net::GameServer::Player::useItem(int itemId)
+{
+ MessageOut msg(PGMSG_USE_ITEM);
+
+ msg.writeLong(itemId);
+
+ Net::GameServer::connection->send(msg);
+}
+
+void Net::GameServer::Player::equip(int itemId, char slot)
+{
+ MessageOut msg(PGMSG_EQUIP);
+
+ msg.writeLong(itemId);
+ msg.writeByte(slot);
+
+ Net::GameServer::connection->send(msg);
+}
diff --git a/src/net/gameserver/player.h b/src/net/gameserver/player.h
new file mode 100644
index 00000000..34d5bb45
--- /dev/null
+++ b/src/net/gameserver/player.h
@@ -0,0 +1,46 @@
+/*
+ * 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$
+ */
+
+#ifndef _TMW_NET_GAMESERVER_PLAYER_H
+#define _TMW_NET_GAMESERVER_PLAYER_H
+
+#include <iosfwd>
+
+namespace Net
+{
+ class Connection;
+
+ namespace GameServer
+ {
+ namespace Player
+ {
+ void say(const std::string &text);
+ void walk(short x, short y);
+// void pickUp(...);
+ void useItem(int itemId);
+ void equip(int itemId, char slot);
+ }
+ }
+}
+
+#endif
diff --git a/src/net/internal.cpp b/src/net/internal.cpp
new file mode 100644
index 00000000..358aa143
--- /dev/null
+++ b/src/net/internal.cpp
@@ -0,0 +1,29 @@
+/*
+ * 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$
+ */
+
+#include "internal.h"
+
+namespace Net
+{
+ int connections = 0;
+}
diff --git a/src/net/internal.h b/src/net/internal.h
new file mode 100644
index 00000000..e1ef648a
--- /dev/null
+++ b/src/net/internal.h
@@ -0,0 +1,32 @@
+/*
+ * 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$
+ */
+
+#ifndef _TMW_NET_INTERNAL_H
+#define _TMW_NET_INTERNAL_H
+
+namespace Net
+{
+ extern int connections;
+}
+
+#endif
diff --git a/src/net/inventoryhandler.cpp b/src/net/inventoryhandler.cpp
index afe653eb..3f7e8709 100644
--- a/src/net/inventoryhandler.cpp
+++ b/src/net/inventoryhandler.cpp
@@ -47,29 +47,27 @@ InventoryHandler::InventoryHandler()
handledMessages = _messages;
}
-void InventoryHandler::handleMessage(MessageIn *msg)
+void InventoryHandler::handleMessage(MessageIn &msg)
{
Sint32 number;
Sint16 index, amount, itemId, equipType;
- switch (msg->getId())
+ switch (msg.getId())
{
case SMSG_PLAYER_INVENTORY:
// Only called on map load / warp. First reset all items
// to not load them twice on map change.
player_node->clearInventory();
- msg->readInt16(); // length
- number = (msg->getLength() - 4) / 18;
+ msg.readShort(); // length
+ number = (msg.getLength() - 4) / 18;
for (int loop = 0; loop < number; loop++)
{
- index = msg->readInt16();
- itemId = msg->readInt16();
- msg->readInt8(); // type
- msg->readInt8(); // identify flag
- amount = msg->readInt16();
- msg->skip(2); // unknown
- msg->skip(8); // card (4 shorts)
+ index = msg.readShort();
+ itemId = msg.readShort();
+ msg.readByte(); // type
+ msg.readByte(); // identify flag
+ amount = msg.readShort();
player_node->addInvItem(index, itemId, amount, false);
@@ -82,17 +80,16 @@ void InventoryHandler::handleMessage(MessageIn *msg)
break;
case SMSG_PLAYER_INVENTORY_ADD:
- index = msg->readInt16();
- amount = msg->readInt16();
- itemId = msg->readInt16();
- msg->readInt8(); // identify flag
- msg->readInt8(); // attribute
- msg->readInt8(); // refine
- msg->skip(8); // card
- equipType = msg->readInt16();
- msg->readInt8(); // type
-
- if (msg->readInt8()> 0) {
+ index = msg.readShort();
+ amount = msg.readShort();
+ itemId = msg.readShort();
+ msg.readByte(); // identify flag
+ msg.readByte(); // attribute
+ msg.readByte(); // refine
+ equipType = msg.readShort();
+ msg.readByte(); // type
+
+ if (msg.readByte()> 0) {
chatWindow->chatLog("Unable to pick up item", BY_SERVER);
} else {
const ItemInfo &itemInfo = itemDb->getItemInfo(itemId);
@@ -103,26 +100,26 @@ void InventoryHandler::handleMessage(MessageIn *msg)
break;
case SMSG_PLAYER_INVENTORY_REMOVE:
- index = msg->readInt16();
- amount = msg->readInt16();
+ index = msg.readShort();
+ amount = msg.readShort();
player_node->getInvItem(index)->increaseQuantity(-amount);
break;
case SMSG_PLAYER_INVENTORY_USE:
- index = msg->readInt16();
- msg->readInt16(); // item id
- msg->readInt32(); // id
- amount = msg->readInt16();
- msg->readInt8(); // type
+ index = msg.readShort();
+ msg.readShort(); // item id
+ msg.readLong(); // id
+ amount = msg.readShort();
+ msg.readByte(); // type
player_node->getInvItem(index)->setQuantity(amount);
break;
case SMSG_ITEM_USE_RESPONSE:
- index = msg->readInt16();
- amount = msg->readInt16();
+ index = msg.readShort();
+ amount = msg.readShort();
- if (msg->readInt8() == 0) {
+ if (msg.readByte() == 0) {
chatWindow->chatLog("Failed to use item", BY_SERVER);
} else {
player_node->getInvItem(index)->setQuantity(amount);
diff --git a/src/net/inventoryhandler.h b/src/net/inventoryhandler.h
index aedbc3a1..4190bf83 100644
--- a/src/net/inventoryhandler.h
+++ b/src/net/inventoryhandler.h
@@ -31,7 +31,7 @@ class InventoryHandler : public MessageHandler
public:
InventoryHandler();
- void handleMessage(MessageIn *msg);
+ void handleMessage(MessageIn &msg);
};
#endif
diff --git a/src/net/itemhandler.cpp b/src/net/itemhandler.cpp
index 567a5382..2961f71b 100644
--- a/src/net/itemhandler.cpp
+++ b/src/net/itemhandler.cpp
@@ -40,29 +40,28 @@ ItemHandler::ItemHandler()
handledMessages = _messages;
}
-void ItemHandler::handleMessage(MessageIn *msg)
+void ItemHandler::handleMessage(MessageIn &msg)
{
Uint32 id;
Uint16 x, y;
Sint16 itemId;
- switch (msg->getId())
+ switch (msg.getId())
{
case SMSG_ITEM_VISIBLE:
case SMSG_ITEM_DROPPED:
- id = msg->readInt32();
- itemId = msg->readInt16();
- msg->readInt8(); // identify flag
- x = msg->readInt16();
- y = msg->readInt16();
- msg->skip(4); // amount,subX,subY / subX,subY,amount
+ id = msg.readLong();
+ itemId = msg.readShort();
+ msg.readByte(); // identify flag
+ x = msg.readShort();
+ y = msg.readShort();
floorItemManager->create(id, itemId, x, y, engine->getCurrentMap());
break;
case SMSG_ITEM_REMOVE:
FloorItem *item;
- item = floorItemManager->findById(msg->readInt32());
+ item = floorItemManager->findById(msg.readLong());
if (item)
floorItemManager->destroy(item);
break;
diff --git a/src/net/itemhandler.h b/src/net/itemhandler.h
index b2104722..5ffcb134 100644
--- a/src/net/itemhandler.h
+++ b/src/net/itemhandler.h
@@ -31,7 +31,7 @@ class ItemHandler : public MessageHandler
public:
ItemHandler();
- void handleMessage(MessageIn *msg);
+ void handleMessage(MessageIn &msg);
};
#endif
diff --git a/src/net/loginhandler.cpp b/src/net/loginhandler.cpp
index 195e54e9..73be4b2f 100644
--- a/src/net/loginhandler.cpp
+++ b/src/net/loginhandler.cpp
@@ -24,92 +24,87 @@
#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,
+ APMSG_LOGIN_RESPONSE,
+ APMSG_REGISTER_RESPONSE,
0
};
handledMessages = _messages;
}
-void LoginHandler::handleMessage(MessageIn *msg)
+void LoginHandler::handleMessage(MessageIn &msg)
{
- switch (msg->getId())
+ 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++)
+ case APMSG_LOGIN_RESPONSE:
+ {
+ int errMsg = msg.readByte();
+ // Successful login
+ if (errMsg == ERRMSG_OK)
{
- 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);
- 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 = STATE_CHAR_SELECT;
}
- state = CHAR_SERVER_STATE;
+ // Login failed
+ else
+ {
+ switch (errMsg) {
+ case LOGIN_INVALID_VERSION:
+ errorMessage = "Client has an insufficient version number to login.";
+ break;
+ case ERRMSG_INVALID_ARGUMENT:
+ errorMessage = "Wrong username or password";
+ break;
+ case ERRMSG_FAILURE:
+ errorMessage = "Already logged in";
+ break;
+ case LOGIN_SERVER_FULL:
+ errorMessage = "Server is full";
+ break;
+ default:
+ errorMessage = "Unknown error";
+ break;
+ }
+ state = STATE_ERROR;
+ }
+ }
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;
+ case APMSG_REGISTER_RESPONSE:
+ {
+ int errMsg = msg.readByte();
+ // Successful registration
+ if (errMsg == ERRMSG_OK)
+ {
+ state = STATE_CHAR_SELECT;
+ }
+ // Registration failed
+ else
+ {
+ switch (errMsg) {
+ case REGISTER_INVALID_VERSION:
+ errorMessage = "Client has an insufficient version number to login.";
+ break;
+ case ERRMSG_INVALID_ARGUMENT:
+ errorMessage = "Wrong username, password or email address";
+ break;
+ case REGISTER_EXISTS_USERNAME:
+ errorMessage = "Username already exists";
+ break;
+ case REGISTER_EXISTS_EMAIL:
+ errorMessage = "Email address already exists";
+ break;
+ default:
+ errorMessage = "Unknown error";
+ break;
+ }
+ state = STATE_ERROR;
}
- state = ERROR_STATE;
+ }
break;
}
}
diff --git a/src/net/loginhandler.h b/src/net/loginhandler.h
index 52014559..5bac079c 100644
--- a/src/net/loginhandler.h
+++ b/src/net/loginhandler.h
@@ -26,19 +26,12 @@
#include "messagehandler.h"
-struct LoginData;
-
class LoginHandler : public MessageHandler
{
public:
LoginHandler();
- void handleMessage(MessageIn *msg);
-
- void setLoginData(LoginData *loginData) { mLoginData = loginData; };
-
- protected:
- LoginData *mLoginData;
+ void handleMessage(MessageIn &msg);
};
#endif
diff --git a/src/net/maploginhandler.cpp b/src/net/maploginhandler.cpp
deleted file mode 100644
index 0afc8357..00000000
--- a/src/net/maploginhandler.cpp
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * 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$
- */
-
-#include "maploginhandler.h"
-
-#include "messagein.h"
-#include "protocol.h"
-
-#include "../localplayer.h"
-#include "../log.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
- msg->readCoordinates(player_node->mX, player_node->mY, direction);
- msg->skip(2); // unknown
- logger->log("Protocol: Player start position: (%d, %d), Direction: %d",
- player_node->mX, player_node->mY, direction);
- state = GAME_STATE;
- break;
-
- case 0x0081:
- logger->log("Warning: Map server D/C");
- state = ERROR_STATE;
- break;
- }
-}
diff --git a/src/net/messagehandler.cpp b/src/net/messagehandler.cpp
index 849b6716..b6074690 100644
--- a/src/net/messagehandler.cpp
+++ b/src/net/messagehandler.cpp
@@ -27,19 +27,7 @@
#include "network.h"
-MessageHandler::MessageHandler():
- mNetwork(0)
-{
-}
-
MessageHandler::~MessageHandler()
{
- if (mNetwork)
- mNetwork->unregisterHandler(this);
-}
-
-void MessageHandler::setNetwork(Network *network)
-{
- assert(!(network && mNetwork));
- mNetwork = network;
+ Net::unregisterHandler(this);
}
diff --git a/src/net/messagehandler.h b/src/net/messagehandler.h
index c09037f6..b21abd72 100644
--- a/src/net/messagehandler.h
+++ b/src/net/messagehandler.h
@@ -27,22 +27,15 @@
#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;
+ virtual void handleMessage(MessageIn &msg) = 0;
};
#endif
diff --git a/src/net/messagein.cpp b/src/net/messagein.cpp
index bbc0a44c..a1707e06 100644
--- a/src/net/messagein.cpp
+++ b/src/net/messagein.cpp
@@ -1,5 +1,5 @@
/*
- * The Mana World
+ * The Mana World Server
* Copyright 2004 The Mana World Development Team
*
* This file is part of The Mana World.
@@ -23,14 +23,9 @@
#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))
+#include <string>
+#include <enet/enet.h>
MessageIn::MessageIn(const char *data, unsigned int length):
mData(data),
@@ -38,157 +33,78 @@ MessageIn::MessageIn(const char *data, unsigned int length):
mPos(0)
{
// Read the message ID
- mId = readInt16();
+ mId = readShort();
}
-Sint8
-MessageIn::readInt8()
+MessageIn::~MessageIn()
{
- 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()
+char MessageIn::readByte()
{
- 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
+ char value = -1;
+ if (mPos < mLength)
+ {
+ value = mData[mPos];
+ }
+ mPos += 1;
+ return value;
}
-void
-MessageIn::readCoordinates(Uint16 &x, Uint16 &y, Uint8 &direction)
+short MessageIn::readShort()
{
- 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)
+ short value = -1;
+ if (mPos + 2 <= mLength)
{
- 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;
+ uint16_t t;
+ memcpy(&t, mData + mPos, 2);
+ value = ENET_NET_TO_HOST_16(t);
}
-
- mPos += 3;
+ mPos += 2;
+ return value;
}
-void
-MessageIn::readCoordinatePair(Uint16 &srcX, Uint16 &srcY,
- Uint16 &dstX, Uint16 &dstY)
+long MessageIn::readLong()
{
- 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;
+ long value = -1;
+ if (mPos + 4 <= mLength)
+ {
+ uint32_t t;
+ memcpy(&t, mData + mPos, 4);
+ value = ENET_NET_TO_HOST_32(t);
+ }
+ mPos += 4;
+ return value;
}
-void
-MessageIn::skip(unsigned int length)
+void MessageIn::readCoordinates(Uint16 &x, Uint16 &y)
{
- assert(mPos + length <= mLength);
- mPos += length;
+ if (mPos + 3 <= mLength)
+ {
+ unsigned char const *p = reinterpret_cast< unsigned char const * >(mData + mPos);
+ x = p[0] | ((p[1] & 0x07) << 8);
+ y = (p[1] >> 3) | ((p[2] & 0x3F) << 5);
+ }
+ mPos += 3;
}
-std::string
-MessageIn::readString(int length)
+std::string MessageIn::readString(int length)
{
// Get string length
if (length < 0) {
- length = readInt16();
+ length = readShort();
}
- // Make sure the string isn't erroneous
+ // Make sure the string isn't erroneus
if (length < 0 || mPos + length > mLength) {
mPos = mLength + 1;
return "";
}
// Read the string
- char const *stringBeg = mData + mPos;
- char const *stringEnd = (char const *)memchr(stringBeg, '\0', length);
- std::string readString(stringBeg,
- stringEnd ? stringEnd - stringBeg : length);
+ char const *stringBeg = mData + mPos,
+ *stringEnd = (char const *)memchr(stringBeg, '\0', length);
+ std::string readString(stringBeg, stringEnd ? stringEnd - stringBeg : length);
mPos += length;
return readString;
}
-
-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
index d97cd8b6..68bbb933 100644
--- a/src/net/messagein.h
+++ b/src/net/messagein.h
@@ -1,5 +1,5 @@
/*
- * The Mana World
+ * The Mana World Server
* Copyright 2004 The Mana World Development Team
*
* This file is part of The Mana World.
@@ -21,10 +21,11 @@
* $Id$
*/
-#ifndef _TMW_MESSAGEIN_
-#define _TMW_MESSAGEIN_
+#ifndef _TMWSERV_MESSAGEIN_H_
+#define _TMWSERV_MESSAGEIN_H_
#include <string>
+
#include <SDL_types.h>
/**
@@ -32,10 +33,6 @@
*/
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.
@@ -43,55 +40,51 @@ class MessageIn
MessageIn(const char *data, unsigned int length);
/**
- * Returns the message ID.
+ * Destructor.
*/
- short
- getId() { return mId; }
+ ~MessageIn();
- /**
- * Returns the message length.
- */
- unsigned int
- getLength() { return mLength; }
+ short getId() { return mId; } /**< Returns the message ID. */
- Sint8 readInt8(); /**< Reads a byte. */
- Sint16 readInt16(); /**< Reads a short. */
- Sint32 readInt32(); /**< Reads a long. */
+ char readByte(); /**< Reads a byte. */
+ short readShort(); /**< Reads a short. */
+ long readLong(); /**< Reads a long. */
/**
- * Reads a special 3 byte block used by eAthena, containing x and y
- * coordinates and direction.
+ * Reads a 3-byte block containing tile-based coordinates.
*/
- void
- readCoordinates(Uint16 &x, Uint16 &y, Uint8 &direction);
+ void readCoordinates(Uint16 &x, Uint16 &y);
/**
- * Reads a special 5 byte block used by eAthena, containing a source
- * and destination coordinate pair.
+ * 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.
*/
- void
- readCoordinatePair(Uint16 &srcX, Uint16 &srcY,
- Uint16 &dstX, Uint16 &dstY);
+ std::string readString(int length = -1);
/**
- * Skips a given number of bytes.
+ * Returns the message length.
*/
- void
- skip(unsigned int length);
+ unsigned int
+ getLength() { return mLength; }
/**
- * 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.
+ * Returns the length of unread data.
*/
- std::string
- readString(int length = -1);
+ unsigned int
+ getUnreadLength() { return mLength - mPos; }
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. */
+
+ /**
+ * Actual position in the packet. From 0 to packet->length.
+ * A value bigger than packet->length means EOP was reached when
+ * reading it.
+ */
+ unsigned int mPos;
};
#endif
diff --git a/src/net/messageout.cpp b/src/net/messageout.cpp
index f6ed5de6..4d68c14f 100644
--- a/src/net/messageout.cpp
+++ b/src/net/messageout.cpp
@@ -1,5 +1,5 @@
/*
- * The Mana World
+ * The Mana World Server
* Copyright 2004 The Mana World Development Team
*
* This file is part of The Mana World.
@@ -24,93 +24,92 @@
#include "messageout.h"
#include <string>
-#include <SDL.h>
-#include <SDL_endian.h>
-#include "network.h"
-#include "packet.h"
+#include <enet/enet.h>
-MessageOut::MessageOut(Network *network):
- mNetwork(network),
+MessageOut::MessageOut(short id):
mData(0),
mDataSize(0),
mPos(0)
{
- mData = mNetwork->mOutBuffer + mNetwork->mOutSize;
+ writeShort(id);
}
-void MessageOut::writeInt8(Sint8 value)
+MessageOut::~MessageOut()
{
- mData[mPos] = value;
- mPos += sizeof(Sint8);
- mNetwork->mOutSize+= sizeof(Sint8);
+ if (mData) {
+ free(mData);
+ }
}
-void MessageOut::writeInt16(Sint16 value)
+void
+MessageOut::expand(size_t bytes)
{
-#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);
+ mData = (char*)realloc(mData, bytes);
+ mDataSize = bytes;
}
-void MessageOut::writeInt32(Sint32 value)
+void
+MessageOut::writeByte(char 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);
+ expand(mPos + 1);
+ mData[mPos] = value;
+ mPos += 1;
}
-void MessageOut::writeString(const std::string &string, int length)
+void MessageOut::writeShort(short value)
{
- std::string toWrite = string;
+ expand(mPos + 2);
+ uint16_t t = ENET_HOST_TO_NET_16(value);
+ memcpy(mData + mPos, &t, 2);
+ mPos += 2;
+}
+void
+MessageOut::writeLong(long value)
+{
+ expand(mPos + 4);
+ uint32_t t = ENET_HOST_TO_NET_32(value);
+ memcpy(mData + mPos, &t, 4);
+ mPos += 4;
+}
+
+void
+MessageOut::writeString(const std::string &string, int length)
+{
+ int stringLength = string.length();
if (length < 0)
{
// Write the length at the start if not fixed
- writeInt16(string.length());
+ writeShort(stringLength);
+ length = stringLength;
}
- else
+ else if (length < stringLength)
{
// Make sure the length of the string is no longer than specified
- toWrite = string.substr(0, length);
+ stringLength = length;
}
+ expand(mPos + length);
// Write the actual string
- memcpy(&mData[mPos], (void*)toWrite.c_str(), toWrite.length());
- mPos += toWrite.length();
- mNetwork->mOutSize += toWrite.length();
+ memcpy(mData + mPos, string.c_str(), stringLength);
// Pad remaining space with zeros
- if (length > (int)toWrite.length())
+ if (length > stringLength)
{
- memset(&mData[mPos], '\0', length - toWrite.length());
- mPos += length - toWrite.length();
- mNetwork->mOutSize += length - toWrite.length();
+ memset(mData + mPos + stringLength, '\0', length - stringLength);
}
+ mPos += length;
}
-MessageOut& operator<<(MessageOut &msg, const Sint8 &rhs)
-{
- msg.writeInt8(rhs);
- return msg;
-}
-
-MessageOut& operator<<(MessageOut &msg, const Sint16 &rhs)
+char*
+MessageOut::getData() const
{
- msg.writeInt16(rhs);
- return msg;
+ return mData;
}
-MessageOut& operator<<(MessageOut &msg, const Sint32 &rhs)
+unsigned int
+MessageOut::getDataSize() const
{
- msg.writeInt32(rhs);
- return msg;
+ return mDataSize;
}
diff --git a/src/net/messageout.h b/src/net/messageout.h
index f6468adb..af25e4b4 100644
--- a/src/net/messageout.h
+++ b/src/net/messageout.h
@@ -1,5 +1,5 @@
/*
- * The Mana World
+ * The Mana World Server
* Copyright 2004 The Mana World Development Team
*
* This file is part of The Mana World.
@@ -21,32 +21,30 @@
* $Id$
*/
-#ifndef _TMW_MESSAGEOUT_
-#define _TMW_MESSAGEOUT_
+#ifndef _TMWSERV_MESSAGEOUT_H_
+#define _TMWSERV_MESSAGEOUT_H_
#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);
+ MessageOut(short id);
- void writeInt8(Sint8 value); /**< Writes a byte. */
- void writeInt16(Sint16 value); /**< Writes a short. */
- void writeInt32(Sint32 value); /**< Writes a long. */
+ /**
+ * Destructor.
+ */
+ ~MessageOut();
+
+ void writeByte(char value); /**< Writes a byte. */
+ void writeShort(short value); /**< Writes a short. */
+ void writeLong(long value); /**< Writes a long. */
/**
* Writes a string. If a fixed length is not given (-1), it is stored
@@ -54,8 +52,25 @@ class MessageOut
*/
void writeString(const std::string &string, int length = -1);
+ /**
+ * Returns the content of the message.
+ */
+ char *getData() const;
+
+ /**
+ * Returns the length of the data.
+ */
+ unsigned int getDataSize() const;
+
private:
- Network *mNetwork;
+ /**
+ * Expand the packet data to be able to hold more data.
+ *
+ * NOTE: For performance enhancements this method could allocate extra
+ * memory in advance instead of expanding size every time more data is
+ * added.
+ */
+ void expand(size_t size);
char *mData; /**< Data building up. */
unsigned int mDataSize; /**< Size of data. */
diff --git a/src/net/network.cpp b/src/net/network.cpp
index 757a533e..b94c9eb8 100644
--- a/src/net/network.cpp
+++ b/src/net/network.cpp
@@ -23,422 +23,153 @@
#include "network.h"
+#include <enet/enet.h>
+
+#include <map>
+
+#include "connection.h"
+#include "internal.h"
#include "messagehandler.h"
#include "messagein.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;
+/**
+ * The local host which is shared for all outgoing connections.
+ */
+namespace {
+ ENetHost *client;
}
-Network::Network():
- mSocket(0),
- 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();
-}
+typedef std::map<unsigned short, MessageHandler*> MessageHandlers;
+typedef MessageHandlers::iterator MessageHandlerIterator;
+static MessageHandlers mMessageHandlers;
-Network::~Network()
+void Net::initialize()
{
- clearHandlers();
-
- if (mState != IDLE && mState != ERROR)
- disconnect();
-
- SDL_DestroyMutex(mMutex);
-
- delete[] mInBuffer;
- delete[] mOutBuffer;
-}
-
-bool Network::connect(const std::string &address, short port)
-{
- if (mState != IDLE && mState != ERROR)
- {
- logger->log("Tried to connect an already connected socket!");
- return false;
- }
-
- if (address.empty())
+ if (enet_initialize())
{
- logger->log("Empty address given to Network::connect()!");
- mState = ERROR;
- return false;
+ logger->error("Failed to initialize ENet.");
}
- logger->log("Network::Connecting to %s:%i", address.c_str(), port);
+ client = enet_host_create(NULL, 3, 0, 0);
- mAddress = address;
- mPort = port;
-
- // Reset to sane values
- mOutSize = 0;
- mInSize = 0;
- mToSkip = 0;
-
- mState = CONNECTING;
- mWorkerThread = SDL_CreateThread(networkThread, this);
- if (!mWorkerThread)
+ if (!client)
{
- logger->log("Unable to create network worker thread");
- mState = ERROR;
- return false;
+ logger->error("Failed to create the local host.");
}
-
- return true;
}
-void Network::disconnect()
+void Net::finalize()
{
- mState = IDLE;
+ if (!client)
+ return; // Wasn't initialized at all
- if (mWorkerThread)
- {
- SDL_WaitThread(mWorkerThread, NULL);
- mWorkerThread = NULL;
+ if (Net::connections) {
+ logger->error("Tried to shutdown the network subsystem while there "
+ "are network connections left!");
}
- if (mSocket)
- {
- SDLNet_TCP_Close(mSocket);
- mSocket = 0;
- }
+ clearHandlers();
+ enet_deinitialize();
}
-void Network::registerHandler(MessageHandler *handler)
+Net::Connection *Net::getConnection()
{
- const Uint16 *i = handler->handledMessages;
-
- while(*i)
+ if (!client)
{
- mMessageHandlers[*i] = handler;
- i++;
+ logger->error("Tried to instantiate a network object before "
+ "initializing the network subsystem!");
}
- handler->setNetwork(this);
+ return new Net::Connection(client);
}
-void Network::unregisterHandler(MessageHandler *handler)
+void
+Net::registerHandler(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;
+ mMessageHandlers[*i] = handler;
}
- mOutSize = 0;
- SDL_mutexV(mMutex);
}
-void Network::skip(int len)
+void
+Net::unregisterHandler(MessageHandler *handler)
{
- SDL_mutexP(mMutex);
- mToSkip += len;
- if (!mInSize)
- {
- SDL_mutexV(mMutex);
- return;
- }
-
- if (mInSize >= mToSkip)
- {
- mInSize -= mToSkip;
- memmove(mInBuffer, mInBuffer + mToSkip, mInSize);
- mToSkip = 0;
- }
- else
+ for (const Uint16 *i = handler->handledMessages; *i; i++)
{
- mToSkip -= mInSize;
- mInSize = 0;
+ mMessageHandlers.erase(*i);
}
- SDL_mutexV(mMutex);
}
-bool Network::messageReady()
+void
+Net::clearHandlers()
{
- 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;
+ mMessageHandlers.clear();
}
-MessageIn Network::getNextMessage()
-{
- while (!messageReady())
- {
- if (mState == ERROR)
- 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()
+/**
+ * Dispatches a message to the appropriate message handler and
+ * destroys it afterwards.
+ */
+namespace
{
- IPaddress ipAddress;
-
- if (SDLNet_ResolveHost(&ipAddress, mAddress.c_str(), mPort) == -1)
- {
- logger->log("Error in SDLNet_ResolveHost(): %s", SDLNet_GetError());
- mState = ERROR;
- return false;
- }
-
- mState = CONNECTING;
-
- mSocket = SDLNet_TCP_Open(&ipAddress);
- if (!mSocket)
- {
- logger->log("Error in SDLNet_TCP_Open(): %s", SDLNet_GetError());
- mState = ERROR;
- return false;
- }
-
- logger->log("Network::Started session with %s:%i",
- iptostring(ipAddress.host), ipAddress.port);
-
- mState = CONNECTED;
-
- return true;
+ void
+ dispatchMessage(ENetPacket *packet)
+ {
+ MessageIn msg((const char *)packet->data, packet->dataLength);
+
+ MessageHandlerIterator iter = mMessageHandlers.find(msg.getId());
+
+ if (iter != mMessageHandlers.end()) {
+ logger->log("Received packet %x (%i B)",
+ msg.getId(), msg.getLength());
+ iter->second->handleMessage(msg);
+ }
+ else {
+ logger->log("Unhandled packet %x (%i B)",
+ msg.getId(), msg.getLength());
+ }
+
+ // Clean up the packet now that we're done using it.
+ enet_packet_destroy(packet);
+ }
}
-void Network::receive()
+void Net::flush()
{
- SDLNet_SocketSet set;
+ ENetEvent event;
- if (!(set = SDLNet_AllocSocketSet(1)))
+ // Wait up to 10 milliseconds for an event.
+ while (enet_host_service(client, &event, 10) > 0)
{
- logger->log("Error in SDLNet_AllocSocketSet(): %s", SDLNet_GetError());
- mState = ERROR;
- return;
- }
-
- if (SDLNet_TCP_AddSocket(set, mSocket) == -1)
- {
- logger->log("Error in SDLNet_AddSocket(): %s", SDLNet_GetError());
- mState = ERROR;
- }
-
- 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)
+ switch (event.type)
{
- case -1:
- logger->log("Error: SDLNet_CheckSockets");
- // FALLTHROUGH
- case 0:
+ case ENET_EVENT_TYPE_CONNECT:
+ logger->log("Connected.");
+ // Store any relevant server information here.
+ event.peer->data = 0;
+ break;
+
+ case ENET_EVENT_TYPE_RECEIVE:
+ dispatchMessage(event.packet);
break;
- case 1:
- // Receive data from the socket
- SDL_mutexP(mMutex);
- ret = SDLNet_TCP_Recv(mSocket, mInBuffer + mInSize, BUFFER_SIZE - mInSize);
+ case ENET_EVENT_TYPE_DISCONNECT:
+ logger->log("Disconnected.");
+ // Reset the server information.
+ event.peer->data = 0;
+ break;
- if (!ret)
- {
- // We got disconnected
- mState = IDLE;
- logger->log("Disconnected.");
- }
- else if (ret < 0)
- {
- logger->log("Error in SDLNet_TCP_Recv(): %s", SDLNet_GetError());
- mState = ERROR;
- }
- 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);
+ case ENET_EVENT_TYPE_NONE:
+ logger->log("No event during 10 milliseconds.");
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;
+ logger->log("Unhandled enet event.");
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
index f4637f73..9ffcbb6d 100644
--- a/src/net/network.h
+++ b/src/net/network.h
@@ -21,83 +21,51 @@
* $Id$
*/
-#ifndef _TMW_NETWORK_
-#define _TMW_NETWORK_
+#ifndef _TMW_NET_NETWORK_H
+#define _TMW_NET_NETWORK_H
-#include <map>
-#include <SDL_net.h>
-#include <SDL_thread.h>
-#include <string>
+#include <iosfwd>
class MessageHandler;
-class MessageIn;
+class MessageOut;
-class Network;
-
-class Network
+namespace Net
{
- 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
- };
-
- 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);
+ class Connection;
+
+ /**
+ * Initializes the network subsystem.
+ */
+ void initialize();
+
+ /**
+ * Finalizes the network subsystem.
+ */
+ void finalize();
+
+ Connection *getConnection();
+
+ /**
+ * Registers a message handler. A message handler handles a certain
+ * subset of incoming messages.
+ */
+ void registerHandler(MessageHandler *handler);
+
+ /**
+ * Unregisters a message handler.
+ */
+ void unregisterHandler(MessageHandler *handler);
+
+ /**
+ * Clears all registered message handlers.
+ */
+ void clearHandlers();
+
+ /*
+ * Handles all events and dispatches incoming messages to the
+ * registered handlers
+ */
+ void flush();
+}
#endif
diff --git a/src/net/npchandler.cpp b/src/net/npchandler.cpp
index a803710e..9c89e71f 100644
--- a/src/net/npchandler.cpp
+++ b/src/net/npchandler.cpp
@@ -47,21 +47,23 @@ NPCHandler::NPCHandler()
handledMessages = _messages;
}
-void NPCHandler::handleMessage(MessageIn *msg)
+void NPCHandler::handleMessage(MessageIn &msg)
{
- switch (msg->getId())
+ switch (msg.getId())
{
case SMSG_NPC_CHOICE:
- msg->readInt16(); // length
- current_npc = dynamic_cast<NPC*>(beingManager->findBeing(msg->readInt32()));
- npcListDialog->parseItems(msg->readString(msg->getLength() - 8));
+ msg.readShort(); // length
+ current_npc = dynamic_cast<NPC*>(
+ beingManager->findBeing(msg.readLong()));
+ npcListDialog->parseItems(msg.readString(msg.getLength() - 8));
npcListDialog->setVisible(true);
break;
case SMSG_NPC_MESSAGE:
- msg->readInt16(); // length
- current_npc = dynamic_cast<NPC*>(beingManager->findBeing(msg->readInt32()));
- npcTextDialog->addText(msg->readString(msg->getLength() - 8));
+ msg.readShort(); // length
+ current_npc = dynamic_cast<NPC*>(
+ beingManager->findBeing(msg.readLong()));
+ npcTextDialog->addText(msg.readString(msg.getLength() - 8));
npcListDialog->setVisible(false);
npcTextDialog->setVisible(true);
break;
diff --git a/src/net/npchandler.h b/src/net/npchandler.h
index 903ecd10..0cb40f64 100644
--- a/src/net/npchandler.h
+++ b/src/net/npchandler.h
@@ -31,7 +31,7 @@ class NPCHandler : public MessageHandler
public:
NPCHandler();
- void handleMessage(MessageIn *msg);
+ void handleMessage(MessageIn &msg);
};
#endif
diff --git a/src/net/playerhandler.cpp b/src/net/playerhandler.cpp
index 3786cd0b..6eb80d59 100644
--- a/src/net/playerhandler.cpp
+++ b/src/net/playerhandler.cpp
@@ -46,7 +46,9 @@ OkDialog *deathNotice = NULL;
namespace {
struct WeightListener : public gcn::ActionListener
{
- void action(const std::string& eventId, gcn::Widget* widget) { weightNotice = NULL; }
+ void action(const std::string &eventId, gcn::Widget *widget) {
+ weightNotice = NULL;
+ }
} weightListener;
}
@@ -56,7 +58,7 @@ namespace {
// TODO Move somewhere else
namespace {
struct DeathListener : public gcn::ActionListener {
- void action(const std::string& eventId, gcn::Widget* widget) {
+ void action(const std::string &eventId, gcn::Widget *widget) {
player_node->revive();
deathNotice = NULL;
}
@@ -66,61 +68,36 @@ namespace {
PlayerHandler::PlayerHandler()
{
static const Uint16 _messages[] = {
- SMSG_WALK_RESPONSE,
- SMSG_PLAYER_WARP,
- SMSG_PLAYER_STAT_UPDATE_1,
- SMSG_PLAYER_STAT_UPDATE_2,
- SMSG_PLAYER_STAT_UPDATE_3,
- SMSG_PLAYER_STAT_UPDATE_4,
- SMSG_PLAYER_STAT_UPDATE_5,
- SMSG_PLAYER_STAT_UPDATE_6,
- SMSG_PLAYER_ARROW_MESSAGE,
+ //SMSG_PLAYER_STAT_UPDATE_1,
+ //SMSG_PLAYER_STAT_UPDATE_2,
+ //SMSG_PLAYER_STAT_UPDATE_3,
+ //SMSG_PLAYER_STAT_UPDATE_4,
+ //SMSG_PLAYER_STAT_UPDATE_5,
+ //SMSG_PLAYER_STAT_UPDATE_6,
+ //SMSG_PLAYER_ARROW_MESSAGE,
+ GPMSG_PLAYER_MAP_CHANGE,
0
};
handledMessages = _messages;
}
-void PlayerHandler::handleMessage(MessageIn *msg)
+void PlayerHandler::handleMessage(MessageIn &msg)
{
- switch (msg->getId())
+ switch (msg.getId())
{
- case SMSG_WALK_RESPONSE:
- // It is assumed by the client any request to walk actually
- // succeeds on the server. The plan is to have a correction
- // message when the server senses the client has the wrong
- // idea.
- break;
-
- case SMSG_PLAYER_WARP:
- {
- std::string mapPath = msg->readString(16);
- Uint16 x = msg->readInt16();
- Uint16 y = msg->readInt16();
-
- logger->log("Warping to %s (%d, %d)", mapPath.c_str(), x, y);
-
- // Switch the actual map, deleting the previous one
- engine->changeMap(mapPath);
-
- current_npc = 0;
-
- player_node->setAction(Being::STAND);
- player_node->stopAttack();
- player_node->mFrame = 0;
- player_node->mX = x;
- player_node->mY = y;
- }
+ case GPMSG_PLAYER_MAP_CHANGE:
+ handleMapChangeMessage(msg);
break;
case SMSG_PLAYER_STAT_UPDATE_1:
{
- Sint16 type = msg->readInt16();
- Uint32 value = msg->readInt32();
+ Sint16 type = msg.readShort();
+ Uint32 value = msg.readLong();
switch (type)
{
//case 0x0000:
- // player_node->setWalkSpeed(msg->readInt32());
+ // player_node->setWalkSpeed(msg.readLong());
// break;
case 0x0005: player_node->mHp = value; break;
case 0x0006: player_node->mMaxHp = value; break;
@@ -169,30 +146,30 @@ void PlayerHandler::handleMessage(MessageIn *msg)
break;
case SMSG_PLAYER_STAT_UPDATE_2:
- switch (msg->readInt16()) {
+ switch (msg.readShort()) {
case 0x0001:
- player_node->mXp = msg->readInt32();
+ player_node->mXp = msg.readLong();
break;
case 0x0002:
- player_node->mJobXp = msg->readInt32();
+ player_node->mJobXp = msg.readLong();
break;
case 0x0014:
- player_node->mGp = msg->readInt32();
+ player_node->mMoney = msg.readLong();
break;
case 0x0016:
- player_node->mXpForNextLevel = msg->readInt32();
+ player_node->mXpForNextLevel = msg.readLong();
break;
case 0x0017:
- player_node->mJobXpForNextLevel = msg->readInt32();
+ player_node->mJobXpForNextLevel = msg.readLong();
break;
}
break;
case SMSG_PLAYER_STAT_UPDATE_3:
{
- Sint32 type = msg->readInt32();
- Sint32 base = msg->readInt32();
- Sint32 bonus = msg->readInt32();
+ Sint32 type = msg.readLong();
+ Sint32 base = msg.readLong();
+ Sint32 bonus = msg.readLong();
Sint32 total = base + bonus;
switch (type) {
@@ -214,9 +191,9 @@ void PlayerHandler::handleMessage(MessageIn *msg)
case SMSG_PLAYER_STAT_UPDATE_4:
{
- Sint16 type = msg->readInt16();
- Sint8 fail = msg->readInt8();
- Sint8 value = msg->readInt8();
+ Sint16 type = msg.readShort();
+ Sint8 fail = msg.readByte();
+ Sint8 value = msg.readByte();
if (fail != 1)
break;
@@ -240,60 +217,60 @@ void PlayerHandler::handleMessage(MessageIn *msg)
// Updates stats and status points
case SMSG_PLAYER_STAT_UPDATE_5:
- player_node->mStatsPointsToAttribute = msg->readInt16();
- player_node->mAttr[LocalPlayer::STR] = msg->readInt8();
- player_node->mAttrUp[LocalPlayer::STR] = msg->readInt8();
- player_node->mAttr[LocalPlayer::AGI] = msg->readInt8();
- player_node->mAttrUp[LocalPlayer::AGI] = msg->readInt8();
- player_node->mAttr[LocalPlayer::VIT] = msg->readInt8();
- player_node->mAttrUp[LocalPlayer::VIT] = msg->readInt8();
- player_node->mAttr[LocalPlayer::INT] = msg->readInt8();
- player_node->mAttrUp[LocalPlayer::INT] = msg->readInt8();
- player_node->mAttr[LocalPlayer::DEX] = msg->readInt8();
- player_node->mAttrUp[LocalPlayer::DEX] = msg->readInt8();
- player_node->mAttr[LocalPlayer::LUK] = msg->readInt8();
- player_node->mAttrUp[LocalPlayer::LUK] = msg->readInt8();
- player_node->ATK = msg->readInt16(); // ATK
- player_node->ATK_BONUS = msg->readInt16(); // ATK bonus
- player_node->MATK = msg->readInt16(); // MATK max
- player_node->MATK_BONUS = msg->readInt16(); // MATK min
- player_node->DEF = msg->readInt16(); // DEF
- player_node->DEF_BONUS = msg->readInt16(); // DEF bonus
- player_node->MDEF = msg->readInt16(); // MDEF
- player_node->MDEF_BONUS = msg->readInt16(); // MDEF bonus
- player_node->HIT = msg->readInt16(); // HIT
- player_node->FLEE = msg->readInt16(); // FLEE
- player_node->FLEE_BONUS = msg->readInt16(); // FLEE bonus
- msg->readInt16(); // critical
- msg->readInt16(); // unknown
+ player_node->mStatsPointsToAttribute = msg.readShort();
+ player_node->mAttr[LocalPlayer::STR] = msg.readByte();
+ player_node->mAttrUp[LocalPlayer::STR] = msg.readByte();
+ player_node->mAttr[LocalPlayer::AGI] = msg.readByte();
+ player_node->mAttrUp[LocalPlayer::AGI] = msg.readByte();
+ player_node->mAttr[LocalPlayer::VIT] = msg.readByte();
+ player_node->mAttrUp[LocalPlayer::VIT] = msg.readByte();
+ player_node->mAttr[LocalPlayer::INT] = msg.readByte();
+ player_node->mAttrUp[LocalPlayer::INT] = msg.readByte();
+ player_node->mAttr[LocalPlayer::DEX] = msg.readByte();
+ player_node->mAttrUp[LocalPlayer::DEX] = msg.readByte();
+ player_node->mAttr[LocalPlayer::LUK] = msg.readByte();
+ player_node->mAttrUp[LocalPlayer::LUK] = msg.readByte();
+ player_node->ATK = msg.readShort(); // ATK
+ player_node->ATK_BONUS = msg.readShort(); // ATK bonus
+ player_node->MATK = msg.readShort(); // MATK max
+ player_node->MATK_BONUS = msg.readShort(); // MATK min
+ player_node->DEF = msg.readShort(); // DEF
+ player_node->DEF_BONUS = msg.readShort(); // DEF bonus
+ player_node->MDEF = msg.readShort(); // MDEF
+ player_node->MDEF_BONUS = msg.readShort(); // MDEF bonus
+ player_node->HIT = msg.readShort(); // HIT
+ player_node->FLEE = msg.readShort(); // FLEE
+ player_node->FLEE_BONUS = msg.readShort(); // FLEE bonus
+ msg.readShort(); // critical
+ msg.readShort(); // unknown
break;
case SMSG_PLAYER_STAT_UPDATE_6:
- switch (msg->readInt16()) {
+ switch (msg.readShort()) {
case 0x0020:
- player_node->mAttrUp[LocalPlayer::STR] = msg->readInt8();
+ player_node->mAttrUp[LocalPlayer::STR] = msg.readByte();
break;
case 0x0021:
- player_node->mAttrUp[LocalPlayer::AGI] = msg->readInt8();
+ player_node->mAttrUp[LocalPlayer::AGI] = msg.readByte();
break;
case 0x0022:
- player_node->mAttrUp[LocalPlayer::VIT] = msg->readInt8();
+ player_node->mAttrUp[LocalPlayer::VIT] = msg.readByte();
break;
case 0x0023:
- player_node->mAttrUp[LocalPlayer::INT] = msg->readInt8();
+ player_node->mAttrUp[LocalPlayer::INT] = msg.readByte();
break;
case 0x0024:
- player_node->mAttrUp[LocalPlayer::DEX] = msg->readInt8();
+ player_node->mAttrUp[LocalPlayer::DEX] = msg.readByte();
break;
case 0x0025:
- player_node->mAttrUp[LocalPlayer::LUK] = msg->readInt8();
+ player_node->mAttrUp[LocalPlayer::LUK] = msg.readByte();
break;
}
break;
case SMSG_PLAYER_ARROW_MESSAGE:
{
- Sint16 type = msg->readInt16();
+ Sint16 type = msg.readShort();
switch (type) {
case 0:
@@ -306,18 +283,38 @@ void PlayerHandler::handleMessage(MessageIn *msg)
}
}
break;
+ }
+}
+
+void
+PlayerHandler::handleMapChangeMessage(MessageIn &msg)
+{
+ // { "mapname", x, y, B new server [, token, "gameserver", W port] }
+
+ std::string mapName = msg.readString();
+ unsigned short x = msg.readShort();
+ unsigned short y = msg.readShort();
+ unsigned char newServer = msg.readByte();
+
+ logger->log("Changing map to %s (%d, %d) on %s server",
+ mapName.c_str(), x, y, (newServer) ? "another" : "same");
- //Stop walking
- //case 0x0088: // Disabled because giving some problems
- //if (being = beingManager->findBeing(readInt32(2))) {
- // if (being->getId() != player_node->getId()) {
- // being->action = STAND;
- // being->mFrame = 0;
- // set_coordinates(being->coordinates,
- // readWord(6), readWord(8),
- // get_direction(being->coordinates));
- // }
- //}
- //break;
+ // Switch the actual map, deleting the previous one
+ engine->changeMap(mapName);
+
+ current_npc = 0;
+
+ player_node->setAction(Being::STAND);
+ player_node->stopAttack();
+
+ player_node->mX = x;
+ player_node->mY = y;
+
+ if (newServer)
+ {
+ // TODO: Implement reconnecting to another game server
+ //std::string token = msg.readString(32);
+ //std::string gameServer = msg.readString();
+ //unsigned short gameServerPort = msg.readShort();
}
}
diff --git a/src/net/playerhandler.h b/src/net/playerhandler.h
index b28a23f5..9b6c9e01 100644
--- a/src/net/playerhandler.h
+++ b/src/net/playerhandler.h
@@ -31,7 +31,12 @@ class PlayerHandler : public MessageHandler
public:
PlayerHandler();
- void handleMessage(MessageIn *msg);
+ void
+ handleMessage(MessageIn &msg);
+
+ private:
+ void
+ handleMapChangeMessage(MessageIn &msg);
};
#endif
diff --git a/src/net/protocol.cpp b/src/net/protocol.cpp
deleted file mode 100644
index d3db50bf..00000000
--- a/src/net/protocol.cpp
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * 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$
- */
-
-#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
index 72b459ed..07b5c926 100644
--- a/src/net/protocol.h
+++ b/src/net/protocol.h
@@ -104,7 +104,147 @@
#define CMSG_PLAYER_EQUIP 0x00a9
#define CMSG_PLAYER_UNEQUIP 0x00ab
-/** Encodes coords and direction in 3 bytes data */
-void set_coordinates(char *data, unsigned short x, unsigned short y, unsigned char direction);
+/**
+ * Enumerated type for communicated messages
+ * - PAMSG_*: from client to account server
+ * - APMSG_*: from account server to client
+ * - PCMSG_*: from client to chat server
+ * - CPMSG_*: from chat server to client
+ * - PGMSG_*: from client to game server
+ * - GPMSG_*: from game server to client
+ * Components: B byte, W word, D double word, S variable-size string
+ * C tile-based coordinates (B*3)
+ */
+enum {
+ // Login/Register
+ PAMSG_REGISTER = 0x0000, // L version, S username, S password, S email
+ APMSG_REGISTER_RESPONSE = 0x0002, // B error
+ PAMSG_UNREGISTER = 0x0003, // -
+ APMSG_UNREGISTER_RESPONSE = 0x0004, // B error
+ PAMSG_LOGIN = 0x0010, // L version, S username, S password
+ APMSG_LOGIN_RESPONSE = 0x0012, // B error
+ PAMSG_LOGOUT = 0x0013, // -
+ APMSG_LOGOUT_RESPONSE = 0x0014, // B error
+ PAMSG_CHAR_CREATE = 0x0020, // S name, B hair style, B hair color, B gender, W*6 stats
+ APMSG_CHAR_CREATE_RESPONSE = 0x0021, // B error
+ PAMSG_CHAR_DELETE = 0x0022, // B index
+ APMSG_CHAR_DELETE_RESPONSE = 0x0023, // B error
+ APMSG_CHAR_INFO = 0x0024, // B index, S name, B gender, B hair style, B hair color, B level, W money, W*6 stats, S mapname, W*2 position
+ APMSG_CHAR_LIST_RESPONSE = 0x0025, // B number, { B index, S name, B gender, B hair style, B hair color, B level, W money, W*6 stats, S mapname, W*2 position }*
+ PAMSG_CHAR_SELECT = 0x0026, // B index
+ APMSG_CHAR_SELECT_RESPONSE = 0x0027, // B error, S mapname, W*2 position
+ PAMSG_EMAIL_CHANGE = 0x0030, // S email
+ APMSG_EMAIL_CHANGE_RESPONSE = 0x0031, // B error
+ PAMSG_EMAIL_GET = 0x0032, // -
+ APMSG_EMAIL_GET_RESPONSE = 0x0033, // B error, S email
+ PAMSG_PASSWORD_CHANGE = 0x0034, // S old password, S new password
+ APMSG_PASSWORD_CHANGE_RESPONSE = 0x0035, // B error
+ PAMSG_ENTER_WORLD = 0x0040, // -
+ APMSG_ENTER_WORLD_RESPONSE = 0x0041, // B error, S address, W port, B*32 token
+ PAMSG_ENTER_CHAT = 0x0042, // -
+ APMSG_ENTER_CHAT_RESPONSE = 0x0043, // B error, S address, W port, B*32 token
+ PGMSG_CONNECT = 0x0050, // B*32 token
+ GPMSG_CONNECT_RESPONSE = 0x0051, // B error
+ PCMSG_CONNECT = 0x0053, // B*32 token
+ CPMSG_CONNECT_RESPONSE = 0x0054, // B error
+
+ // Game
+ GPMSG_PLAYER_MAP_CHANGE = 0x0100, // S filename, W x, W y, B newserv
+ // [, S32 token, S server, W port]
+ PGMSG_PICKUP = 0x0110,
+ GPMSG_PICKUP_RESPONSE = 0x0111,
+ GPMSG_BEING_ENTER = 0x0200, // B type, W being id
+ // player: S name, B hair style, B hair color, B gender
+ // monster: W type id
+ GPMSG_BEING_LEAVE = 0x0201, // W being id
+ PGMSG_WALK = 0x0260, // W*2 destination
+ GPMSG_BEINGS_MOVE = 0x0280, // { W being id, B flags [, C position] [, W*2 destination] }*
+ PGMSG_SAY = 0x02A0, // S text
+ GPMSG_SAY = 0x02A1, // W being id, S text
+ PGMSG_USE_ITEM = 0x0300, // L item id
+ GPMSG_USE_RESPONSE = 0x0301, // B error
+ PGMSG_EQUIP = 0x0302, // L item id, B slot
+ GPMSG_EQUIP_RESPONSE = 0x0303, // B error
+
+ // Chat
+ CPMSG_ERROR = 0x0401, // B error
+ CPMSG_ANNOUNCEMENT = 0x0402, // S text
+ CPMSG_PRIVMSG = 0x0403, // S user, S text
+ CPMSG_PUBMSG = 0x0404, // W channel, S user, S text
+ PCMSG_CHAT = 0x0410, // S text, W channel
+ PCMSG_ANNOUNCE = 0x0411, // S text
+ PCMSG_PRIVMSG = 0x0412, // S user, S text
+ // -- Channeling
+ PCMSG_REGISTER_CHANNEL = 0x0413, // B pub/priv, S name, S announcement, S password
+ CPMSG_REGISTER_CHANNEL_RESPONSE = 0x0414, // B error
+ PCMSG_UNREGISTER_CHANNEL = 0x0415, // W channel
+ CPMSG_UNREGISTER_CHANNEL_RESPONSE = 0x0416, // B error
+ CPMSG_CHANNEL_EVENT = 0x0418, // W channel, B event, S user
+ PCMSG_ENTER_CHANNEL = 0x0419, // W channel, S password
+ CPMSG_ENTER_CHANNEL_RESPONSE = 0x0420, // B error
+ PCMSG_QUIT_CHANNEL = 0x0421, // W channel
+ CPMSG_QUIT_CHANNEL_RESPONSE = 0x0422, // B error
+
+ XXMSG_INVALID = 0x7FFF
+};
+
+// Generic return values
+
+enum {
+ ERRMSG_OK = 0, // everything is fine
+ ERRMSG_FAILURE, // the action failed
+ ERRMSG_NO_LOGIN, // the user is not yet logged
+ ERRMSG_NO_CHARACTER_SELECTED, // the user needs a character
+ ERRMSG_INSUFFICIENT_RIGHTS, // the user is not privileged
+ ERRMSG_INVALID_ARGUMENT // part of the received message was invalid
+};
+
+// Login specific return values
+enum {
+ LOGIN_INVALID_VERSION = 0x40, // the user is using an incompatible protocol
+ LOGIN_SERVER_FULL // the server is overloaded
+};
+
+// Account register specific return values
+enum {
+ REGISTER_INVALID_VERSION = 0x40, // the user is using an incompatible protocol
+ REGISTER_EXISTS_USERNAME, // there already is an account with this username
+ REGISTER_EXISTS_EMAIL // there already is an account with this email address
+};
+
+// Character creation specific return values
+enum {
+ CREATE_INVALID_HAIRSTYLE = 0x40,
+ CREATE_INVALID_HAIRCOLOR,
+ CREATE_INVALID_GENDER,
+ CREATE_RAW_STATS_TOO_HIGH,
+ CREATE_RAW_STATS_TOO_LOW,
+ CREATE_RAW_STATS_INVALID_DIFF,
+ CREATE_RAW_STATS_EQUAL_TO_ZERO,
+ CREATE_EXISTS_NAME,
+ CREATE_TOO_MUCH_CHARACTERS
+};
+
+// Object type enumeration
+enum {
+ // A simple item
+ OBJECT_ITEM = 0,
+ // An item that can be activated (doors, switchs, sign, ...)
+ OBJECT_ACTOR,
+ // Non-Playable-Character is an actor capable of movement and maybe actions
+ OBJECT_NPC,
+ // A monster (moving actor with AI. able to toggle map/quest actions, too)
+ OBJECT_MONSTER,
+ // A player
+ OBJECT_PLAYER
+};
+
+// Moving object flags
+enum {
+ // Payload contains the current position.
+ MOVING_POSITION = 1,
+ // Payload contains the destination.
+ MOVING_DESTINATION = 2
+};
#endif
diff --git a/src/net/skillhandler.cpp b/src/net/skillhandler.cpp
index e9dc9c19..d9bea775 100644
--- a/src/net/skillhandler.cpp
+++ b/src/net/skillhandler.cpp
@@ -39,27 +39,27 @@ SkillHandler::SkillHandler()
handledMessages = _messages;
}
-void SkillHandler::handleMessage(MessageIn *msg)
+void SkillHandler::handleMessage(MessageIn &msg)
{
int skillCount;
- switch (msg->getId())
+ switch (msg.getId())
{
case SMSG_PLAYER_SKILLS:
- msg->readInt16(); // length
- skillCount = (msg->getLength() - 4) / 37;
+ msg.readShort(); // length
+ skillCount = (msg.getLength() - 4) / 37;
skillDialog->cleanList();
for (int k = 0; k < skillCount; k++)
{
- Sint16 skillId = msg->readInt16();
- msg->readInt16(); // target type
- msg->readInt16(); // unknown
- Sint16 level = msg->readInt16();
- Sint16 sp = msg->readInt16();
- msg->readInt16(); // range
- std::string skillName = msg->readString(24);
- Sint8 up = msg->readInt8();
+ Sint16 skillId = msg.readShort();
+ msg.readShort(); // target type
+ msg.readShort(); // unknown
+ Sint16 level = msg.readShort();
+ Sint16 sp = msg.readShort();
+ msg.readShort(); // range
+ std::string skillName = msg.readString(24);
+ Sint8 up = msg.readByte();
if (level != 0 || up != 0)
{
@@ -77,11 +77,11 @@ void SkillHandler::handleMessage(MessageIn *msg)
// Action failed (ex. sit because you have not reached the
// right level)
CHATSKILL action;
- action.skill = msg->readInt16();
- action.bskill = msg->readInt16();
- action.unused = msg->readInt16(); // unknown
- action.success = msg->readInt8();
- action.reason = msg->readInt8();
+ action.skill = msg.readShort();
+ action.bskill = msg.readShort();
+ action.unused = msg.readShort(); // unknown
+ action.success = msg.readByte();
+ action.reason = msg.readByte();
if (action.success != SKILL_FAILED &&
action.bskill == BSKILL_EMOTE)
{
diff --git a/src/net/skillhandler.h b/src/net/skillhandler.h
index 820a7b6a..8c0653d4 100644
--- a/src/net/skillhandler.h
+++ b/src/net/skillhandler.h
@@ -31,7 +31,7 @@ class SkillHandler : public MessageHandler
public:
SkillHandler();
- void handleMessage(MessageIn *msg);
+ void handleMessage(MessageIn &msg);
};
#endif
diff --git a/src/net/tradehandler.cpp b/src/net/tradehandler.cpp
index 8f9788a2..2ebc160f 100644
--- a/src/net/tradehandler.cpp
+++ b/src/net/tradehandler.cpp
@@ -41,7 +41,7 @@ std::string tradePartnerName;
namespace {
struct RequestTradeListener : public gcn::ActionListener
{
- void action(const std::string& eventId, gcn::Widget* widget)
+ void action(const std::string &eventId, gcn::Widget *widget)
{
player_node->tradeReply(eventId == "yes");
};
@@ -63,9 +63,9 @@ TradeHandler::TradeHandler()
handledMessages = _messages;
}
-void TradeHandler::handleMessage(MessageIn *msg)
+void TradeHandler::handleMessage(MessageIn &msg)
{
- switch (msg->getId())
+ switch (msg.getId())
{
case SMSG_TRADE_REQUEST:
// If a trade window or request window is already open, send a
@@ -81,7 +81,7 @@ void TradeHandler::handleMessage(MessageIn *msg)
}
player_node->setTrading(true);
- tradePartnerName = msg->readString(24);
+ tradePartnerName = msg.readString(24);
ConfirmDialog *dlg;
dlg = new ConfirmDialog("Request for trade",
tradePartnerName +
@@ -90,7 +90,7 @@ void TradeHandler::handleMessage(MessageIn *msg)
break;
case SMSG_TRADE_RESPONSE:
- switch (msg->readInt8())
+ switch (msg.readByte())
{
case 0: // Too far away
chatWindow->chatLog("Trading isn't possible. "
@@ -126,12 +126,11 @@ void TradeHandler::handleMessage(MessageIn *msg)
case SMSG_TRADE_ITEM_ADD:
{
- Sint32 amount = msg->readInt32();
- Sint16 type = msg->readInt16();
- msg->readInt8(); // identified flag
- msg->readInt8(); // attribute
- msg->readInt8(); // refine
- msg->skip(8); // card (4 shorts)
+ Sint32 amount = msg.readLong();
+ Sint16 type = msg.readShort();
+ msg.readByte(); // identified flag
+ msg.readByte(); // attribute
+ msg.readByte(); // refine
// TODO: handle also identified, etc
if (type == 0) {
@@ -145,10 +144,10 @@ void TradeHandler::handleMessage(MessageIn *msg)
case SMSG_TRADE_ITEM_ADD_RESPONSE:
// Trade: New Item add response (was 0x00ea, now 01b1)
{
- Item *item = player_node->getInvItem(msg->readInt16());
- Sint16 quantity = msg->readInt16();
+ Item *item = player_node->getInvItem(msg.readShort());
+ Sint16 quantity = msg.readShort();
- switch (msg->readInt8())
+ switch (msg.readByte())
{
case 0:
// Successfully added item
@@ -176,7 +175,7 @@ void TradeHandler::handleMessage(MessageIn *msg)
case SMSG_TRADE_OK:
// 0 means ok from myself, 1 means ok from other;
- tradeWindow->receivedOk(msg->readInt8() == 0);
+ tradeWindow->receivedOk(msg.readByte() == 0);
break;
case SMSG_TRADE_CANCEL:
diff --git a/src/net/tradehandler.h b/src/net/tradehandler.h
index a1971004..1ab3c2e4 100644
--- a/src/net/tradehandler.h
+++ b/src/net/tradehandler.h
@@ -26,14 +26,12 @@
#include "messagehandler.h"
-class Network;
-
class TradeHandler : public MessageHandler
{
public:
TradeHandler();
- void handleMessage(MessageIn *msg);
+ void handleMessage(MessageIn &msg);
};
#endif
diff --git a/src/npc.cpp b/src/npc.cpp
index 6fa5ac37..3bd4371b 100644
--- a/src/npc.cpp
+++ b/src/npc.cpp
@@ -25,16 +25,13 @@
#include "animatedsprite.h"
-#include "net/messageout.h"
-#include "net/protocol.h"
-
class Spriteset;
extern Spriteset *npcset;
NPC *current_npc = 0;
-NPC::NPC(Uint32 id, Uint16 job, Map *map, Network *network):
- Being(id, job, map), mNetwork(network)
+NPC::NPC(Uint16 id, Uint16 job, Map *map):
+ Being(id, job, map)
{
mSprites[BASE_SPRITE] = new AnimatedSprite("graphics/sprites/npc.xml", job-100);
}
@@ -48,28 +45,34 @@ NPC::getType() const
void
NPC::talk()
{
- MessageOut outMsg(mNetwork);
- outMsg.writeInt16(CMSG_NPC_TALK);
- outMsg.writeInt32(mId);
- outMsg.writeInt8(0);
+ // XXX Convert for new server
+ /*
+ MessageOut outMsg(CMSG_NPC_TALK);
+ outMsg.writeLong(mId);
+ outMsg.writeByte(0);
current_npc = this;
+ */
}
void
NPC::nextDialog()
{
- MessageOut outMsg(mNetwork);
- outMsg.writeInt16(CMSG_NPC_NEXT_REQUEST);
- outMsg.writeInt32(mId);
+ // XXX Convert for new server
+ /*
+ MessageOut outMsg(CMSG_NPC_NEXT_REQUEST);
+ outMsg.writeLong(mId);
+ */
}
void
NPC::dialogChoice(char choice)
{
- MessageOut outMsg(mNetwork);
- outMsg.writeInt16(CMSG_NPC_LIST_CHOICE);
- outMsg.writeInt32(mId);
- outMsg.writeInt8(choice);
+ // XXX Convert for new server
+ /*
+ MessageOut outMsg(CMSG_NPC_LIST_CHOICE);
+ outMsg.writeLong(mId);
+ outMsg.writeByte(choice);
+ */
}
/*
@@ -79,17 +82,21 @@ NPC::dialogChoice(char choice)
void
NPC::buy()
{
- MessageOut outMsg(mNetwork);
- outMsg.writeInt16(CMSG_NPC_BUY_SELL_REQUEST);
- outMsg.writeInt32(mId);
- outMsg.writeInt8(0);
+ // XXX Convert for new server
+ /*
+ MessageOut outMsg(CMSG_NPC_BUY_SELL_REQUEST);
+ outMsg.writeLong(mId);
+ outMsg.writeByte(0);
+ */
}
void
NPC::sell()
{
- MessageOut outMsg(mNetwork);
- outMsg.writeInt16(CMSG_NPC_BUY_SELL_REQUEST);
- outMsg.writeInt32(mId);
- outMsg.writeInt8(1);
+ // XXX Convert for new server
+ /*
+ MessageOut outMsg(CMSG_NPC_BUY_SELL_REQUEST);
+ outMsg.writeLong(mId);
+ outMsg.writeByte(1);
+ */
}
diff --git a/src/npc.h b/src/npc.h
index b08c315c..3b61123b 100644
--- a/src/npc.h
+++ b/src/npc.h
@@ -26,12 +26,10 @@
#include "being.h"
-class Network;
-
class NPC : public Being
{
public:
- NPC(Uint32 id, Uint16 job, Map *map, Network *network);
+ NPC(Uint16 id, Uint16 job, Map *map);
virtual Type getType() const;
@@ -41,9 +39,6 @@ class NPC : public Being
void buy();
void sell();
-
- protected:
- Network *mNetwork;
};
extern NPC *current_npc;
diff --git a/src/openglgraphics.cpp b/src/openglgraphics.cpp
index 2a6c931d..05bbb6b3 100644
--- a/src/openglgraphics.cpp
+++ b/src/openglgraphics.cpp
@@ -21,6 +21,8 @@
* $Id$
*/
+#include "main.h"
+
#ifdef USE_OPENGL
#include "openglgraphics.h"
diff --git a/src/player.cpp b/src/player.cpp
index 3f0ebfc4..12f5f3d5 100644
--- a/src/player.cpp
+++ b/src/player.cpp
@@ -26,43 +26,20 @@
#include "animatedsprite.h"
#include "game.h"
#include "graphics.h"
+#include "log.h"
#include "utils/tostring.h"
#include "gui/gui.h"
-Player::Player(Uint32 id, Uint16 job, Map *map):
+Player::Player(Uint16 id, Uint16 job, Map *map):
Being(id, job, map)
{
- // Load the weapon sprite.
- // When there are more different weapons this should be moved to the
- // setWeapon Method.
- setWeapon(0);
-}
-
-void
-Player::logic()
-{
- switch (mAction) {
- case WALK:
- mFrame = (get_elapsed_time(mWalkTime) * 6) / mWalkSpeed;
- if (mFrame >= 6) {
- nextStep();
- }
- break;
- case ATTACK:
- int frames = 4;
- if (getWeapon() == 2)
- {
- frames = 5;
- }
- mFrame = (get_elapsed_time(mWalkTime) * frames) / mAttackSpeed;
- if (mFrame >= frames) {
- nextStep();
- }
- break;
- }
- Being::logic();
+ /* Load the weapon sprite. When there are more different weapons this
+ * should be moved to the setWeapon Method.
+ */
+ mSprites[WEAPON_SPRITE] =
+ new AnimatedSprite("graphics/sprites/weapons.xml", 0);
}
Being::Type
@@ -85,6 +62,13 @@ Player::drawName(Graphics *graphics, Sint32 offsetX, Sint32 offsetY)
void
Player::setSex(Uint8 sex)
{
+ // Players can only be male or female
+ if (sex > 1)
+ {
+ logger->log("Warning: unsupported gender %i, assuming male.", sex);
+ sex = 0;
+ }
+
if (sex != mSex)
{
delete mSprites[BASE_SPRITE];
@@ -98,48 +82,20 @@ Player::setSex(Uint8 sex)
mSprites[BASE_SPRITE] = new AnimatedSprite(
"graphics/sprites/player_female_base.xml", 0);
}
- resetAnimations();
- }
- Being::setSex(sex);
-}
-
-void
-Player::setWeapon(Uint16 weapon)
-{
- if (weapon != mWeapon)
- {
- delete mSprites[WEAPON_SPRITE];
- mSprites[WEAPON_SPRITE] = NULL;
-
- switch (weapon)
- {
- case 0:
- mSprites[WEAPON_SPRITE] = new AnimatedSprite("graphics/sprites/weapon-fist.xml", 0);
- break;
- case 1:
- mSprites[WEAPON_SPRITE] = new AnimatedSprite("graphics/sprites/weapon-dagger.xml", 0);
- break;
- case 2:
- mSprites[WEAPON_SPRITE] = new AnimatedSprite("graphics/sprites/weapon-bow.xml", 0);
- break;
- case 3:
- mSprites[WEAPON_SPRITE] = new AnimatedSprite("graphics/sprites/weapon-scythe.xml", 0);
- break;
- }
+ Being::setSex(sex);
+ resetAnimations();
}
- Being::setWeapon(weapon);
}
-
void
Player::setHairColor(Uint16 color)
{
- if (color != mHairColor && mHairStyle > 0)
+ if (color != mHairColor)
{
AnimatedSprite *newHairSprite = new AnimatedSprite(
"graphics/sprites/hairstyle" + toString(mHairStyle) + ".xml",
- color - 1);
+ color);
newHairSprite->setDirection(getSpriteDirection());
delete mSprites[HAIR_SPRITE];
@@ -155,11 +111,11 @@ Player::setHairColor(Uint16 color)
void
Player::setHairStyle(Uint16 style)
{
- if (style != mHairStyle && mHairColor > 0)
+ if (style != mHairStyle)
{
AnimatedSprite *newHairSprite = new AnimatedSprite(
"graphics/sprites/hairstyle" + toString(style) + ".xml",
- mHairColor - 1);
+ mHairColor);
newHairSprite->setDirection(getSpriteDirection());
delete mSprites[HAIR_SPRITE];
diff --git a/src/player.h b/src/player.h
index e23110be..6ff4babe 100644
--- a/src/player.h
+++ b/src/player.h
@@ -35,10 +35,10 @@ class AnimatedSprite;
class Player : public Being
{
public:
- Player(Uint32 id, Uint16 job, Map *map);
-
- virtual void
- logic();
+ /**
+ * Constructor.
+ */
+ Player(Uint16 id, Uint16 job, Map *map);
virtual Type
getType() const;
@@ -58,9 +58,6 @@ class Player : public Being
virtual void
setVisibleEquipment(Uint8 slot, Uint8 id);
- virtual void
- setWeapon(Uint16 weapon);
-
private:
/**
* Resets all animations associated with this player. This is used to
diff --git a/src/resources/image.h b/src/resources/image.h
index c769ecb6..a1ab7f48 100644
--- a/src/resources/image.h
+++ b/src/resources/image.h
@@ -24,6 +24,8 @@
#ifndef _TMW_IMAGE_H
#define _TMW_IMAGE_H
+#include "../main.h"
+
#include <SDL.h>
#ifdef USE_OPENGL
diff --git a/src/resources/openglsdlimageloader.cpp b/src/resources/openglsdlimageloader.cpp
index c7ddec74..b3e1601e 100644
--- a/src/resources/openglsdlimageloader.cpp
+++ b/src/resources/openglsdlimageloader.cpp
@@ -21,14 +21,16 @@
* $Id: sdlimageloader.cpp 2121 2006-01-31 02:55:26Z der_doener $
*/
-#ifdef USE_OPENGL
-
#include "openglsdlimageloader.h"
#include <string>
#include "resourcemanager.h"
+#include "../main.h"
+
+#ifdef USE_OPENGL
+
SDL_Surface* OpenGLSDLImageLoader::loadSDLSurface(const std::string& filename)
{
ResourceManager *resman = ResourceManager::getInstance();
diff --git a/src/resources/resourcemanager.cpp b/src/resources/resourcemanager.cpp
index e729ecfc..23a73497 100644
--- a/src/resources/resourcemanager.cpp
+++ b/src/resources/resourcemanager.cpp
@@ -73,7 +73,10 @@ void
ResourceManager::cleanUp(Resource *res)
{
logger->log("ResourceManager::~ResourceManager() cleaning up %d "
- "references to %s", res->mRefCount, res->mIdPath.c_str());
+ "reference%s to %s",
+ res->mRefCount,
+ (res->mRefCount == 1) ? "" : "s",
+ res->mIdPath.c_str());
delete res;
}
@@ -119,9 +122,13 @@ ResourceManager::get(const E_RESOURCE_TYPE &type, const std::string &idPath)
return resIter->second;
}
+ logger->log("ResourceManager::get(%s)", idPath.c_str());
+
int fileSize;
void *buffer = loadFile(idPath, fileSize);
+
if (!buffer) {
+ logger->log("Warning: resource doesn't exist!");
return NULL;
}
@@ -258,10 +265,6 @@ ResourceManager::loadFile(const std::string &fileName, int &fileSize)
return NULL;
}
- // Log the real dir of the file
- logger->log("Loaded %s/%s", PHYSFS_getRealDir(fileName.c_str()),
- fileName.c_str());
-
// Get the size of the file
fileSize = PHYSFS_fileLength(file);
diff --git a/src/sound.cpp b/src/sound.cpp
index 8b012176..182be3d6 100644
--- a/src/sound.cpp
+++ b/src/sound.cpp
@@ -208,6 +208,6 @@ void Sound::close()
stopMusic();
mInstalled = false;
- Mix_CloseAudio();
logger->log("Sound::close() Shutting down sound...");
+ Mix_CloseAudio();
}
diff --git a/src/tmw.rc b/src/tmw.rc
index d3a43b72..5a3b1649 100644
--- a/src/tmw.rc
+++ b/src/tmw.rc
@@ -7,8 +7,8 @@ A ICON MOVEABLE PURE LOADONCALL DISCARDABLE "data/icons/tmw-icon.ico"
// TO CHANGE VERSION INFORMATION, EDIT PROJECT OPTIONS...
//
1 VERSIONINFO
-FILEVERSION 0,0,21,1
-PRODUCTVERSION 0,0,21,1
+FILEVERSION 0,1,0,0
+PRODUCTVERSION 0,1,0,0
FILETYPE VFT_APP
{
BLOCK "StringFileInfo"
@@ -16,14 +16,14 @@ FILETYPE VFT_APP
BLOCK "040904E4"
{
VALUE "CompanyName", "The Mana World Development Team"
- VALUE "FileVersion", "0.0.21.1"
+ VALUE "FileVersion", "0.1.0"
VALUE "FileDescription", "The Mana World"
VALUE "InternalName", "tmw.exe"
VALUE "LegalCopyright", "2004-2006 (C)"
VALUE "LegalTrademarks", ""
VALUE "OriginalFilename", "tmw.exe"
VALUE "ProductName", "The Mana World MMORPG"
- VALUE "ProductVersion", "0.0.21.1"
+ VALUE "ProductVersion", "0.1.0"
}
}
BLOCK "VarFileInfo"