00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "game-server/accountconnection.hpp"
00023
00024 #include "defines.h"
00025 #include "common/configuration.hpp"
00026 #include "game-server/character.hpp"
00027 #include "game-server/gamehandler.hpp"
00028 #include "game-server/map.hpp"
00029 #include "game-server/mapcomposite.hpp"
00030 #include "game-server/mapmanager.hpp"
00031 #include "game-server/itemmanager.hpp"
00032 #include "game-server/postman.hpp"
00033 #include "game-server/quest.hpp"
00034 #include "game-server/state.hpp"
00035 #include "net/messagein.hpp"
00036 #include "serialize/characterdata.hpp"
00037 #include "utils/logger.h"
00038 #include "utils/tokendispenser.hpp"
00039 #include "utils/tokencollector.hpp"
00040
00041 AccountConnection::AccountConnection():
00042 mSyncBuffer(0)
00043 {
00044 }
00045
00046 AccountConnection::~AccountConnection()
00047 {
00048 delete mSyncBuffer;
00049 }
00050
00051 bool AccountConnection::start()
00052 {
00053 const std::string accountServerAddress =
00054 Configuration::getValue("net_accountServerAddress", "localhost");
00055 const int accountServerPort =
00056 Configuration::getValue("net_accountServerPort", DEFAULT_SERVER_PORT) + 1;
00057
00058 if (!Connection::start(accountServerAddress, accountServerPort))
00059 {
00060 LOG_INFO("Unable to create a connection to an account server.");
00061 return false;
00062 }
00063
00064 LOG_INFO("Connection established to the account server.");
00065
00066 const std::string gameServerAddress =
00067 Configuration::getValue("net_gameServerAddress", "localhost");
00068 const int gameServerPort =
00069 Configuration::getValue("net_gameServerPort", DEFAULT_SERVER_PORT + 3);
00070
00071
00072 MessageOut msg(GAMSG_REGISTER);
00073 msg.writeString(gameServerAddress);
00074 msg.writeShort(gameServerPort);
00075 msg.writeLong(ItemManager::GetDatabaseVersion());
00076 const MapManager::Maps &m = MapManager::getMaps();
00077 for (MapManager::Maps::const_iterator i = m.begin(), i_end = m.end();
00078 i != i_end; ++i)
00079 {
00080 msg.writeShort(i->first);
00081 }
00082 send(msg);
00083
00084
00085 mSyncBuffer = new MessageOut(GAMSG_PLAYER_SYNC);
00086 mSyncMessages = 0;
00087
00088 return true;
00089 }
00090
00091 void AccountConnection::sendCharacterData(Character *p)
00092 {
00093 MessageOut msg(GAMSG_PLAYER_DATA);
00094 msg.writeLong(p->getDatabaseID());
00095 serializeCharacterData(*p, msg);
00096 send(msg);
00097 }
00098
00099 void AccountConnection::processMessage(MessageIn &msg)
00100 {
00101 switch (msg.getId())
00102 {
00103 case AGMSG_REGISTER_RESPONSE:
00104 {
00105 if (msg.readShort() != DATA_VERSION_OK)
00106 {
00107 LOG_ERROR("Item database is outdated! Please update to "
00108 "prevent inconsistencies");
00109 stop();
00110 exit(1);
00111 }
00112 else
00113 {
00114 LOG_DEBUG("Local item database is in sync with account server.");
00115 }
00116 } break;
00117
00118 case AGMSG_PLAYER_ENTER:
00119 {
00120 std::string token = msg.readString(MAGIC_TOKEN_LENGTH);
00121 Character *ptr = new Character(msg);
00122 ptr->setSpeed(250);
00123 gameHandler->addPendingCharacter(token, ptr);
00124 } break;
00125
00126 case AGMSG_ACTIVE_MAP:
00127 {
00128 int id = msg.readShort();
00129 MapManager::raiseActive(id);
00130 } break;
00131
00132 case AGMSG_REDIRECT_RESPONSE:
00133 {
00134 int id = msg.readLong();
00135 std::string token = msg.readString(MAGIC_TOKEN_LENGTH);
00136 std::string address = msg.readString();
00137 int port = msg.readShort();
00138 gameHandler->completeServerChange(id, token, address, port);
00139 } break;
00140
00141 case AGMSG_GET_QUEST_RESPONSE:
00142 {
00143 int id = msg.readLong();
00144 std::string name = msg.readString();
00145 std::string value = msg.readString();
00146 recoveredQuestVar(id, name, value);
00147 } break;
00148
00149 case CGMSG_CHANGED_PARTY:
00150 {
00151
00152 int charid = msg.readLong();
00153
00154 int partyid = msg.readLong();
00155 gameHandler->updateCharacter(charid, partyid);
00156 } break;
00157
00158 case CGMSG_POST_RESPONSE:
00159 {
00160
00161 Character *character = postMan->getCharacter(msg.readLong());
00162
00163
00164 if (!character)
00165 {
00166 break;
00167 }
00168
00169 std::string sender = msg.readString();
00170 std::string letter = msg.readString();
00171
00172 postMan->gotPost(character, sender, letter);
00173
00174 } break;
00175
00176 case CGMSG_STORE_POST_RESPONSE:
00177 {
00178
00179 Character *character = postMan->getCharacter(msg.readLong());
00180
00181
00182 if (!character)
00183 {
00184 break;
00185 }
00186
00187
00188
00189
00190 } break;
00191
00192 default:
00193 LOG_WARN("Invalid message type");
00194 break;
00195 }
00196 }
00197
00198 void AccountConnection::playerReconnectAccount(int id,
00199 const std::string &magic_token)
00200 {
00201 LOG_DEBUG("Send GAMSG_PLAYER_RECONNECT.");
00202 MessageOut msg(GAMSG_PLAYER_RECONNECT);
00203 msg.writeLong(id);
00204 msg.writeString(magic_token, MAGIC_TOKEN_LENGTH);
00205 send(msg);
00206 }
00207
00208 void AccountConnection::requestQuestVar(Character *ch, const std::string &name)
00209 {
00210 MessageOut msg(GAMSG_GET_QUEST);
00211 msg.writeLong(ch->getDatabaseID());
00212 msg.writeString(name);
00213 send(msg);
00214 }
00215
00216 void AccountConnection::updateQuestVar(Character *ch, const std::string &name,
00217 const std::string &value)
00218 {
00219 MessageOut msg(GAMSG_SET_QUEST);
00220 msg.writeLong(ch->getDatabaseID());
00221 msg.writeString(name);
00222 msg.writeString(value);
00223 send(msg);
00224 }
00225
00226 void AccountConnection::banCharacter(Character *ch, int duration)
00227 {
00228 MessageOut msg(GAMSG_BAN_PLAYER);
00229 msg.writeLong(ch->getDatabaseID());
00230 msg.writeShort(duration);
00231 send(msg);
00232 }
00233
00234 void AccountConnection::sendStatistics()
00235 {
00236 MessageOut msg(GAMSG_STATISTICS);
00237 const MapManager::Maps &maps = MapManager::getMaps();
00238 for (MapManager::Maps::const_iterator i = maps.begin(),
00239 i_end = maps.end(); i != i_end; ++i)
00240 {
00241 MapComposite *m = i->second;
00242 if (!m->isActive()) continue;
00243 msg.writeShort(i->first);
00244 int nbThings = 0, nbMonsters = 0;
00245 typedef std::vector< Thing * > Things;
00246 const Things &things = m->getEverything();
00247 std::vector< int > players;
00248 for (Things::const_iterator j = things.begin(),
00249 j_end = things.end(); j != j_end; ++j)
00250 {
00251 Thing *t = *j;
00252 switch (t->getType())
00253 {
00254 case OBJECT_CHARACTER:
00255 players.push_back
00256 (static_cast< Character * >(t)->getDatabaseID());
00257 break;
00258 case OBJECT_MONSTER:
00259 ++nbMonsters;
00260 break;
00261 default:
00262 ++nbThings;
00263 }
00264 }
00265 msg.writeShort(nbThings);
00266 msg.writeShort(nbMonsters);
00267 msg.writeShort(players.size());
00268 for (std::vector< int >::const_iterator j = players.begin(),
00269 j_end = players.end(); j != j_end; ++j)
00270 {
00271 msg.writeLong(*j);
00272 }
00273 }
00274 send(msg);
00275 }
00276
00277 void AccountConnection::sendPost(Character *c, MessageIn &msg)
00278 {
00279
00280
00281 LOG_DEBUG("Sending GCMSG_STORE_POST.");
00282 MessageOut out(GCMSG_STORE_POST);
00283 out.writeLong(c->getDatabaseID());
00284 out.writeString(msg.readString());
00285 out.writeString(msg.readString());
00286 while (msg.getUnreadLength())
00287 {
00288
00289 out.writeLong(msg.readShort());
00290 out.writeLong(msg.readShort());
00291 }
00292 send(out);
00293 }
00294
00295 void AccountConnection::getPost(Character *c)
00296 {
00297
00298 postMan->addCharacter(c);
00299
00300
00301 LOG_DEBUG("Sending GCMSG_REQUEST_POST");
00302 MessageOut out(GCMSG_REQUEST_POST);
00303 out.writeLong(c->getDatabaseID());
00304 send(out);
00305 }
00306
00307 void AccountConnection::changeAccountLevel(Character *c, int level)
00308 {
00309 MessageOut msg(GAMSG_CHANGE_ACCOUNT_LEVEL);
00310 msg.writeLong(c->getDatabaseID());
00311 msg.writeShort(level);
00312 send(msg);
00313 }
00314
00315 void AccountConnection::syncChanges(bool force)
00316 {
00317 if (mSyncMessages == 0)
00318 return;
00319
00320
00321
00322
00323
00324
00325 if (force ||
00326 mSyncMessages > SYNC_BUFFER_LIMIT ||
00327 mSyncBuffer->getLength() > SYNC_BUFFER_SIZE )
00328 {
00329 LOG_DEBUG("Sending GAMSG_PLAYER_SYNC with "
00330 << mSyncMessages << " messages." );
00331
00332
00333 mSyncBuffer->writeByte(SYNC_END_OF_BUFFER);
00334 send(*mSyncBuffer);
00335 delete (mSyncBuffer);
00336
00337 mSyncBuffer = new MessageOut(GAMSG_PLAYER_SYNC);
00338 mSyncMessages = 0;
00339 }
00340 else
00341 {
00342 LOG_DEBUG("No changes to sync with account server.");
00343 }
00344 }
00345
00346 void AccountConnection::updateCharacterPoints(int charId, int charPoints,
00347 int corrPoints,
00348 int attribId,
00349 int attribValue)
00350 {
00351 mSyncMessages++;
00352 mSyncBuffer->writeByte(SYNC_CHARACTER_POINTS);
00353 mSyncBuffer->writeLong(charId);
00354 mSyncBuffer->writeLong(charPoints);
00355 mSyncBuffer->writeLong(corrPoints);
00356 mSyncBuffer->writeByte(attribId);
00357 mSyncBuffer->writeLong(attribValue);
00358 syncChanges();
00359 }
00360
00361 void AccountConnection::updateExperience(int charId, int skillId,
00362 int skillValue)
00363 {
00364 mSyncMessages++;
00365 mSyncBuffer->writeByte(SYNC_CHARACTER_SKILL);
00366 mSyncBuffer->writeLong(charId);
00367 mSyncBuffer->writeByte(skillId);
00368 mSyncBuffer->writeLong(skillValue);
00369 syncChanges();
00370 }
00371
00372 void AccountConnection::updateOnlineStatus(int charId, bool online)
00373 {
00374 mSyncMessages++;
00375 mSyncBuffer->writeByte(SYNC_ONLINE_STATUS);
00376 mSyncBuffer->writeLong(charId);
00377 mSyncBuffer->writeByte(online ? 0x01 : 0x00);
00378 syncChanges();
00379 }
00380
00381 void AccountConnection::sendTransaction(int id, int action, const std::string &message)
00382 {
00383 MessageOut msg(GAMSG_TRANSACTION);
00384 msg.writeLong(id);
00385 msg.writeLong(action);
00386 msg.writeString(message);
00387 send(msg);
00388 }