summaryrefslogtreecommitdiff
path: root/src/net
diff options
context:
space:
mode:
Diffstat (limited to 'src/net')
-rw-r--r--src/net/ea/beinghandler.cpp (renamed from src/net/beinghandler.cpp)226
-rw-r--r--src/net/ea/beinghandler.h (renamed from src/net/beinghandler.h)4
-rw-r--r--src/net/ea/buysellhandler.cpp (renamed from src/net/buysellhandler.cpp)62
-rw-r--r--src/net/ea/buysellhandler.h (renamed from src/net/buysellhandler.h)4
-rw-r--r--src/net/ea/charserverhandler.cpp (renamed from src/net/charserverhandler.cpp)64
-rw-r--r--src/net/ea/charserverhandler.h (renamed from src/net/charserverhandler.h)6
-rw-r--r--src/net/ea/chathandler.cpp (renamed from src/net/chathandler.cpp)44
-rw-r--r--src/net/ea/chathandler.h (renamed from src/net/chathandler.h)4
-rw-r--r--src/net/ea/equipmenthandler.cpp (renamed from src/net/equipmenthandler.cpp)58
-rw-r--r--src/net/ea/equipmenthandler.h (renamed from src/net/equipmenthandler.h)4
-rw-r--r--src/net/ea/inventoryhandler.cpp (renamed from src/net/inventoryhandler.cpp)136
-rw-r--r--src/net/ea/inventoryhandler.h (renamed from src/net/inventoryhandler.h)4
-rw-r--r--src/net/ea/loginhandler.cpp (renamed from src/net/loginhandler.cpp)60
-rw-r--r--src/net/ea/loginhandler.h (renamed from src/net/loginhandler.h)4
-rw-r--r--src/net/ea/maploginhandler.cpp (renamed from src/net/maploginhandler.cpp)26
-rw-r--r--src/net/ea/maploginhandler.h (renamed from src/net/maploginhandler.h)4
-rw-r--r--src/net/ea/network.cpp (renamed from src/net/network.cpp)10
-rw-r--r--src/net/ea/network.h (renamed from src/net/network.h)0
-rw-r--r--src/net/ea/npchandler.cpp (renamed from src/net/npchandler.cpp)40
-rw-r--r--src/net/ea/npchandler.h (renamed from src/net/npchandler.h)4
-rw-r--r--src/net/ea/partyhandler.cpp (renamed from src/net/partyhandler.cpp)36
-rw-r--r--src/net/ea/partyhandler.h (renamed from src/net/partyhandler.h)4
-rw-r--r--src/net/ea/playerhandler.cpp (renamed from src/net/playerhandler.cpp)178
-rw-r--r--src/net/ea/playerhandler.h (renamed from src/net/playerhandler.h)4
-rw-r--r--src/net/ea/protocol.cpp (renamed from src/net/protocol.cpp)0
-rw-r--r--src/net/ea/protocol.h (renamed from src/net/protocol.h)4
-rw-r--r--src/net/ea/skillhandler.cpp206
-rw-r--r--src/net/ea/skillhandler.h (renamed from src/net/skillhandler.h)4
-rw-r--r--src/net/ea/tradehandler.cpp (renamed from src/net/tradehandler.cpp)48
-rw-r--r--src/net/ea/tradehandler.h (renamed from src/net/tradehandler.h)4
-rw-r--r--src/net/messagehandler.cpp18
-rw-r--r--src/net/messagehandler.h9
-rw-r--r--src/net/messagein.cpp89
-rw-r--r--src/net/messagein.h37
-rw-r--r--src/net/messageout.cpp106
-rw-r--r--src/net/messageout.h43
-rw-r--r--src/net/skillhandler.cpp93
-rw-r--r--src/net/tmwserv/accountserver/account.cpp107
-rw-r--r--src/net/tmwserv/accountserver/account.h54
-rw-r--r--src/net/tmwserv/accountserver/accountserver.cpp81
-rw-r--r--src/net/tmwserv/accountserver/accountserver.h47
-rw-r--r--src/net/tmwserv/accountserver/internal.cpp32
-rw-r--r--src/net/tmwserv/accountserver/internal.h35
-rw-r--r--src/net/tmwserv/beinghandler.cpp359
-rw-r--r--src/net/tmwserv/beinghandler.h45
-rw-r--r--src/net/tmwserv/buysellhandler.cpp92
-rw-r--r--src/net/tmwserv/buysellhandler.h35
-rw-r--r--src/net/tmwserv/charserverhandler.cpp227
-rw-r--r--src/net/tmwserv/charserverhandler.h72
-rw-r--r--src/net/tmwserv/chathandler.cpp285
-rw-r--r--src/net/tmwserv/chathandler.h84
-rw-r--r--src/net/tmwserv/chatserver/chatserver.cpp146
-rw-r--r--src/net/tmwserv/chatserver/chatserver.h60
-rw-r--r--src/net/tmwserv/chatserver/guild.cpp95
-rw-r--r--src/net/tmwserv/chatserver/guild.h69
-rw-r--r--src/net/tmwserv/chatserver/internal.cpp32
-rw-r--r--src/net/tmwserv/chatserver/internal.h35
-rw-r--r--src/net/tmwserv/chatserver/party.cpp70
-rw-r--r--src/net/tmwserv/chatserver/party.h57
-rw-r--r--src/net/tmwserv/connection.cpp103
-rw-r--r--src/net/tmwserv/connection.h80
-rw-r--r--src/net/tmwserv/effecthandler.cpp58
-rw-r--r--src/net/tmwserv/effecthandler.h38
-rw-r--r--src/net/tmwserv/gameserver/gameserver.cpp49
-rw-r--r--src/net/tmwserv/gameserver/gameserver.h39
-rw-r--r--src/net/tmwserv/gameserver/internal.cpp32
-rw-r--r--src/net/tmwserv/gameserver/internal.h35
-rw-r--r--src/net/tmwserv/gameserver/player.cpp202
-rw-r--r--src/net/tmwserv/gameserver/player.h71
-rw-r--r--src/net/tmwserv/guildhandler.cpp240
-rw-r--r--src/net/tmwserv/guildhandler.h40
-rw-r--r--src/net/tmwserv/internal.cpp27
-rw-r--r--src/net/tmwserv/internal.h30
-rw-r--r--src/net/tmwserv/inventoryhandler.cpp79
-rw-r--r--src/net/tmwserv/inventoryhandler.h35
-rw-r--r--src/net/tmwserv/itemhandler.cpp (renamed from src/net/itemhandler.cpp)55
-rw-r--r--src/net/tmwserv/itemhandler.h (renamed from src/net/itemhandler.h)4
-rw-r--r--src/net/tmwserv/loginhandler.cpp225
-rw-r--r--src/net/tmwserv/loginhandler.h47
-rw-r--r--src/net/tmwserv/logouthandler.cpp215
-rw-r--r--src/net/tmwserv/logouthandler.h62
-rw-r--r--src/net/tmwserv/network.cpp169
-rw-r--r--src/net/tmwserv/network.h79
-rw-r--r--src/net/tmwserv/npchandler.cpp86
-rw-r--r--src/net/tmwserv/npchandler.h35
-rw-r--r--src/net/tmwserv/partyhandler.cpp103
-rw-r--r--src/net/tmwserv/partyhandler.h41
-rw-r--r--src/net/tmwserv/playerhandler.cpp329
-rw-r--r--src/net/tmwserv/playerhandler.h38
-rw-r--r--src/net/tmwserv/protocol.h295
-rw-r--r--src/net/tmwserv/tradehandler.cpp137
-rw-r--r--src/net/tmwserv/tradehandler.h53
92 files changed, 6162 insertions, 735 deletions
diff --git a/src/net/beinghandler.cpp b/src/net/ea/beinghandler.cpp
index b92e0e31..3629b075 100644
--- a/src/net/beinghandler.cpp
+++ b/src/net/ea/beinghandler.cpp
@@ -23,19 +23,19 @@
#include <SDL_types.h>
#include "beinghandler.h"
-#include "messagein.h"
+#include "../messagein.h"
#include "protocol.h"
-#include "../being.h"
-#include "../beingmanager.h"
-#include "../effectmanager.h"
-#include "../game.h"
-#include "../localplayer.h"
-#include "../log.h"
-#include "../npc.h"
-#include "../player_relations.h"
+#include "../../being.h"
+#include "../../beingmanager.h"
+#include "../../effectmanager.h"
+#include "../../game.h"
+#include "../../localplayer.h"
+#include "../../log.h"
+#include "../../npc.h"
+#include "../../player_relations.h"
-#include "../gui/npc_text.h"
+#include "../../gui/npc_text.h"
extern NpcTextDialog *npcTextDialog;
@@ -67,7 +67,7 @@ BeingHandler::BeingHandler(bool enableSync):
handledMessages = _messages;
}
-void BeingHandler::handleMessage(MessageIn *msg)
+void BeingHandler::handleMessage(MessageIn &msg)
{
int id;
Uint16 job, speed;
@@ -83,17 +83,17 @@ void BeingHandler::handleMessage(MessageIn *msg)
Being *srcBeing, *dstBeing;
int hairStyle, hairColor, flag;
- switch (msg->getId())
+ switch (msg.getId())
{
case SMSG_BEING_VISIBLE:
case SMSG_BEING_MOVE:
// Information about a being in range
- id = msg->readInt32();
- speed = msg->readInt16();
- stunMode = msg->readInt16(); // opt1
- statusEffects = msg->readInt16(); // opt2
- statusEffects |= ((Uint32)msg->readInt16()) << 16; // option
- job = msg->readInt16(); // class
+ id = msg.readInt32();
+ speed = msg.readInt16();
+ stunMode = msg.readInt16(); // opt1
+ statusEffects = msg.readInt16(); // opt2
+ statusEffects |= ((Uint32)msg.readInt16()) << 16; // option
+ job = msg.readInt16(); // class
dstBeing = beingManager->findBeing(id);
@@ -108,7 +108,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;
@@ -122,29 +122,29 @@ void BeingHandler::handleMessage(MessageIn *msg)
dstBeing->setWalkSpeed(speed);
dstBeing->mJob = job;
- hairStyle = msg->readInt16();
- dstBeing->setSprite(Being::WEAPON_SPRITE, msg->readInt16());
- headBottom = msg->readInt16();
+ hairStyle = msg.readInt16();
+ dstBeing->setSprite(Being::WEAPON_SPRITE, msg.readInt16());
+ headBottom = msg.readInt16();
- if (msg->getId() == SMSG_BEING_MOVE)
+ if (msg.getId() == SMSG_BEING_MOVE)
{
- msg->readInt32(); // server tick
+ msg.readInt32(); // server tick
}
- dstBeing->setSprite(Being::SHIELD_SPRITE, msg->readInt16());
- headTop = msg->readInt16();
- headMid = msg->readInt16();
- hairColor = msg->readInt16();
- shoes = msg->readInt16(); // clothes color - "abused" as shoes
- gloves = msg->readInt16(); // head dir - "abused" as gloves
- msg->readInt16(); // guild
- msg->readInt16(); // unknown
- msg->readInt16(); // unknown
- msg->readInt16(); // manner
- dstBeing->setStatusEffectBlock(32, msg->readInt16()); // opt3
- msg->readInt8(); // karma
+ dstBeing->setSprite(Being::SHIELD_SPRITE, msg.readInt16());
+ headTop = msg.readInt16();
+ headMid = msg.readInt16();
+ hairColor = msg.readInt16();
+ shoes = msg.readInt16(); // clothes color - "abused" as shoes
+ gloves = msg.readInt16(); // head dir - "abused" as gloves
+ msg.readInt16(); // guild
+ msg.readInt16(); // unknown
+ msg.readInt16(); // unknown
+ msg.readInt16(); // manner
+ dstBeing->setStatusEffectBlock(32, msg.readInt16()); // opt3
+ msg.readInt8(); // karma
dstBeing->setGender(
- (msg->readInt8() == 0) ? GENDER_FEMALE : GENDER_MALE);
+ (msg.readInt8() == 0) ? GENDER_FEMALE : GENDER_MALE);
// Set these after the gender, as the sprites may be gender-specific
dstBeing->setSprite(Being::BOTTOMCLOTHES_SPRITE, headBottom);
@@ -154,10 +154,10 @@ void BeingHandler::handleMessage(MessageIn *msg)
dstBeing->setSprite(Being::GLOVES_SPRITE, gloves);
dstBeing->setHairStyle(hairStyle, hairColor);
- if (msg->getId() == SMSG_BEING_MOVE)
+ if (msg.getId() == SMSG_BEING_MOVE)
{
Uint16 srcX, srcY, dstX, dstY;
- msg->readCoordinatePair(srcX, srcY, dstX, dstY);
+ msg.readCoordinatePair(srcX, srcY, dstX, dstY);
dstBeing->setAction(Being::STAND);
dstBeing->mX = srcX;
dstBeing->mY = srcY;
@@ -166,13 +166,13 @@ void BeingHandler::handleMessage(MessageIn *msg)
else
{
Uint8 dir;
- msg->readCoordinates(dstBeing->mX, dstBeing->mY, dir);
+ msg.readCoordinates(dstBeing->mX, dstBeing->mY, dir);
dstBeing->setDirection(dir);
}
- msg->readInt8(); // unknown
- msg->readInt8(); // unknown
- msg->readInt8(); // unknown / sit
+ msg.readInt8(); // unknown
+ msg.readInt8(); // unknown
+ msg.readInt8(); // unknown / sit
dstBeing->setStunMode(stunMode);
dstBeing->setStatusEffectBlock(0, (statusEffects >> 16) & 0xffff);
@@ -185,11 +185,11 @@ void BeingHandler::handleMessage(MessageIn *msg)
* later versions of eAthena for both mobs and
* players
*/
- dstBeing = beingManager->findBeing(msg->readInt32());
+ dstBeing = beingManager->findBeing(msg.readInt32());
Uint16 srcX, srcY, dstX, dstY;
- msg->readCoordinatePair(srcX, srcY, dstX, dstY);
- msg->readInt32(); // Server tick
+ msg.readCoordinatePair(srcX, srcY, dstX, dstY);
+ msg.readInt32(); // Server tick
/*
* This packet doesn't have enough info to actually
@@ -208,7 +208,7 @@ void BeingHandler::handleMessage(MessageIn *msg)
case SMSG_BEING_REMOVE:
// A being should be removed or has died
- id = msg->readInt32();
+ id = msg.readInt32();
if (id == current_npc)
npcTextDialog->showCloseButton();
@@ -222,7 +222,7 @@ void BeingHandler::handleMessage(MessageIn *msg)
if (dstBeing == player_node->getTarget())
player_node->stopAttack();
- if (msg->readInt8() == 1)
+ if (msg.readInt8() == 1)
dstBeing->setAction(Being::DEAD);
else
beingManager->destroyBeing(dstBeing);
@@ -230,15 +230,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.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
switch (type)
{
@@ -274,11 +274,11 @@ void BeingHandler::handleMessage(MessageIn *msg)
break;
case SMSG_BEING_SELFEFFECT: {
- id = (Uint32)msg->readInt32();
+ id = (Uint32)msg.readInt32();
if (!beingManager->findBeing(id))
break;
- int effectType = msg->readInt32();
+ int effectType = msg.readInt32();
Being* being = beingManager->findBeing(id);
effectManager->trigger(effectType, being);
@@ -287,13 +287,13 @@ void BeingHandler::handleMessage(MessageIn *msg)
}
case SMSG_BEING_EMOTION:
- if (!(dstBeing = beingManager->findBeing(msg->readInt32())))
+ if (!(dstBeing = beingManager->findBeing(msg.readInt32())))
{
break;
}
if (player_relations.hasPermission(dstBeing, PlayerRelation::EMOTE))
- dstBeing->setEmote(msg->readInt8(), EMOTION_TIME);
+ dstBeing->setEmote(msg.readInt8(), EMOTION_TIME);
break;
@@ -312,20 +312,20 @@ void BeingHandler::handleMessage(MessageIn *msg)
* 16 bit value will be 0.
*/
- if (!(dstBeing = beingManager->findBeing(msg->readInt32())))
+ if (!(dstBeing = beingManager->findBeing(msg.readInt32())))
{
break;
}
- int type = msg->readInt8();
+ int type = msg.readInt8();
int id = 0;
int id2 = 0;
- if (msg->getId() == SMSG_BEING_CHANGE_LOOKS) {
- id = msg->readInt8();
+ if (msg.getId() == SMSG_BEING_CHANGE_LOOKS) {
+ id = msg.readInt8();
} else { // SMSG_BEING_CHANGE_LOOKS2
- id = msg->readInt16();
- id2 = msg->readInt16();
+ id = msg.readInt16();
+ id2 = msg.readInt16();
}
switch (type) {
@@ -375,9 +375,9 @@ void BeingHandler::handleMessage(MessageIn *msg)
break;
case SMSG_BEING_NAME_RESPONSE:
- if ((dstBeing = beingManager->findBeing(msg->readInt32())))
+ if ((dstBeing = beingManager->findBeing(msg.readInt32())))
{
- dstBeing->setName(msg->readString(24));
+ dstBeing->setName(msg.readString(24));
}
break;
@@ -385,13 +385,13 @@ 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();
- stunMode = msg->readInt16(); // opt1; Aethyra use this as cape
- statusEffects = msg->readInt16(); // opt2; Aethyra use this as misc1
- statusEffects |= ((Uint32) msg->readInt16())
+ id = msg.readInt32();
+ speed = msg.readInt16();
+ stunMode = msg.readInt16(); // opt1; Aethyra use this as cape
+ statusEffects = msg.readInt16(); // opt2; Aethyra use this as misc1
+ statusEffects |= ((Uint32) msg.readInt16())
<< 16; // status.options; Aethyra uses this as misc2
- job = msg->readInt16();
+ job = msg.readInt16();
dstBeing = beingManager->findBeing(id);
@@ -402,28 +402,28 @@ void BeingHandler::handleMessage(MessageIn *msg)
dstBeing->setWalkSpeed(speed);
dstBeing->mJob = job;
- hairStyle = msg->readInt16();
- weapon = msg->readInt16();
- shield = msg->readInt16();
- headBottom = msg->readInt16();
+ hairStyle = msg.readInt16();
+ weapon = msg.readInt16();
+ shield = msg.readInt16();
+ headBottom = msg.readInt16();
- if (msg->getId() == SMSG_PLAYER_MOVE)
+ if (msg.getId() == SMSG_PLAYER_MOVE)
{
- msg->readInt32(); // server tick
+ msg.readInt32(); // server tick
}
- headTop = msg->readInt16();
- headMid = msg->readInt16();
- hairColor = msg->readInt16();
- msg->readInt16(); // clothes color - Aethyra-"abused" as shoes, we ignore it
- msg->readInt16(); // head dir - Aethyra-"abused" as gloves, we ignore it
- msg->readInt32(); // guild
- msg->readInt16(); // emblem
- msg->readInt16(); // manner
- dstBeing->setStatusEffectBlock(32, msg->readInt16()); // opt3
- msg->readInt8(); // karma
+ headTop = msg.readInt16();
+ headMid = msg.readInt16();
+ hairColor = msg.readInt16();
+ msg.readInt16(); // clothes color - Aethyra-"abused" as shoes, we ignore it
+ msg.readInt16(); // head dir - Aethyra-"abused" as gloves, we ignore it
+ msg.readInt32(); // guild
+ msg.readInt16(); // emblem
+ msg.readInt16(); // manner
+ dstBeing->setStatusEffectBlock(32, msg.readInt16()); // opt3
+ msg.readInt8(); // karma
dstBeing->setGender(
- (msg->readInt8() == 0) ? GENDER_FEMALE : GENDER_MALE);
+ (msg.readInt8() == 0) ? GENDER_FEMALE : GENDER_MALE);
// Set these after the gender, as the sprites may be gender-specific
dstBeing->setSprite(Being::WEAPON_SPRITE, weapon);
@@ -436,10 +436,10 @@ void BeingHandler::handleMessage(MessageIn *msg)
//dstBeing->setSprite(Being::MISC2_SPRITE, misc2);
dstBeing->setHairStyle(hairStyle, hairColor);
- if (msg->getId() == SMSG_PLAYER_MOVE)
+ if (msg.getId() == SMSG_PLAYER_MOVE)
{
Uint16 srcX, srcY, dstX, dstY;
- msg->readCoordinatePair(srcX, srcY, dstX, dstY);
+ msg.readCoordinatePair(srcX, srcY, dstX, dstY);
dstBeing->mX = srcX;
dstBeing->mY = srcY;
dstBeing->setDestination(dstX, dstY);
@@ -447,30 +447,30 @@ void BeingHandler::handleMessage(MessageIn *msg)
else
{
Uint8 dir;
- msg->readCoordinates(dstBeing->mX, dstBeing->mY, dir);
+ msg.readCoordinates(dstBeing->mX, dstBeing->mY, dir);
dstBeing->setDirection(dir);
}
- gmstatus = msg->readInt16();
+ gmstatus = msg.readInt16();
if (gmstatus & 0x80)
dstBeing->setGM();
- if (msg->getId() == SMSG_PLAYER_UPDATE_1)
+ if (msg.getId() == SMSG_PLAYER_UPDATE_1)
{
- switch (msg->readInt8())
+ switch (msg.readInt8())
{
case 2:
dstBeing->setAction(Being::SIT);
break;
}
}
- else if (msg->getId() == SMSG_PLAYER_MOVE)
+ else if (msg.getId() == SMSG_PLAYER_MOVE)
{
- msg->readInt8(); // unknown
+ msg.readInt8(); // unknown
}
- msg->readInt8(); // Lv
- msg->readInt8(); // unknown
+ msg.readInt8(); // Lv
+ msg.readInt8(); // unknown
dstBeing->mWalkTime = tick_time;
dstBeing->mFrame = 0;
@@ -493,12 +493,12 @@ void BeingHandler::handleMessage(MessageIn *msg)
* of the config setting.
*/
- id = msg->readInt32();
+ id = msg.readInt32();
if (mSync || id != player_node->getId()) {
dstBeing = beingManager->findBeing(id);
if (dstBeing) {
- dstBeing->mX = msg->readInt16();
- dstBeing->mY = msg->readInt16();
+ dstBeing->mX = msg.readInt16();
+ dstBeing->mY = msg.readInt16();
if (dstBeing->mAction == Being::WALK) {
dstBeing->mFrame = 0;
dstBeing->setAction(Being::STAND);
@@ -518,12 +518,12 @@ void BeingHandler::handleMessage(MessageIn *msg)
case 0x0119:
// Change in players' flags
- id = msg->readInt32();
+ id = msg.readInt32();
dstBeing = beingManager->findBeing(id);
- stunMode = msg->readInt16();
- statusEffects = msg->readInt16();
- statusEffects |= ((Uint32) msg->readInt16()) << 16;
- msg->readInt8();
+ stunMode = msg.readInt16();
+ statusEffects = msg.readInt16();
+ statusEffects |= ((Uint32) msg.readInt16()) << 16;
+ msg.readInt8();
if (dstBeing) {
dstBeing->setStunMode(stunMode);
@@ -534,9 +534,9 @@ void BeingHandler::handleMessage(MessageIn *msg)
case 0x0196:
// Status change
- status = msg->readInt16();
- id = msg->readInt32();
- flag = msg->readInt8(); // 0: stop, 1: start
+ status = msg.readInt16();
+ id = msg.readInt32();
+ flag = msg.readInt8(); // 0: stop, 1: start
dstBeing = beingManager->findBeing(id);
if (dstBeing)
diff --git a/src/net/beinghandler.h b/src/net/ea/beinghandler.h
index 54b82075..16a7c8d6 100644
--- a/src/net/beinghandler.h
+++ b/src/net/ea/beinghandler.h
@@ -22,14 +22,14 @@
#ifndef NET_BEINGHANDLER_H
#define NET_BEINGHANDLER_H
-#include "messagehandler.h"
+#include "../messagehandler.h"
class BeingHandler : public MessageHandler
{
public:
BeingHandler(bool enableSync);
- void handleMessage(MessageIn *msg);
+ void handleMessage(MessageIn &msg);
private:
// Should we honor server "Stop Walking" packets
diff --git a/src/net/buysellhandler.cpp b/src/net/ea/buysellhandler.cpp
index dcefe905..8dbc2953 100644
--- a/src/net/buysellhandler.cpp
+++ b/src/net/ea/buysellhandler.cpp
@@ -22,21 +22,21 @@
#include <SDL_types.h>
#include "buysellhandler.h"
-#include "messagein.h"
+#include "../messagein.h"
#include "protocol.h"
-#include "../beingmanager.h"
-#include "../inventory.h"
-#include "../item.h"
-#include "../localplayer.h"
-#include "../npc.h"
+#include "../../beingmanager.h"
+#include "../../inventory.h"
+#include "../../item.h"
+#include "../../localplayer.h"
+#include "../../npc.h"
-#include "../gui/buy.h"
-#include "../gui/buysell.h"
-#include "../gui/chat.h"
-#include "../gui/sell.h"
+#include "../../gui/buy.h"
+#include "../../gui/buysell.h"
+#include "../../gui/chat.h"
+#include "../../gui/sell.h"
-#include "../utils/gettext.h"
+#include "../../utils/gettext.h"
BuySellHandler::BuySellHandler()
{
@@ -51,51 +51,51 @@ 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);
buyDialog->reset();
sellDialog->setVisible(false);
sellDialog->reset();
- current_npc = msg->readInt32();
+ current_npc = msg.readInt32();
buySellDialog->setVisible(true);
break;
case SMSG_NPC_BUY:
- msg->readInt16(); // length
- n_items = (msg->getLength() - 4) / 11;
+ msg.readInt16(); // length
+ n_items = (msg.getLength() - 4) / 11;
buyDialog->reset();
- buyDialog->setMoney(player_node->mGp);
+ buyDialog->setMoney(player_node->getMoney());
buyDialog->setVisible(true);
for (int k = 0; k < n_items; k++)
{
- int value = msg->readInt32();
- msg->readInt32(); // DCvalue
- msg->readInt8(); // type
- int itemId = msg->readInt16();
- buyDialog->addItem(itemId, value);
+ int value = msg.readInt32();
+ msg.readInt32(); // DCvalue
+ msg.readInt8(); // type
+ int itemId = msg.readInt16();
+ buyDialog->addItem(itemId, 0, value);
}
break;
case SMSG_NPC_SELL:
- msg->readInt16(); // length
- n_items = (msg->getLength() - 4) / 10;
+ msg.readInt16(); // length
+ n_items = (msg.getLength() - 4) / 10;
if (n_items > 0)
{
- sellDialog->setMoney(player_node->mGp);
+ sellDialog->setMoney(player_node->getMoney());
sellDialog->reset();
sellDialog->setVisible(true);
for (int k = 0; k < n_items; k++)
{
- int index = msg->readInt16();
- int value = msg->readInt32();
- msg->readInt32(); // OCvalue
+ int index = msg.readInt16();
+ int value = msg.readInt32();
+ msg.readInt32(); // OCvalue
Item *item = player_node->getInventory()->getItem(index);
@@ -111,7 +111,7 @@ void BuySellHandler::handleMessage(MessageIn *msg)
break;
case SMSG_NPC_BUY_RESPONSE:
- if (msg->readInt8() == 0)
+ if (msg.readInt8() == 0)
{
chatWindow->chatLog(_("Thanks for buying"), BY_SERVER);
}
@@ -119,13 +119,13 @@ void BuySellHandler::handleMessage(MessageIn *msg)
{
// Reset player money since buy dialog already assumed purchase
// would go fine
- buyDialog->setMoney(player_node->mGp);
+ buyDialog->setMoney(player_node->getMoney());
chatWindow->chatLog(_("Unable to buy"), BY_SERVER);
}
break;
case SMSG_NPC_SELL_RESPONSE:
- if (msg->readInt8() == 0)
+ if (msg.readInt8() == 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/ea/buysellhandler.h
index 0ede7b48..5bf58d8e 100644
--- a/src/net/buysellhandler.h
+++ b/src/net/ea/buysellhandler.h
@@ -22,14 +22,14 @@
#ifndef NET_BUYSELLHANDLER_H
#define NET_BUYSELLHANDLER_H
-#include "messagehandler.h"
+#include "../messagehandler.h"
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/ea/charserverhandler.cpp
index 8e743bf0..0fef3de7 100644
--- a/src/net/charserverhandler.cpp
+++ b/src/net/ea/charserverhandler.cpp
@@ -20,20 +20,20 @@
*/
#include "charserverhandler.h"
-#include "messagein.h"
+#include "../messagein.h"
#include "protocol.h"
-#include "../game.h"
-#include "../localplayer.h"
-#include "../log.h"
-#include "../logindata.h"
-#include "../main.h"
+#include "../../game.h"
+#include "../../localplayer.h"
+#include "../../log.h"
+#include "../../logindata.h"
+#include "../../main.h"
-#include "../gui/char_select.h"
-#include "../gui/ok_dialog.h"
+#include "../../gui/char_select.h"
+#include "../../gui/ok_dialog.h"
-#include "../utils/gettext.h"
-#include "../utils/stringutils.h"
+#include "../../utils/gettext.h"
+#include "../../utils/stringutils.h"
CharServerHandler::CharServerHandler():
mCharCreateDialog(0)
@@ -52,17 +52,17 @@ CharServerHandler::CharServerHandler():
handledMessages = _messages;
}
-void CharServerHandler::handleMessage(MessageIn *msg)
+void CharServerHandler::handleMessage(MessageIn &msg)
{
int slot, flags, code;
LocalPlayer *tempPlayer;
logger->log("CharServerHandler: Packet ID: %x, Length: %d",
- msg->getId(), msg->getLength());
- switch (msg->getId())
+ msg.getId(), msg.getLength());
+ switch (msg.getId())
{
case SMSG_CONNECTION_PROBLEM:
- code = msg->readInt8();
+ code = msg.readInt8();
logger->log("Connection problem: %i", code);
switch (code) {
@@ -85,32 +85,32 @@ void CharServerHandler::handleMessage(MessageIn *msg)
errorMessage = _("Unknown connection error");
break;
}
- state = ERROR_STATE;
+ state = STATE_ERROR;
break;
case 0x006b:
- msg->skip(2); // Length word
- flags = msg->readInt32(); // Aethyra extensions flags
+ msg.skip(2); // Length word
+ flags = msg.readInt32(); // Aethyra extensions flags
logger->log("Server flags are: %x", flags);
- msg->skip(16); // Unused
+ msg.skip(16); // Unused
// Derive number of characters from message length
- n_character = (msg->getLength() - 24) / 106;
+ n_character = (msg.getLength() - 24) / 106;
for (int i = 0; i < n_character; i++)
{
- tempPlayer = readPlayerData(*msg, slot);
+ tempPlayer = readPlayerData(msg, slot);
mCharInfo->select(slot);
mCharInfo->setEntry(tempPlayer);
logger->log("CharServer: Player: %s (%d)",
tempPlayer->getName().c_str(), slot);
}
- state = CHAR_SELECT_STATE;
+ state = STATE_CHAR_SELECT;
break;
case 0x006c:
- switch (msg->readInt8()) {
+ switch (msg.readInt8()) {
case 0:
errorMessage = _("Access denied");
break;
@@ -125,7 +125,7 @@ void CharServerHandler::handleMessage(MessageIn *msg)
break;
case 0x006d:
- tempPlayer = readPlayerData(*msg, slot);
+ tempPlayer = readPlayerData(msg, slot);
mCharInfo->unlock();
mCharInfo->select(slot);
mCharInfo->setEntry(tempPlayer);
@@ -163,10 +163,10 @@ void CharServerHandler::handleMessage(MessageIn *msg)
case 0x0071:
player_node = mCharInfo->getEntry();
slot = mCharInfo->getPos();
- 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();
+ 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
@@ -182,7 +182,7 @@ void CharServerHandler::handleMessage(MessageIn *msg)
} while (mCharInfo->getPos());
mCharInfo->select(slot);
- state = CONNECTING_STATE;
+ state = STATE_CONNECTING;
break;
}
}
@@ -195,7 +195,7 @@ LocalPlayer *CharServerHandler::readPlayerData(MessageIn &msg, int &slot)
tempPlayer->mCharId = msg.readInt32();
tempPlayer->setXp(msg.readInt32());
- tempPlayer->mGp = msg.readInt32();
+ tempPlayer->setMoney(msg.readInt32());
tempPlayer->mJobXp = msg.readInt32();
tempPlayer->mJobLevel = msg.readInt32();
tempPlayer->setSprite(Being::SHOE_SPRITE, msg.readInt16());
@@ -206,8 +206,8 @@ LocalPlayer *CharServerHandler::readPlayerData(MessageIn &msg, int &slot)
msg.readInt32(); // karma
msg.readInt32(); // manner
msg.skip(2); // unknown
- tempPlayer->mHp = msg.readInt16();
- tempPlayer->mMaxHp = msg.readInt16();
+ tempPlayer->setHp(msg.readInt16());
+ tempPlayer->setMaxHp(msg.readInt16());
tempPlayer->mMp = msg.readInt16();
tempPlayer->mMaxMp = msg.readInt16();
msg.readInt16(); // speed
@@ -215,7 +215,7 @@ LocalPlayer *CharServerHandler::readPlayerData(MessageIn &msg, int &slot)
int hairStyle = msg.readInt16();
Uint16 weapon = msg.readInt16();
tempPlayer->setSprite(Being::WEAPON_SPRITE, weapon);
- tempPlayer->mLevel = msg.readInt16();
+ tempPlayer->setLevel(msg.readInt16());
msg.readInt16(); // skill point
tempPlayer->setSprite(Being::BOTTOMCLOTHES_SPRITE, msg.readInt16()); // head bottom
tempPlayer->setSprite(Being::SHIELD_SPRITE, msg.readInt16());
diff --git a/src/net/charserverhandler.h b/src/net/ea/charserverhandler.h
index 37b378f2..237f5e49 100644
--- a/src/net/charserverhandler.h
+++ b/src/net/ea/charserverhandler.h
@@ -22,9 +22,9 @@
#ifndef NET_CHARSERVERHANDLER_H
#define NET_CHARSERVERHANDLER_H
-#include "messagehandler.h"
+#include "../messagehandler.h"
-#include "../lockedarray.h"
+#include "../../lockedarray.h"
class CharCreateDialog;
class LocalPlayer;
@@ -38,7 +38,7 @@ class CharServerHandler : public MessageHandler
public:
CharServerHandler();
- void handleMessage(MessageIn *msg);
+ void handleMessage(MessageIn &msg);
void setCharInfo(LockedArray<LocalPlayer*> *charInfo)
{ mCharInfo = charInfo; }
diff --git a/src/net/chathandler.cpp b/src/net/ea/chathandler.cpp
index 8e108142..4842c86f 100644
--- a/src/net/chathandler.cpp
+++ b/src/net/ea/chathandler.cpp
@@ -23,18 +23,18 @@
#include <string>
#include "chathandler.h"
-#include "messagein.h"
+#include "../messagein.h"
#include "protocol.h"
-#include "../being.h"
-#include "../beingmanager.h"
-#include "../game.h"
-#include "../player_relations.h"
+#include "../../being.h"
+#include "../../beingmanager.h"
+#include "../../game.h"
+#include "../../player_relations.h"
-#include "../gui/chat.h"
+#include "../../gui/chat.h"
-#include "../utils/gettext.h"
-#include "../utils/stringutils.h"
+#include "../../utils/gettext.h"
+#include "../../utils/stringutils.h"
extern Being *player_node;
@@ -55,17 +55,17 @@ ChatHandler::ChatHandler()
handledMessages = _messages;
}
-void ChatHandler::handleMessage(MessageIn *msg)
+void ChatHandler::handleMessage(MessageIn &msg)
{
Being *being;
std::string chatMsg;
std::string nick;
int chatMsgLength;
- switch (msg->getId())
+ switch (msg.getId())
{
case SMSG_WHISPER_RESPONSE:
- switch (msg->readInt8())
+ switch (msg.readInt8())
{
case 0x00:
// comment out since we'll local echo in chat.cpp instead, then only report failures
@@ -82,13 +82,13 @@ void ChatHandler::handleMessage(MessageIn *msg)
// Received whisper
case SMSG_WHISPER:
- chatMsgLength = msg->readInt16() - 28;
- nick = msg->readString(24);
+ chatMsgLength = msg.readInt16() - 28;
+ nick = msg.readString(24);
if (chatMsgLength <= 0)
break;
- chatMsg = msg->readString(chatMsgLength);
+ chatMsg = msg.readString(chatMsgLength);
if (nick != SERVER_NAME)
chatMsg = nick + " : " + chatMsg;
@@ -103,15 +103,15 @@ void ChatHandler::handleMessage(MessageIn *msg)
// Received speech from being
case SMSG_BEING_CHAT: {
- chatMsgLength = msg->readInt16() - 8;
- being = beingManager->findBeing(msg->readInt32());
+ chatMsgLength = msg.readInt16() - 8;
+ being = beingManager->findBeing(msg.readInt32());
if (!being || chatMsgLength <= 0)
{
break;
}
- chatMsg = msg->readString(chatMsgLength);
+ chatMsg = msg.readString(chatMsgLength);
std::string::size_type pos = chatMsg.find(" : ", 0);
std::string sender_name = ((pos == std::string::npos)
@@ -133,17 +133,17 @@ void ChatHandler::handleMessage(MessageIn *msg)
case SMSG_PLAYER_CHAT:
case SMSG_GM_CHAT: {
- chatMsgLength = msg->readInt16() - 4;
+ chatMsgLength = msg.readInt16() - 4;
if (chatMsgLength <= 0)
{
break;
}
- chatMsg = msg->readString(chatMsgLength);
+ chatMsg = msg.readString(chatMsgLength);
std::string::size_type pos = chatMsg.find(" : ", 0);
- if (msg->getId() == SMSG_PLAYER_CHAT)
+ if (msg.getId() == SMSG_PLAYER_CHAT)
{
chatWindow->chatLog(chatMsg, BY_PLAYER);
@@ -162,13 +162,13 @@ void ChatHandler::handleMessage(MessageIn *msg)
}
case SMSG_WHO_ANSWER:
- chatWindow->chatLog("Online users: " + toString(msg->readInt32()),
+ chatWindow->chatLog("Online users: " + toString(msg.readInt32()),
BY_SERVER);
break;
case 0x010c:
// Display MVP player
- msg->readInt32(); // id
+ msg.readInt32(); // id
chatWindow->chatLog("MVP player", BY_SERVER);
break;
}
diff --git a/src/net/chathandler.h b/src/net/ea/chathandler.h
index ff649205..8207b1d5 100644
--- a/src/net/chathandler.h
+++ b/src/net/ea/chathandler.h
@@ -22,14 +22,14 @@
#ifndef NET_CHATHANDLER_H
#define NET_CHATHANDLER_H
-#include "messagehandler.h"
+#include "../messagehandler.h"
class ChatHandler : public MessageHandler
{
public:
ChatHandler();
- void handleMessage(MessageIn *msg);
+ void handleMessage(MessageIn &msg);
};
#endif
diff --git a/src/net/equipmenthandler.cpp b/src/net/ea/equipmenthandler.cpp
index a31da38e..f5377cf2 100644
--- a/src/net/equipmenthandler.cpp
+++ b/src/net/ea/equipmenthandler.cpp
@@ -20,18 +20,18 @@
*/
#include "equipmenthandler.h"
-#include "messagein.h"
+#include "../messagein.h"
#include "protocol.h"
-#include "../equipment.h"
-#include "../inventory.h"
-#include "../item.h"
-#include "../localplayer.h"
-#include "../log.h"
+#include "../../equipment.h"
+#include "../../inventory.h"
+#include "../../item.h"
+#include "../../localplayer.h"
+#include "../../log.h"
-#include "../gui/chat.h"
+#include "../../gui/chat.h"
-#include "../utils/gettext.h"
+#include "../../utils/gettext.h"
EquipmentHandler::EquipmentHandler()
{
@@ -46,7 +46,7 @@ EquipmentHandler::EquipmentHandler()
handledMessages = _messages;
}
-void EquipmentHandler::handleMessage(MessageIn *msg)
+void EquipmentHandler::handleMessage(MessageIn &msg)
{
int itemCount;
int index, equipPoint, itemId;
@@ -55,23 +55,23 @@ void EquipmentHandler::handleMessage(MessageIn *msg)
Item *item;
Inventory *inventory = player_node->getInventory();
- switch (msg->getId())
+ switch (msg.getId())
{
case SMSG_PLAYER_EQUIPMENT:
- msg->readInt16(); // length
- itemCount = (msg->getLength() - 4) / 20;
+ msg.readInt16(); // 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.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
inventory->setItem(index, itemId, 1, true);
@@ -91,9 +91,9 @@ void EquipmentHandler::handleMessage(MessageIn *msg)
break;
case SMSG_PLAYER_EQUIP:
- index = msg->readInt16();
- equipPoint = msg->readInt16();
- type = msg->readInt8();
+ index = msg.readInt16();
+ equipPoint = msg.readInt16();
+ type = msg.readInt8();
logger->log("Equipping: %i %i %i", index, equipPoint, type);
@@ -131,9 +131,9 @@ void EquipmentHandler::handleMessage(MessageIn *msg)
break;
case SMSG_PLAYER_UNEQUIP:
- index = msg->readInt16();
- equipPoint = msg->readInt16();
- type = msg->readInt8();
+ index = msg.readInt16();
+ equipPoint = msg.readInt16();
+ type = msg.readInt8();
if (!type) {
chatWindow->chatLog(_("Unable to unequip."), BY_SERVER);
@@ -169,11 +169,11 @@ void EquipmentHandler::handleMessage(MessageIn *msg)
break;
case SMSG_PLAYER_ATTACK_RANGE:
- player_node->setAttackRange(msg->readInt16());
+ player_node->setAttackRange(msg.readInt16());
break;
case SMSG_PLAYER_ARROW_EQUIP:
- index = msg->readInt16();
+ index = msg.readInt16();
if (index <= 1)
break;
diff --git a/src/net/equipmenthandler.h b/src/net/ea/equipmenthandler.h
index c66d7932..fe4a7ecc 100644
--- a/src/net/equipmenthandler.h
+++ b/src/net/ea/equipmenthandler.h
@@ -22,14 +22,14 @@
#ifndef NET_EQUIPMENTHANDLER_H
#define NET_EQUIPMENTHANDLER_H
-#include "messagehandler.h"
+#include "../messagehandler.h"
class EquipmentHandler : public MessageHandler
{
public:
EquipmentHandler();
- void handleMessage(MessageIn *msg);
+ void handleMessage(MessageIn &msg);
};
#endif
diff --git a/src/net/inventoryhandler.cpp b/src/net/ea/inventoryhandler.cpp
index fa66821d..addcb06f 100644
--- a/src/net/inventoryhandler.cpp
+++ b/src/net/ea/inventoryhandler.cpp
@@ -22,24 +22,24 @@
#include <SDL_types.h>
#include "inventoryhandler.h"
-#include "messagein.h"
+#include "../messagein.h"
#include "protocol.h"
-#include "../configuration.h"
-#include "../inventory.h"
-#include "../item.h"
-#include "../itemshortcut.h"
-#include "../localplayer.h"
-#include "../log.h"
+#include "../../configuration.h"
+#include "../../inventory.h"
+#include "../../item.h"
+#include "../../itemshortcut.h"
+#include "../../localplayer.h"
+#include "../../log.h"
-#include "../gui/chat.h"
-#include "../gui/storagewindow.h"
+#include "../../gui/chat.h"
+#include "../../gui/storagewindow.h"
-#include "../resources/iteminfo.h"
+#include "../../resources/iteminfo.h"
-#include "../utils/gettext.h"
-#include "../utils/strprintf.h"
-#include "../utils/stringutils.h"
+#include "../../utils/gettext.h"
+#include "../../utils/strprintf.h"
+#include "../../utils/stringutils.h"
InventoryHandler::InventoryHandler()
{
@@ -60,7 +60,7 @@ InventoryHandler::InventoryHandler()
handledMessages = _messages;
}
-void InventoryHandler::handleMessage(MessageIn *msg)
+void InventoryHandler::handleMessage(MessageIn &msg)
{
int number;
int index, amount, itemId, equipType, arrow;
@@ -68,11 +68,11 @@ void InventoryHandler::handleMessage(MessageIn *msg)
Inventory *inventory = player_node->getInventory();
Inventory *storage = player_node->getStorage();
- switch (msg->getId())
+ switch (msg.getId())
{
case SMSG_PLAYER_INVENTORY:
case SMSG_PLAYER_STORAGE_ITEMS:
- switch (msg->getId()) {
+ switch (msg.getId()) {
case SMSG_PLAYER_INVENTORY:
// Clear inventory - this will be a complete refresh
inventory->clear();
@@ -90,20 +90,20 @@ void InventoryHandler::handleMessage(MessageIn *msg)
logger->log("HOW DID WE GET HERE?");
return;
}
- msg->readInt16(); // length
- number = (msg->getLength() - 4) / 18;
+ msg.readInt16(); // length
+ number = (msg.getLength() - 4) / 18;
for (int loop = 0; loop < number; loop++) {
- index = msg->readInt16();
- itemId = msg->readInt16();
- itemType = msg->readInt8();
- identified = msg->readInt8();
- amount = msg->readInt16();
- arrow = msg->readInt16();
+ index = msg.readInt16();
+ itemId = msg.readInt16();
+ itemType = msg.readInt8();
+ identified = msg.readInt8();
+ amount = msg.readInt16();
+ arrow = msg.readInt16();
for (int i = 0; i < 4; i++)
- cards[i] = msg->readInt16();
+ cards[i] = msg.readInt16();
- if (msg->getId() == SMSG_PLAYER_INVENTORY) {
+ if (msg.getId() == SMSG_PLAYER_INVENTORY) {
inventory->setItem(index, itemId, amount, false);
// Trick because arrows are not considered equipment
@@ -120,21 +120,21 @@ void InventoryHandler::handleMessage(MessageIn *msg)
break;
case SMSG_PLAYER_STORAGE_EQUIP:
- msg->readInt16(); // length
- number = (msg->getLength() - 4) / 20;
+ msg.readInt16(); // length
+ number = (msg.getLength() - 4) / 20;
for (int loop = 0; loop < number; loop++) {
- index = msg->readInt16();
- itemId = msg->readInt16();
- itemType = msg->readInt8();
- identified = msg->readInt8();
+ index = msg.readInt16();
+ itemId = msg.readInt16();
+ itemType = msg.readInt8();
+ identified = msg.readInt8();
amount = 1;
- msg->readInt16(); // Equip Point?
- msg->readInt16(); // Another Equip Point?
- msg->readInt8(); // Attribute (broken)
- msg->readInt8(); // Refine level
+ msg.readInt16(); // Equip Point?
+ msg.readInt16(); // Another Equip Point?
+ msg.readInt8(); // Attribute (broken)
+ msg.readInt8(); // Refine level
for (int i = 0; i < 4; i++)
- cards[i] = msg->readInt16();
+ cards[i] = msg.readInt16();
logger->log("Index:%d, ID:%d, Type:%d, Identified:%d, Qty:%d, Cards:%d, %d, %d, %d",
index, itemId, itemType, identified, amount, cards[0], cards[1], cards[2], cards[3]);
@@ -143,18 +143,18 @@ void InventoryHandler::handleMessage(MessageIn *msg)
break;
case SMSG_PLAYER_INVENTORY_ADD:
- index = msg->readInt16();
- amount = msg->readInt16();
- itemId = msg->readInt16();
- identified = msg->readInt8();
- msg->readInt8(); // attribute
- msg->readInt8(); // refine
+ index = msg.readInt16();
+ amount = msg.readInt16();
+ itemId = msg.readInt16();
+ identified = msg.readInt8();
+ msg.readInt8(); // attribute
+ msg.readInt8(); // refine
for (int i = 0; i < 4; i++)
- cards[i] = msg->readInt16();
- equipType = msg->readInt16();
- itemType = msg->readInt8();
+ cards[i] = msg.readInt16();
+ equipType = msg.readInt16();
+ itemType = msg.readInt8();
- if (msg->readInt8() > 0) {
+ if (msg.readInt8() > 0) {
if (config.getValue("showpickupchat", true)) {
chatWindow->chatLog(_("Unable to pick up item"), BY_SERVER);
}
@@ -181,8 +181,8 @@ void InventoryHandler::handleMessage(MessageIn *msg)
break;
case SMSG_PLAYER_INVENTORY_REMOVE:
- index = msg->readInt16();
- amount = msg->readInt16();
+ index = msg.readInt16();
+ amount = msg.readInt16();
if (Item *item = inventory->getItem(index)) {
item->increaseQuantity(-amount);
if (item->getQuantity() == 0)
@@ -191,21 +191,21 @@ void InventoryHandler::handleMessage(MessageIn *msg)
break;
case SMSG_PLAYER_INVENTORY_USE:
- index = msg->readInt16();
- msg->readInt16(); // item id
- msg->readInt32(); // id
- amount = msg->readInt16();
- msg->readInt8(); // type
+ index = msg.readInt16();
+ msg.readInt16(); // item id
+ msg.readInt32(); // id
+ amount = msg.readInt16();
+ msg.readInt8(); // type
if (Item *item = inventory->getItem(index))
item->setQuantity(amount);
break;
case SMSG_ITEM_USE_RESPONSE:
- index = msg->readInt16();
- amount = msg->readInt16();
+ index = msg.readInt16();
+ amount = msg.readInt16();
- if (msg->readInt8() == 0) {
+ if (msg.readInt8() == 0) {
chatWindow->chatLog(_("Failed to use item"), BY_SERVER);
} else {
if (Item *item = inventory->getItem(index))
@@ -220,22 +220,22 @@ void InventoryHandler::handleMessage(MessageIn *msg)
* packets that update storage contents.
*/
player_node->setInStorage(true);
- msg->readInt16(); // Storage capacity
- msg->readInt16(); // Used count
+ msg.readInt16(); // Storage capacity
+ msg.readInt16(); // Used count
break;
case SMSG_PLAYER_STORAGE_ADD:
/*
* Move an item into storage
*/
- index = msg->readInt16();
- amount = msg->readInt32();
- itemId = msg->readInt16();
- identified = msg->readInt8();
- msg->readInt8(); // attribute
- msg->readInt8(); // refine
+ index = msg.readInt16();
+ amount = msg.readInt32();
+ itemId = msg.readInt16();
+ identified = msg.readInt8();
+ msg.readInt8(); // attribute
+ msg.readInt8(); // refine
for (int i = 0; i < 4; i++)
- cards[i] = msg->readInt16();
+ cards[i] = msg.readInt16();
if (Item *item = storage->getItem(index)) {
item->setId(itemId);
@@ -249,8 +249,8 @@ void InventoryHandler::handleMessage(MessageIn *msg)
/*
* Move an item out of storage
*/
- index = msg->readInt16();
- amount = msg->readInt16();
+ index = msg.readInt16();
+ amount = msg.readInt16();
if (Item *item = storage->getItem(index)) {
item->increaseQuantity(-amount);
if (item->getQuantity() == 0)
diff --git a/src/net/inventoryhandler.h b/src/net/ea/inventoryhandler.h
index 336b2e98..b2e469fa 100644
--- a/src/net/inventoryhandler.h
+++ b/src/net/ea/inventoryhandler.h
@@ -22,14 +22,14 @@
#ifndef NET_INVENTORYHANDLER_H
#define NET_INVENTORYHANDLER_H
-#include "messagehandler.h"
+#include "../messagehandler.h"
class InventoryHandler : public MessageHandler
{
public:
InventoryHandler();
- void handleMessage(MessageIn *msg);
+ void handleMessage(MessageIn &msg);
};
#endif
diff --git a/src/net/loginhandler.cpp b/src/net/ea/loginhandler.cpp
index 2695fc7b..3f58f2c0 100644
--- a/src/net/loginhandler.cpp
+++ b/src/net/ea/loginhandler.cpp
@@ -20,17 +20,17 @@
*/
#include "loginhandler.h"
-#include "messagein.h"
+#include "../messagein.h"
#include "protocol.h"
-#include "../log.h"
-#include "../logindata.h"
-#include "../main.h"
-#include "../serverinfo.h"
+#include "../../log.h"
+#include "../../logindata.h"
+#include "../../main.h"
+#include "../../serverinfo.h"
-#include "../utils/gettext.h"
-#include "../utils/strprintf.h"
-#include "../utils/stringutils.h"
+#include "../../utils/gettext.h"
+#include "../../utils/strprintf.h"
+#include "../../utils/stringutils.h"
extern SERVER_INFO **server_info;
@@ -46,14 +46,14 @@ LoginHandler::LoginHandler()
handledMessages = _messages;
}
-void LoginHandler::handleMessage(MessageIn *msg)
+void LoginHandler::handleMessage(MessageIn &msg)
{
int code;
- switch (msg->getId())
+ switch (msg.getId())
{
case SMSG_CONNECTION_PROBLEM:
- code = msg->readInt8();
+ code = msg.readInt8();
logger->log("Connection problem: %i", code);
switch (code) {
@@ -70,14 +70,14 @@ void LoginHandler::handleMessage(MessageIn *msg)
errorMessage = _("Unknown connection error");
break;
}
- state = ERROR_STATE;
+ state = STATE_ERROR;
break;
case SMSG_UPDATE_HOST:
int len;
- len = msg->readInt16() - 4;
- mUpdateHost = msg->readString(len);
+ len = msg.readInt16() - 4;
+ mUpdateHost = msg.readString(len);
logger->log("Received update host \"%s\" from login server",
mUpdateHost.c_str());
@@ -85,39 +85,39 @@ void LoginHandler::handleMessage(MessageIn *msg)
case 0x0069:
// Skip the length word
- msg->skip(2);
+ msg.skip(2);
- n_server = (msg->getLength() - 47) / 32;
+ 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();
+ mLoginData->session_ID1 = msg.readInt32();
+ mLoginData->account_ID = msg.readInt32();
+ mLoginData->session_ID2 = msg.readInt32();
+ msg.skip(30); // unknown
+ mLoginData->sex = msg.readInt8();
for (int i = 0; i < n_server; i++)
{
server_info[i] = new SERVER_INFO;
- server_info[i]->address = msg->readInt32();
- server_info[i]->port = msg->readInt16();
- server_info[i]->name = msg->readString(20);
- server_info[i]->online_users = msg->readInt32();
+ 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();
server_info[i]->updateHost = mUpdateHost;
- msg->skip(2); // unknown
+ msg.skip(2); // unknown
logger->log("Network: Server: %s (%s:%d)",
server_info[i]->name.c_str(),
ipToString(server_info[i]->address),
server_info[i]->port);
}
- state = CHAR_SERVER_STATE;
+ state = STATE_CHAR_SERVER;
break;
case 0x006a:
- code = msg->readInt8();
+ code = msg.readInt8();
logger->log("Login::error code: %i", code);
switch (code) {
@@ -143,7 +143,7 @@ void LoginHandler::handleMessage(MessageIn *msg)
"banned from the game until "
"%s.\n Please contact the GM "
"team via the forums."),
- msg->readString(20).c_str());
+ msg.readString(20).c_str());
break;
case 9:
errorMessage = _("This user name is already taken");
@@ -152,7 +152,7 @@ void LoginHandler::handleMessage(MessageIn *msg)
errorMessage = _("Unknown error");
break;
}
- state = ERROR_STATE;
+ state = STATE_ERROR;
break;
}
}
diff --git a/src/net/loginhandler.h b/src/net/ea/loginhandler.h
index df86b634..c2ba5083 100644
--- a/src/net/loginhandler.h
+++ b/src/net/ea/loginhandler.h
@@ -24,7 +24,7 @@
#include <string>
-#include "messagehandler.h"
+#include "../messagehandler.h"
struct LoginData;
@@ -33,7 +33,7 @@ class LoginHandler : public MessageHandler
public:
LoginHandler();
- void handleMessage(MessageIn *msg);
+ void handleMessage(MessageIn &msg);
void setLoginData(LoginData *loginData) { mLoginData = loginData; };
diff --git a/src/net/maploginhandler.cpp b/src/net/ea/maploginhandler.cpp
index b5192bd7..6931024e 100644
--- a/src/net/maploginhandler.cpp
+++ b/src/net/ea/maploginhandler.cpp
@@ -20,14 +20,14 @@
*/
#include "maploginhandler.h"
-#include "messagein.h"
+#include "../messagein.h"
#include "protocol.h"
-#include "../localplayer.h"
-#include "../log.h"
-#include "../main.h"
+#include "../../localplayer.h"
+#include "../../log.h"
+#include "../../main.h"
-#include "../utils/gettext.h"
+#include "../../utils/gettext.h"
MapLoginHandler::MapLoginHandler()
{
@@ -39,15 +39,15 @@ MapLoginHandler::MapLoginHandler()
handledMessages = _messages;
}
-void MapLoginHandler::handleMessage(MessageIn *msg)
+void MapLoginHandler::handleMessage(MessageIn &msg)
{
int code;
unsigned char direction;
- switch (msg->getId())
+ switch (msg.getId())
{
case SMSG_CONNECTION_PROBLEM:
- code = msg->readInt8();
+ code = msg.readInt8();
logger->log("Connection problem: %i", code);
switch (code) {
@@ -61,16 +61,16 @@ void MapLoginHandler::handleMessage(MessageIn *msg)
errorMessage = _("Unknown connection error");
break;
}
- state = ERROR_STATE;
+ state = STATE_ERROR;
break;
case SMSG_LOGIN_SUCCESS:
- msg->readInt32(); // server tick
- msg->readCoordinates(player_node->mX, player_node->mY, direction);
- msg->skip(2); // unknown
+ 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;
+ state = STATE_GAME;
break;
}
}
diff --git a/src/net/maploginhandler.h b/src/net/ea/maploginhandler.h
index c7fee70c..1ce5ee79 100644
--- a/src/net/maploginhandler.h
+++ b/src/net/ea/maploginhandler.h
@@ -22,14 +22,14 @@
#ifndef NET_MAPLOGINHANDLER_H
#define NET_MAPLOGINHANDLER_H
-#include "messagehandler.h"
+#include "../messagehandler.h"
class MapLoginHandler : public MessageHandler
{
public:
MapLoginHandler();
- void handleMessage(MessageIn *msg);
+ void handleMessage(MessageIn &msg);
};
#endif
diff --git a/src/net/network.cpp b/src/net/ea/network.cpp
index 3fa046c4..199e94da 100644
--- a/src/net/network.cpp
+++ b/src/net/ea/network.cpp
@@ -21,12 +21,12 @@
#include <sstream>
-#include "messagehandler.h"
-#include "messagein.h"
+#include "../messagehandler.h"
+#include "../messagein.h"
#include "network.h"
-#include "../log.h"
-#include "../utils/stringutils.h"
+#include "../../log.h"
+#include "../../utils/stringutils.h"
/** Warning: buffers and other variables are shared,
so there can be only one connection active at a time */
@@ -207,7 +207,7 @@ void Network::dispatchMessages()
MessageHandlerIterator iter = mMessageHandlers.find(msg.getId());
if (iter != mMessageHandlers.end())
- iter->second->handleMessage(&msg);
+ iter->second->handleMessage(msg);
else
logger->log("Unhandled packet: %x", msg.getId());
diff --git a/src/net/network.h b/src/net/ea/network.h
index 02fe7538..02fe7538 100644
--- a/src/net/network.h
+++ b/src/net/ea/network.h
diff --git a/src/net/npchandler.cpp b/src/net/ea/npchandler.cpp
index 69346b65..7bd23135 100644
--- a/src/net/npchandler.cpp
+++ b/src/net/ea/npchandler.cpp
@@ -21,18 +21,18 @@
#include <SDL_types.h>
-#include "messagein.h"
+#include "../messagein.h"
#include "npchandler.h"
#include "protocol.h"
-#include "../beingmanager.h"
-#include "../localplayer.h"
-#include "../npc.h"
+#include "../../beingmanager.h"
+#include "../../localplayer.h"
+#include "../../npc.h"
-#include "../gui/npc_text.h"
-#include "../gui/npcintegerdialog.h"
-#include "../gui/npclistdialog.h"
-#include "../gui/npcstringdialog.h"
+#include "../../gui/npc_text.h"
+#include "../../gui/npcintegerdialog.h"
+#include "../../gui/npclistdialog.h"
+#include "../../gui/npcstringdialog.h"
NPCHandler::NPCHandler()
{
@@ -48,30 +48,30 @@ NPCHandler::NPCHandler()
handledMessages = _messages;
}
-void NPCHandler::handleMessage(MessageIn *msg)
+void NPCHandler::handleMessage(MessageIn &msg)
{
int id;
- switch (msg->getId())
+ switch (msg.getId())
{
case SMSG_NPC_CHOICE:
- msg->readInt16(); // length
- current_npc = msg->readInt32();
+ msg.readInt16(); // length
+ current_npc = msg.readInt32();
player_node->setAction(LocalPlayer::STAND);
- npcListDialog->parseItems(msg->readString(msg->getLength() - 8));
+ npcListDialog->parseItems(msg.readString(msg.getLength() - 8));
npcListDialog->requestFocus();
break;
case SMSG_NPC_MESSAGE:
- msg->readInt16(); // length
- current_npc = msg->readInt32();
+ msg.readInt16(); // length
+ current_npc = msg.readInt32();
player_node->setAction(LocalPlayer::STAND);
- npcTextDialog->addText(msg->readString(msg->getLength() - 8));
+ npcTextDialog->addText(msg.readString(msg.getLength() - 8));
npcTextDialog->requestFocus();
break;
case SMSG_NPC_CLOSE:
- id = msg->readInt32();
+ id = msg.readInt32();
// If we're talking to that NPC, show the close button
if (id == current_npc)
npcTextDialog->showCloseButton();
@@ -81,7 +81,7 @@ void NPCHandler::handleMessage(MessageIn *msg)
break;
case SMSG_NPC_NEXT:
- id = msg->readInt32();
+ id = msg.readInt32();
// If we're talking to that NPC, show the next button
if (id == current_npc)
npcTextDialog->showNextButton();
@@ -92,7 +92,7 @@ void NPCHandler::handleMessage(MessageIn *msg)
case SMSG_NPC_INT_INPUT:
// Request for an integer
- current_npc = msg->readInt32();
+ current_npc = msg.readInt32();
player_node->setAction(LocalPlayer::STAND);
npcIntegerDialog->setRange(0, 2147483647);
npcIntegerDialog->setDefaultValue(0);
@@ -102,7 +102,7 @@ void NPCHandler::handleMessage(MessageIn *msg)
case SMSG_NPC_STR_INPUT:
// Request for a string
- current_npc = msg->readInt32();
+ current_npc = msg.readInt32();
player_node->setAction(LocalPlayer::STAND);
npcStringDialog->setValue("");
npcStringDialog->setVisible(true);
diff --git a/src/net/npchandler.h b/src/net/ea/npchandler.h
index 7ac962eb..49df20c3 100644
--- a/src/net/npchandler.h
+++ b/src/net/ea/npchandler.h
@@ -22,14 +22,14 @@
#ifndef NET_NPCHANDLER_H
#define NET_NPCHANDLER_H
-#include "messagehandler.h"
+#include "../messagehandler.h"
class NPCHandler : public MessageHandler
{
public:
NPCHandler();
- void handleMessage(MessageIn *msg);
+ void handleMessage(MessageIn &msg);
};
#endif
diff --git a/src/net/partyhandler.cpp b/src/net/ea/partyhandler.cpp
index 96200add..d1d3b55e 100644
--- a/src/net/partyhandler.cpp
+++ b/src/net/ea/partyhandler.cpp
@@ -23,13 +23,13 @@
#include "partyhandler.h"
#include "protocol.h"
-#include "messagein.h"
+#include "../messagein.h"
-#include "../gui/chat.h"
-#include "../gui/confirm_dialog.h"
+#include "../../gui/chat.h"
+#include "../../gui/confirm_dialog.h"
-#include "../beingmanager.h"
-#include "../party.h"
+#include "../../beingmanager.h"
+#include "../../party.h"
PartyHandler::PartyHandler(Party *party) : mParty(party)
{
@@ -49,25 +49,25 @@ PartyHandler::PartyHandler(Party *party) : mParty(party)
handledMessages = _messages;
}
-void PartyHandler::handleMessage(MessageIn *msg)
+void PartyHandler::handleMessage(MessageIn &msg)
{
- switch (msg->getId())
+ switch (msg.getId())
{
case SMSG_PARTY_CREATE:
- mParty->createResponse(msg->readInt8());
+ mParty->createResponse(msg.readInt8());
break;
case SMSG_PARTY_INFO:
break;
case SMSG_PARTY_INVITE:
{
- std::string nick = msg->readString(24);
- int status = msg->readInt8();
+ std::string nick = msg.readString(24);
+ int status = msg.readInt8();
mParty->inviteResponse(nick, status);
break;
}
case SMSG_PARTY_INVITED:
{
- int id = msg->readInt32();
+ int id = msg.readInt32();
Being *being = beingManager->findBeing(id);
if (!being)
{
@@ -84,7 +84,7 @@ void PartyHandler::handleMessage(MessageIn *msg)
{
nick = being->getName();
gender = being->getGender();
- partyName = msg->readString(24);
+ partyName = msg.readString(24);
}
mParty->invitedAsk(nick, gender, partyName);
break;
@@ -95,9 +95,9 @@ void PartyHandler::handleMessage(MessageIn *msg)
break;
case SMSG_PARTY_LEAVE:
{
- /*int id = */msg->readInt32();
- std::string nick = msg->readString(24);
- /*int fail = */msg->readInt8();
+ /*int id = */msg.readInt32();
+ std::string nick = msg.readString(24);
+ /*int fail = */msg.readInt8();
mParty->leftResponse(nick);
break;
}
@@ -107,14 +107,14 @@ void PartyHandler::handleMessage(MessageIn *msg)
break;
case SMSG_PARTY_MESSAGE:
{ // new block to enable local variables
- int msgLength = msg->readInt16() - 8;
+ int msgLength = msg.readInt16() - 8;
if (msgLength <= 0)
{
return;
}
- int id = msg->readInt32();
+ int id = msg.readInt32();
Being *being = beingManager->findBeing(id);
- std::string chatMsg = msg->readString(msgLength);
+ std::string chatMsg = msg.readString(msgLength);
mParty->receiveChat(being, chatMsg);
}
break;
diff --git a/src/net/partyhandler.h b/src/net/ea/partyhandler.h
index fc02bf0a..5c10eb21 100644
--- a/src/net/partyhandler.h
+++ b/src/net/ea/partyhandler.h
@@ -22,7 +22,7 @@
#ifndef PARTYHANDLER_H
#define PARTYHANDLER_H
-#include "messagehandler.h"
+#include "../messagehandler.h"
class Party;
@@ -31,7 +31,7 @@ class PartyHandler : public MessageHandler
public:
PartyHandler(Party *party);
- void handleMessage(MessageIn *msg);
+ void handleMessage(MessageIn &msg);
private:
Party *mParty;
};
diff --git a/src/net/playerhandler.cpp b/src/net/ea/playerhandler.cpp
index aa0ef16c..fcc44cb0 100644
--- a/src/net/playerhandler.cpp
+++ b/src/net/ea/playerhandler.cpp
@@ -19,32 +19,32 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "messagein.h"
+#include "../messagein.h"
#include "playerhandler.h"
#include "protocol.h"
-#include "../engine.h"
-#include "../localplayer.h"
-#include "../log.h"
-#include "../npc.h"
-#include "../units.h"
-
-#include "../gui/buy.h"
-#include "../gui/buysell.h"
-#include "../gui/chat.h"
-#include "../gui/gui.h"
-#include "../gui/npc_text.h"
-#include "../gui/npcintegerdialog.h"
-#include "../gui/npclistdialog.h"
-#include "../gui/npcstringdialog.h"
-#include "../gui/ok_dialog.h"
-#include "../gui/sell.h"
-#include "../gui/skill.h"
-#include "../gui/storagewindow.h"
-#include "../gui/viewport.h"
-
-#include "../utils/stringutils.h"
-#include "../utils/gettext.h"
+#include "../../engine.h"
+#include "../../localplayer.h"
+#include "../../log.h"
+#include "../../npc.h"
+#include "../../units.h"
+
+#include "../../gui/buy.h"
+#include "../../gui/buysell.h"
+#include "../../gui/chat.h"
+#include "../../gui/gui.h"
+#include "../../gui/npc_text.h"
+#include "../../gui/npcintegerdialog.h"
+#include "../../gui/npclistdialog.h"
+#include "../../gui/npcstringdialog.h"
+#include "../../gui/ok_dialog.h"
+#include "../../gui/sell.h"
+#include "../../gui/skill.h"
+#include "../../gui/storagewindow.h"
+#include "../../gui/viewport.h"
+
+#include "../../utils/stringutils.h"
+#include "../../utils/gettext.h"
// TODO Move somewhere else
OkDialog *weightNotice = NULL;
@@ -113,9 +113,9 @@ PlayerHandler::PlayerHandler()
handledMessages = _messages;
}
-void PlayerHandler::handleMessage(MessageIn *msg)
+void PlayerHandler::handleMessage(MessageIn &msg)
{
- switch (msg->getId())
+ switch (msg.getId())
{
case SMSG_WALK_RESPONSE:
/*
@@ -127,10 +127,10 @@ void PlayerHandler::handleMessage(MessageIn *msg)
case SMSG_PLAYER_WARP:
{
- std::string mapPath = msg->readString(16);
+ std::string mapPath = msg.readString(16);
bool nearby;
- Uint16 x = msg->readInt16();
- Uint16 y = msg->readInt16();
+ Uint16 x = msg.readInt16();
+ Uint16 y = msg.readInt16();
logger->log("Warping to %s (%d, %d)", mapPath.c_str(), x, y);
@@ -172,30 +172,30 @@ void PlayerHandler::handleMessage(MessageIn *msg)
case SMSG_PLAYER_STAT_UPDATE_1:
{
- int type = msg->readInt16();
- Uint32 value = msg->readInt32();
+ int type = msg.readInt16();
+ Uint32 value = msg.readInt32();
switch (type)
{
//case 0x0000:
- // player_node->setWalkSpeed(msg->readInt32());
+ // player_node->setWalkSpeed(msg.readInt32());
// break;
- case 0x0005: player_node->mHp = value; break;
- case 0x0006: player_node->mMaxHp = value; break;
+ case 0x0005: player_node->setHp(value); break;
+ case 0x0006: player_node->setMaxHp(value); break;
case 0x0007: player_node->mMp = value; break;
case 0x0008: player_node->mMaxMp = value; break;
case 0x0009:
player_node->mStatsPointsToAttribute = value;
break;
- case 0x000b: player_node->mLevel = value; break;
+ case 0x000b: player_node->setLevel(value); break;
case 0x000c:
player_node->mSkillPoint = value;
skillDialog->update();
break;
case 0x0018:
- if (value >= player_node->mMaxWeight / 2 &&
- player_node->mTotalWeight <
- player_node->mMaxWeight / 2)
+ if ((int) value >= player_node->getMaxWeight() / 2 &&
+ player_node->getTotalWeight() <
+ player_node->getMaxWeight() / 2)
{
weightNotice = new OkDialog(_("Message"),
_("You are carrying more than "
@@ -204,9 +204,9 @@ void PlayerHandler::handleMessage(MessageIn *msg)
weightNotice->addActionListener(
&weightListener);
}
- player_node->mTotalWeight = value;
+ player_node->setTotalWeight(value);
break;
- case 0x0019: player_node->mMaxWeight = value; break;
+ case 0x0019: player_node->setMaxWeight(value); break;
case 0x0029: player_node->ATK = value; break;
case 0x002b: player_node->MATK = value; break;
case 0x002d: player_node->DEF = value; break;
@@ -218,7 +218,7 @@ void PlayerHandler::handleMessage(MessageIn *msg)
case 0x0037: player_node->mJobLevel = value; break;
}
- if (player_node->mHp == 0 && !deathNotice)
+ if (player_node->getHp() == 0 && !deathNotice)
{
static char const *const deadMsg[] =
{
@@ -273,36 +273,36 @@ void PlayerHandler::handleMessage(MessageIn *msg)
break;
case SMSG_PLAYER_STAT_UPDATE_2:
- switch (msg->readInt16()) {
+ switch (msg.readInt16()) {
case 0x0001:
- player_node->setXp(msg->readInt32());
+ player_node->setXp(msg.readInt32());
break;
case 0x0002:
- player_node->mJobXp = msg->readInt32();
+ player_node->mJobXp = msg.readInt32();
break;
case 0x0014: {
- Uint32 curGp = player_node->mGp;
- player_node->mGp = msg->readInt32();
- if (player_node->mGp > curGp)
+ int curGp = player_node->getMoney();
+ player_node->setMoney(msg.readInt32());
+ if (player_node->getMoney() > curGp)
chatWindow->chatLog(_("You picked up ") +
- Units::formatCurrency(player_node->mGp
+ Units::formatCurrency(player_node->getMoney()
- curGp), BY_SERVER);
}
break;
case 0x0016:
- player_node->mXpForNextLevel = msg->readInt32();
+ player_node->mXpForNextLevel = msg.readInt32();
break;
case 0x0017:
- player_node->mJobXpForNextLevel = msg->readInt32();
+ player_node->mJobXpForNextLevel = msg.readInt32();
break;
}
break;
case SMSG_PLAYER_STAT_UPDATE_3:
{
- int type = msg->readInt32();
- int base = msg->readInt32();
- int bonus = msg->readInt32();
+ int type = msg.readInt32();
+ int base = msg.readInt32();
+ int bonus = msg.readInt32();
int total = base + bonus;
switch (type) {
@@ -324,9 +324,9 @@ void PlayerHandler::handleMessage(MessageIn *msg)
case SMSG_PLAYER_STAT_UPDATE_4:
{
- int type = msg->readInt16();
- int fail = msg->readInt8();
- int value = msg->readInt8();
+ int type = msg.readInt16();
+ int fail = msg.readInt8();
+ int value = msg.readInt8();
if (fail != 1)
break;
@@ -350,60 +350,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.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
break;
case SMSG_PLAYER_STAT_UPDATE_6:
- switch (msg->readInt16()) {
+ switch (msg.readInt16()) {
case 0x0020:
- player_node->mAttrUp[LocalPlayer::STR] = msg->readInt8();
+ player_node->mAttrUp[LocalPlayer::STR] = msg.readInt8();
break;
case 0x0021:
- player_node->mAttrUp[LocalPlayer::AGI] = msg->readInt8();
+ player_node->mAttrUp[LocalPlayer::AGI] = msg.readInt8();
break;
case 0x0022:
- player_node->mAttrUp[LocalPlayer::VIT] = msg->readInt8();
+ player_node->mAttrUp[LocalPlayer::VIT] = msg.readInt8();
break;
case 0x0023:
- player_node->mAttrUp[LocalPlayer::INT] = msg->readInt8();
+ player_node->mAttrUp[LocalPlayer::INT] = msg.readInt8();
break;
case 0x0024:
- player_node->mAttrUp[LocalPlayer::DEX] = msg->readInt8();
+ player_node->mAttrUp[LocalPlayer::DEX] = msg.readInt8();
break;
case 0x0025:
- player_node->mAttrUp[LocalPlayer::LUK] = msg->readInt8();
+ player_node->mAttrUp[LocalPlayer::LUK] = msg.readInt8();
break;
}
break;
case SMSG_PLAYER_ARROW_MESSAGE:
{
- int type = msg->readInt16();
+ int type = msg.readInt16();
switch (type) {
case 0:
diff --git a/src/net/playerhandler.h b/src/net/ea/playerhandler.h
index 1a7c8da3..f3352289 100644
--- a/src/net/playerhandler.h
+++ b/src/net/ea/playerhandler.h
@@ -22,14 +22,14 @@
#ifndef NET_PLAYERHANDLER_H
#define NET_PLAYERHANDLER_H
-#include "messagehandler.h"
+#include "../messagehandler.h"
class PlayerHandler : public MessageHandler
{
public:
PlayerHandler();
- void handleMessage(MessageIn *msg);
+ void handleMessage(MessageIn &msg);
};
#endif
diff --git a/src/net/protocol.cpp b/src/net/ea/protocol.cpp
index 69d69901..69d69901 100644
--- a/src/net/protocol.cpp
+++ b/src/net/ea/protocol.cpp
diff --git a/src/net/protocol.h b/src/net/ea/protocol.h
index 4b470d12..b806b13b 100644
--- a/src/net/protocol.h
+++ b/src/net/ea/protocol.h
@@ -19,8 +19,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef PROTOCOL_
-#define PROTOCOL_
+#ifndef PROTOCOL_H
+#define PROTOCOL_H
/*********************************
* Packets from server to client *
diff --git a/src/net/ea/skillhandler.cpp b/src/net/ea/skillhandler.cpp
new file mode 100644
index 00000000..12c38aaa
--- /dev/null
+++ b/src/net/ea/skillhandler.cpp
@@ -0,0 +1,206 @@
+/*
+ * The Mana World
+ * Copyright (C) 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "../messagein.h"
+#include "protocol.h"
+#include "skillhandler.h"
+
+#include "../../log.h"
+
+#include "../../gui/chat.h"
+#include "../../gui/skill.h"
+
+#include "../../utils/gettext.h"
+
+/** job dependend identifiers (?) */
+#define SKILL_BASIC 0x0001
+#define SKILL_WARP 0x001b
+#define SKILL_STEAL 0x0032
+#define SKILL_ENVENOM 0x0034
+
+/** basic skills identifiers */
+#define BSKILL_TRADE 0x0000
+#define BSKILL_EMOTE 0x0001
+#define BSKILL_SIT 0x0002
+#define BSKILL_CREATECHAT 0x0003
+#define BSKILL_JOINPARTY 0x0004
+#define BSKILL_SHOUT 0x0005
+#define BSKILL_PK 0x0006 // ??
+#define BSKILL_SETALLIGN 0x0007 // ??
+
+/** reasons why action failed */
+#define RFAIL_SKILLDEP 0x00
+#define RFAIL_INSUFHP 0x01
+#define RFAIL_INSUFSP 0x02
+#define RFAIL_NOMEMO 0x03
+#define RFAIL_SKILLDELAY 0x04
+#define RFAIL_ZENY 0x05
+#define RFAIL_WEAPON 0x06
+#define RFAIL_REDGEM 0x07
+#define RFAIL_BLUEGEM 0x08
+#define RFAIL_OVERWEIGHT 0x09
+#define RFAIL_GENERIC 0x0a
+
+/** should always be zero if failed */
+#define SKILL_FAILED 0x00
+
+SkillHandler::SkillHandler()
+{
+ static const Uint16 _messages[] = {
+ SMSG_PLAYER_SKILLS,
+ SMSG_SKILL_FAILED,
+ 0
+ };
+ handledMessages = _messages;
+}
+
+void SkillHandler::handleMessage(MessageIn &msg)
+{
+ int skillCount;
+
+ switch (msg.getId())
+ {
+ case SMSG_PLAYER_SKILLS:
+ msg.readInt16(); // length
+ skillCount = (msg.getLength() - 4) / 37;
+ skillDialog->cleanList();
+
+ for (int k = 0; k < skillCount; k++)
+ {
+ int skillId = msg.readInt16();
+ msg.readInt16(); // target type
+ msg.readInt16(); // unknown
+ int level = msg.readInt16();
+ int sp = msg.readInt16();
+ msg.readInt16(); // range
+ std::string skillName = msg.readString(24);
+ int up = msg.readInt8();
+
+ if (level != 0 || up != 0)
+ {
+ if (skillDialog->hasSkill(skillId)) {
+ skillDialog->setSkill(skillId, level, sp);
+ }
+ else {
+ skillDialog->addSkill(skillId, level, sp);
+ }
+ }
+ }
+ skillDialog->update();
+ break;
+
+ case SMSG_SKILL_FAILED:
+ // Action failed (ex. sit because you have not reached the
+ // right level)
+ short skill = msg.readInt16();
+ short bskill = msg.readInt16();
+ short unused = msg.readInt16(); // unknown
+ char success = msg.readInt8();
+ char reason = msg.readInt8();
+ if (success != SKILL_FAILED && bskill == BSKILL_EMOTE)
+ {
+ logger->log("Action: %d/%d", bskill, success);
+ }
+
+ std::string msg;
+ if (success == SKILL_FAILED && skill == SKILL_BASIC)
+ {
+ switch (bskill)
+ {
+ case BSKILL_TRADE:
+ msg = _("Trade failed!");
+ break;
+ case BSKILL_EMOTE:
+ msg = _("Emote failed!");
+ break;
+ case BSKILL_SIT:
+ msg = _("Sit failed!");
+ break;
+ case BSKILL_CREATECHAT:
+ msg = _("Chat creating failed!");
+ break;
+ case BSKILL_JOINPARTY:
+ msg = _("Could not join party!");
+ break;
+ case BSKILL_SHOUT:
+ msg = _("Cannot shout!");
+ break;
+ }
+
+ msg += " ";
+
+ switch (reason)
+ {
+ case RFAIL_SKILLDEP:
+ msg += _("You have not yet reached a high enough lvl!");
+ break;
+ case RFAIL_INSUFHP:
+ msg += _("Insufficient HP!");
+ break;
+ case RFAIL_INSUFSP:
+ msg += _("Insufficient SP!");
+ break;
+ case RFAIL_NOMEMO:
+ msg += _("You have no memos!");
+ break;
+ case RFAIL_SKILLDELAY:
+ msg += _("You cannot do that right now!");
+ break;
+ case RFAIL_ZENY:
+ msg += _("Seems you need more money... ;-)");
+ break;
+ case RFAIL_WEAPON:
+ msg += _("You cannot use this skill with that kind of weapon!");
+ break;
+ case RFAIL_REDGEM:
+ msg += _("You need another red gem!");
+ break;
+ case RFAIL_BLUEGEM:
+ msg += _("You need another blue gem!");
+ break;
+ case RFAIL_OVERWEIGHT:
+ msg += _("You're carrying to much to do this!");
+ break;
+ default:
+ msg += _("Huh? What's that?");
+ break;
+ }
+ }
+ else
+ {
+ switch (skill)
+ {
+ case SKILL_WARP :
+ msg = _("Warp failed...");
+ break;
+ case SKILL_STEAL :
+ msg = _("Could not steal anything...");
+ break;
+ case SKILL_ENVENOM :
+ msg = _("Poison had no effect...");
+ break;
+ }
+ }
+
+ chatWindow->chatLog(msg);
+ break;
+ }
+}
diff --git a/src/net/skillhandler.h b/src/net/ea/skillhandler.h
index 2b55605d..57d68f47 100644
--- a/src/net/skillhandler.h
+++ b/src/net/ea/skillhandler.h
@@ -22,14 +22,14 @@
#ifndef NET_SKILLHANDLER_H
#define NET_SKILLHANDLER_H
-#include "messagehandler.h"
+#include "../messagehandler.h"
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/ea/tradehandler.cpp
index ab2eba31..78472083 100644
--- a/src/net/tradehandler.cpp
+++ b/src/net/ea/tradehandler.cpp
@@ -19,20 +19,20 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "messagein.h"
+#include "../messagein.h"
#include "protocol.h"
#include "tradehandler.h"
-#include "../inventory.h"
-#include "../item.h"
-#include "../localplayer.h"
-#include "../player_relations.h"
+#include "../../inventory.h"
+#include "../../item.h"
+#include "../../localplayer.h"
+#include "../../player_relations.h"
-#include "../gui/chat.h"
-#include "../gui/confirm_dialog.h"
-#include "../gui/trade.h"
+#include "../../gui/chat.h"
+#include "../../gui/confirm_dialog.h"
+#include "../../gui/trade.h"
-#include "../utils/gettext.h"
+#include "../../utils/gettext.h"
std::string tradePartnerName;
@@ -65,9 +65,9 @@ TradeHandler::TradeHandler()
}
-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
@@ -76,7 +76,7 @@ void TradeHandler::handleMessage(MessageIn *msg)
// Note that it would be nice if the server would prevent this
// situation, and that the requesting player would get a
// special message about the player being occupied.
- tradePartnerName = msg->readString(24);
+ tradePartnerName = msg.readString(24);
if (player_relations.hasPermission(tradePartnerName, PlayerRelation::TRADE))
{
@@ -101,7 +101,7 @@ void TradeHandler::handleMessage(MessageIn *msg)
break;
case SMSG_TRADE_RESPONSE:
- switch (msg->readInt8())
+ switch (msg.readInt8())
{
case 0: // Too far away
chatWindow->chatLog(_("Trading isn't possible. Trade partner is too far away."),
@@ -140,16 +140,16 @@ void TradeHandler::handleMessage(MessageIn *msg)
case SMSG_TRADE_ITEM_ADD:
{
- int amount = msg->readInt32();
- int type = msg->readInt16();
- msg->readInt8(); // identified flag
- msg->readInt8(); // attribute
- msg->readInt8(); // refine
- msg->skip(8); // card (4 shorts)
+ int amount = msg.readInt32();
+ int type = msg.readInt16();
+ msg.readInt8(); // identified flag
+ msg.readInt8(); // attribute
+ msg.readInt8(); // refine
+ msg.skip(8); // card (4 shorts)
// TODO: handle also identified, etc
if (type == 0) {
- tradeWindow->addMoney(amount);
+ tradeWindow->setMoney(amount);
} else {
tradeWindow->addItem(type, false, amount, false);
}
@@ -159,16 +159,16 @@ void TradeHandler::handleMessage(MessageIn *msg)
case SMSG_TRADE_ITEM_ADD_RESPONSE:
// Trade: New Item add response (was 0x00ea, now 01b1)
{
- const int index = msg->readInt16();
+ const int index = msg.readInt16();
Item *item = player_node->getInventory()->getItem(index);
if (!item)
{
tradeWindow->receivedOk(true);
return;
}
- int quantity = msg->readInt16();
+ int quantity = msg.readInt16();
- switch (msg->readInt8())
+ switch (msg.readInt8())
{
case 0:
// Successfully added item
@@ -200,7 +200,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.readInt8() == 0);
break;
case SMSG_TRADE_CANCEL:
diff --git a/src/net/tradehandler.h b/src/net/ea/tradehandler.h
index d479e43f..04335069 100644
--- a/src/net/tradehandler.h
+++ b/src/net/ea/tradehandler.h
@@ -22,7 +22,7 @@
#ifndef NET_TRADEHANDLER_H
#define NET_TRADEHANDLER_H
-#include "messagehandler.h"
+#include "../messagehandler.h"
class Network;
@@ -31,7 +31,7 @@ class TradeHandler : public MessageHandler
public:
TradeHandler();
- void handleMessage(MessageIn *msg);
+ void handleMessage(MessageIn &msg);
};
#endif
diff --git a/src/net/messagehandler.cpp b/src/net/messagehandler.cpp
index f1561a31..85f10090 100644
--- a/src/net/messagehandler.cpp
+++ b/src/net/messagehandler.cpp
@@ -22,21 +22,33 @@
#include <cassert>
#include "messagehandler.h"
-#include "network.h"
+#ifdef TMWSERV_SUPPORT
+#include "tmwserv/network.h"
+#else
+#include "ea/network.h"
+#endif
-MessageHandler::MessageHandler():
- mNetwork(0)
+MessageHandler::MessageHandler()
+#ifdef EATHENA_SUPPORT
+ : mNetwork(0)
+#endif
{
}
MessageHandler::~MessageHandler()
{
+#ifdef TMWSERV_SUPPORT
+ Net::unregisterHandler(this);
+#else
if (mNetwork)
mNetwork->unregisterHandler(this);
+#endif
}
+#ifdef EATHENA_SUPPORT
void MessageHandler::setNetwork(Network *network)
{
assert(!(network && mNetwork));
mNetwork = network;
}
+#endif
diff --git a/src/net/messagehandler.h b/src/net/messagehandler.h
index 45cdf8cd..261a8351 100644
--- a/src/net/messagehandler.h
+++ b/src/net/messagehandler.h
@@ -25,8 +25,13 @@
#include <SDL_types.h>
class MessageIn;
+#ifdef EATHENA_SUPPORT
class Network;
+#endif
+/**
+ * \ingroup Network
+ */
class MessageHandler
{
public:
@@ -35,12 +40,14 @@ class MessageHandler
MessageHandler();
virtual ~MessageHandler();
- virtual void handleMessage(MessageIn *msg) =0;
+ virtual void handleMessage(MessageIn &msg) = 0;
+#ifdef EATHENA_SUPPORT
void setNetwork(Network *network);
protected:
Network *mNetwork;
+#endif
};
#endif
diff --git a/src/net/messagein.cpp b/src/net/messagein.cpp
index a288d936..813b440f 100644
--- a/src/net/messagein.cpp
+++ b/src/net/messagein.cpp
@@ -19,11 +19,16 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include <cassert>
+#include "messagein.h"
+
+#ifdef TMWSERV_SUPPORT
+#include <enet/enet.h>
+#else
#include <SDL.h>
#include <SDL_endian.h>
+#endif
-#include "messagein.h"
+#include <cassert>
#define MAKEWORD(low,high) \
((unsigned short)(((unsigned char)(low)) | \
@@ -38,32 +43,68 @@ MessageIn::MessageIn(const char *data, unsigned int length):
mId = readInt16();
}
-Sint8 MessageIn::readInt8()
+int MessageIn::readInt8()
{
- assert(mPos < mLength);
- return mData[mPos++];
+ int value = -1;
+ if (mPos < mLength)
+ {
+ value = (unsigned char) mData[mPos];
+ }
+ mPos += 1;
+ return value;
}
-Sint16 MessageIn::readInt16()
+int MessageIn::readInt16()
{
- assert(mPos + 2 <= mLength);
- mPos += 2;
+ int value = -1;
+ if (mPos + 2 <= mLength)
+ {
+#ifdef TMWSERV_SUPPORT
+ uint16_t t;
+ memcpy(&t, mData + mPos, 2);
+ value = (unsigned short) ENET_NET_TO_HOST_16(t);
+#else
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
- return SDL_Swap16(*(Sint16*)(mData + (mPos - 2)));
+ value = SDL_Swap16(*(Sint16*)(mData + mPos));
#else
- return (*(Sint16*)(mData + (mPos - 2)));
+ value = (*(Sint16*)(mData + mPos));
#endif
+#endif // TMWSERV_SUPPORT
+ }
+ mPos += 2;
+ return value;
}
-Sint32 MessageIn::readInt32()
+int MessageIn::readInt32()
{
- assert(mPos + 4 <= mLength);
- mPos += 4;
+ int value = -1;
+ if (mPos + 4 <= mLength)
+ {
+#ifdef TMWSERV_SUPPORT
+ uint32_t t;
+ memcpy(&t, mData + mPos, 4);
+ value = ENET_NET_TO_HOST_32(t);
+#else
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
- return SDL_Swap32(*(Sint32*)(mData + (mPos - 4)));
+ value = SDL_Swap32(*(Sint32*)(mData + mPos));
#else
- return (*(Sint32*)(mData + (mPos - 4)));
+ value = (*(Sint32*)(mData + mPos));
#endif
+#endif // TMWSERV_SUPPORT
+ }
+ mPos += 4;
+ return value;
+}
+
+void MessageIn::readCoordinates(Uint16 &x, Uint16 &y)
+{
+ 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;
}
void MessageIn::readCoordinates(Uint16 &x, Uint16 &y, Uint8 &direction)
@@ -164,21 +205,3 @@ std::string MessageIn::readString(int 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 0ff6e78a..0d0e9981 100644
--- a/src/net/messagein.h
+++ b/src/net/messagein.h
@@ -27,13 +27,11 @@
/**
* Used for parsing an incoming message.
+ *
+ * \ingroup Network
*/
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,16 +41,27 @@ class MessageIn
/**
* Returns the message ID.
*/
- short getId() { return mId; }
+ int getId() const { return mId; }
/**
* Returns the message length.
*/
- unsigned int getLength() { return mLength; }
+ unsigned int getLength() const { return mLength; }
+
+ /**
+ * Returns the length of unread data.
+ */
+ unsigned int getUnreadLength() const { return mLength - mPos; }
- Sint8 readInt8(); /**< Reads a byte. */
- Sint16 readInt16(); /**< Reads a short. */
- Sint32 readInt32(); /**< Reads a long. */
+ int readInt8(); /**< Reads a byte. */
+ int readInt16(); /**< Reads a short. */
+ int readInt32(); /**< Reads a long. */
+
+ /**
+ * Reads a 3-byte block containing tile-based coordinates. Used by
+ * tmwserv.
+ */
+ void readCoordinates(Uint16 &x, Uint16 &y);
/**
* Reads a special 3 byte block used by eAthena, containing x and y
@@ -82,8 +91,14 @@ class MessageIn
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. */
+ unsigned 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 bf4957be..f7ab6b41 100644
--- a/src/net/messageout.cpp
+++ b/src/net/messageout.cpp
@@ -19,95 +19,131 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include <cstring>
+#include "messageout.h"
+
+#ifdef TMWSERV_SUPPORT
+#include <enet/enet.h>
+#else
+#include "ea/network.h"
#include <SDL.h>
#include <SDL_endian.h>
-#include <string>
+#endif
-#include "messageout.h"
-#include "network.h"
+#include <cstring>
+#include <string>
+#ifdef TMWSERV_SUPPORT
+MessageOut::MessageOut(short id):
+ mData(0),
+#else
MessageOut::MessageOut(Network *network):
mNetwork(network),
- mData(0),
+#endif
mDataSize(0),
mPos(0)
{
+#ifdef TMWSERV_SUPPORT
+ writeInt16(id);
+#else
mData = mNetwork->mOutBuffer + mNetwork->mOutSize;
+#endif
+}
+
+#ifdef TMWSERV_SUPPORT
+MessageOut::~MessageOut()
+{
+ free(mData);
+}
+
+void MessageOut::expand(size_t bytes)
+{
+ mData = (char*)realloc(mData, bytes);
+ mDataSize = bytes;
}
+#endif
void MessageOut::writeInt8(Sint8 value)
{
+#ifdef TMWSERV_SUPPORT
+ expand(mPos + 1);
+#else
+ mNetwork->mOutSize += 1;
+#endif
mData[mPos] = value;
- mPos += sizeof(Sint8);
- mNetwork->mOutSize+= sizeof(Sint8);
+ mPos += 1;
}
void MessageOut::writeInt16(Sint16 value)
{
+#ifdef TMWSERV_SUPPORT
+ expand(mPos + 2);
+ uint16_t t = ENET_HOST_TO_NET_16(value);
+ memcpy(mData + mPos, &t, 2);
+#else
#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);
+ mNetwork->mOutSize += 2;
+#endif // TMWSERV_SUPPORT
+ mPos += 2;
}
void MessageOut::writeInt32(Sint32 value)
{
+#ifdef TMWSERV_SUPPORT
+ expand(mPos + 4);
+ uint32_t t = ENET_HOST_TO_NET_32(value);
+ memcpy(mData + mPos, &t, 4);
+#else
#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);
+ mNetwork->mOutSize += 4;
+#endif // TMWSERV_SUPPORT
+ mPos += 4;
}
void MessageOut::writeString(const std::string &string, int length)
{
- std::string toWrite = string;
-
+ int stringLength = string.length();
if (length < 0)
{
// Write the length at the start if not fixed
- writeInt16(string.length());
+ writeInt16(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;
}
+#ifdef TMWSERV_SUPPORT
+ expand(mPos + length);
+#else
+ mNetwork->mOutSize += length;
+#endif
// 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 b3a4ef68..bc701b92 100644
--- a/src/net/messageout.h
+++ b/src/net/messageout.h
@@ -25,26 +25,38 @@
#include <iosfwd>
#include <SDL_types.h>
+#ifdef EATHENA_SUPPORT
class Network;
+#endif
/**
* Used for building an outgoing message.
+ *
+ * With tmwserv, the message is sent using Net::Connection::send() when
+ * finished.
+ *
+ * \ingroup Network
*/
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.
*/
+#ifdef TMWSERV_SUPPORT
+ MessageOut(short id);
+
+ /**
+ * Destructor.
+ */
+ ~MessageOut();
+#else
MessageOut(Network *network);
+#endif
void writeInt8(Sint8 value); /**< Writes a byte. */
void writeInt16(Sint16 value); /**< Writes a short. */
- void writeInt32(Sint32 value); /**< Writes a long. */
+ void writeInt32(Sint32 value); /**< Writes a long. */
/**
* Writes a string. If a fixed length is not given (-1), it is stored
@@ -52,8 +64,29 @@ 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:
+#ifdef TMWSERV_SUPPORT
+ /**
+ * 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);
+#else
Network *mNetwork;
+#endif
char *mData; /**< Data building up. */
unsigned int mDataSize; /**< Size of data. */
diff --git a/src/net/skillhandler.cpp b/src/net/skillhandler.cpp
deleted file mode 100644
index 526698f4..00000000
--- a/src/net/skillhandler.cpp
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * The Mana World
- * Copyright (C) 2004 The Mana World Development Team
- *
- * This file is part of The Mana World.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include "messagein.h"
-#include "protocol.h"
-#include "skillhandler.h"
-
-#include "../log.h"
-
-#include "../gui/chat.h"
-#include "../gui/skill.h"
-
-SkillHandler::SkillHandler()
-{
- static const Uint16 _messages[] = {
- SMSG_PLAYER_SKILLS,
- SMSG_SKILL_FAILED,
- 0
- };
- handledMessages = _messages;
-}
-
-void SkillHandler::handleMessage(MessageIn *msg)
-{
- int skillCount;
-
- switch (msg->getId())
- {
- case SMSG_PLAYER_SKILLS:
- msg->readInt16(); // length
- skillCount = (msg->getLength() - 4) / 37;
- skillDialog->cleanList();
-
- for (int k = 0; k < skillCount; k++)
- {
- int skillId = msg->readInt16();
- msg->readInt16(); // target type
- msg->readInt16(); // unknown
- int level = msg->readInt16();
- int sp = msg->readInt16();
- msg->readInt16(); // range
- std::string skillName = msg->readString(24);
- int up = msg->readInt8();
-
- if (level != 0 || up != 0)
- {
- if (skillDialog->hasSkill(skillId)) {
- skillDialog->setSkill(skillId, level, sp);
- }
- else {
- skillDialog->addSkill(skillId, level, sp);
- }
- }
- }
- skillDialog->update();
- break;
-
- case SMSG_SKILL_FAILED:
- // 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();
- if (action.success != SKILL_FAILED &&
- action.bskill == BSKILL_EMOTE)
- {
- logger->log("Action: %d/%d", action.bskill, action.success);
- }
- chatWindow->chatLog(action);
- break;
- }
-}
diff --git a/src/net/tmwserv/accountserver/account.cpp b/src/net/tmwserv/accountserver/account.cpp
new file mode 100644
index 00000000..a679e233
--- /dev/null
+++ b/src/net/tmwserv/accountserver/account.cpp
@@ -0,0 +1,107 @@
+/*
+ * 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
+ */
+
+#include "account.h"
+
+#include <string>
+
+#include "internal.h"
+
+#include "../connection.h"
+#include "../../messageout.h"
+#include "../protocol.h"
+
+#include "../../../utils/sha256.h"
+
+void Net::AccountServer::Account::createCharacter(
+ const std::string &name, char hairStyle, char hairColor, char gender,
+ short strength, short agility, short vitality,
+ short intelligence, short dexterity, short willpower)
+{
+ MessageOut msg(PAMSG_CHAR_CREATE);
+
+ msg.writeString(name);
+ msg.writeInt8(hairStyle);
+ msg.writeInt8(hairColor);
+ msg.writeInt8(gender);
+ msg.writeInt16(strength);
+ msg.writeInt16(agility);
+ msg.writeInt16(vitality);
+ msg.writeInt16(intelligence);
+ msg.writeInt16(dexterity);
+ msg.writeInt16(willpower);
+
+ Net::AccountServer::connection->send(msg);
+}
+
+void Net::AccountServer::Account::deleteCharacter(char slot)
+{
+ MessageOut msg(PAMSG_CHAR_DELETE);
+
+ msg.writeInt8(slot);
+
+ Net::AccountServer::connection->send(msg);
+}
+
+void Net::AccountServer::Account::selectCharacter(char slot)
+{
+ MessageOut msg(PAMSG_CHAR_SELECT);
+
+ msg.writeInt8(slot);
+
+ Net::AccountServer::connection->send(msg);
+}
+
+void Net::AccountServer::Account::unregister(const std::string &username,
+ const std::string &password)
+{
+ MessageOut msg(PAMSG_UNREGISTER);
+
+ msg.writeString(username);
+ msg.writeString(sha256(username + password));
+
+ Net::AccountServer::connection->send(msg);
+}
+
+void Net::AccountServer::Account::changeEmail(const std::string &email)
+{
+ MessageOut msg(PAMSG_EMAIL_CHANGE);
+
+ // Email is sent clearly so the server can validate the data.
+ // Encryption is assumed server-side.
+ msg.writeString(email);
+
+ Net::AccountServer::connection->send(msg);
+}
+
+void Net::AccountServer::Account::changePassword(
+ const std::string &username,
+ const std::string &oldPassword,
+ const std::string &newPassword)
+{
+ MessageOut msg(PAMSG_PASSWORD_CHANGE);
+
+ // Change password using SHA2 encryption
+ msg.writeString(sha256(username + oldPassword));
+ msg.writeString(sha256(username + newPassword));
+
+ Net::AccountServer::connection->send(msg);
+}
diff --git a/src/net/tmwserv/accountserver/account.h b/src/net/tmwserv/accountserver/account.h
new file mode 100644
index 00000000..581bcb42
--- /dev/null
+++ b/src/net/tmwserv/accountserver/account.h
@@ -0,0 +1,54 @@
+/*
+ * 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
+ */
+
+#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 hairStyle, char hairColor, char gender,
+ short strength, short agility, short vitality,
+ short intelligence, short dexterity, short willpower);
+
+ void deleteCharacter(char slot);
+
+ void selectCharacter(char slot);
+
+ void unregister(const std::string &username,
+ const std::string &password);
+
+ void changeEmail(const std::string &email);
+
+ void changePassword(const std::string &username,
+ const std::string &oldPassword,
+ const std::string &newPassword);
+ }
+ }
+}
+
+#endif
diff --git a/src/net/tmwserv/accountserver/accountserver.cpp b/src/net/tmwserv/accountserver/accountserver.cpp
new file mode 100644
index 00000000..8093468c
--- /dev/null
+++ b/src/net/tmwserv/accountserver/accountserver.cpp
@@ -0,0 +1,81 @@
+/*
+ * 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
+ */
+
+#include "accountserver.h"
+
+#include <string>
+
+#include "internal.h"
+
+#include "../connection.h"
+#include "../../messageout.h"
+#include "../protocol.h"
+
+#include "../../../utils/sha256.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.writeInt32(version);
+ msg.writeString(username);
+ msg.writeString(sha256(username + 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.writeInt32(version); // client version
+ msg.writeString(username);
+ // When registering, the password and email hash is assumed by server.
+ // Hence, data can be validated safely server-side.
+ // This is the only time we send a clear password.
+ msg.writeString(password);
+ msg.writeString(email);
+
+ Net::AccountServer::connection->send(msg);
+}
+
+void Net::AccountServer::logout()
+{
+ MessageOut msg(PAMSG_LOGOUT);
+ Net::AccountServer::connection->send(msg);
+}
+
+void Net::AccountServer::reconnectAccount(Net::Connection *connection,
+ const std::string &passToken)
+{
+ Net::AccountServer::connection = connection;
+
+ MessageOut msg(PAMSG_RECONNECT);
+ msg.writeString(passToken, 32);
+ Net::AccountServer::connection->send(msg);
+}
diff --git a/src/net/tmwserv/accountserver/accountserver.h b/src/net/tmwserv/accountserver/accountserver.h
new file mode 100644
index 00000000..8e0573fc
--- /dev/null
+++ b/src/net/tmwserv/accountserver/accountserver.h
@@ -0,0 +1,47 @@
+/*
+ * The Mana World
+ * Copyright 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * The Mana World is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#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();
+
+ void reconnectAccount(Net::Connection *connection,
+ const std::string &passToken);
+ }
+}
+
+#endif
diff --git a/src/net/tmwserv/accountserver/internal.cpp b/src/net/tmwserv/accountserver/internal.cpp
new file mode 100644
index 00000000..a3be76a1
--- /dev/null
+++ b/src/net/tmwserv/accountserver/internal.cpp
@@ -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
+ */
+
+#include "internal.h"
+
+namespace Net
+{
+ class Connection;
+
+ namespace AccountServer
+ {
+ Connection *connection = 0;
+ }
+}
diff --git a/src/net/tmwserv/accountserver/internal.h b/src/net/tmwserv/accountserver/internal.h
new file mode 100644
index 00000000..b3d64582
--- /dev/null
+++ b/src/net/tmwserv/accountserver/internal.h
@@ -0,0 +1,35 @@
+/*
+ * The Mana World
+ * Copyright (C) 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _TMW_NET_ACCOUNTSERVER_INTERNAL_H
+#define _TMW_NET_ACCOUNTSERVER_INTERNAL_H
+
+namespace Net
+{
+ class Connection;
+
+ namespace AccountServer
+ {
+ extern Connection *connection;
+ }
+}
+
+#endif
diff --git a/src/net/tmwserv/beinghandler.cpp b/src/net/tmwserv/beinghandler.cpp
new file mode 100644
index 00000000..947d6b80
--- /dev/null
+++ b/src/net/tmwserv/beinghandler.cpp
@@ -0,0 +1,359 @@
+/*
+ * 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
+ */
+
+#include "beinghandler.h"
+
+#include <SDL_types.h>
+
+#include "../messagein.h"
+#include "protocol.h"
+
+#include "../../being.h"
+#include "../../beingmanager.h"
+#include "../../game.h"
+#include "../../localplayer.h"
+#include "../../log.h"
+#include "../../main.h"
+#include "../../npc.h"
+#include "../../particle.h"
+#include "../../sound.h"
+
+#include "../../gui/ok_dialog.h"
+
+#include "../../utils/gettext.h"
+
+#include "gameserver/player.h"
+
+const int EMOTION_TIME = 150; /**< Duration of emotion icon */
+
+BeingHandler::BeingHandler()
+{
+ static const Uint16 _messages[] = {
+ GPMSG_BEING_ATTACK,
+ GPMSG_BEING_ENTER,
+ GPMSG_BEING_LEAVE,
+ GPMSG_BEINGS_MOVE,
+ GPMSG_BEINGS_DAMAGE,
+ GPMSG_BEING_ACTION_CHANGE,
+ GPMSG_BEING_LOOKS_CHANGE,
+ GPMSG_BEING_DIR_CHANGE,
+ 0
+ };
+ handledMessages = _messages;
+}
+
+void BeingHandler::handleMessage(MessageIn &msg)
+{
+ 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 GPMSG_BEING_ATTACK:
+ handleBeingAttackMessage(msg);
+ break;
+ case GPMSG_BEINGS_DAMAGE:
+ handleBeingsDamageMessage(msg);
+ break;
+ case GPMSG_BEING_ACTION_CHANGE:
+ handleBeingActionChangeMessage(msg);
+ break;
+ case GPMSG_BEING_LOOKS_CHANGE:
+ handleBeingLooksChangeMessage(msg);
+ break;
+ case GPMSG_BEING_DIR_CHANGE:
+ handleBeingDirChangeMessage(msg);
+ break;
+ }
+}
+
+static void handleLooks(Player *being, MessageIn &msg)
+{
+ // Order of sent slots. Has to be in sync with the server code.
+ static int const nb_slots = 4;
+ static int const slots[nb_slots] =
+ { Being::WEAPON_SPRITE, Being::HAT_SPRITE, Being::TOPCLOTHES_SPRITE,
+ Being::BOTTOMCLOTHES_SPRITE };
+
+ int mask = msg.readInt8();
+
+ if (mask & (1 << 7))
+ {
+ // The equipment has to be cleared first.
+ for (int i = 0; i < nb_slots; ++i)
+ {
+ being->setSprite(slots[i], 0);
+ }
+ }
+
+ // Fill slots enumerated by the bitmask.
+ for (int i = 0; i < nb_slots; ++i)
+ {
+ if (!(mask & (1 << i))) continue;
+ int id = msg.readInt16();
+ being->setSprite(slots[i], id);
+ }
+}
+
+void BeingHandler::handleBeingEnterMessage(MessageIn &msg)
+{
+ int type = msg.readInt8();
+ int id = msg.readInt16();
+ Being::Action action = (Being::Action)msg.readInt8();
+ int px = msg.readInt16();
+ int py = msg.readInt16();
+ Being *being;
+
+ switch (type)
+ {
+ case OBJECT_PLAYER:
+ {
+ std::string name = msg.readString();
+ if (player_node->getName() == name)
+ {
+ being = player_node;
+ being->setId(id);
+ }
+ else
+ {
+ being = beingManager->createBeing(id, type, 0);
+ being->setName(name);
+ }
+ Player *p = static_cast< Player * >(being);
+ int hs = msg.readInt8(), hc = msg.readInt8();
+ p->setHairStyle(hs, hc);
+ p->setGender(msg.readInt8() == GENDER_MALE ?
+ GENDER_MALE : GENDER_FEMALE);
+ handleLooks(p, msg);
+ } break;
+
+ case OBJECT_MONSTER:
+ case OBJECT_NPC:
+ {
+ int subtype = msg.readInt16();
+ being = beingManager->createBeing(id, type, subtype);
+ std::string name = msg.readString();
+ if (name.length() > 0) being->setName(name);
+ } break;
+
+ default:
+ return;
+ }
+
+ being->setPosition(px, py);
+ being->setDestination(px, py);
+ being->setAction(action);
+}
+
+void BeingHandler::handleBeingLeaveMessage(MessageIn &msg)
+{
+ Being *being = beingManager->findBeing(msg.readInt16());
+ if (!being) return;
+
+ beingManager->destroyBeing(being);
+}
+
+void BeingHandler::handleBeingsMoveMessage(MessageIn &msg)
+{
+ while (msg.getUnreadLength())
+ {
+ int id = msg.readInt16();
+ int flags = msg.readInt8();
+ Being *being = beingManager->findBeing(id);
+ int sx = 0;
+ int sy = 0;
+ int dx = 0;
+ int dy = 0;
+ int speed = 0;
+
+ printf("handleBeingsMoveMessage for %p (%s | %s)\n",
+ (void*) being,
+ (flags & MOVING_POSITION) ? "pos" : "",
+ (flags & MOVING_DESTINATION) ? "dest" : "");
+
+ if (flags & MOVING_POSITION)
+ {
+ Uint16 sx2, sy2;
+ msg.readCoordinates(sx2, sy2);
+ sx = sx2 * 32 + 16;
+ sy = sy2 * 32 + 16;
+ speed = msg.readInt8();
+ }
+ if (flags & MOVING_DESTINATION)
+ {
+ dx = msg.readInt16();
+ dy = msg.readInt16();
+ if (!(flags & MOVING_POSITION))
+ {
+ sx = dx;
+ sy = dy;
+ }
+ }
+ if (!being || !(flags & (MOVING_POSITION | MOVING_DESTINATION)))
+ {
+ continue;
+ }
+ if (speed)
+ {
+ /* The speed on the server is the cost of moving from one tile to
+ * the next. Beings get 1000 cost units per second. The speed is
+ * transferred as devided by 10, so that slower speeds fit in a
+ * byte. Here we convert the speed to pixels per second.
+ */
+ const float tilesPerSecond = 100.0f / speed;
+ being->setWalkSpeed((int) (tilesPerSecond * 32));
+ }
+
+ // Ignore messages from the server for the local player
+ if (being == player_node)
+ continue;
+
+ // If being is a player, and he only moves a little, its ok to be a little out of sync
+ if (being->getType() == Being::PLAYER && abs(being->getPixelX() - dx) +
+ abs(being->getPixelY() - dy) < 2 * 32 &&
+ (dx != being->getDestination().x && dy != being->getDestination().y))
+ {
+ being->setDestination(being->getPixelX(),being->getPixelY());
+ continue;
+ }
+ if (abs(being->getPixelX() - sx) +
+ abs(being->getPixelY() - sy) > 10 * 32)
+ {
+ // Too large a desynchronization.
+ being->setPosition(sx, 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);
+ }
+ }
+}
+
+void BeingHandler::handleBeingAttackMessage(MessageIn &msg)
+{
+ Being *being = beingManager->findBeing(msg.readInt16());
+ int direction = msg.readInt8();
+ int attackType = msg.readInt8();
+
+ if (!being) return;
+
+ switch (direction)
+ {
+ case DIRECTION_UP: being->setDirection(Being::UP); break;
+ case DIRECTION_DOWN: being->setDirection(Being::DOWN); break;
+ case DIRECTION_LEFT: being->setDirection(Being::LEFT); break;
+ case DIRECTION_RIGHT: being->setDirection(Being::RIGHT); break;
+ }
+
+ being->setAction(Being::ATTACK, attackType);
+}
+
+void BeingHandler::handleBeingsDamageMessage(MessageIn &msg)
+{
+ while (msg.getUnreadLength())
+ {
+ Being *being = beingManager->findBeing(msg.readInt16());
+ int damage = msg.readInt16();
+ if (being)
+ {
+ being->takeDamage(0, damage, Being::HIT);
+ }
+ }
+}
+
+void BeingHandler::handleBeingActionChangeMessage(MessageIn &msg)
+{
+ Being* being = beingManager->findBeing(msg.readInt16());
+ Being::Action action = (Being::Action) msg.readInt8();
+ if (!being) return;
+
+ being->setAction(action);
+
+ if (action == Being::DEAD && being==player_node)
+ {
+ static char const *const deadMsg[] =
+ {
+ _("You are dead."),
+ _("We regret to inform you that your character was killed in battle."),
+ _("You are not that alive anymore."),
+ _("The cold hands of the grim reaper are grabbing for your soul."),
+ _("Game Over!"),
+ _("No, kids. Your character did not really die. It... err... went to a better place."),
+ _("Your plan of breaking your enemies weapon by bashing it with your throat failed."),
+ _("I guess this did not run too well."),
+ _("Do you want your possessions identified?"), // Nethack reference
+ _("Sadly, no trace of you was ever found..."), // Secret of Mana reference
+ _("Annihilated."), // Final Fantasy VI reference
+ _("Looks like you got your head handed to you."), //Earthbound reference
+ _("You screwed up again, dump your body down the tubes and get you another one.") // Leisure Suit Larry 1 Reference
+
+ };
+ std::string message(deadMsg[rand()%13]);
+ message.append(_(" Press OK to respawn"));
+ OkDialog *dlg = new OkDialog(_("You died"), message);
+ dlg->addActionListener(&(Net::GameServer::Player::respawnListener));
+ }
+}
+
+void BeingHandler::handleBeingLooksChangeMessage(MessageIn &msg)
+{
+ Being *being = beingManager->findBeing(msg.readInt16());
+ if (!being || being->getType() != Being::PLAYER) return;
+ Player * player = static_cast< Player * >(being);
+ handleLooks(player, msg);
+ if (msg.getUnreadLength())
+ {
+ int style = msg.readInt16();
+ int color = msg.readInt16();
+ player->setHairStyle(style, color);
+ player->setGender((Gender)msg.readInt16());
+ }
+}
+
+void BeingHandler::handleBeingDirChangeMessage(MessageIn &msg)
+{
+ Being *being = beingManager->findBeing(msg.readInt16());
+ if (!being) return;
+ int data = msg.readInt8();
+ switch (data)
+ {
+ case DIRECTION_UP: being->setDirection(Being::UP); break;
+ case DIRECTION_DOWN: being->setDirection(Being::DOWN); break;
+ case DIRECTION_LEFT: being->setDirection(Being::LEFT); break;
+ case DIRECTION_RIGHT: being->setDirection(Being::RIGHT); break;
+ }
+}
+
diff --git a/src/net/tmwserv/beinghandler.h b/src/net/tmwserv/beinghandler.h
new file mode 100644
index 00000000..759a0ba3
--- /dev/null
+++ b/src/net/tmwserv/beinghandler.h
@@ -0,0 +1,45 @@
+/*
+ * The Mana World
+ * Copyright 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * The Mana World is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _TMW_NET_BEINGHANDLER_H
+#define _TMW_NET_BEINGHANDLER_H
+
+#include "../messagehandler.h"
+
+class BeingHandler : public MessageHandler
+{
+ public:
+ BeingHandler();
+
+ void handleMessage(MessageIn &msg);
+
+ private:
+ void handleBeingAttackMessage(MessageIn &msg);
+ void handleBeingEnterMessage(MessageIn &msg);
+ void handleBeingLeaveMessage(MessageIn &msg);
+ void handleBeingsMoveMessage(MessageIn &msg);
+ void handleBeingsDamageMessage(MessageIn &msg);
+ void handleBeingActionChangeMessage(MessageIn &msg);
+ void handleBeingLooksChangeMessage(MessageIn &msg);
+ void handleBeingDirChangeMessage(MessageIn &msg);
+};
+
+#endif
diff --git a/src/net/tmwserv/buysellhandler.cpp b/src/net/tmwserv/buysellhandler.cpp
new file mode 100644
index 00000000..6e4b9d56
--- /dev/null
+++ b/src/net/tmwserv/buysellhandler.cpp
@@ -0,0 +1,92 @@
+/*
+ * 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
+ */
+
+#include "buysellhandler.h"
+
+#include <SDL_types.h>
+
+#include "../messagein.h"
+#include "protocol.h"
+
+#include "../../beingmanager.h"
+#include "../../item.h"
+#include "../../localplayer.h"
+#include "../../npc.h"
+
+#include "../../gui/buy.h"
+#include "../../gui/chat.h"
+#include "../../gui/sell.h"
+
+extern BuyDialog *buyDialog;
+extern SellDialog *sellDialog;
+extern Window *buySellDialog;
+
+BuySellHandler::BuySellHandler()
+{
+ static const Uint16 _messages[] = {
+ GPMSG_NPC_BUY,
+ GPMSG_NPC_SELL,
+ 0
+ };
+ handledMessages = _messages;
+}
+
+void BuySellHandler::handleMessage(MessageIn &msg)
+{
+ Being *being = beingManager->findBeing(msg.readInt16());
+ if (!being || being->getType() != Being::NPC)
+ {
+ return;
+ }
+
+ current_npc = being->getId();
+
+ switch (msg.getId())
+ {
+ case GPMSG_NPC_BUY:
+ buyDialog->reset();
+ buyDialog->setMoney(player_node->getMoney());
+ buyDialog->setVisible(true);
+
+ while (msg.getUnreadLength())
+ {
+ int itemId = msg.readInt16();
+ int amount = msg.readInt16();
+ int value = msg.readInt16();
+ buyDialog->addItem(itemId, amount, value);
+ }
+ break;
+
+ case GPMSG_NPC_SELL:
+ sellDialog->setMoney(player_node->getMoney());
+ sellDialog->reset();
+ sellDialog->setVisible(true);
+
+ while (msg.getUnreadLength())
+ {
+ int itemId = msg.readInt16();
+ int amount = msg.readInt16();
+ int value = msg.readInt16();
+ sellDialog->addItem(itemId, amount, value);
+ }
+ break;
+ }
+}
diff --git a/src/net/tmwserv/buysellhandler.h b/src/net/tmwserv/buysellhandler.h
new file mode 100644
index 00000000..5bf58d8e
--- /dev/null
+++ b/src/net/tmwserv/buysellhandler.h
@@ -0,0 +1,35 @@
+/*
+ * The Mana World
+ * Copyright (C) 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef NET_BUYSELLHANDLER_H
+#define NET_BUYSELLHANDLER_H
+
+#include "../messagehandler.h"
+
+class BuySellHandler : public MessageHandler
+{
+ public:
+ BuySellHandler();
+
+ void handleMessage(MessageIn &msg);
+};
+
+#endif
diff --git a/src/net/tmwserv/charserverhandler.cpp b/src/net/tmwserv/charserverhandler.cpp
new file mode 100644
index 00000000..50b0e739
--- /dev/null
+++ b/src/net/tmwserv/charserverhandler.cpp
@@ -0,0 +1,227 @@
+/*
+ * 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
+ */
+
+#include "charserverhandler.h"
+
+#include "connection.h"
+#include "../messagein.h"
+#include "protocol.h"
+
+#include "../../game.h"
+#include "../../localplayer.h"
+#include "../../log.h"
+#include "../../logindata.h"
+#include "../../main.h"
+
+#include "../../gui/ok_dialog.h"
+#include "../../gui/char_select.h"
+
+extern Net::Connection *gameServerConnection;
+extern Net::Connection *chatServerConnection;
+
+CharServerHandler::CharServerHandler():
+ mCharCreateDialog(0)
+{
+ static const Uint16 _messages[] = {
+ APMSG_CHAR_CREATE_RESPONSE,
+ APMSG_CHAR_DELETE_RESPONSE,
+ APMSG_CHAR_INFO,
+ APMSG_CHAR_SELECT_RESPONSE,
+ 0
+ };
+ handledMessages = _messages;
+}
+
+void CharServerHandler::handleMessage(MessageIn &msg)
+{
+ int slot;
+ LocalPlayer *tempPlayer;
+
+ switch (msg.getId())
+ {
+ case APMSG_CHAR_CREATE_RESPONSE:
+ handleCharCreateResponse(msg);
+ break;
+
+ case APMSG_CHAR_DELETE_RESPONSE:
+ {
+ int errMsg = msg.readInt8();
+ // Character deletion successful
+ if (errMsg == ERRMSG_OK)
+ {
+ delete mCharInfo->getEntry();
+ mCharInfo->setEntry(0);
+ mCharInfo->unlock();
+ new OkDialog("Info", "Player deleted");
+ }
+ // 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);
+ }
+ }
+ break;
+
+ case APMSG_CHAR_INFO:
+ tempPlayer = readPlayerData(msg, slot);
+ mCharInfo->unlock();
+ mCharInfo->select(slot);
+ mCharInfo->setEntry(tempPlayer);
+
+ // Close the character create dialog
+ if (mCharCreateDialog)
+ {
+ mCharCreateDialog->scheduleDelete();
+ mCharCreateDialog = 0;
+ }
+ break;
+
+ case APMSG_CHAR_SELECT_RESPONSE:
+ handleCharSelectResponse(msg);
+ break;
+ }
+}
+
+void CharServerHandler::handleCharCreateResponse(MessageIn &msg)
+{
+ int errMsg = msg.readInt8();
+
+ // 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_EQUAL_TO_ZERO:
+ message = "One stat is zero";
+ break;
+ default:
+ message = "Unknown error";
+ break;
+ }
+ new OkDialog("Error", message);
+ }
+
+ if (mCharCreateDialog)
+ mCharCreateDialog->unlock();
+}
+
+void CharServerHandler::handleCharSelectResponse(MessageIn &msg)
+{
+ int errMsg = msg.readInt8();
+
+ if (errMsg == ERRMSG_OK)
+ {
+ token = msg.readString(32);
+ std::string gameServer = msg.readString();
+ unsigned short gameServerPort = msg.readInt16();
+ std::string chatServer = msg.readString();
+ unsigned short chatServerPort = msg.readInt16();
+
+ 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();
+ int slot = mCharInfo->getPos();
+ mCharInfo->unlock();
+ mCharInfo->select(0);
+
+ do {
+ LocalPlayer *tmp = mCharInfo->getEntry();
+ if (tmp != player_node)
+ {
+ delete tmp;
+ mCharInfo->setEntry(0);
+ }
+ mCharInfo->next();
+ } while (mCharInfo->getPos());
+ mCharInfo->select(slot);
+
+ mCharInfo->clear(); //player_node will be deleted by ~Game
+
+ state = STATE_CONNECT_GAME;
+ }
+}
+
+LocalPlayer* CharServerHandler::readPlayerData(MessageIn &msg, int &slot)
+{
+ LocalPlayer *tempPlayer = new LocalPlayer;
+ slot = msg.readInt8(); // character slot
+ tempPlayer->setName(msg.readString());
+ tempPlayer->setGender(msg.readInt8() == GENDER_MALE ? GENDER_MALE : GENDER_FEMALE);
+ int hs = msg.readInt8(), hc = msg.readInt8();
+ tempPlayer->setHairStyle(hs, hc);
+ tempPlayer->setLevel(msg.readInt16());
+ tempPlayer->setCharacterPoints(msg.readInt16());
+ tempPlayer->setCorrectionPoints(msg.readInt16());
+ tempPlayer->setMoney(msg.readInt32());
+
+ for (int i = 0; i < 7; i++)
+ {
+ tempPlayer->setAttributeBase(i, msg.readInt8());
+ }
+
+ return tempPlayer;
+}
diff --git a/src/net/tmwserv/charserverhandler.h b/src/net/tmwserv/charserverhandler.h
new file mode 100644
index 00000000..41afa321
--- /dev/null
+++ b/src/net/tmwserv/charserverhandler.h
@@ -0,0 +1,72 @@
+/*
+ * 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
+ */
+
+#ifndef _TMW_NET_CHARSERVERHANDLER_H
+#define _TMW_NET_CHARSERVERHANDLER_H
+
+#include "../messagehandler.h"
+
+#include "../../lockedarray.h"
+
+class CharCreateDialog;
+class LocalPlayer;
+class LoginData;
+
+/**
+ * Deals with incoming messages related to character selection.
+ */
+class CharServerHandler : public MessageHandler
+{
+ public:
+ CharServerHandler();
+
+ void
+ handleMessage(MessageIn &msg);
+
+ void
+ setCharInfo(LockedArray<LocalPlayer*> *charInfo)
+ {
+ mCharInfo = charInfo;
+ }
+
+ /**
+ * Sets the character create dialog. The handler will clean up this
+ * dialog when a new character is succesfully created, and will unlock
+ * the dialog when a new character failed to be created.
+ */
+ void setCharCreateDialog(CharCreateDialog *window)
+ { mCharCreateDialog = window; }
+
+ protected:
+ void
+ handleCharCreateResponse(MessageIn &msg);
+
+ void
+ handleCharSelectResponse(MessageIn &msg);
+
+ LockedArray<LocalPlayer*> *mCharInfo;
+ CharCreateDialog *mCharCreateDialog;
+
+ LocalPlayer*
+ readPlayerData(MessageIn &msg, int &slot);
+};
+
+#endif
diff --git a/src/net/tmwserv/chathandler.cpp b/src/net/tmwserv/chathandler.cpp
new file mode 100644
index 00000000..0d66d8aa
--- /dev/null
+++ b/src/net/tmwserv/chathandler.cpp
@@ -0,0 +1,285 @@
+/*
+ * 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
+ */
+
+#include "chathandler.h"
+
+#include <SDL_types.h>
+#include <string>
+#include <iostream>
+
+#include "../messagein.h"
+#include "protocol.h"
+
+#include "../../being.h"
+#include "../../beingmanager.h"
+#include "../../game.h"
+#include "../../channel.h"
+#include "../../channelmanager.h"
+
+#include "../../gui/chat.h"
+#include "../../gui/guildwindow.h"
+
+extern Being *player_node;
+
+ChatHandler::ChatHandler()
+{
+ static const Uint16 _messages[] = {
+ GPMSG_SAY,
+ CPMSG_ENTER_CHANNEL_RESPONSE,
+ CPMSG_LIST_CHANNELS_RESPONSE,
+ CPMSG_PUBMSG,
+ CPMSG_ANNOUNCEMENT,
+ CPMSG_PRIVMSG,
+ CPMSG_QUIT_CHANNEL_RESPONSE,
+ CPMSG_LIST_CHANNELUSERS_RESPONSE,
+ CPMSG_CHANNEL_EVENT,
+ 0
+ };
+ handledMessages = _messages;
+}
+
+void ChatHandler::handleMessage(MessageIn &msg)
+{
+ switch (msg.getId())
+ {
+ case GPMSG_SAY:
+ handleGameChatMessage(msg);
+ break;
+
+ case CPMSG_ENTER_CHANNEL_RESPONSE:
+ handleEnterChannelResponse(msg);
+ break;
+
+ case CPMSG_LIST_CHANNELS_RESPONSE:
+ handleListChannelsResponse(msg);
+ break;
+
+ case CPMSG_PRIVMSG:
+ handlePrivateMessage(msg);
+ break;
+
+ case CPMSG_ANNOUNCEMENT:
+ handleAnnouncement(msg);
+ break;
+
+ case CPMSG_PUBMSG:
+ handleChatMessage(msg);
+ break;
+
+ case CPMSG_QUIT_CHANNEL_RESPONSE:
+ handleQuitChannelResponse(msg);
+ break;
+
+ case CPMSG_LIST_CHANNELUSERS_RESPONSE:
+ handleListChannelUsersResponse(msg);
+ break;
+
+ case CPMSG_CHANNEL_EVENT:
+ handleChannelEvent(msg);
+ }
+}
+
+void ChatHandler::handleGameChatMessage(MessageIn &msg)
+{
+ short id = msg.readInt16();
+ std::string chatMsg = msg.readString();
+
+ if (id == 0)
+ {
+ chatWindow->chatLog(chatMsg, BY_SERVER);
+ return;
+ }
+
+ Being *being = beingManager->findBeing(id);
+
+ if (being)
+ {
+ chatWindow->chatLog(being->getName() + " : " + chatMsg,
+ being == player_node ? BY_PLAYER : BY_OTHER, "General");
+ being->setSpeech(chatMsg, SPEECH_TIME);
+ }
+ else
+ {
+ chatWindow->chatLog("Unknown : " + chatMsg, BY_OTHER, "General");
+ }
+}
+
+void ChatHandler::handleEnterChannelResponse(MessageIn &msg)
+{
+ if(msg.readInt8() == ERRMSG_OK)
+ {
+ short channelId = msg.readInt16();
+ std::string channelName = msg.readString();
+ std::string announcement = msg.readString();
+ Channel *channel = new Channel(channelId, channelName, announcement);
+ channelManager->addChannel(channel);
+ chatWindow->createNewChannelTab(channelName);
+ chatWindow->chatLog("Topic: " + announcement, BY_CHANNEL, channelName);
+
+ std::string user;
+ std::string userModes;
+ chatWindow->chatLog("Players in this channel:", BY_CHANNEL, channelName);
+ while(msg.getUnreadLength())
+ {
+ user = msg.readString();
+ if (user == "")
+ return;
+ userModes = msg.readString();
+ if (userModes.find('o') != std::string::npos)
+ {
+ user = "@" + user;
+ }
+ chatWindow->chatLog(user, BY_CHANNEL, channelName);
+ }
+
+ }
+ else
+ {
+ chatWindow->chatLog("Error joining channel", BY_SERVER);
+ }
+}
+
+void ChatHandler::handleListChannelsResponse(MessageIn &msg)
+{
+ chatWindow->chatLog("Listing Channels", BY_SERVER);
+ while(msg.getUnreadLength())
+ {
+ std::string channelName = msg.readString();
+ if (channelName == "")
+ return;
+ std::ostringstream numUsers;
+ numUsers << msg.readInt16();
+ channelName += " - ";
+ channelName += numUsers.str();
+ chatWindow->chatLog(channelName, BY_SERVER);
+ }
+ chatWindow->chatLog("End of channel list", BY_SERVER);
+}
+
+void ChatHandler::handlePrivateMessage(MessageIn &msg)
+{
+ std::string userNick = msg.readString();
+ std::string chatMsg = msg.readString();
+
+ if (!chatWindow->tabExists(userNick))
+ {
+ chatWindow->createNewChannelTab(userNick);
+
+ }
+ chatWindow->chatLog(userNick + ": " + chatMsg, BY_OTHER, userNick);
+}
+
+void ChatHandler::handleAnnouncement(MessageIn &msg)
+{
+ std::string chatMsg = msg.readString();
+ chatWindow->chatLog(chatMsg, BY_GM);
+}
+
+void ChatHandler::handleChatMessage(MessageIn &msg)
+{
+ short channelId = msg.readInt16();
+ std::string userNick = msg.readString();
+ std::string chatMsg = msg.readString();
+
+ chatWindow->sendToChannel(channelId, userNick, chatMsg);
+}
+
+void ChatHandler::handleQuitChannelResponse(MessageIn &msg)
+{
+ if(msg.readInt8() == ERRMSG_OK)
+ {
+ short channelId = msg.readInt16();
+ // remove the chat tab
+ chatWindow->removeChannel(channelId);
+ }
+}
+
+void ChatHandler::handleListChannelUsersResponse(MessageIn &msg)
+{
+ std::string channel = msg.readString();
+ std::string userNick;
+ std::string userModes;
+ chatWindow->chatLog("Players in this channel:", BY_CHANNEL, channel);
+ while(msg.getUnreadLength())
+ {
+ userNick = msg.readString();
+ if (userNick == "")
+ {
+ break;
+ }
+ userModes = msg.readString();
+ if (userModes.find('o') != std::string::npos)
+ {
+ userNick = "@" + userNick;
+ }
+ chatWindow->chatLog(userNick, BY_CHANNEL, channel);
+ }
+}
+
+void ChatHandler::handleChannelEvent(MessageIn &msg)
+{
+ short channelId = msg.readInt16();
+ char eventId = msg.readInt8();
+ std::string line = msg.readString();
+ Channel *channel = channelManager->findById(channelId);
+
+ if(channel)
+ {
+ switch(eventId)
+ {
+ case CHAT_EVENT_NEW_PLAYER:
+ line += " entered the channel.";
+ break;
+
+ case CHAT_EVENT_LEAVING_PLAYER:
+ line += " left the channel.";
+ break;
+
+ case CHAT_EVENT_TOPIC_CHANGE:
+ line = "Topic: " + line;
+ break;
+
+ case CHAT_EVENT_MODE_CHANGE:
+ {
+ int first = line.find(":");
+ int second = line.find(":", first+1);
+ std::string user1 = line.substr(0, first);
+ std::string user2 = line.substr(first+1, second);
+ std::string mode = line.substr(second+1, line.length());
+ line = user1 + " has set mode " + mode + " on user " + user2;
+ } break;
+
+ case CHAT_EVENT_KICKED_PLAYER:
+ {
+ int first = line.find(":");
+ std::string user1 = line.substr(0, first);
+ std::string user2 = line.substr(first+1, line.length());
+ line = user1 + " has kicked " + user2;
+ } break;
+
+ default:
+ line = "Unknown channel event.";
+ }
+
+ chatWindow->chatLog(line, BY_CHANNEL, channel->getName());
+ }
+}
+
diff --git a/src/net/tmwserv/chathandler.h b/src/net/tmwserv/chathandler.h
new file mode 100644
index 00000000..013b955d
--- /dev/null
+++ b/src/net/tmwserv/chathandler.h
@@ -0,0 +1,84 @@
+/*
+ * The Mana World
+ * Copyright (C) 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef NET_CHATHANDLER_H
+#define NET_CHATHANDLER_H
+
+#include "../messagehandler.h"
+
+class ChatHandler : public MessageHandler
+{
+ public:
+ ChatHandler();
+
+ /**
+ * Handle the given message appropriately.
+ */
+ void handleMessage(MessageIn &msg);
+
+ private:
+ /**
+ * Handle chat messages sent from the game server.
+ */
+ void handleGameChatMessage(MessageIn &msg);
+
+ /**
+ * Handle channel entry responses.
+ */
+ void handleEnterChannelResponse(MessageIn &msg);
+
+ /**
+ * Handle list channels responses.
+ */
+ void handleListChannelsResponse(MessageIn &msg);
+
+ /**
+ * Handle private messages.
+ */
+ void handlePrivateMessage(MessageIn &msg);
+
+ /**
+ * Handle announcements.
+ */
+ void handleAnnouncement(MessageIn &msg);
+
+ /**
+ * Handle chat messages.
+ */
+ void handleChatMessage(MessageIn &msg);
+
+ /**
+ * Handle quit channel responses.
+ */
+ void handleQuitChannelResponse(MessageIn &msg);
+
+ /**
+ * Handle list channel users responses.
+ */
+ void handleListChannelUsersResponse(MessageIn &msg);
+
+ /**
+ * Handle channel events.
+ */
+ void handleChannelEvent(MessageIn &msg);
+};
+
+#endif
diff --git a/src/net/tmwserv/chatserver/chatserver.cpp b/src/net/tmwserv/chatserver/chatserver.cpp
new file mode 100644
index 00000000..39ffef4a
--- /dev/null
+++ b/src/net/tmwserv/chatserver/chatserver.cpp
@@ -0,0 +1,146 @@
+/*
+ * The Mana World
+ * Copyright 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * The Mana World is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#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::logout()
+{
+ MessageOut msg(PCMSG_DISCONNECT);
+
+ connection->send(msg);
+}
+
+void Net::ChatServer::chat(short channel, const std::string &text)
+{
+ MessageOut msg(PCMSG_CHAT);
+
+ msg.writeString(text);
+ msg.writeInt16(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::enterChannel(const std::string &channel, const std::string &password)
+{
+ MessageOut msg(PCMSG_ENTER_CHANNEL);
+
+ msg.writeString(channel);
+ msg.writeString(password);
+
+ connection->send(msg);
+}
+
+void Net::ChatServer::quitChannel(short channel)
+{
+ MessageOut msg(PCMSG_QUIT_CHANNEL);
+
+ msg.writeInt16(channel);
+
+ connection->send(msg);
+}
+
+void Net::ChatServer::getChannelList()
+{
+ MessageOut msg(PCMSG_LIST_CHANNELS);
+
+ connection->send(msg);
+}
+
+void Net::ChatServer::getUserList(const std::string &channel)
+{
+ MessageOut msg(PCMSG_LIST_CHANNELUSERS);
+
+ msg.writeString(channel);
+
+ connection->send(msg);
+}
+
+void Net::ChatServer::setChannelTopic(short channel, const std::string &topic)
+{
+ MessageOut msg(PCMSG_TOPIC_CHANGE);
+
+ msg.writeInt16(channel);
+ msg.writeString(topic);
+
+ connection->send(msg);
+}
+
+void Net::ChatServer::setUserMode(short channel, const std::string &user,
+ unsigned char mode)
+{
+ MessageOut msg(PCMSG_USER_MODE);
+
+ msg.writeInt16(channel);
+ msg.writeString(user);
+ msg.writeInt8(mode);
+
+ connection->send(msg);
+}
+
+void Net::ChatServer::kickUser(short channel, const std::string &user)
+{
+ MessageOut msg(PCMSG_KICK_USER);
+
+ msg.writeInt16(channel);
+ msg.writeString(user);
+
+ connection->send(msg);
+}
diff --git a/src/net/tmwserv/chatserver/chatserver.h b/src/net/tmwserv/chatserver/chatserver.h
new file mode 100644
index 00000000..1129239a
--- /dev/null
+++ b/src/net/tmwserv/chatserver/chatserver.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
+ */
+
+#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 logout();
+
+ 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 enterChannel(const std::string &channel, const std::string &password);
+
+ void quitChannel(short channel);
+
+ void getChannelList();
+
+ void getUserList(const std::string &channel);
+
+ void setChannelTopic(short channel, const std::string &topic);
+
+ void setUserMode(short channel, const std::string &user, unsigned char mode);
+
+ void kickUser(short channel, const std::string &user);
+
+ }
+}
+
+#endif
diff --git a/src/net/tmwserv/chatserver/guild.cpp b/src/net/tmwserv/chatserver/guild.cpp
new file mode 100644
index 00000000..649eccdf
--- /dev/null
+++ b/src/net/tmwserv/chatserver/guild.cpp
@@ -0,0 +1,95 @@
+/*
+ * 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
+ */
+
+
+#include "guild.h"
+
+#include "internal.h"
+
+#include "../connection.h"
+#include "../../messageout.h"
+#include "../protocol.h"
+
+#include "../../../log.h"
+
+void Net::ChatServer::Guild::createGuild(const std::string &name)
+{
+ logger->log("Sending PCMSG_GUILD_CREATE");
+ MessageOut msg(PCMSG_GUILD_CREATE);
+
+ msg.writeString(name);
+
+ Net::ChatServer::connection->send(msg);
+}
+
+void Net::ChatServer::Guild::invitePlayer(const std::string &name, short guildId)
+{
+ logger->log("Sending PCMSG_GUILD_INVITE");
+ MessageOut msg(PCMSG_GUILD_INVITE);
+
+ msg.writeInt16(guildId);
+ msg.writeString(name);
+
+ Net::ChatServer::connection->send(msg);
+}
+
+void Net::ChatServer::Guild::acceptInvite(const std::string &name)
+{
+ logger->log("Sending PCMSG_GUILD_ACCEPT");
+ MessageOut msg(PCMSG_GUILD_ACCEPT);
+
+ msg.writeString(name);
+
+ Net::ChatServer::connection->send(msg);
+}
+
+void Net::ChatServer::Guild::getGuildMembers(short guildId)
+{
+ logger->log("Sending PCMSG_GUILD_GET_MEMBERS");
+ MessageOut msg(PCMSG_GUILD_GET_MEMBERS);
+
+ msg.writeInt16(guildId);
+
+ Net::ChatServer::connection->send(msg);
+}
+
+void Net::ChatServer::Guild::promoteMember(const std::string &name,
+ short guildId, short level)
+{
+ logger->log("Sending PCMSG_GUILD_PROMOTE_MEMBER");
+ MessageOut msg(PCMSG_GUILD_PROMOTE_MEMBER);
+
+ msg.writeInt16(guildId);
+ msg.writeString(name);
+ msg.writeInt8(level);
+
+ Net::ChatServer::connection->send(msg);
+}
+
+void Net::ChatServer::Guild::quitGuild(short guildId)
+{
+ logger->log("Sending PCMSG_GUILD_QUIT");
+ MessageOut msg(PCMSG_GUILD_QUIT);
+
+ msg.writeInt16(guildId);
+
+ Net::ChatServer::connection->send(msg);
+}
diff --git a/src/net/tmwserv/chatserver/guild.h b/src/net/tmwserv/chatserver/guild.h
new file mode 100644
index 00000000..6c35be9f
--- /dev/null
+++ b/src/net/tmwserv/chatserver/guild.h
@@ -0,0 +1,69 @@
+/*
+ * 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
+ */
+
+
+#ifndef _TMW_NET_CHATSERVER_GUILD_H
+#define _TMW_NET_CHATSERVER_GUILD_H
+
+#include <iosfwd>
+
+namespace Net
+{
+ namespace ChatServer
+ {
+ namespace Guild
+ {
+ /**
+ * Create guild.
+ */
+ void createGuild(const std::string &name);
+
+ /**
+ * Invite a player to your guild.
+ */
+ void invitePlayer(const std::string &name, short guildId);
+
+ /**
+ * Accept an invite another player has sent to join their guild.
+ */
+ void acceptInvite(const std::string &name);
+
+ /**
+ * Get a list of members in a guild.
+ */
+ void getGuildMembers(short guildId);
+
+ /**
+ * Promote guild member
+ */
+ void promoteMember(const std::string &name, short guildId,
+ short level);
+
+ /**
+ * Quit guild.
+ */
+ void quitGuild(short guildId);
+ }
+ }
+}
+
+#endif
+
diff --git a/src/net/tmwserv/chatserver/internal.cpp b/src/net/tmwserv/chatserver/internal.cpp
new file mode 100644
index 00000000..0822d93d
--- /dev/null
+++ b/src/net/tmwserv/chatserver/internal.cpp
@@ -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
+ */
+
+#include "internal.h"
+
+namespace Net
+{
+ class Connection;
+
+ namespace ChatServer
+ {
+ Connection *connection = 0;
+ }
+}
diff --git a/src/net/tmwserv/chatserver/internal.h b/src/net/tmwserv/chatserver/internal.h
new file mode 100644
index 00000000..b0f137c5
--- /dev/null
+++ b/src/net/tmwserv/chatserver/internal.h
@@ -0,0 +1,35 @@
+/*
+ * 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
+ */
+
+#ifndef _TMW_NET_CHATSERVER_INTERNAL_H
+#define _TMW_NET_CHATSERVER_INTERNAL_H
+
+namespace Net
+{
+ class Connection;
+
+ namespace ChatServer
+ {
+ extern Connection *connection;
+ }
+}
+
+#endif
diff --git a/src/net/tmwserv/chatserver/party.cpp b/src/net/tmwserv/chatserver/party.cpp
new file mode 100644
index 00000000..c2c0b00a
--- /dev/null
+++ b/src/net/tmwserv/chatserver/party.cpp
@@ -0,0 +1,70 @@
+/*
+ * The Mana World
+ * Copyright 2008 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
+ */
+
+
+#include "party.h"
+
+#include "internal.h"
+
+#include "../connection.h"
+#include "../../messageout.h"
+#include "../protocol.h"
+
+#include "../../../log.h"
+
+void Net::ChatServer::Party::invitePlayer(const std::string &name)
+{
+ logger->log("Sending PCMSG_PARTY_INVITE");
+ MessageOut msg(PCMSG_PARTY_INVITE);
+
+ msg.writeString(name);
+
+ Net::ChatServer::connection->send(msg);
+}
+
+void Net::ChatServer::Party::acceptInvite(const std::string &name)
+{
+ logger->log("Sending PCMSG_PARTY_ACCEPT_INVITE");
+ MessageOut msg(PCMSG_PARTY_ACCEPT_INVITE);
+
+ msg.writeString(name);
+
+ Net::ChatServer::connection->send(msg);
+}
+
+void Net::ChatServer::Party::getPartyMembers()
+{
+ logger->log("Sending PCMSG_PARTY_GET_MEMBERS");
+// MessageOut msg(PCMSG_GUILD_GET_MEMBERS);
+
+// msg.writeInt16(guildId);
+
+// Net::ChatServer::connection->send(msg);
+}
+
+void Net::ChatServer::Party::quitParty()
+{
+ logger->log("Sending PCMSG_PARTY_QUIT");
+ MessageOut msg(PCMSG_PARTY_QUIT);
+
+ Net::ChatServer::connection->send(msg);
+}
+
diff --git a/src/net/tmwserv/chatserver/party.h b/src/net/tmwserv/chatserver/party.h
new file mode 100644
index 00000000..c1febd66
--- /dev/null
+++ b/src/net/tmwserv/chatserver/party.h
@@ -0,0 +1,57 @@
+/*
+ * The Mana World
+ * Copyright 2008 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
+ */
+
+
+#ifndef _TMW_NET_CHATSERVER_PARTY_H
+#define _TMW_NET_CHATSERVER_PARTY_H
+
+#include <iosfwd>
+
+namespace Net
+{
+ namespace ChatServer
+ {
+ namespace Party
+ {
+ /**
+ * Invite a player to the party.
+ */
+ void invitePlayer(const std::string &name);
+
+ /**
+ * Accept an invite another player has sent to join their party
+ */
+ void acceptInvite(const std::string &name);
+
+ /**
+ * Get a list of party members
+ */
+ void getPartyMembers();
+
+ /**
+ * Leave party
+ */
+ void quitParty();
+ }
+ }
+}
+
+#endif
diff --git a/src/net/tmwserv/connection.cpp b/src/net/tmwserv/connection.cpp
new file mode 100644
index 00000000..5e61ba61
--- /dev/null
+++ b/src/net/tmwserv/connection.cpp
@@ -0,0 +1,103 @@
+/*
+ * The Mana World
+ * Copyright 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * The Mana World is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#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 = NET_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 = NET_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 bool (mConnection) ?
+ (mConnection->state == ENET_PEER_STATE_CONNECTED) : false;
+}
+
+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/tmwserv/connection.h b/src/net/tmwserv/connection.h
new file mode 100644
index 00000000..4ab3d24d
--- /dev/null
+++ b/src/net/tmwserv/connection.h
@@ -0,0 +1,80 @@
+/*
+ * 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
+ */
+
+#ifndef _TMW_NET_CONNECTION_H
+#define _TMW_NET_CONNECTION_H
+
+#include <iosfwd>
+
+#include <enet/enet.h>
+
+class MessageOut;
+
+namespace Net
+{
+ /**
+ * \ingroup Network
+ */
+ class Connection
+ {
+ public:
+ enum State {
+ OK,
+ NET_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/tmwserv/effecthandler.cpp b/src/net/tmwserv/effecthandler.cpp
new file mode 100644
index 00000000..ef8d63fb
--- /dev/null
+++ b/src/net/tmwserv/effecthandler.cpp
@@ -0,0 +1,58 @@
+/*
+ * The Mana World
+ * Copyright (C) 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "effecthandler.h"
+
+#include "../messagein.h"
+#include "protocol.h"
+
+#include "../../effectmanager.h"
+
+
+EffectHandler::EffectHandler()
+{
+ static const Uint16 _messages[] = {
+ GPMSG_CREATE_EFFECT,
+ 0
+ };
+ handledMessages = _messages;
+}
+
+void EffectHandler::handleMessage(MessageIn &msg)
+{
+ switch (msg.getId())
+ {
+ case GPMSG_CREATE_EFFECT:
+ handleCreateEffects(msg);
+ break;
+ default:
+ break;
+ }
+}
+
+void EffectHandler::handleCreateEffects(MessageIn &msg)
+{
+ int id = msg.readInt16();
+ Uint16 x = msg.readInt16();
+ Uint16 y = msg.readInt16();
+ effectManager->trigger(id, x, y);
+}
+
diff --git a/src/net/tmwserv/effecthandler.h b/src/net/tmwserv/effecthandler.h
new file mode 100644
index 00000000..a19f13c3
--- /dev/null
+++ b/src/net/tmwserv/effecthandler.h
@@ -0,0 +1,38 @@
+/*
+ * The Mana World
+ * Copyright 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * The Mana World is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _TMW_NET_EFFECTSHANDLER_H
+#define _TMW_NET_EFFECTSHANDLER_H
+
+#include "../messagehandler.h"
+
+class EffectHandler : public MessageHandler
+{
+ public:
+ EffectHandler();
+
+ void handleMessage(MessageIn &msg);
+
+ private:
+ void handleCreateEffects(MessageIn &msg);
+};
+
+#endif
diff --git a/src/net/tmwserv/gameserver/gameserver.cpp b/src/net/tmwserv/gameserver/gameserver.cpp
new file mode 100644
index 00000000..013356d8
--- /dev/null
+++ b/src/net/tmwserv/gameserver/gameserver.cpp
@@ -0,0 +1,49 @@
+/*
+ * 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
+ */
+
+#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);
+}
+
+void Net::GameServer::logout(bool reconnectAccount)
+{
+ MessageOut msg(PGMSG_DISCONNECT);
+
+ msg.writeInt8((unsigned char) reconnectAccount);
+
+ Net::GameServer::connection->send(msg);
+}
diff --git a/src/net/tmwserv/gameserver/gameserver.h b/src/net/tmwserv/gameserver/gameserver.h
new file mode 100644
index 00000000..5ea2c718
--- /dev/null
+++ b/src/net/tmwserv/gameserver/gameserver.h
@@ -0,0 +1,39 @@
+/*
+ * 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
+ */
+
+#ifndef _TMW_NET_GAMESERVER_GAMESERVER_H
+#define _TMW_NET_GAMESERVER_GAMESERVER_H
+
+#include <iosfwd>
+
+namespace Net
+{
+ class Connection;
+
+ namespace GameServer
+ {
+ void connect(Net::Connection *connection, const std::string &token);
+
+ void logout(bool reconnectAccount);
+ }
+}
+
+#endif
diff --git a/src/net/tmwserv/gameserver/internal.cpp b/src/net/tmwserv/gameserver/internal.cpp
new file mode 100644
index 00000000..6b6ba081
--- /dev/null
+++ b/src/net/tmwserv/gameserver/internal.cpp
@@ -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
+ */
+
+#include "internal.h"
+
+namespace Net
+{
+ class Connection;
+
+ namespace GameServer
+ {
+ Connection *connection = 0;
+ }
+}
diff --git a/src/net/tmwserv/gameserver/internal.h b/src/net/tmwserv/gameserver/internal.h
new file mode 100644
index 00000000..df9787fe
--- /dev/null
+++ b/src/net/tmwserv/gameserver/internal.h
@@ -0,0 +1,35 @@
+/*
+ * 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
+ */
+
+#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/tmwserv/gameserver/player.cpp b/src/net/tmwserv/gameserver/player.cpp
new file mode 100644
index 00000000..4eccdceb
--- /dev/null
+++ b/src/net/tmwserv/gameserver/player.cpp
@@ -0,0 +1,202 @@
+/*
+ * 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
+ */
+
+#include "player.h"
+
+#include "internal.h"
+
+#include "../connection.h"
+#include "../../messageout.h"
+#include "../protocol.h"
+
+void RespawnRequestListener::action(const gcn::ActionEvent &event)
+{
+ Net::GameServer::Player::respawn();
+}
+
+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(int x, int y)
+{
+ MessageOut msg(PGMSG_WALK);
+ msg.writeInt16(x);
+ msg.writeInt16(y);
+ Net::GameServer::connection->send(msg);
+}
+
+void Net::GameServer::Player::pickUp(int x, int y)
+{
+ MessageOut msg(PGMSG_PICKUP);
+ msg.writeInt16(x);
+ msg.writeInt16(y);
+ Net::GameServer::connection->send(msg);
+}
+
+void Net::GameServer::Player::moveItem(int oldSlot, int newSlot, int amount)
+{
+ MessageOut msg(PGMSG_MOVE_ITEM);
+ msg.writeInt8(oldSlot);
+ msg.writeInt8(newSlot);
+ msg.writeInt8(amount);
+ Net::GameServer::connection->send(msg);
+}
+
+void Net::GameServer::Player::drop(int slot, int amount)
+{
+ MessageOut msg(PGMSG_DROP);
+ msg.writeInt8(slot);
+ msg.writeInt8(amount);
+ Net::GameServer::connection->send(msg);
+}
+
+void Net::GameServer::Player::equip(int slot)
+{
+ MessageOut msg(PGMSG_EQUIP);
+ msg.writeInt8(slot);
+ Net::GameServer::connection->send(msg);
+}
+
+void Net::GameServer::Player::unequip(int slot)
+{
+ MessageOut msg(PGMSG_UNEQUIP);
+ msg.writeInt8(slot);
+ Net::GameServer::connection->send(msg);
+}
+
+void Net::GameServer::Player::useItem(int slot)
+{
+ MessageOut msg(PGMSG_USE_ITEM);
+ msg.writeInt8(slot);
+ Net::GameServer::connection->send(msg);
+}
+
+void Net::GameServer::Player::attack(int direction)
+{
+ MessageOut msg(PGMSG_ATTACK);
+ msg.writeInt8(direction);
+ Net::GameServer::connection->send(msg);
+}
+
+void Net::GameServer::Player::useSpecial(int special)
+{
+ MessageOut msg(PGMSG_USE_SPECIAL);
+ msg.writeInt8(special);
+ Net::GameServer::connection->send(msg);
+}
+
+void Net::GameServer::Player::changeAction(Being::Action action)
+{
+ MessageOut msg(PGMSG_ACTION_CHANGE);
+ msg.writeInt8(action);
+ Net::GameServer::connection->send(msg);
+}
+
+void Net::GameServer::Player::talkToNPC(int id, bool restart)
+{
+ MessageOut msg(restart ? PGMSG_NPC_TALK : PGMSG_NPC_TALK_NEXT);
+ msg.writeInt16(id);
+ Net::GameServer::connection->send(msg);
+}
+
+void Net::GameServer::Player::selectFromNPC(int id, int choice)
+{
+ MessageOut msg(PGMSG_NPC_SELECT);
+ msg.writeInt16(id);
+ msg.writeInt8(choice);
+ Net::GameServer::connection->send(msg);
+}
+
+void Net::GameServer::Player::requestTrade(int id)
+{
+ MessageOut msg(PGMSG_TRADE_REQUEST);
+ msg.writeInt16(id);
+ Net::GameServer::connection->send(msg);
+}
+
+void Net::GameServer::Player::acceptTrade(bool accept)
+{
+ MessageOut msg(accept ? PGMSG_TRADE_ACCEPT : PGMSG_TRADE_CANCEL);
+ Net::GameServer::connection->send(msg);
+}
+
+void Net::GameServer::Player::tradeItem(int slot, int amount)
+{
+ MessageOut msg(PGMSG_TRADE_ADD_ITEM);
+ msg.writeInt8(slot);
+ msg.writeInt8(amount);
+ Net::GameServer::connection->send(msg);
+}
+
+void Net::GameServer::Player::tradeMoney(int amount)
+{
+ MessageOut msg(PGMSG_TRADE_SET_MONEY);
+ msg.writeInt32(amount);
+ Net::GameServer::connection->send(msg);
+}
+
+void Net::GameServer::Player::tradeWithNPC(int item, int amount)
+{
+ MessageOut msg(PGMSG_NPC_BUYSELL);
+ msg.writeInt16(item);
+ msg.writeInt16(amount);
+ Net::GameServer::connection->send(msg);
+}
+
+void Net::GameServer::Player::sendLetter(const std::string &player,
+ const std::string &text)
+{
+ MessageOut msg(PGMSG_NPC_POST_SEND);
+ msg.writeString(player);
+ msg.writeString(text);
+ Net::GameServer::connection->send(msg);
+}
+
+void Net::GameServer::Player::raiseAttribute(int attribute)
+{
+ MessageOut msg(PGMSG_RAISE_ATTRIBUTE);
+ msg.writeInt8(attribute);
+ Net::GameServer::connection->send(msg);
+}
+
+void Net::GameServer::Player::lowerAttribute(int attribute)
+{
+ MessageOut msg(PGMSG_LOWER_ATTRIBUTE);
+ msg.writeInt8(attribute);
+ Net::GameServer::connection->send(msg);
+}
+
+void Net::GameServer::Player::respawn()
+{
+ MessageOut msg(PGMSG_RESPAWN);
+ Net::GameServer::connection->send(msg);
+}
+
+void Net::GameServer::Player::changeDir(unsigned char dir)
+{
+ MessageOut msg(PGMSG_DIRECTION_CHANGE);
+ msg.writeInt8(dir);
+ Net::GameServer::connection->send(msg);
+}
diff --git a/src/net/tmwserv/gameserver/player.h b/src/net/tmwserv/gameserver/player.h
new file mode 100644
index 00000000..496e3a70
--- /dev/null
+++ b/src/net/tmwserv/gameserver/player.h
@@ -0,0 +1,71 @@
+/*
+ * 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
+ */
+
+#ifndef _TMW_NET_GAMESERVER_PLAYER_H
+#define _TMW_NET_GAMESERVER_PLAYER_H
+
+#include "../../../being.h"
+
+#include <guichan/actionlistener.hpp>
+
+#include <iosfwd>
+
+
+struct RespawnRequestListener : public gcn::ActionListener
+{
+ void action(const gcn::ActionEvent &event);
+};
+
+namespace Net
+{
+ namespace GameServer
+ {
+ namespace Player
+ {
+ void say(const std::string &text);
+ void walk(int x, int y);
+ void pickUp(int x, int y);
+ void moveItem(int oldSlot, int newSlot, int amount);
+ void drop(int slot, int amount);
+ void equip(int slot);
+ void unequip(int slot);
+ void useItem(int slot);
+ void attack(int direction);
+ void useSpecial(int special);
+ void changeAction(Being::Action action);
+ void talkToNPC(int id, bool restart);
+ void selectFromNPC(int id, int choice);
+ void requestTrade(int id);
+ void acceptTrade(bool accept);
+ void tradeItem(int slot, int amount);
+ void tradeMoney(int amount);
+ void tradeWithNPC(int item, int amount);
+ void sendLetter(const std::string &player, const std::string &text);
+ void raiseAttribute(int attribute);
+ void lowerAttribute(int attribute);
+ void respawn();
+ static RespawnRequestListener respawnListener;
+ void changeDir(unsigned char dir);
+ }
+ }
+}
+
+#endif
diff --git a/src/net/tmwserv/guildhandler.cpp b/src/net/tmwserv/guildhandler.cpp
new file mode 100644
index 00000000..1699ffac
--- /dev/null
+++ b/src/net/tmwserv/guildhandler.cpp
@@ -0,0 +1,240 @@
+/*
+ * The Mana World
+ * Copyright 2008 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
+ */
+
+#include <iostream>
+#include "guildhandler.h"
+
+#include "protocol.h"
+#include "../messagein.h"
+
+#include "chatserver/chatserver.h"
+#include "chatserver/guild.h"
+
+#include "../../gui/guildwindow.h"
+#include "../../gui/chat.h"
+#include "../../guild.h"
+#include "../../log.h"
+#include "../../localplayer.h"
+#include "../../channel.h"
+#include "../../channelmanager.h"
+
+GuildHandler::GuildHandler()
+{
+ static const Uint16 _messages[] = {
+ CPMSG_GUILD_CREATE_RESPONSE,
+ CPMSG_GUILD_INVITE_RESPONSE,
+ CPMSG_GUILD_ACCEPT_RESPONSE,
+ CPMSG_GUILD_GET_MEMBERS_RESPONSE,
+ CPMSG_GUILD_UPDATE_LIST,
+ CPMSG_GUILD_INVITED,
+ CPMSG_GUILD_REJOIN,
+ CPMSG_GUILD_QUIT_RESPONSE,
+ 0
+ };
+ handledMessages = _messages;
+
+}
+
+void GuildHandler::handleMessage(MessageIn &msg)
+{
+ switch (msg.getId())
+ {
+ case CPMSG_GUILD_CREATE_RESPONSE:
+ {
+ logger->log("Received CPMSG_GUILD_CREATE_RESPONSE");
+ if(msg.readInt8() == ERRMSG_OK)
+ {
+ // TODO - Acknowledge guild was created
+ chatWindow->chatLog("Guild created.");
+ joinedGuild(msg);
+ }
+ else
+ {
+ chatWindow->chatLog("Error creating guild.");
+ }
+ } break;
+
+ case CPMSG_GUILD_INVITE_RESPONSE:
+ {
+ logger->log("Received CPMSG_GUILD_INVITE_RESPONSE");
+ if(msg.readInt8() == ERRMSG_OK)
+ {
+ // TODO - Acknowledge invite was sent
+ chatWindow->chatLog("Invite sent.");
+ }
+ } break;
+
+ case CPMSG_GUILD_ACCEPT_RESPONSE:
+ {
+ logger->log("Received CPMSG_GUILD_ACCEPT_RESPONSE");
+ if(msg.readInt8() == ERRMSG_OK)
+ {
+ // TODO - Acknowledge accepted into guild
+ joinedGuild(msg);
+ }
+ } break;
+
+ case CPMSG_GUILD_GET_MEMBERS_RESPONSE:
+ {
+ logger->log("Received CPMSG_GUILD_GET_MEMBERS_RESPONSE");
+ if(msg.readInt8() == ERRMSG_OK)
+ {
+ std::string guildMember;
+ bool online;
+ std::string guildName;
+ Guild *guild;
+
+ short guildId = msg.readInt16();
+ guild = player_node->getGuild(guildId);
+
+ if (!guild)
+ return;
+
+ guildName = guild->getName();
+
+ while(msg.getUnreadLength())
+ {
+ guildMember = msg.readString();
+ online = msg.readInt8();
+ if(guildMember != "")
+ {
+ guild->addMember(guildMember);
+ guildWindow->setOnline(guildName, guildMember, online);
+ }
+ }
+
+ guildWindow->updateTab();
+ }
+ } break;
+
+ case CPMSG_GUILD_UPDATE_LIST:
+ {
+ logger->log("Received CPMSG_GUILD_UPDATE_LIST");
+ short guildId = msg.readInt16();
+ std::string guildMember = msg.readString();
+ char eventId = msg.readInt8();
+
+ Guild *guild = player_node->getGuild(guildId);
+ if (guild)
+ {
+ switch(eventId)
+ {
+ case GUILD_EVENT_NEW_PLAYER:
+ guild->addMember(guildMember);
+ guildWindow->setOnline(guild->getName(), guildMember, true);
+ break;
+
+ case GUILD_EVENT_LEAVING_PLAYER:
+ guild->removeMember(guildMember);
+ break;
+
+ case GUILD_EVENT_ONLINE_PLAYER:
+ guildWindow->setOnline(guild->getName(), guildMember, true);
+ break;
+
+ case GUILD_EVENT_OFFLINE_PLAYER:
+ guildWindow->setOnline(guild->getName(), guildMember, false);
+ break;
+
+ default:
+ logger->log("Invalid guild event");
+ }
+ }
+ guildWindow->updateTab();
+
+
+ } break;
+
+ case CPMSG_GUILD_INVITED:
+ {
+ logger->log("Received CPMSG_GUILD_INVITED");
+ std::string inviterName = msg.readString();
+ std::string guildName = msg.readString();
+
+ // Open a dialog asking if the player accepts joining the guild.
+ guildWindow->openAcceptDialog(inviterName, guildName);
+ } break;
+
+ case CPMSG_GUILD_PROMOTE_MEMBER_RESPONSE:
+ {
+ logger->log("Received CPMSG_GUILD_PROMOTE_MEMBER_RESPONSE");
+
+ if (msg.readInt8() == ERRMSG_OK)
+ {
+ // promotion succeeded
+ chatWindow->chatLog("Member was promoted successfully");
+ }
+ else
+ {
+ // promotion failed
+ chatWindow->chatLog("Failed to promote member");
+ }
+ }
+
+ case CPMSG_GUILD_REJOIN:
+ {
+ logger->log("Received CPMSG_GUILD_REJOIN");
+
+ joinedGuild(msg);
+ } break;
+
+ case CPMSG_GUILD_QUIT_RESPONSE:
+ {
+ logger->log("Received CPMSG_GUILD_QUIT_RESPONSE");
+
+ if (msg.readInt8() == ERRMSG_OK)
+ {
+ // Must remove tab first, as it wont find the guild
+ // name after its removed from the player
+ int guildId = msg.readInt16();
+ Guild *guild = player_node->getGuild(guildId);
+ if (guild)
+ {
+ chatWindow->removeChannel(guild->getName());
+ guildWindow->removeTab(guildId);
+ player_node->removeGuild(guildId);
+ }
+ }
+ } break;
+ }
+}
+
+void GuildHandler::joinedGuild(MessageIn &msg)
+{
+ std::string guildName = msg.readString();
+ short guildId = msg.readInt16();
+ short permissions = msg.readInt16();
+ short channelId = msg.readInt16();
+ std::string announcement = msg.readString();
+
+ // Add guild to player and create new guild tab
+ Guild *guild = player_node->addGuild(guildId, permissions);
+ guild->setName(guildName);
+ guildWindow->newGuildTab(guildName);
+ guildWindow->requestMemberList(guildId);
+
+ // Automatically create the guild channel
+ // COMMENT: Should this go here??
+ Channel *channel = new Channel(channelId, guildName, announcement);
+ channelManager->addChannel(channel);
+ chatWindow->createNewChannelTab(guildName);
+ chatWindow->chatLog("Topic: " + announcement, BY_CHANNEL, guildName);
+}
diff --git a/src/net/tmwserv/guildhandler.h b/src/net/tmwserv/guildhandler.h
new file mode 100644
index 00000000..a962a577
--- /dev/null
+++ b/src/net/tmwserv/guildhandler.h
@@ -0,0 +1,40 @@
+/*
+ * The Mana World
+ * Copyright 2008 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
+ */
+
+#ifndef _TMW_NET_GUILDHANDLER_H
+#define _TMW_NET_GUILDHANDLER_H
+
+#include "../messagehandler.h"
+
+#include <string>
+
+class GuildHandler : public MessageHandler
+{
+public:
+ GuildHandler();
+
+ void handleMessage(MessageIn &msg);
+
+protected:
+ void joinedGuild(MessageIn &msg);
+};
+
+#endif
diff --git a/src/net/tmwserv/internal.cpp b/src/net/tmwserv/internal.cpp
new file mode 100644
index 00000000..4cb88a4e
--- /dev/null
+++ b/src/net/tmwserv/internal.cpp
@@ -0,0 +1,27 @@
+/*
+ * 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
+ */
+
+#include "internal.h"
+
+namespace Net
+{
+ int connections = 0;
+}
diff --git a/src/net/tmwserv/internal.h b/src/net/tmwserv/internal.h
new file mode 100644
index 00000000..1e411605
--- /dev/null
+++ b/src/net/tmwserv/internal.h
@@ -0,0 +1,30 @@
+/*
+ * 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
+ */
+
+#ifndef _TMW_NET_INTERNAL_H
+#define _TMW_NET_INTERNAL_H
+
+namespace Net
+{
+ extern int connections;
+}
+
+#endif
diff --git a/src/net/tmwserv/inventoryhandler.cpp b/src/net/tmwserv/inventoryhandler.cpp
new file mode 100644
index 00000000..c6e82410
--- /dev/null
+++ b/src/net/tmwserv/inventoryhandler.cpp
@@ -0,0 +1,79 @@
+/*
+ * The Mana World
+ * Copyright 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * The Mana World is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "inventoryhandler.h"
+
+#include <SDL_types.h>
+
+#include "../messagein.h"
+#include "protocol.h"
+
+#include "../../equipment.h"
+#include "../../inventory.h"
+#include "../../item.h"
+#include "../../itemshortcut.h"
+#include "../../localplayer.h"
+
+#include "../../gui/chat.h"
+#include "../../resources/iteminfo.h"
+
+InventoryHandler::InventoryHandler()
+{
+ static const Uint16 _messages[] = {
+ GPMSG_INVENTORY_FULL,
+ GPMSG_INVENTORY,
+ 0
+ };
+ handledMessages = _messages;
+}
+
+void InventoryHandler::handleMessage(MessageIn &msg)
+{
+ switch (msg.getId())
+ {
+ case GPMSG_INVENTORY_FULL:
+ player_node->clearInventory();
+ // no break!
+
+ case GPMSG_INVENTORY:
+ while (msg.getUnreadLength())
+ {
+ int slot = msg.readInt8();
+ if (slot == 255)
+ {
+ player_node->setMoney(msg.readInt32());
+ continue;
+ }
+
+ int id = msg.readInt16();
+ if (slot < EQUIPMENT_SIZE)
+ {
+ player_node->mEquipment->setEquipment(slot, id);
+ }
+ else if (slot >= 32 && slot < 32 + INVENTORY_SIZE)
+ {
+ int amount = id ? msg.readInt8() : 0;
+ player_node->setInvItem(slot - 32, id, amount);
+ }
+ };
+ break;
+ }
+}
diff --git a/src/net/tmwserv/inventoryhandler.h b/src/net/tmwserv/inventoryhandler.h
new file mode 100644
index 00000000..b2e469fa
--- /dev/null
+++ b/src/net/tmwserv/inventoryhandler.h
@@ -0,0 +1,35 @@
+/*
+ * The Mana World
+ * Copyright (C) 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef NET_INVENTORYHANDLER_H
+#define NET_INVENTORYHANDLER_H
+
+#include "../messagehandler.h"
+
+class InventoryHandler : public MessageHandler
+{
+ public:
+ InventoryHandler();
+
+ void handleMessage(MessageIn &msg);
+};
+
+#endif
diff --git a/src/net/itemhandler.cpp b/src/net/tmwserv/itemhandler.cpp
index b7ac23a8..23d210cf 100644
--- a/src/net/itemhandler.cpp
+++ b/src/net/tmwserv/itemhandler.cpp
@@ -20,48 +20,45 @@
*/
#include "itemhandler.h"
-#include "messagein.h"
+#include "../messagein.h"
#include "protocol.h"
-#include "../engine.h"
-#include "../flooritemmanager.h"
+#include "../../engine.h"
+#include "../../flooritemmanager.h"
ItemHandler::ItemHandler()
{
static const Uint16 _messages[] = {
- SMSG_ITEM_VISIBLE,
- SMSG_ITEM_DROPPED,
- SMSG_ITEM_REMOVE,
+ GPMSG_ITEMS,
+ GPMSG_ITEM_APPEAR,
0
};
handledMessages = _messages;
}
-void ItemHandler::handleMessage(MessageIn *msg)
+void ItemHandler::handleMessage(MessageIn &msg)
{
- Uint32 id;
- Uint16 x, y;
- int 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
-
- floorItemManager->create(id, itemId, x, y, engine->getCurrentMap());
- break;
+ case GPMSG_ITEM_APPEAR:
+ case GPMSG_ITEMS:
+ {
+ while (msg.getUnreadLength())
+ {
+ int itemId = msg.readInt16();
+ int x = msg.readInt16();
+ int y = msg.readInt16();
+ int id = (x << 16) | y; // dummy id
- case SMSG_ITEM_REMOVE:
- FloorItem *item;
- item = floorItemManager->findById(msg->readInt32());
- if (item)
- floorItemManager->destroy(item);
- break;
+ if (itemId)
+ {
+ floorItemManager->create(id, itemId, x / 32, y / 32, engine->getCurrentMap());
+ }
+ else if (FloorItem *item = floorItemManager->findById(id))
+ {
+ floorItemManager->destroy(item);
+ }
+ }
+ } break;
}
}
diff --git a/src/net/itemhandler.h b/src/net/tmwserv/itemhandler.h
index 0cb3b42a..da93f6b4 100644
--- a/src/net/itemhandler.h
+++ b/src/net/tmwserv/itemhandler.h
@@ -22,14 +22,14 @@
#ifndef NET_ITEMHANDLER_H
#define NET_ITEMHANDLER_H
-#include "messagehandler.h"
+#include "../messagehandler.h"
class ItemHandler : public MessageHandler
{
public:
ItemHandler();
- void handleMessage(MessageIn *msg);
+ void handleMessage(MessageIn &msg);
};
#endif
diff --git a/src/net/tmwserv/loginhandler.cpp b/src/net/tmwserv/loginhandler.cpp
new file mode 100644
index 00000000..c49d6e47
--- /dev/null
+++ b/src/net/tmwserv/loginhandler.cpp
@@ -0,0 +1,225 @@
+/*
+ * 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
+ */
+
+#include "loginhandler.h"
+
+#include "../messagein.h"
+#include "protocol.h"
+
+#include "../../logindata.h"
+#include "../../main.h"
+
+LoginHandler::LoginHandler()
+{
+ static const Uint16 _messages[] = {
+ APMSG_LOGIN_RESPONSE,
+ APMSG_REGISTER_RESPONSE,
+ APMSG_RECONNECT_RESPONSE,
+ APMSG_PASSWORD_CHANGE_RESPONSE,
+ APMSG_EMAIL_CHANGE_RESPONSE,
+ 0
+ };
+ handledMessages = _messages;
+}
+
+void LoginHandler::setLoginData(LoginData *loginData)
+{
+ mLoginData = loginData;
+}
+
+void LoginHandler::handleMessage(MessageIn &msg)
+{
+ switch (msg.getId())
+ {
+ case APMSG_LOGIN_RESPONSE:
+ handleLoginResponse(msg);
+ break;
+ case APMSG_REGISTER_RESPONSE:
+ handleRegisterResponse(msg);
+ break;
+ case APMSG_RECONNECT_RESPONSE:
+ {
+ int errMsg = msg.readInt8();
+ // Successful login
+ if (errMsg == ERRMSG_OK)
+ {
+ state = STATE_CHAR_SELECT;
+ }
+ // Login failed
+ else
+ {
+ switch (errMsg) {
+ case ERRMSG_INVALID_ARGUMENT:
+ errorMessage = "Wrong magic_token";
+ 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 APMSG_PASSWORD_CHANGE_RESPONSE:
+ {
+ int errMsg = msg.readInt8();
+ // Successful pass change
+ if (errMsg == ERRMSG_OK)
+ {
+ state = STATE_CHANGEPASSWORD;
+ }
+ // pass change failed
+ else
+ {
+ switch (errMsg) {
+ case ERRMSG_INVALID_ARGUMENT:
+ errorMessage = "New password incorrect";
+ break;
+ case ERRMSG_FAILURE:
+ errorMessage = "Old password incorrect";
+ break;
+ case ERRMSG_NO_LOGIN:
+ errorMessage = "Account not connected. Please login first.";
+ break;
+ default:
+ errorMessage = "Unknown error";
+ break;
+ }
+ state = STATE_ACCOUNTCHANGE_ERROR;
+ }
+ }
+ break;
+
+ case APMSG_EMAIL_CHANGE_RESPONSE:
+ {
+ int errMsg = msg.readInt8();
+ // Successful pass change
+ if (errMsg == ERRMSG_OK)
+ {
+ state = STATE_CHANGEEMAIL;
+ }
+ // pass change failed
+ else
+ {
+ switch (errMsg) {
+ case ERRMSG_INVALID_ARGUMENT:
+ errorMessage = "New email address incorrect";
+ break;
+ case ERRMSG_FAILURE:
+ errorMessage = "Old email address incorrect";
+ break;
+ case ERRMSG_NO_LOGIN:
+ errorMessage = "Account not connected. Please login first.";
+ break;
+ case ERRMSG_EMAIL_ALREADY_EXISTS:
+ errorMessage = "The new Email Address already exists.";
+ break;
+ default:
+ errorMessage = "Unknown error";
+ break;
+ }
+ state = STATE_ACCOUNTCHANGE_ERROR;
+ }
+ }
+ break;
+
+ }
+}
+
+void LoginHandler::handleLoginResponse(MessageIn &msg)
+{
+ const int errMsg = msg.readInt8();
+
+ if (errMsg == ERRMSG_OK)
+ {
+ readUpdateHost(msg);
+ state = STATE_CHAR_SELECT;
+ }
+ else
+ {
+ switch (errMsg) {
+ case LOGIN_INVALID_VERSION:
+ errorMessage = "Client version is too old";
+ 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_LOGIN_ERROR;
+ }
+}
+
+void LoginHandler::handleRegisterResponse(MessageIn &msg)
+{
+ const int errMsg = msg.readInt8();
+
+ if (errMsg == ERRMSG_OK)
+ {
+ readUpdateHost(msg);
+ state = STATE_CHAR_SELECT;
+ }
+ else
+ {
+ switch (errMsg) {
+ case REGISTER_INVALID_VERSION:
+ errorMessage = "Client version is too old";
+ 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_LOGIN_ERROR;
+ }
+}
+
+void LoginHandler::readUpdateHost(MessageIn &msg)
+{
+ // Set the update host when included in the message
+ if (msg.getUnreadLength() > 0)
+ {
+ mLoginData->updateHost = msg.readString();
+ }
+}
diff --git a/src/net/tmwserv/loginhandler.h b/src/net/tmwserv/loginhandler.h
new file mode 100644
index 00000000..a7310407
--- /dev/null
+++ b/src/net/tmwserv/loginhandler.h
@@ -0,0 +1,47 @@
+/*
+ * The Mana World
+ * Copyright 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * The Mana World is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _TMW_NET_LOGINHANDLER_H
+#define _TMW_NET_LOGINHANDLER_H
+
+#include "../messagehandler.h"
+
+class LoginData;
+
+class LoginHandler : public MessageHandler
+{
+ public:
+ LoginHandler();
+
+ void setLoginData(LoginData *loginData);
+
+ void handleMessage(MessageIn &msg);
+
+ private:
+ void handleLoginResponse(MessageIn &msg);
+ void handleRegisterResponse(MessageIn &msg);
+
+ void readUpdateHost(MessageIn &msg);
+
+ LoginData *mLoginData;
+};
+
+#endif // _TMW_NET_LOGINHANDLER_H
diff --git a/src/net/tmwserv/logouthandler.cpp b/src/net/tmwserv/logouthandler.cpp
new file mode 100644
index 00000000..a7a1eb2e
--- /dev/null
+++ b/src/net/tmwserv/logouthandler.cpp
@@ -0,0 +1,215 @@
+/*
+ * 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
+ */
+
+#include "logouthandler.h"
+
+#include "../messagein.h"
+#include "protocol.h"
+
+#include "../../main.h"
+
+LogoutHandler::LogoutHandler():
+mPassToken(NULL), mScenario(LOGOUT_EXIT),
+mLoggedOutAccount(false), mLoggedOutGame(false), mLoggedOutChat(false)
+{
+ static const Uint16 _messages[] = {
+ APMSG_LOGOUT_RESPONSE,
+ APMSG_UNREGISTER_RESPONSE,
+ GPMSG_DISCONNECT_RESPONSE,
+ CPMSG_DISCONNECT_RESPONSE,
+ 0
+ };
+ handledMessages = _messages;
+}
+
+void LogoutHandler::handleMessage(MessageIn &msg)
+{
+ switch (msg.getId())
+ {
+ case APMSG_LOGOUT_RESPONSE:
+ {
+ int errMsg = msg.readInt8();
+
+ // Successful logout
+ if (errMsg == ERRMSG_OK)
+ {
+ mLoggedOutAccount = true;
+
+ switch (mScenario)
+ {
+ case LOGOUT_SWITCH_ACCOUNTSERVER:
+ if (mLoggedOutGame && mLoggedOutChat)
+ state = STATE_SWITCH_ACCOUNTSERVER;
+ break;
+
+ case LOGOUT_EXIT:
+ default:
+ if (mLoggedOutGame && mLoggedOutChat)
+ state = STATE_FORCE_QUIT;
+ break;
+ }
+ }
+ // Logout failed
+ else
+ {
+ switch (errMsg) {
+ case ERRMSG_NO_LOGIN:
+ errorMessage = "Accountserver: Not logged in";
+ break;
+ default:
+ errorMessage = "Accountserver: Unknown error";
+ break;
+ }
+ state = STATE_ERROR;
+ }
+ }
+ break;
+ case APMSG_UNREGISTER_RESPONSE:
+ {
+ int errMsg = msg.readInt8();
+ // Successful unregistration
+ if (errMsg == ERRMSG_OK)
+ {
+ state = STATE_UNREGISTER;
+ }
+ // Unregistration failed
+ else
+ {
+ switch (errMsg) {
+ case ERRMSG_INVALID_ARGUMENT:
+ errorMessage =
+ "Accountserver: Wrong username or password";
+ break;
+ default:
+ errorMessage = "Accountserver: Unknown error";
+ break;
+ }
+ state = STATE_ACCOUNTCHANGE_ERROR;
+ }
+ }
+ break;
+ case GPMSG_DISCONNECT_RESPONSE:
+ {
+ int errMsg = msg.readInt8();
+ // Successful logout
+ if (errMsg == ERRMSG_OK)
+ {
+ mLoggedOutGame = true;
+
+ switch (mScenario)
+ {
+ case LOGOUT_SWITCH_CHARACTER:
+ if (mPassToken)
+ {
+ *mPassToken = msg.readString(32);
+ mPassToken = NULL;
+ }
+ if (mLoggedOutChat) state = STATE_RECONNECT_ACCOUNT;
+ break;
+
+ case LOGOUT_SWITCH_ACCOUNTSERVER:
+ if (mLoggedOutAccount && mLoggedOutChat)
+ state = STATE_SWITCH_ACCOUNTSERVER;
+ break;
+
+ case LOGOUT_EXIT:
+ default:
+ if (mLoggedOutAccount && mLoggedOutChat)
+ state = STATE_FORCE_QUIT;
+ break;
+ }
+ }
+ // Logout failed
+ else
+ {
+ switch (errMsg) {
+ case ERRMSG_NO_LOGIN:
+ errorMessage = "Gameserver: Not logged in";
+ break;
+ default:
+ errorMessage = "Gameserver: Unknown error";
+ break;
+ }
+ state = STATE_ERROR;
+ }
+ }
+ break;
+ case CPMSG_DISCONNECT_RESPONSE:
+ {
+ int errMsg = msg.readInt8();
+ // Successful logout
+ if (errMsg == ERRMSG_OK)
+ {
+ mLoggedOutChat = true;
+
+ switch (mScenario)
+ {
+ case LOGOUT_SWITCH_CHARACTER:
+ if (mLoggedOutGame) state = STATE_RECONNECT_ACCOUNT;
+ break;
+
+ case LOGOUT_SWITCH_ACCOUNTSERVER:
+ if (mLoggedOutAccount && mLoggedOutGame)
+ state = STATE_SWITCH_ACCOUNTSERVER;
+ break;
+
+ case LOGOUT_EXIT:
+ default:
+ if (mLoggedOutAccount && mLoggedOutGame)
+ {
+ state = STATE_FORCE_QUIT;
+ }
+ break;
+ }
+ }
+ else
+ {
+ switch (errMsg) {
+ case ERRMSG_NO_LOGIN:
+ errorMessage = "Chatserver: Not logged in";
+ break;
+ default:
+ errorMessage = "Chatserver: Unknown error";
+ break;
+ }
+ state = STATE_ERROR;
+ }
+ }
+ break;
+ }
+}
+
+void
+LogoutHandler::setScenario(unsigned short scenario, std::string* passToken)
+{
+ mScenario = scenario;
+ mPassToken = passToken;
+}
+
+void
+LogoutHandler::reset()
+{
+ mPassToken = NULL;
+ mScenario = LOGOUT_EXIT;
+ mLoggedOutAccount = false;
+ mLoggedOutGame = false;
+ mLoggedOutChat = false;
+}
diff --git a/src/net/tmwserv/logouthandler.h b/src/net/tmwserv/logouthandler.h
new file mode 100644
index 00000000..3b4f9738
--- /dev/null
+++ b/src/net/tmwserv/logouthandler.h
@@ -0,0 +1,62 @@
+/*
+ * The Mana World
+ * Copyright 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * The Mana World is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _TMW_NET_LOGOUTHANDLER_H
+#define _TMW_NET_LOGOUTHANDLER_H
+
+#include <string>
+
+#include "../messagehandler.h"
+
+/**
+ * The different scenarios for which LogoutHandler can be used
+ */
+enum {
+ LOGOUT_EXIT,
+ LOGOUT_SWITCH_ACCOUNTSERVER,
+ LOGOUT_SWITCH_CHARACTER
+};
+
+class LogoutHandler : public MessageHandler
+{
+ public:
+ LogoutHandler();
+
+ void handleMessage(MessageIn &msg);
+
+ void setScenario(unsigned short scenario,
+ std::string* passToken = NULL);
+
+ void reset();
+
+ void setAccountLoggedOut(){ mLoggedOutAccount = true; }
+ void setGameLoggedOut(){ mLoggedOutGame = true; }
+ void setChatLoggedOut(){ mLoggedOutChat = true; }
+
+ private:
+ std::string* mPassToken;
+ unsigned short mScenario;
+ bool mLoggedOutAccount;
+ bool mLoggedOutGame;
+ bool mLoggedOutChat;
+};
+
+#endif
diff --git a/src/net/tmwserv/network.cpp b/src/net/tmwserv/network.cpp
new file mode 100644
index 00000000..d3bc88fa
--- /dev/null
+++ b/src/net/tmwserv/network.cpp
@@ -0,0 +1,169 @@
+/*
+ * 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
+ */
+
+#include "network.h"
+
+#include <enet/enet.h>
+
+#include <map>
+
+#include "connection.h"
+#include "internal.h"
+#include "../messagehandler.h"
+#include "../messagein.h"
+
+#include "../../log.h"
+
+/**
+ * The local host which is shared for all outgoing connections.
+ */
+namespace {
+ ENetHost *client;
+}
+
+typedef std::map<unsigned short, MessageHandler*> MessageHandlers;
+typedef MessageHandlers::iterator MessageHandlerIterator;
+static MessageHandlers mMessageHandlers;
+
+void Net::initialize()
+{
+ if (enet_initialize())
+ {
+ logger->error("Failed to initialize ENet.");
+ }
+
+ client = enet_host_create(NULL, 3, 0, 0);
+
+ if (!client)
+ {
+ logger->error("Failed to create the local host.");
+ }
+}
+
+void Net::finalize()
+{
+ if (!client)
+ return; // Wasn't initialized at all
+
+ if (Net::connections) {
+ logger->error("Tried to shutdown the network subsystem while there "
+ "are network connections left!");
+ }
+
+ clearHandlers();
+ enet_deinitialize();
+}
+
+Net::Connection *Net::getConnection()
+{
+ if (!client)
+ {
+ logger->error("Tried to instantiate a network object before "
+ "initializing the network subsystem!");
+ }
+
+ return new Net::Connection(client);
+}
+
+void Net::registerHandler(MessageHandler *handler)
+{
+ for (const Uint16 *i = handler->handledMessages; *i; i++)
+ {
+ mMessageHandlers[*i] = handler;
+ }
+}
+
+void Net::unregisterHandler(MessageHandler *handler)
+{
+ for (const Uint16 *i = handler->handledMessages; *i; i++)
+ {
+ mMessageHandlers.erase(*i);
+ }
+}
+
+void Net::clearHandlers()
+{
+ mMessageHandlers.clear();
+}
+
+
+/**
+ * Dispatches a message to the appropriate message handler and
+ * destroys it afterwards.
+ */
+namespace
+{
+ 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 Net::flush()
+{
+ ENetEvent event;
+
+ // Wait up to 10 milliseconds for an event.
+ while (enet_host_service(client, &event, 10) > 0)
+ {
+ switch (event.type)
+ {
+ case ENET_EVENT_TYPE_CONNECT:
+ logger->log("Connected to port %d.", event.peer->address.port);
+ // Store any relevant server information here.
+ event.peer->data = 0;
+ break;
+
+ case ENET_EVENT_TYPE_RECEIVE:
+ dispatchMessage(event.packet);
+ break;
+
+ case ENET_EVENT_TYPE_DISCONNECT:
+ logger->log("Disconnected.");
+ // Reset the server information.
+ event.peer->data = 0;
+ break;
+
+ case ENET_EVENT_TYPE_NONE:
+ logger->log("No event during 10 milliseconds.");
+ break;
+
+ default:
+ logger->log("Unhandled enet event.");
+ break;
+ }
+ }
+}
diff --git a/src/net/tmwserv/network.h b/src/net/tmwserv/network.h
new file mode 100644
index 00000000..13576e79
--- /dev/null
+++ b/src/net/tmwserv/network.h
@@ -0,0 +1,79 @@
+/*
+ * The Mana World
+ * Copyright 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * The Mana World is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _TMW_NET_NETWORK_H
+#define _TMW_NET_NETWORK_H
+
+#include <iosfwd>
+
+/**
+ * \defgroup Network Core network layer
+ */
+
+class MessageHandler;
+class MessageOut;
+
+/**
+ * \ingroup Network
+ */
+namespace Net
+{
+ class Connection;
+
+ /**
+ * Initializes the network subsystem.
+ */
+ void initialize();
+
+ /**
+ * Finalizes the network subsystem.
+ */
+ void finalize();
+
+ /**
+ * Returns a new Connection object. Should be deleted by the caller.
+ */
+ 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/tmwserv/npchandler.cpp b/src/net/tmwserv/npchandler.cpp
new file mode 100644
index 00000000..b3e36749
--- /dev/null
+++ b/src/net/tmwserv/npchandler.cpp
@@ -0,0 +1,86 @@
+/*
+ * 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
+ */
+
+#include "npchandler.h"
+
+#include "../messagein.h"
+#include "protocol.h"
+
+#include "../../beingmanager.h"
+#include "../../npc.h"
+
+#include "../../gui/npclistdialog.h"
+#include "../../gui/npcpostdialog.h"
+#include "../../gui/npc_text.h"
+
+extern NpcListDialog *npcListDialog;
+extern NpcTextDialog *npcTextDialog;
+extern NpcPostDialog *npcPostDialog;
+
+NPCHandler::NPCHandler()
+{
+ static const Uint16 _messages[] = {
+ GPMSG_NPC_CHOICE,
+ GPMSG_NPC_POST,
+ GPMSG_NPC_MESSAGE,
+ GPMSG_NPC_ERROR,
+ 0
+ };
+ handledMessages = _messages;
+}
+
+void NPCHandler::handleMessage(MessageIn &msg)
+{
+ Being *being = beingManager->findBeing(msg.readInt16());
+ if (!being || being->getType() != Being::NPC)
+ {
+ return;
+ }
+
+ current_npc = being->getId();
+
+ switch (msg.getId())
+ {
+ case GPMSG_NPC_CHOICE:
+ npcListDialog->reset();
+ while (msg.getUnreadLength())
+ {
+ npcListDialog->addItem(msg.readString());
+ }
+ npcListDialog->setVisible(true);
+ break;
+
+ case GPMSG_NPC_POST:
+ npcTextDialog->setVisible(false);
+ npcPostDialog->clear();
+ npcPostDialog->setVisible(true);
+ break;
+
+ case GPMSG_NPC_ERROR:
+ current_npc = NULL;
+ case GPMSG_NPC_MESSAGE:
+ npcTextDialog->addText(msg.readString(msg.getUnreadLength()));
+ npcListDialog->setVisible(false);
+ npcTextDialog->setVisible(true);
+ npcPostDialog->setVisible(false);
+ break;
+ }
+}
diff --git a/src/net/tmwserv/npchandler.h b/src/net/tmwserv/npchandler.h
new file mode 100644
index 00000000..49df20c3
--- /dev/null
+++ b/src/net/tmwserv/npchandler.h
@@ -0,0 +1,35 @@
+/*
+ * The Mana World
+ * Copyright (C) 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef NET_NPCHANDLER_H
+#define NET_NPCHANDLER_H
+
+#include "../messagehandler.h"
+
+class NPCHandler : public MessageHandler
+{
+ public:
+ NPCHandler();
+
+ void handleMessage(MessageIn &msg);
+};
+
+#endif
diff --git a/src/net/tmwserv/partyhandler.cpp b/src/net/tmwserv/partyhandler.cpp
new file mode 100644
index 00000000..eb331bac
--- /dev/null
+++ b/src/net/tmwserv/partyhandler.cpp
@@ -0,0 +1,103 @@
+/*
+ * The Mana World
+ * Copyright 2008 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
+ */
+
+#include <iostream>
+#include "partyhandler.h"
+
+#include "protocol.h"
+#include "../messagein.h"
+
+#include "chatserver/chatserver.h"
+
+#include "../../gui/chat.h"
+#include "../../gui/partywindow.h"
+#include "../../log.h"
+#include "../../localplayer.h"
+
+PartyHandler::PartyHandler()
+{
+ static const Uint16 _messages[] = {
+ CPMSG_PARTY_INVITE_RESPONSE,
+ CPMSG_PARTY_INVITED,
+ CPMSG_PARTY_ACCEPT_INVITE_RESPONSE,
+ CPMSG_PARTY_QUIT_RESPONSE,
+ CPMSG_PARTY_NEW_MEMBER,
+ CPMSG_PARTY_MEMBER_LEFT,
+ 0
+ };
+ handledMessages = _messages;
+
+}
+
+void PartyHandler::handleMessage(MessageIn &msg)
+{
+ switch (msg.getId())
+ {
+ case CPMSG_PARTY_INVITE_RESPONSE:
+ {
+ if (msg.readInt8() == ERRMSG_OK)
+ {
+
+ }
+ } break;
+
+ case CPMSG_PARTY_INVITED:
+ {
+ std::string inviter = msg.readString();
+ partyWindow->showPartyInvite(inviter);
+ } break;
+
+ case CPMSG_PARTY_ACCEPT_INVITE_RESPONSE:
+ {
+ if (msg.readInt8() == ERRMSG_OK)
+ {
+ player_node->setInParty(true);
+ chatWindow->chatLog("Joined party");
+ }
+ }
+
+ case CPMSG_PARTY_QUIT_RESPONSE:
+ {
+ if (msg.readInt8() == ERRMSG_OK)
+ {
+ player_node->setInParty(false);
+ }
+ } break;
+
+ case CPMSG_PARTY_NEW_MEMBER:
+ {
+ msg.readInt16(); // being id
+ std::string name = msg.readString();
+
+ chatWindow->chatLog(name + " joined the party");
+
+ if (!player_node->getInParty())
+ player_node->setInParty(true);
+
+ partyWindow->addPartyMember(name);
+ } break;
+
+ case CPMSG_PARTY_MEMBER_LEFT:
+ {
+ partyWindow->removePartyMember(msg.readString());
+ } break;
+ }
+}
diff --git a/src/net/tmwserv/partyhandler.h b/src/net/tmwserv/partyhandler.h
new file mode 100644
index 00000000..c1ec6eda
--- /dev/null
+++ b/src/net/tmwserv/partyhandler.h
@@ -0,0 +1,41 @@
+/*
+ * The Mana World
+ * Copyright 2008 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
+ */
+
+#ifndef _TMW_NET_PARTYHANDLER_H
+#define _TMW_NET_PARTYHANDLER_H
+
+#include "../messagehandler.h"
+
+#include <string>
+
+class PartyHandler : public MessageHandler
+{
+public:
+ PartyHandler();
+
+ void handleMessage(MessageIn &msg);
+
+protected:
+
+};
+
+#endif
+
diff --git a/src/net/tmwserv/playerhandler.cpp b/src/net/tmwserv/playerhandler.cpp
new file mode 100644
index 00000000..f4cc4b23
--- /dev/null
+++ b/src/net/tmwserv/playerhandler.cpp
@@ -0,0 +1,329 @@
+/*
+ * 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
+ */
+
+#include "playerhandler.h"
+
+#include "../messagein.h"
+#include "protocol.h"
+
+#include "../../engine.h"
+#include "../../localplayer.h"
+#include "../../log.h"
+#include "../../particle.h"
+#include "../../npc.h"
+
+#include "../../gui/buy.h"
+#include "../../gui/chat.h"
+#include "../../gui/gui.h"
+#include "../../gui/npclistdialog.h"
+#include "../../gui/npc_text.h"
+#include "../../gui/ok_dialog.h"
+#include "../../gui/sell.h"
+#include "../../gui/skill.h"
+#include "../../gui/viewport.h"
+
+// TODO Move somewhere else
+OkDialog *weightNotice = NULL;
+OkDialog *deathNotice = NULL;
+
+extern NpcListDialog *npcListDialog;
+extern NpcTextDialog *npcTextDialog;
+extern BuyDialog *buyDialog;
+extern SellDialog *sellDialog;
+extern Window *buySellDialog;
+
+/* Max. distance we are willing to scroll after a teleport;
+ * everything beyond will reset the port hard.
+ */
+static const int MAP_TELEPORT_SCROLL_DISTANCE = 8 * 32;
+
+/**
+ * Listener used for handling the overweigth message.
+ */
+// TODO Move somewhere else
+namespace {
+ struct WeightListener : public gcn::ActionListener
+ {
+ void action(const gcn::ActionEvent &event)
+ {
+ weightNotice = NULL;
+ }
+ } weightListener;
+}
+
+/**
+ * Listener used for handling death message.
+ */
+// TODO Move somewhere else
+namespace {
+ struct DeathListener : public gcn::ActionListener
+ {
+ void action(const gcn::ActionEvent &event)
+ {
+ player_node->revive();
+ deathNotice = NULL;
+ npcListDialog->setVisible(false);
+ npcTextDialog->setVisible(false);
+ buyDialog->setVisible(false);
+ sellDialog->setVisible(false);
+#ifdef EATHENA_SUPPORT
+ buySellDialog->setVisible(false);
+#endif
+ current_npc = 0;
+ }
+ } deathListener;
+}
+
+PlayerHandler::PlayerHandler()
+{
+ static const Uint16 _messages[] = {
+ GPMSG_PLAYER_MAP_CHANGE,
+ GPMSG_PLAYER_SERVER_CHANGE,
+ GPMSG_PLAYER_ATTRIBUTE_CHANGE,
+ GPMSG_PLAYER_EXP_CHANGE,
+ GPMSG_LEVELUP,
+ GPMSG_LEVEL_PROGRESS,
+ GPMSG_RAISE_ATTRIBUTE_RESPONSE,
+ GPMSG_LOWER_ATTRIBUTE_RESPONSE,
+ 0
+ };
+ handledMessages = _messages;
+}
+
+void PlayerHandler::handleMessage(MessageIn &msg)
+{
+ switch (msg.getId())
+ {
+ case GPMSG_PLAYER_MAP_CHANGE:
+ handleMapChangeMessage(msg);
+ break;
+
+ case GPMSG_PLAYER_SERVER_CHANGE:
+ { // TODO: Implement reconnecting to another game server
+ std::string token = msg.readString(32);
+ std::string address = msg.readString();
+ int port = msg.readInt16();
+ logger->log("Changing server to %s:%d", address.c_str(), port);
+ } break;
+
+ case GPMSG_PLAYER_ATTRIBUTE_CHANGE:
+ {
+ logger->log("ATTRIBUTE UPDATE:");
+ while (msg.getUnreadLength())
+ {
+ int stat = msg.readInt8();
+ int base = msg.readInt16();
+ int value = msg.readInt16();
+ logger->log("%d set to %d %d", stat, base, value);
+
+ if (stat == BASE_ATTR_HP)
+ {
+ player_node->setMaxHp(base);
+ player_node->setHp(value);
+ }
+ else if (stat < NB_CHARACTER_ATTRIBUTES)
+ {
+ if (stat >= CHAR_SKILL_BEGIN && stat < CHAR_SKILL_END
+ && player_node->getAttributeBase(stat) < base
+ && player_node->getAttributeBase(stat) > -1)
+ {
+ Particle* effect = particleEngine->addEffect("graphics/particles/skillup.particle.xml", 0, 0);
+ player_node->controlParticle(effect);
+ }
+
+ player_node->setAttributeBase(stat, base);
+ player_node->setAttributeEffective(stat, value);
+ }
+ else
+ {
+ logger->log("Warning: server wants to update unknown "
+ "attribute %d to %d", stat, value);
+ }
+ }
+ } break;
+
+ case GPMSG_PLAYER_EXP_CHANGE:
+ {
+ logger->log("EXP Update");
+ while (msg.getUnreadLength())
+ {
+ int skill = msg.readInt8();
+ int current = msg.readInt32();
+ int next = msg.readInt32();
+
+ if (skill < CHAR_SKILL_NB)
+ {
+ player_node->setExperience(skill, current, next);
+ }
+ else
+ {
+ logger->log("Warning: server wants to update experience of unknown "
+ "skill %d to %d / %d", skill, current, next);
+ }
+ }
+ } break;
+
+ case GPMSG_LEVELUP:
+ {
+ player_node->setLevel(msg.readInt16());
+ player_node->setCharacterPoints(msg.readInt16());
+ player_node->setCorrectionPoints(msg.readInt16());
+ Particle* effect = particleEngine->addEffect("graphics/particles/levelup.particle.xml", 0, 0);
+ player_node->controlParticle(effect);
+ } break;
+
+
+ case GPMSG_LEVEL_PROGRESS:
+ {
+ logger->log("Level Progress Update");
+ player_node->setLevelProgress(msg.readInt8());
+ } break;
+
+
+ case GPMSG_RAISE_ATTRIBUTE_RESPONSE:
+ {
+ int errCode = msg.readInt8();
+ int attrNum = msg.readInt8() - CHAR_ATTR_BEGIN;
+ switch (errCode)
+ {
+ case ATTRIBMOD_OK:
+ {
+ // feel(acknowledgment);
+ } break;
+ case ATTRIBMOD_INVALID_ATTRIBUTE:
+ {
+ logger->log("Warning: Server denied increase of attribute %d (unknown attribute) ", attrNum);
+ } break;
+ case ATTRIBMOD_NO_POINTS_LEFT:
+ {
+ // when the server says "you got no points" it
+ // has to be correct. The server is always right!
+ // undo attribute change and set points to 0
+ logger->log("Warning: Server denied increase of attribute %d (no points left) ", attrNum);
+ int attrValue = player_node->getAttributeBase(attrNum) - 1;
+ player_node->setCharacterPoints(0);
+ player_node->setAttributeBase(attrNum, attrValue);
+ } break;
+ case ATTRIBMOD_DENIED:
+ {
+ // undo attribute change
+ logger->log("Warning: Server denied increase of attribute %d (reason unknown) ", attrNum);
+ int points = player_node->getCharacterPoints() - 1;
+ player_node->setCharacterPoints(points);
+ int attrValue = player_node->getAttributeBase(attrNum) - 1;
+ player_node->setAttributeBase(attrNum, attrValue);
+ } break;
+ }
+ } break;
+
+ case GPMSG_LOWER_ATTRIBUTE_RESPONSE:
+ {
+ int errCode = msg.readInt8();
+ int attrNum = msg.readInt8() - CHAR_ATTR_BEGIN;
+ switch (errCode)
+ {
+ case ATTRIBMOD_OK:
+ {
+ // feel(acknowledgment);
+ } break;
+ case ATTRIBMOD_INVALID_ATTRIBUTE:
+ {
+ logger->log("Warning: Server denied reduction of attribute %d (unknown attribute) ", attrNum);
+ } break;
+ case ATTRIBMOD_NO_POINTS_LEFT:
+ {
+ // when the server says "you got no points" it
+ // has to be correct. The server is always right!
+ // undo attribute change and set points to 0
+ logger->log("Warning: Server denied reduction of attribute %d (no points left) ", attrNum);
+ int attrValue = player_node->getAttributeBase(attrNum) + 1;
+ player_node->setCorrectionPoints(0);
+ player_node->setAttributeBase(attrNum, attrValue);
+ break;
+ } break;
+ case ATTRIBMOD_DENIED:
+ {
+ // undo attribute change
+ logger->log("Warning: Server denied reduction of attribute %d (reason unknown) ", attrNum);
+ int charaPoints = player_node->getCharacterPoints() - 1;
+ player_node->setCharacterPoints(charaPoints);
+ int correctPoints = player_node->getCorrectionPoints() + 1;
+ player_node->setCorrectionPoints(correctPoints);
+ int attrValue = player_node->getAttributeBase(attrNum) + 1;
+ player_node->setAttributeBase(attrNum, attrValue);
+ } break;
+ }
+
+ } break;
+ /*
+ case SMSG_PLAYER_ARROW_MESSAGE:
+ {
+ Sint16 type = msg.readInt16();
+
+ switch (type) {
+ case 0:
+ chatWindow->chatLog("Equip arrows first",
+ BY_SERVER);
+ break;
+ default:
+ logger->log("0x013b: Unhandled message %i", type);
+ break;
+ }
+ }
+ break;
+ */
+ }
+}
+
+void
+PlayerHandler::handleMapChangeMessage(MessageIn &msg)
+{
+ const std::string mapName = msg.readString();
+ const unsigned short x = msg.readInt16();
+ const unsigned short y = msg.readInt16();
+ const bool nearby = (engine->getCurrentMapName() == mapName);
+
+ logger->log("Changing map to %s (%d, %d)", mapName.c_str(), x, y);
+
+ // Switch the actual map, deleting the previous one
+ engine->changeMap(mapName);
+
+ current_npc = 0;
+
+ const Vector &playerPos = player_node->getPosition();
+ float scrollOffsetX = 0.0f;
+ float scrollOffsetY = 0.0f;
+
+ /* Scroll if neccessary */
+ if (!nearby
+ || (abs(x - (int) playerPos.x) > MAP_TELEPORT_SCROLL_DISTANCE)
+ || (abs(y - (int) playerPos.y) > MAP_TELEPORT_SCROLL_DISTANCE)) {
+ scrollOffsetX = x - (int) playerPos.x;
+ scrollOffsetY = y - (int) playerPos.y;
+ }
+
+ player_node->setAction(Being::STAND);
+ player_node->setPosition(x, y);
+
+ logger->log("Adjust scrolling by %d,%d", (int) scrollOffsetX,
+ (int) scrollOffsetY);
+ viewport->scrollBy(scrollOffsetX, scrollOffsetY);
+}
diff --git a/src/net/tmwserv/playerhandler.h b/src/net/tmwserv/playerhandler.h
new file mode 100644
index 00000000..a11109c6
--- /dev/null
+++ b/src/net/tmwserv/playerhandler.h
@@ -0,0 +1,38 @@
+/*
+ * The Mana World
+ * Copyright (C) 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef NET_PLAYERHANDLER_H
+#define NET_PLAYERHANDLER_H
+
+#include "../messagehandler.h"
+
+class PlayerHandler : public MessageHandler
+{
+ public:
+ PlayerHandler();
+
+ void handleMessage(MessageIn &msg);
+
+ private:
+ void handleMapChangeMessage(MessageIn &msg);
+};
+
+#endif
diff --git a/src/net/tmwserv/protocol.h b/src/net/tmwserv/protocol.h
new file mode 100644
index 00000000..73dd65e0
--- /dev/null
+++ b/src/net/tmwserv/protocol.h
@@ -0,0 +1,295 @@
+/*
+ * 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
+ */
+
+#ifndef _TMW_PROTOCOL_
+#define _TMW_PROTOCOL_
+
+/**
+ * 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)
+ *
+ * Hosts: P (player's client), A (account server), C (char server),
+ * G (game server)
+ */
+enum {
+ // Login/Register
+ PAMSG_REGISTER = 0x0000, // L version, S username, S password, S email
+ APMSG_REGISTER_RESPONSE = 0x0002, // B error [, S updatehost]
+ PAMSG_UNREGISTER = 0x0003, // -
+ APMSG_UNREGISTER_RESPONSE = 0x0004, // B error
+ PAMSG_LOGIN = 0x0010, // L version, S username, S password
+ APMSG_LOGIN_RESPONSE = 0x0012, // B error [, S updatehost]
+ 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, W level, W character points, W correction points, D money, W*6 stats
+ PAMSG_CHAR_SELECT = 0x0026, // B index
+ APMSG_CHAR_SELECT_RESPONSE = 0x0027, // B error, B*32 token, S game address, W game port, S chat address, W chat port
+ PAMSG_EMAIL_CHANGE = 0x0030, // S email
+ APMSG_EMAIL_CHANGE_RESPONSE = 0x0031, // B error
+ PAMSG_PASSWORD_CHANGE = 0x0034, // S old password, S new password
+ APMSG_PASSWORD_CHANGE_RESPONSE = 0x0035, // B error
+
+ PGMSG_CONNECT = 0x0050, // B*32 token
+ GPMSG_CONNECT_RESPONSE = 0x0051, // B error
+ PCMSG_CONNECT = 0x0053, // B*32 token
+ CPMSG_CONNECT_RESPONSE = 0x0054, // B error
+
+ PGMSG_DISCONNECT = 0x0060, // B reconnect account
+ GPMSG_DISCONNECT_RESPONSE = 0x0061, // B error, B*32 token
+ PCMSG_DISCONNECT = 0x0063, // -
+ CPMSG_DISCONNECT_RESPONSE = 0x0064, // B error
+
+ PAMSG_RECONNECT = 0x0065, // B*32 token
+ APMSG_RECONNECT_RESPONSE = 0x0066, // B error
+
+ // Game
+ GPMSG_PLAYER_MAP_CHANGE = 0x0100, // S filename, W x, W y
+ GPMSG_PLAYER_SERVER_CHANGE = 0x0101, // B*32 token, S game address, W game port
+ PGMSG_PICKUP = 0x0110, // W*2 position
+ PGMSG_DROP = 0x0111, // B slot, B amount
+ PGMSG_EQUIP = 0x0112, // B slot
+ PGMSG_UNEQUIP = 0x0113, // B slot
+ PGMSG_MOVE_ITEM = 0x0114, // B slot1, B slot2, B amount
+ GPMSG_INVENTORY = 0x0120, // { B slot, W item id [, B amount] }*
+ GPMSG_INVENTORY_FULL = 0x0121, // { B slot, W item id [, B amount] }*
+ GPMSG_PLAYER_ATTRIBUTE_CHANGE = 0x0130, // { B attribute, W base value, W modified value }*
+ GPMSG_PLAYER_EXP_CHANGE = 0x0140, // { B skill, D exp got, D exp needed }*
+ GPMSG_LEVELUP = 0x0150, // W new level
+ GPMSG_LEVEL_PROGRESS = 0x0151, // B percent completed to next levelup
+ PGMSG_RAISE_ATTRIBUTE = 0x0160, // B attribute
+ GPMSG_RAISE_ATTRIBUTE_RESPONSE = 0x0161, // B error, B attribute
+ PGMSG_LOWER_ATTRIBUTE = 0x0170, // B attribute
+ GPMSG_LOWER_ATTRIBUTE_RESPONSE = 0x0171, // B error, B attribute
+ PGMSG_RESPAWN = 0x0180, // -
+ GPMSG_BEING_ENTER = 0x0200, // B type, W being id, B action, W*2 position
+ // player: S name, B hair style, B hair color, B gender, B item bitmask, { W item id }*
+ // monster: W type id
+ // npc: W type id
+ GPMSG_BEING_LEAVE = 0x0201, // W being id
+ GPMSG_ITEM_APPEAR = 0x0202, // W item id, W*2 position
+ GPMSG_BEING_LOOKS_CHANGE = 0x0210, // W weapon, W hat, W top clothes, W bottom clothes
+ PGMSG_WALK = 0x0260, // W*2 destination
+ PGMSG_ACTION_CHANGE = 0x0270, // B Action
+ GPMSG_BEING_ACTION_CHANGE = 0x0271, // W being id, B action
+ PGMSG_DIRECTION_CHANGE = 0x0272, // B Direction
+ GPMSG_BEING_DIR_CHANGE = 0x0273, // W being id, B direction
+ GPMSG_BEINGS_MOVE = 0x0280, // { W being id, B flags [, C position, B speed] [, W*2 destination] }*
+ GPMSG_ITEMS = 0x0281, // { W item id, W*2 position }*
+ PGMSG_ATTACK = 0x0290, // B direction
+ PGMSG_USE_SPECIAL = 0x0292, // B specialID
+ GPMSG_BEING_ATTACK = 0x0291, // W being id
+ PGMSG_SAY = 0x02A0, // S text
+ GPMSG_SAY = 0x02A1, // W being id, S text
+ GPMSG_NPC_CHOICE = 0x02B0, // W being id, { S text }*
+ GPMSG_NPC_MESSAGE = 0x02B1, // W being id, B* text
+ PGMSG_NPC_TALK = 0x02B2, // W being id
+ PGMSG_NPC_TALK_NEXT = 0x02B3, // W being id
+ PGMSG_NPC_SELECT = 0x02B4, // W being id, B choice
+ GPMSG_NPC_BUY = 0x02B5, // W being id, { W item id, W amount, W cost }*
+ GPMSG_NPC_SELL = 0x02B6, // W being id, { W item id, W amount, W cost }*
+ PGMSG_NPC_BUYSELL = 0x02B7, // W item id, W amount
+ GPMSG_NPC_ERROR = 0x02B8, // B error
+ GPMSG_NPC_POST = 0x02D0, // W being id
+ PGMSG_NPC_POST_SEND = 0x02D1, // S name, S text, W item id
+ GPMSG_NPC_POST_GET = 0x02D2, // W being id, { S name, S text, W item id }
+ PGMSG_TRADE_REQUEST = 0x02C0, // W being id
+ GPMSG_TRADE_REQUEST = 0x02C1, // W being id
+ GPMSG_TRADE_START = 0x02C2, // -
+ GPMSG_TRADE_COMPLETE = 0x02C3, // -
+ PGMSG_TRADE_CANCEL = 0x02C4, // -
+ GPMSG_TRADE_CANCEL = 0x02C5, // -
+ PGMSG_TRADE_ACCEPT = 0x02C6, // -
+ GPMSG_TRADE_ACCEPT = 0x02C7, // -
+ PGMSG_TRADE_ADD_ITEM = 0x02C8, // B slot, B amount
+ GPMSG_TRADE_ADD_ITEM = 0x02C9, // W item id, B amount
+ PGMSG_TRADE_SET_MONEY = 0x02CA, // L amount
+ GPMSG_TRADE_SET_MONEY = 0x02CB, // L amount
+ PGMSG_USE_ITEM = 0x0300, // B slot
+ GPMSG_USE_RESPONSE = 0x0301, // B error
+ GPMSG_BEINGS_DAMAGE = 0x0310, // { W being id, W amount }*
+ GPMSG_CREATE_EFFECT = 0x0320, // W effect id, W*2 position
+
+ // Guild
+ PCMSG_GUILD_CREATE = 0x0350, // S name
+ CPMSG_GUILD_CREATE_RESPONSE = 0x0351, // B error, W guild, B rights, W channel
+ PCMSG_GUILD_INVITE = 0x0352, // W id, S name
+ CPMSG_GUILD_INVITE_RESPONSE = 0x0353, // B error
+ PCMSG_GUILD_ACCEPT = 0x0354, // W id
+ CPMSG_GUILD_ACCEPT_RESPONSE = 0x0355, // B error, W guild, B rights, W channel
+ PCMSG_GUILD_GET_MEMBERS = 0x0356, // W id
+ CPMSG_GUILD_GET_MEMBERS_RESPONSE = 0x0357, // S names, B online
+ CPMSG_GUILD_UPDATE_LIST = 0x0358, // W id, S name, B event
+ PCMSG_GUILD_QUIT = 0x0360, // W id
+ CPMSG_GUILD_QUIT_RESPONSE = 0x0361, // B error
+ PCMSG_GUILD_PROMOTE_MEMBER = 0x0365, // W guild, S name, B rights
+ CPMSG_GUILD_PROMOTE_MEMBER_RESPONSE = 0x0366, // B error
+
+ CPMSG_GUILD_INVITED = 0x0370, // S char name, S guild name, W id
+ CPMSG_GUILD_REJOIN = 0x0371, // S name, W guild, W rights, W channel, S announce
+
+ // Party
+ PCMSG_PARTY_INVITE = 0x03A0, // S name
+ CPMSG_PARTY_INVITE_RESPONSE = 0x03A1, // B error
+ CPMSG_PARTY_INVITED = 0x03A2, // S name
+ PCMSG_PARTY_ACCEPT_INVITE = 0x03A5, // S name
+ CPMSG_PARTY_ACCEPT_INVITE_RESPONSE = 0x03A6, // B error, { S name }
+ PCMSG_PARTY_QUIT = 0x03AA, // -
+ CPMSG_PARTY_QUIT_RESPONSE = 0x03AB, // B error
+ CPMSG_PARTY_NEW_MEMBER = 0x03B0, // W being id, S name
+ CPMSG_PARTY_MEMBER_LEFT = 0x03B1, // W being id
+
+ // 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
+ CPMSG_CHANNEL_EVENT = 0x0430, // W channel, B event, S info
+ PCMSG_ENTER_CHANNEL = 0x0440, // S channel, S password
+ CPMSG_ENTER_CHANNEL_RESPONSE = 0x0441, // B error, W id, S name, S topic, S userlist
+ PCMSG_QUIT_CHANNEL = 0x0443, // W channel id
+ CPMSG_QUIT_CHANNEL_RESPONSE = 0x0444, // B error, W channel id
+ PCMSG_LIST_CHANNELS = 0x0445, // -
+ CPMSG_LIST_CHANNELS_RESPONSE = 0x0446, // S names, W number of users
+ PCMSG_LIST_CHANNELUSERS = 0x0460, // S channel
+ CPMSG_LIST_CHANNELUSERS_RESPONSE = 0x0461, // S channel, { S user, B mode }
+ PCMSG_TOPIC_CHANGE = 0x0462, // W channel id, S topic
+ // -- User mode
+ PCMSG_USER_MODE = 0x0465, // W channel id, S name, B mode
+ PCMSG_KICK_USER = 0x0466, // W channel id, S name
+
+ 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
+ ERRMSG_EMAIL_ALREADY_EXISTS, // The Email Address already exists
+ ERRMSG_ALREADY_TAKEN, // name used was already taken
+ ERRMSG_SERVER_FULL, // the server is overloaded
+ ERRMSG_TIME_OUT // data failed to arrive in due time
+};
+
+// 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_EQUAL_TO_ZERO,
+ CREATE_EXISTS_NAME,
+ CREATE_TOO_MUCH_CHARACTERS
+};
+
+// Character attribute modification specific return value
+enum AttribmodResponseCode {
+ ATTRIBMOD_OK = ERRMSG_OK,
+ ATTRIBMOD_INVALID_ATTRIBUTE = 0x40,
+ ATTRIBMOD_NO_POINTS_LEFT,
+ ATTRIBMOD_DENIED
+};
+// 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
+};
+
+// Email change specific return values
+enum {
+ EMAILCHG_EXISTS_EMAIL = 0x40
+};
+
+// Chat errors return values
+enum {
+ CHAT_USING_BAD_WORDS = 0x40,
+ CHAT_UNHANDLED_COMMAND
+};
+
+// Chat channels event values
+enum {
+ CHAT_EVENT_NEW_PLAYER = 0,
+ CHAT_EVENT_LEAVING_PLAYER,
+ CHAT_EVENT_TOPIC_CHANGE,
+ CHAT_EVENT_MODE_CHANGE,
+ CHAT_EVENT_KICKED_PLAYER
+};
+
+// Guild member event values
+enum {
+ GUILD_EVENT_NEW_PLAYER = 0,
+ GUILD_EVENT_LEAVING_PLAYER,
+ GUILD_EVENT_ONLINE_PLAYER,
+ GUILD_EVENT_OFFLINE_PLAYER
+};
+
+#endif
diff --git a/src/net/tmwserv/tradehandler.cpp b/src/net/tmwserv/tradehandler.cpp
new file mode 100644
index 00000000..12d47745
--- /dev/null
+++ b/src/net/tmwserv/tradehandler.cpp
@@ -0,0 +1,137 @@
+/*
+ * 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
+ */
+
+#include "tradehandler.h"
+
+#include "../messagein.h"
+#include "protocol.h"
+
+#include "gameserver/player.h"
+
+#include "../../beingmanager.h"
+#include "../../item.h"
+#include "../../localplayer.h"
+
+#include "../../gui/chat.h"
+#include "../../gui/confirm_dialog.h"
+#include "../../gui/trade.h"
+
+std::string tradePartnerName;
+int tradePartnerID;
+
+/**
+ * Listener for request trade dialogs
+ */
+namespace {
+ struct RequestTradeListener : public gcn::ActionListener
+ {
+ void action(const gcn::ActionEvent &event)
+ {
+ if (event.getId() == "yes")
+ Net::GameServer::Player::requestTrade(tradePartnerID);
+ else
+ Net::GameServer::Player::acceptTrade(false);
+ }
+ } listener;
+}
+
+TradeHandler::TradeHandler():
+ mAcceptTradeRequests(true)
+{
+ static const Uint16 _messages[] = {
+ GPMSG_TRADE_REQUEST,
+ GPMSG_TRADE_CANCEL,
+ GPMSG_TRADE_START,
+ GPMSG_TRADE_COMPLETE,
+ GPMSG_TRADE_ACCEPT,
+ GPMSG_TRADE_ADD_ITEM,
+ GPMSG_TRADE_SET_MONEY,
+ 0
+ };
+ handledMessages = _messages;
+}
+
+void TradeHandler::setAcceptTradeRequests(bool acceptTradeRequests)
+{
+ mAcceptTradeRequests = acceptTradeRequests;
+ if (mAcceptTradeRequests) {
+ chatWindow->chatLog("Accepting incoming trade requests", BY_SERVER);
+ } else {
+ chatWindow->chatLog("Ignoring incoming trade requests", BY_SERVER);
+ }
+}
+
+void TradeHandler::handleMessage(MessageIn &msg)
+{
+ switch (msg.getId())
+ {
+ case GPMSG_TRADE_REQUEST:
+ {
+ Being *being = beingManager->findBeing(msg.readInt16());
+ if (!being || !mAcceptTradeRequests)
+ {
+ Net::GameServer::Player::acceptTrade(false);
+ break;
+ }
+ player_node->setTrading(true);
+ tradePartnerName = being->getName();
+ tradePartnerID = being->getId();
+ ConfirmDialog *dlg = new ConfirmDialog("Request for trade",
+ tradePartnerName + " wants to trade with you, do you accept?");
+ dlg->addActionListener(&listener);
+ } break;
+
+ case GPMSG_TRADE_ADD_ITEM:
+ {
+ int type = msg.readInt16();
+ int amount = msg.readInt8();
+ tradeWindow->addItem(type, false, amount);
+ } break;
+
+ case GPMSG_TRADE_SET_MONEY:
+ tradeWindow->setMoney(msg.readInt32());
+ break;
+
+ case GPMSG_TRADE_START:
+ tradeWindow->reset();
+ tradeWindow->setCaption("Trading with " + tradePartnerName);
+ tradeWindow->setVisible(true);
+ break;
+
+ case GPMSG_TRADE_ACCEPT:
+ tradeWindow->receivedOk();
+ break;
+
+ case GPMSG_TRADE_CANCEL:
+ chatWindow->chatLog("Trade canceled.", BY_SERVER);
+ tradeWindow->setVisible(false);
+ tradeWindow->reset();
+ player_node->setTrading(false);
+ break;
+
+ case GPMSG_TRADE_COMPLETE:
+ chatWindow->chatLog("Trade completed.", BY_SERVER);
+ tradeWindow->setVisible(false);
+ tradeWindow->reset();
+ player_node->setTrading(false);
+ break;
+ }
+}
diff --git a/src/net/tmwserv/tradehandler.h b/src/net/tmwserv/tradehandler.h
new file mode 100644
index 00000000..0b634b66
--- /dev/null
+++ b/src/net/tmwserv/tradehandler.h
@@ -0,0 +1,53 @@
+/*
+ * The Mana World
+ * Copyright (C) 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef NET_TRADEHANDLER_H
+#define NET_TRADEHANDLER_H
+
+#include "../messagehandler.h"
+
+class TradeHandler : public MessageHandler
+{
+ public:
+ TradeHandler();
+
+ void handleMessage(MessageIn &msg);
+
+ /**
+ * Returns whether trade requests are accepted.
+ *
+ * @see setAcceptTradeRequests
+ */
+ bool acceptTradeRequests() const
+ { return mAcceptTradeRequests; }
+
+ /**
+ * Sets whether trade requests are accepted. When set to false, trade
+ * requests are automatically denied. When true, a popup will ask the
+ * player whether he wants to trade.
+ */
+ void setAcceptTradeRequests(bool acceptTradeRequests);
+
+ private:
+ bool mAcceptTradeRequests;
+};
+
+#endif