ManaPlus
charserverrecv.cpp
Go to the documentation of this file.
1 /*
2  * The ManaPlus Client
3  * Copyright (C) 2004-2009 The Mana World Development Team
4  * Copyright (C) 2009-2010 The Mana Developers
5  * Copyright (C) 2011-2019 The ManaPlus Developers
6  * Copyright (C) 2019-2021 Andrei Karas
7  *
8  * This file is part of The ManaPlus Client.
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program. If not, see <http://www.gnu.org/licenses/>.
22  */
23 
25 
26 #include "client.h"
27 #include "configuration.h"
28 #include "settings.h"
29 
31 #include "gui/windows/okdialog.h"
32 
34 
35 #include "net/character.h"
36 #include "net/charserverhandler.h"
37 #include "net/messagein.h"
38 #include "net/serverfeatures.h"
39 
40 #include "net/ea/token.h"
41 
42 #include "net/tmwa/gamehandler.h"
43 #include "net/tmwa/loginhandler.h"
44 #include "net/tmwa/network.h"
45 #include "net/tmwa/sprite.h"
46 
47 #include "resources/iteminfo.h"
48 
49 #include "resources/db/itemdb.h"
50 
51 #include "utils/dtor.h"
52 #include "utils/gettext.h"
53 
54 #include "debug.h"
55 
56 namespace TmwAthena
57 {
58 
60 
62 
64  Net::Character *const character)
65 {
66  if (character == nullptr)
67  return;
68 
69  const Token &token =
70  static_cast<LoginHandler*>(loginHandler)->getToken();
71 
72  LocalPlayer *const tempPlayer = new LocalPlayer(
73  msg.readBeingId("account id"), BeingTypeId_zero);
74 
75  PlayerInfoBackend &data = character->data;
76  data.mAttributes[Attributes::PLAYER_EXP] = msg.readInt32("base exp");
77  data.mAttributes[Attributes::MONEY] = msg.readInt32("money");
78  data.mAttributes[Attributes::PLAYER_JOB_EXP] = msg.readInt32("job exp");
79  data.mAttributes[Attributes::PLAYER_JOB_LEVEL] =
80  msg.readInt32("job level");
81 
82  const int shoes = msg.readInt16("shoes");
83  const int gloves = msg.readInt16("gloves");
84  const int cape = msg.readInt16("cape");
85  const int misc1 = msg.readInt16("misc1");
86 
87  msg.readInt32("option");
88  tempPlayer->setKarma(msg.readInt32("karma"));
89  tempPlayer->setManner(msg.readInt32("manner"));
90  msg.readInt16("character points left");
91 
92  data.mAttributes[Attributes::PLAYER_HP] = msg.readInt16("hp");
93  data.mAttributes[Attributes::PLAYER_MAX_HP] = msg.readInt16("max hp");
94  data.mAttributes[Attributes::PLAYER_MP] = msg.readInt16("mp");
95  data.mAttributes[Attributes::PLAYER_MAX_MP] = msg.readInt16("max mp");
96 
97  msg.readInt16("speed");
98  const uint16_t race = msg.readInt16("class");
99  const uint8_t hairStyle = msg.readUInt8("hair style");
100  const uint16_t look = msg.readUInt8("look");
101  tempPlayer->setSubtype(fromInt(race, BeingTypeId), look);
102  const uint16_t weapon = msg.readInt16("weapon");
103  tempPlayer->setSpriteId(SPRITE_BODY,
104  weapon);
105  tempPlayer->setWeaponId(weapon);
106 
107  data.mAttributes[Attributes::PLAYER_BASE_LEVEL] = msg.readInt16("level");
108 
109  msg.readInt16("skill point");
110  const int bottomClothes = msg.readInt16("bottom clothes");
111  const int shield = msg.readInt16("shield");
112 
113  const int hat = msg.readInt16("hat");
114  const int topClothes = msg.readInt16("top clothes");
115 
116  const ItemColor hairColor = fromInt(
117  msg.readUInt8("hair color"), ItemColor);
118  msg.readUInt8("unused");
119  if (hairStyle == 0)
120  {
121  tempPlayer->unSetSprite(SPRITE_HAIR_COLOR);
122  }
123  else
124  {
125  tempPlayer->setSpriteColor(SPRITE_HAIR_COLOR,
126  hairStyle * -1,
127  ItemDB::get(-hairStyle).getDyeColorsString(hairColor));
128  }
129  tempPlayer->setHairColor(hairColor);
130 
131  const int misc2 = msg.readInt16("misc2");
132  tempPlayer->setName(msg.readString(24, "name"));
133 
134  character->dummy = tempPlayer;
135 
136  character->data.mStats[Attributes::PLAYER_STR].base = msg.readUInt8("str");
137  character->data.mStats[Attributes::PLAYER_AGI].base = msg.readUInt8("agi");
138  character->data.mStats[Attributes::PLAYER_VIT].base = msg.readUInt8("vit");
139  character->data.mStats[Attributes::PLAYER_INT].base = msg.readUInt8("int");
140  character->data.mStats[Attributes::PLAYER_DEX].base = msg.readUInt8("dex");
141  character->data.mStats[Attributes::PLAYER_LUK].base = msg.readUInt8("luk");
142 
143  tempPlayer->setSpriteId(SPRITE_HAIR,
144  shoes);
145  tempPlayer->setSpriteId(SPRITE_SHOES,
146  gloves);
147  tempPlayer->setSpriteId(SPRITE_SHIELD,
148  cape);
149  tempPlayer->setSpriteId(SPRITE_HEAD_TOP,
150  misc1);
151  tempPlayer->setSpriteId(SPRITE_WEAPON,
152  bottomClothes);
153  tempPlayer->setSpriteId(SPRITE_FLOOR,
154  shield);
155  tempPlayer->setSpriteId(SPRITE_CLOTHES_COLOR,
156  hat);
157  tempPlayer->setSpriteId(SPRITE_HEAD_BOTTOM,
158  topClothes);
159  tempPlayer->setSpriteId(SPRITE_HEAD_MID,
160  misc2);
161 
162  character->slot = msg.readUInt8("slot");
163  const uint8_t sex = CAST_U8(msg.readUInt8("gender"));
165  tempPlayer->setGender(Being::intToGender(sex));
166  else
167  tempPlayer->setGender(token.sex);
168 }
169 
171 {
172  BLOCK_START("CharServerRecv::processCharLogin")
173 
174  msg.readInt16("len");
175  const int slots = msg.readInt16("slots");
176  if (slots > 0 && slots < 30)
178 
179  msg.skip(18, "unused");
180 
183 
184  // Derive number of characters from message length
185  const int count = (msg.getLength() - 24) / 106;
186 
187  for (int i = 0; i < count; ++i)
188  {
189  Net::Character *const character = new Net::Character;
190  readPlayerData(msg, character);
191  Net::CharServerHandler::mCharacters.push_back(character);
192  if (character->dummy != nullptr)
193  {
194  logger->log("CharServer: Player: %s (%d)",
195  character->dummy->getName().c_str(), character->slot);
196  }
197  }
198 
200  BLOCK_END("CharServerRecv::processCharLogin")
201 }
202 
204 {
205  Network *const network = Network::mInstance;
206  ServerInfo &server = mapServer;
207  BLOCK_START("CharServerRecv::processCharMapInfo")
208  PlayerInfo::setCharId(msg.readInt32("char id?"));
209  GameHandler::setMap(msg.readString(16, "map name"));
210  if (config.getBoolValue("usePersistentIP") || settings.persistentIp)
211  {
212  msg.readInt32("ip address");
213  server.hostname = settings.serverName;
214  }
215  else
216  {
217  server.hostname = ipToString(msg.readInt32("ip address"));
218  }
219  server.port = msg.readInt16("port");
221 
222  // Prevent the selected local player from being deleted
225 
227 
230 
231  if (network != nullptr)
232  network->disconnect();
234  BLOCK_END("CharServerRecv::processCharMapInfo")
235 }
236 
238 {
239  Network *const network = Network::mInstance;
240  ServerInfo &server = mapServer;
241  BLOCK_START("CharServerRecv::processChangeMapServer")
242  if (network == nullptr)
243  {
244  BLOCK_END("CharServerRecv::processChangeMapServer")
245  return;
246  }
247  GameHandler::setMap(msg.readString(16, "map name"));
248  const int x = msg.readInt16("x");
249  const int y = msg.readInt16("y");
250  if (config.getBoolValue("usePersistentIP") || settings.persistentIp)
251  {
252  msg.readInt32("ip address");
253  server.hostname = settings.serverName;
254  }
255  else
256  {
257  server.hostname = ipToString(msg.readInt32("ip address"));
258  }
259  server.port = msg.readInt16("port");
260 
261  network->disconnect();
263  if (localPlayer != nullptr)
264  {
266  localPlayer->setMap(nullptr);
267  }
268  BLOCK_END("CharServerRecv::processChangeMapServer")
269 }
270 
272 {
273  BLOCK_START("CharServerRecv::processCharCreate")
274  Net::Character *const character = new Net::Character;
275  readPlayerData(msg, character);
276  Net::CharServerHandler::mCharacters.push_back(character);
277 
279 
280  // Close the character create dialog
283  BLOCK_END("CharServerRecv::processCharCreate")
284 }
285 
287 {
288  BLOCK_START("CharServerRecv::processCharDeleteFailed")
290  msg.readUInt8("error");
292  // TRANSLATORS: error header
293  _("Error"),
294  // TRANSLATORS: error message
295  _("Failed to delete character."),
296  // TRANSLATORS: ok dialog button
297  _("OK"),
299  Modal_true,
301  nullptr,
302  260);
303  BLOCK_END("CharServerRecv::processCharDeleteFailed")
304 }
305 
306 } // namespace TmwAthena
int BeingTypeId
Definition: beingtypeid.h:30
const BeingTypeId BeingTypeId_zero
Definition: beingtypeid.h:30
#define CAST_U16
Definition: cast.h:29
#define CAST_U8
Definition: cast.h:27
Net::CharServerHandler * charServerHandler
Definition: net.cpp:85
void setKarma(const int karma)
Definition: being.h:1031
void setWeaponId(const int id)
Definition: being.cpp:3135
static GenderT intToGender(const uint8_t sex) A_CONST
Definition: being.h:941
void setName(const std::string &name)
Definition: being.cpp:1136
void setSubtype(const BeingTypeId subtype, const uint16_t look)
Definition: being.cpp:371
void setHairColor(const unsigned int slot, const ItemColor color)
Definition: being.cpp:3389
const std::string & getName() const
Definition: being.h:232
void setSpriteId(const unsigned int slot, const int id)
Definition: being.cpp:2789
virtual void setGender(const GenderT gender)
Definition: being.cpp:3581
void unSetSprite(const unsigned int slot)
Definition: being.cpp:2861
void setManner(const int manner)
Definition: being.h:1037
void setSpriteColor(const unsigned int slot, const int id, const std::string &color)
Definition: being.cpp:2890
void setState(const StateT state)
Definition: client.h:66
bool getBoolValue(const std::string &key) const
static void setMap(const std::string &map)
Definition: gamehandler.cpp:46
void disconnect()
Definition: network.cpp:139
void setTileCoords(const int x, const int y)
void setMap(Map *const map)
void log(const char *const log_text,...)
Definition: logger.cpp:269
uint16_t characterSlots
Definition: logindata.h:77
static void unlockCharSelectDialog()
static void updateCharSelectDialog()
virtual void clear() const =0
static Net::Character * mSelectedCharacter
static Net::Characters mCharacters
static CharCreateDialog * mCharCreateDialog
virtual bool haveCreateCharGender() const =0
std::string hostname
Definition: serverinfo.h:45
std::string althostname
Definition: serverinfo.h:46
uint16_t port
Definition: serverinfo.h:58
bool persistentIp
Definition: settings.h:153
std::string serverName
Definition: settings.h:114
static Network * mInstance
Definition: network.h:54
virtual void scheduleDelete()
Definition: window.cpp:831
Configuration config
#define CREATEWIDGET(type,...)
Definition: createwidget.h:29
void delete_all(Container &c)
Definition: dtor.h:56
Client * client
Definition: client.cpp:118
#define _(s)
Definition: gettext.h:35
#define fromInt(val, name)
Definition: intdefines.h:46
uint16_t ItemColor
Definition: itemcolor.h:30
#define restrict
Definition: localconsts.h:165
LocalPlayer * localPlayer
Logger * logger
Definition: logger.cpp:89
Net::LoginHandler * loginHandler
Definition: net.cpp:90
LoginData loginData
Definition: client.cpp:185
uint32_t data
const bool Modal_true
Definition: modal.h:30
bool msg(InputEvent &event)
Definition: chat.cpp:39
bool hat(InputEvent &event)
Definition: chat.cpp:62
@ PLAYER_MAX_MP
Definition: attributes.h:35
@ PLAYER_BASE_LEVEL
Definition: attributes.h:31
@ PLAYER_JOB_EXP
Definition: attributes.h:66
@ PLAYER_JOB_LEVEL
Definition: attributes.h:41
@ PLAYER_MAX_HP
Definition: attributes.h:33
void readPlayerData(Net::MessageIn &msg, Net::Character *const character)
const ItemInfo & get(const int id)
Definition: itemdb.cpp:792
void setBackend(const PlayerInfoBackend &backend)
Definition: playerinfo.cpp:376
void setCharId(const int charId)
Definition: playerinfo.cpp:381
@ CHANGE_MAP
Definition: state.h:50
@ CHAR_SELECT
Definition: state.h:47
@ CONNECT_GAME
Definition: state.h:48
void processCharLogin(Net::MessageIn &msg)
void readPlayerData(Net::MessageIn &msg, Net::Character *const character)
void processChangeMapServer(Net::MessageIn &msg)
void processCharMapInfo(Net::MessageIn &msg)
void processCharDeleteFailed(Net::MessageIn &msg)
void processCharCreate(Net::MessageIn &msg)
ServerInfo mapServer
ServerInfo charServer
@ SPRITE_HAIR_COLOR
Definition: sprite.h:35
@ SPRITE_WEAPON
Definition: sprite.h:31
@ SPRITE_FLOOR
Definition: sprite.h:40
@ SPRITE_HEAD_TOP
Definition: sprite.h:33
@ SPRITE_SHOES
Definition: sprite.h:38
@ SPRITE_SHIELD
Definition: sprite.h:37
@ SPRITE_HEAD_MID
Definition: sprite.h:34
@ SPRITE_BODY
Definition: sprite.h:39
@ SPRITE_CLOTHES_COLOR
Definition: sprite.h:36
@ SPRITE_HEAD_BOTTOM
Definition: sprite.h:32
Net::ServerFeatures * serverFeatures
Definition: net.cpp:101
#define BLOCK_END(name)
Definition: perfomance.h:80
#define BLOCK_START(name)
Definition: perfomance.h:79
Settings settings
Definition: settings.cpp:32
const bool ShowCenter_true
Definition: showcenter.h:30
const char * ipToString(const uint32_t address)
Definition: stringutils.cpp:86
LocalPlayer * dummy
Definition: character.h:56
PlayerInfoBackend data
Definition: character.h:57
uint16_t slot
Definition: character.h:58
Definition: token.h:31
GenderT sex
Definition: token.h:44