void ItemHandler::handleMessage(MessageIn &msg) { switch (msg.getId()) { 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 if (itemId) { floorItemManager->create(id, itemId, x / 32, y / 32, engine->getCurrentMap()); } else if (FloorItem *item = floorItemManager->findById(id)) { floorItemManager->destroy(item); } } } break; } }
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); ChatTab *tab = channel->getTab(); tab->chatLog(strprintf(_("Topic: %s"), announcement.c_str()), BY_CHANNEL); std::string user; std::string userModes; tab->chatLog(_("Players in this channel:"), BY_CHANNEL); while(msg.getUnreadLength()) { user = msg.readString(); if (user == "") return; userModes = msg.readString(); if (userModes.find('o') != std::string::npos) { user = "******" + user; } tab->chatLog(user, BY_CHANNEL); } } else { localChatTab->chatLog(_("Error joining channel."), BY_SERVER); } }
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; } }
void ItemHandler::handleMessage(MessageIn &msg) { switch (msg.getId()) { 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 if (itemId) { actorSpriteManager->createItem(id, itemId, Vector(x, y)); } else if (FloorItem *item = actorSpriteManager->findItem(id)) { actorSpriteManager->destroy(item); } } } break; } }
void EffectHandler::handleShake(MessageIn &msg) { int16_t intensityX = 0; int16_t intensityY = 0; float decay; int duration; switch (msg.getUnreadLength()) { case 4: intensityX = msg.readInt16(); intensityY = msg.readInt16(); viewport->shakeScreen(intensityX, intensityY); break; case 6: intensityX = msg.readInt16(); intensityY = msg.readInt16(); decay = msg.readInt16() / 10000.0f; viewport->shakeScreen(intensityX, intensityY, decay); break; case 8: intensityX = msg.readInt16(); intensityY = msg.readInt16(); decay = msg.readInt16() / 10000.0f; duration = msg.readInt16(); viewport->shakeScreen(intensityX, intensityY, decay, duration); break; default: logger->log("Warning: Received GPMSG_SHAKE message with unexpected length of %d bytes", msg.getUnreadLength()); } }
void LoginHandler::readUpdateHost(MessageIn &msg) { // Set the update host when included in the message if (msg.getUnreadLength() > 0) { mLoginData->updateHost = msg.readString(); } }
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(new Item(itemId, amount, false), value); } break; } }
void GameServerHandler::syncDatabase(MessageIn &msg) { // It is safe to perform the following updates in a transaction dal::PerformTransaction transaction(storage->database()); while (msg.getUnreadLength() > 0) { int msgType = msg.readInt8(); switch (msgType) { case SYNC_CHARACTER_POINTS: { LOG_DEBUG("received SYNC_CHARACTER_POINTS"); int charId = msg.readInt32(); int charPoints = msg.readInt32(); int corrPoints = msg.readInt32(); storage->updateCharacterPoints(charId, charPoints, corrPoints); } break; case SYNC_CHARACTER_ATTRIBUTE: { LOG_DEBUG("received SYNC_CHARACTER_ATTRIBUTE"); int charId = msg.readInt32(); int attrId = msg.readInt32(); double base = msg.readDouble(); double mod = msg.readDouble(); storage->updateAttribute(charId, attrId, base, mod); } break; case SYNC_CHARACTER_SKILL: { LOG_DEBUG("received SYNC_CHARACTER_SKILL"); int charId = msg.readInt32(); int skillId = msg.readInt8(); int skillValue = msg.readInt32(); storage->updateExperience(charId, skillId, skillValue); } break; case SYNC_ONLINE_STATUS: { LOG_DEBUG("received SYNC_ONLINE_STATUS"); int charId = msg.readInt32(); bool online = (msg.readInt8() == 1); storage->setOnlineStatus(charId, online); } } } transaction.commit(); }
void ChatHandler::handleWhoResponse(MessageIn &msg) { std::string userNick; while(msg.getUnreadLength()) { userNick = msg.readString(); if (userNick == "") { break; } localChatTab->chatLog(userNick, BY_SERVER); } }
void ChatHandler::handleListChannelsResponse(MessageIn &msg) { localChatTab->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(); localChatTab->chatLog(channelName, BY_SERVER); } localChatTab->chatLog(_("End of channel list."), BY_SERVER); }
void AccountConnection::sendPost(Character *c, MessageIn &msg) { // send message to account server with id of sending player, // the id of receiving player, the letter receiver and contents, and attachments LOG_DEBUG("Sending GCMSG_STORE_POST."); MessageOut out(GCMSG_STORE_POST); out.writeInt32(c->getDatabaseID()); out.writeString(msg.readString()); // name of receiver out.writeString(msg.readString()); // content of letter while (msg.getUnreadLength()) // attachments { // write the item id and amount for each attachment out.writeInt32(msg.readInt16()); out.writeInt32(msg.readInt16()); } send(out); }
void ChatHandler::handleListChannelUsersResponse(MessageIn &msg) { std::string channelName = msg.readString(); std::string userNick; std::string userModes; Channel *channel = channelManager->findByName(channelName); channel->getTab()->chatLog(_("Players in this channel:"), BY_CHANNEL); while(msg.getUnreadLength()) { userNick = msg.readString(); if (userNick == "") { break; } userModes = msg.readString(); if (userModes.find('o') != std::string::npos) { userNick = "@" + userNick; } localChatTab->chatLog(userNick, BY_CHANNEL, channel); } }
void CharacterComponent::deserialize(Entity &entity, MessageIn &msg) { auto *beingComponent = entity.getComponent<BeingComponent>(); // general character properties setAccountLevel(msg.readInt8()); beingComponent->setGender(ManaServ::getGender(msg.readInt8())); setHairStyle(msg.readInt8()); setHairColor(msg.readInt8()); setAttributePoints(msg.readInt16()); setCorrectionPoints(msg.readInt16()); // character attributes unsigned attrSize = msg.readInt16(); for (unsigned i = 0; i < attrSize; ++i) { unsigned id = msg.readInt16(); double base = msg.readDouble(); auto *attributeInfo = attributeManager->getAttributeInfo(id); if (attributeInfo) beingComponent->setAttribute(entity, attributeInfo, base); } // status effects currently affecting the character int statusSize = msg.readInt16(); for (int i = 0; i < statusSize; i++) { int status = msg.readInt16(); int time = msg.readInt16(); beingComponent->applyStatusEffect(status, time); } // location auto *map = MapManager::getMap(msg.readInt16()); entity.setMap(map); Point temporaryPoint; temporaryPoint.x = msg.readInt16(); temporaryPoint.y = msg.readInt16(); entity.getComponent<ActorComponent>()->setPosition(entity, temporaryPoint); // kill count int killSize = msg.readInt16(); for (int i = 0; i < killSize; i++) { int monsterId = msg.readInt16(); int kills = msg.readInt32(); setKillCount(monsterId, kills); } // character abilities int abilitiesSize = msg.readInt16(); for (int i = 0; i < abilitiesSize; i++) { const int id = msg.readInt32(); entity.getComponent<AbilityComponent>()->giveAbility(id); } // questlog int questlogSize = msg.readInt16(); for (int i = 0; i < questlogSize; ++i) { unsigned id = msg.readInt16(); QuestState state = (QuestState) msg.readInt8(); std::string title = msg.readString(); std::string description = msg.readString(); setQuestlog(id, state, title, description); } Possessions &poss = getPossessions(); // Loads inventory - must be last because size isn't transmitted InventoryData inventoryData; EquipData equipmentData; while (msg.getUnreadLength()) { InventoryItem i; i.slot = msg.readInt16(); i.itemId = msg.readInt16(); i.amount = msg.readInt16(); bool isEquipped = msg.readInt8() != 0; inventoryData.insert(std::make_pair(i.slot, i)); if (isEquipped) equipmentData.insert(i.slot); } poss.setInventory(inventoryData); poss.setEquipment(equipmentData); }
void PlayerHandler::handleMessage(MessageIn &msg) { switch (msg.getId()) { case GPMSG_PLAYER_MAP_CHANGE: handleMapChangeMessage(msg); break; case GPMSG_PLAYER_SERVER_CHANGE: { // TODO: Fix the servers to test this netToken = msg.readString(32); std::string address = msg.readString(); int port = msg.readInt16(); logger->log("Changing server to %s:%d", address.c_str(), port); gameServer.hostname = address; gameServer.port = port; gameServerConnection->disconnect(); Client::setState(STATE_CHANGE_MAP); local_player->setMap(0); } break; case GPMSG_PLAYER_ATTRIBUTE_CHANGE: { while (msg.getUnreadLength()) { int attrId = msg.readInt16(); double base = msg.readInt32() / 256.0; double value = msg.readInt32() / 256.0; // Set the core player attribute the stat // depending on attribute link. int playerInfoId = Attributes::getPlayerInfoIdFromAttrId(attrId); if (playerInfoId > -1) { PlayerInfo::setAttribute(playerInfoId, value); } else { PlayerInfo::setStatBase(attrId, base); PlayerInfo::setStatMod(attrId, value - base); } } } break; case GPMSG_PLAYER_EXP_CHANGE: { logger->log("EXP Update"); while (msg.getUnreadLength()) { int skill = msg.readInt16(); int current = msg.readInt32(); int next = msg.readInt32(); int level = msg.readInt16(); PlayerInfo::setStatExperience(skill, current, next); PlayerInfo::setStatBase(skill, level); } } break; case GPMSG_LEVELUP: { PlayerInfo::setAttribute(LEVEL, msg.readInt16()); PlayerInfo::setAttribute(CHAR_POINTS, msg.readInt16()); PlayerInfo::setAttribute(CORR_POINTS, msg.readInt16()); Particle* effect = particleEngine->addEffect( paths.getStringValue("particles") + paths.getStringValue("levelUpEffectFile") ,0, 0); local_player->controlParticle(effect); } break; case GPMSG_LEVEL_PROGRESS: { PlayerInfo::setAttribute(EXP, msg.readInt8()); } break; case GPMSG_RAISE_ATTRIBUTE_RESPONSE: { int errCode = msg.readInt8(); int attrNum = msg.readInt16(); 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 = PlayerInfo::getStatBase(attrNum) - 1; PlayerInfo::setAttribute(CHAR_POINTS, 0); PlayerInfo::setStatBase(attrNum, attrValue); } break; case ATTRIBMOD_DENIED: { // undo attribute change logger->log("Warning: Server denied increase of attribute %d (reason unknown) ", attrNum); int points = PlayerInfo::getAttribute(CHAR_POINTS) - 1; PlayerInfo::setAttribute(CHAR_POINTS, points); int attrValue = PlayerInfo::getStatBase(attrNum) - 1; PlayerInfo::setStatBase(attrNum, attrValue); } break; } } break; case GPMSG_LOWER_ATTRIBUTE_RESPONSE: { int errCode = msg.readInt8(); int attrNum = msg.readInt16(); 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 = PlayerInfo::getStatBase(attrNum) + 1; // TODO are these right? PlayerInfo::setAttribute(CHAR_POINTS, 0); PlayerInfo::setAttribute(CORR_POINTS, 0); PlayerInfo::setStatBase(attrNum, attrValue); } break; case ATTRIBMOD_DENIED: { // undo attribute change logger->log("Warning: Server denied reduction of attribute %d (reason unknown) ", attrNum); int charaPoints = PlayerInfo::getAttribute(CHAR_POINTS) - 1; PlayerInfo::setAttribute(CHAR_POINTS, charaPoints); int correctPoints = PlayerInfo::getAttribute(CORR_POINTS) + 1; PlayerInfo::setAttribute(CORR_POINTS, correctPoints); int attrValue = PlayerInfo::getStatBase(attrNum) + 1; PlayerInfo::setStatBase(attrNum, attrValue); } break; } } break; case GPMSG_SPECIAL_STATUS : { while (msg.getUnreadLength()) { // { B specialID, L current, L max, L recharge } int id = msg.readInt8(); int current = msg.readInt32(); int max = msg.readInt32(); int recharge = msg.readInt32(); PlayerInfo::setSpecialStatus(id, current, max, recharge); } } break; /* case SMSG_PLAYER_ARROW_MESSAGE: { Sint16 type = msg.readInt16(); switch (type) { case 0: localChatTab->chatLog(_("Equip arrows first."), BY_SERVER); break; default: logger->log("0x013b: Unhandled message %i", type); break; } } break; */ } }
void ServerHandler::processMessage(NetComputer *comp, MessageIn &msg) { GameServer *server = static_cast<GameServer *>(comp); switch (msg.getId()) { case GAMSG_REGISTER: { LOG_DEBUG("GAMSG_REGISTER"); // TODO: check the credentials of the game server server->address = msg.readString(); server->port = msg.readInt16(); const std::string password = msg.readString(); // checks the version of the remote item database with our local copy unsigned int dbversion = msg.readInt32(); LOG_INFO("Game server uses itemsdatabase with version " << dbversion); LOG_DEBUG("AGMSG_REGISTER_RESPONSE"); MessageOut outMsg(AGMSG_REGISTER_RESPONSE); if (dbversion == storage->getItemDatabaseVersion()) { LOG_DEBUG("Item databases between account server and " "gameserver are in sync"); outMsg.writeInt16(DATA_VERSION_OK); } else { LOG_DEBUG("Item database of game server has a wrong version"); outMsg.writeInt16(DATA_VERSION_OUTDATED); } if (password == Configuration::getValue("net_password", "changeMe")) { outMsg.writeInt16(PASSWORD_OK); // transmit global world state variables std::map<std::string, std::string> variables; variables = storage->getAllWorldStateVars(Storage::WorldMap); for (std::map<std::string, std::string>::iterator i = variables.begin(); i != variables.end(); i++) { outMsg.writeString(i->first); outMsg.writeString(i->second); } comp->send(outMsg); } else { LOG_INFO("The password given by " << server->address << ':' << server->port << " was bad."); outMsg.writeInt16(PASSWORD_BAD); comp->disconnect(outMsg); break; } LOG_INFO("Game server " << server->address << ':' << server->port << " wants to register " << (msg.getUnreadLength() / 2) << " maps."); while (msg.getUnreadLength()) { int id = msg.readInt16(); LOG_INFO("Registering map " << id << '.'); if (GameServer *s = getGameServerFromMap(id)) { LOG_ERROR("Server Handler: map is already registered by " << s->address << ':' << s->port << '.'); } else { MessageOut outMsg(AGMSG_ACTIVE_MAP); // Map variables outMsg.writeInt16(id); std::map<std::string, std::string> variables; variables = storage->getAllWorldStateVars(id); // Map vars number outMsg.writeInt16(variables.size()); for (std::map<std::string, std::string>::iterator i = variables.begin(); i != variables.end(); i++) { outMsg.writeString(i->first); outMsg.writeString(i->second); } // Persistent Floor Items std::list<FloorItem> items; items = storage->getFloorItemsFromMap(id); outMsg.writeInt16(items.size()); //number of floor items // Send each map item: item_id, amount, pos_x, pos_y for (std::list<FloorItem>::iterator i = items.begin(); i != items.end(); ++i) { outMsg.writeInt32(i->getItemId()); outMsg.writeInt16(i->getItemAmount()); outMsg.writeInt16(i->getPosX()); outMsg.writeInt16(i->getPosY()); } comp->send(outMsg); MapStatistics &m = server->maps[id]; m.nbEntities = 0; m.nbMonsters = 0; } } } break; case GAMSG_PLAYER_DATA: { LOG_DEBUG("GAMSG_PLAYER_DATA"); int id = msg.readInt32(); if (Character *ptr = storage->getCharacter(id, NULL)) { deserializeCharacterData(*ptr, msg); if (!storage->updateCharacter(ptr)) { LOG_ERROR("Failed to update character " << id << '.'); } delete ptr; } else { LOG_ERROR("Received data for non-existing character " << id << '.'); } } break; case GAMSG_PLAYER_SYNC: { LOG_DEBUG("GAMSG_PLAYER_SYNC"); GameServerHandler::syncDatabase(msg); } break; case GAMSG_REDIRECT: { LOG_DEBUG("GAMSG_REDIRECT"); int id = msg.readInt32(); std::string magic_token(utils::getMagicToken()); if (Character *ptr = storage->getCharacter(id, NULL)) { int mapId = ptr->getMapId(); if (GameServer *s = getGameServerFromMap(mapId)) { registerGameClient(s, magic_token, ptr); MessageOut result(AGMSG_REDIRECT_RESPONSE); result.writeInt32(id); result.writeString(magic_token, MAGIC_TOKEN_LENGTH); result.writeString(s->address); result.writeInt16(s->port); comp->send(result); } else { LOG_ERROR("Server Change: No game server for map " << mapId << '.'); } delete ptr; } else { LOG_ERROR("Received data for non-existing character " << id << '.'); } } break; case GAMSG_PLAYER_RECONNECT: { LOG_DEBUG("GAMSG_PLAYER_RECONNECT"); int id = msg.readInt32(); std::string magic_token = msg.readString(MAGIC_TOKEN_LENGTH); if (Character *ptr = storage->getCharacter(id, NULL)) { int accountID = ptr->getAccountID(); AccountClientHandler::prepareReconnect(magic_token, accountID); delete ptr; } else { LOG_ERROR("Received data for non-existing character " << id << '.'); } } break; case GAMSG_GET_VAR_CHR: { int id = msg.readInt32(); std::string name = msg.readString(); std::string value = storage->getQuestVar(id, name); MessageOut result(AGMSG_GET_VAR_CHR_RESPONSE); result.writeInt32(id); result.writeString(name); result.writeString(value); comp->send(result); } break; case GAMSG_SET_VAR_CHR: { int id = msg.readInt32(); std::string name = msg.readString(); std::string value = msg.readString(); storage->setQuestVar(id, name, value); } break; case GAMSG_SET_VAR_WORLD: { std::string name = msg.readString(); std::string value = msg.readString(); // save the new value to the database storage->setWorldStateVar(name, value, Storage::WorldMap); // relay the new value to all gameservers for (ServerHandler::NetComputers::iterator i = clients.begin(); i != clients.end(); i++) { MessageOut varUpdateMessage(AGMSG_SET_VAR_WORLD); varUpdateMessage.writeString(name); varUpdateMessage.writeString(value); (*i)->send(varUpdateMessage); } } break; case GAMSG_SET_VAR_MAP: { int mapid = msg.readInt32(); std::string name = msg.readString(); std::string value = msg.readString(); storage->setWorldStateVar(name, value, mapid); } break; case GAMSG_BAN_PLAYER: { int id = msg.readInt32(); int duration = msg.readInt32(); storage->banCharacter(id, duration); } break; case GAMSG_CHANGE_PLAYER_LEVEL: { int id = msg.readInt32(); int level = msg.readInt16(); storage->setPlayerLevel(id, level); } break; case GAMSG_CHANGE_ACCOUNT_LEVEL: { int id = msg.readInt32(); int level = msg.readInt16(); // get the character so we can get the account id Character *c = storage->getCharacter(id, NULL); if (c) { storage->setAccountLevel(c->getAccountID(), level); } } break; case GAMSG_STATISTICS: { while (msg.getUnreadLength()) { int mapId = msg.readInt16(); ServerStatistics::iterator i = server->maps.find(mapId); if (i == server->maps.end()) { LOG_ERROR("Server " << server->address << ':' << server->port << " should not be sending stati" "stics for map " << mapId << '.'); // Skip remaining data. break; } MapStatistics &m = i->second; m.nbEntities = msg.readInt16(); m.nbMonsters = msg.readInt16(); int nb = msg.readInt16(); m.players.resize(nb); for (int j = 0; j < nb; ++j) { m.players[j] = msg.readInt32(); } } } break; case GCMSG_REQUEST_POST: { // Retrieve the post for user LOG_DEBUG("GCMSG_REQUEST_POST"); MessageOut result(CGMSG_POST_RESPONSE); // get the character id int characterId = msg.readInt32(); // send the character id of sender result.writeInt32(characterId); // get the character based on the id Character *ptr = storage->getCharacter(characterId, NULL); if (!ptr) { // Invalid character LOG_ERROR("Error finding character id for post"); break; } // get the post for that character Post *post = postalManager->getPost(ptr); // send the post if valid if (post) { for (unsigned int i = 0; i < post->getNumberOfLetters(); ++i) { // get each letter, send the sender's name, // the contents and any attachments Letter *letter = post->getLetter(i); result.writeString(letter->getSender()->getName()); result.writeString(letter->getContents()); std::vector<InventoryItem> items = letter->getAttachments(); for (unsigned int j = 0; j < items.size(); ++j) { result.writeInt16(items[j].itemId); result.writeInt16(items[j].amount); } } // clean up postalManager->clearPost(ptr); } comp->send(result); } break; case GCMSG_STORE_POST: { // Store the letter for the user LOG_DEBUG("GCMSG_STORE_POST"); MessageOut result(CGMSG_STORE_POST_RESPONSE); // get the sender and receiver int senderId = msg.readInt32(); std::string receiverName = msg.readString(); // for sending it back result.writeInt32(senderId); // get their characters Character *sender = storage->getCharacter(senderId, NULL); Character *receiver = storage->getCharacter(receiverName); if (!sender || !receiver) { // Invalid character LOG_ERROR("Error finding character id for post"); result.writeInt8(ERRMSG_INVALID_ARGUMENT); break; } // get the letter contents std::string contents = msg.readString(); std::vector< std::pair<int, int> > items; while (msg.getUnreadLength()) { items.push_back(std::pair<int, int>(msg.readInt16(), msg.readInt16())); } // save the letter LOG_DEBUG("Creating letter"); Letter *letter = new Letter(0, sender, receiver); letter->addText(contents); for (unsigned int i = 0; i < items.size(); ++i) { InventoryItem item; item.itemId = items[i].first; item.amount = items[i].second; letter->addAttachment(item); } postalManager->addLetter(letter); result.writeInt8(ERRMSG_OK); comp->send(result); } break; case GAMSG_TRANSACTION: { LOG_DEBUG("TRANSACTION"); int id = msg.readInt32(); int action = msg.readInt32(); std::string message = msg.readString(); Transaction trans; trans.mCharacterId = id; trans.mAction = action; trans.mMessage = message; storage->addTransaction(trans); } break; case GCMSG_PARTY_INVITE: chatHandler->handlePartyInvite(msg); break; case GAMSG_CREATE_ITEM_ON_MAP: { int mapId = msg.readInt32(); int itemId = msg.readInt32(); int amount = msg.readInt16(); int posX = msg.readInt16(); int posY = msg.readInt16(); LOG_DEBUG("Gameserver create item " << itemId << " on map " << mapId); storage->addFloorItem(mapId, itemId, amount, posX, posY); } break; case GAMSG_REMOVE_ITEM_ON_MAP: { int mapId = msg.readInt32(); int itemId = msg.readInt32(); int amount = msg.readInt16(); int posX = msg.readInt16(); int posY = msg.readInt16(); LOG_DEBUG("Gameserver removed item " << itemId << " from map " << mapId); storage->removeFloorItem(mapId, itemId, amount, posX, posY); } break; case GAMSG_ANNOUNCE: { const std::string message = msg.readString(); const int senderId = msg.readInt16(); const std::string senderName = msg.readString(); chatHandler->handleAnnounce(message, senderId, senderName); } break; default: LOG_WARN("ServerHandler::processMessage, Invalid message type: " << msg.getId()); MessageOut result(XXMSG_INVALID); comp->send(result); break; } }
void AccountConnection::processMessage(MessageIn &msg) { LOG_DEBUG("Received message " << msg << " from account server"); switch (msg.getId()) { case AGMSG_REGISTER_RESPONSE: { if (msg.readInt16() != DATA_VERSION_OK) { LOG_ERROR("Item database is outdated! Please update to " "prevent inconsistencies"); stop(); // Disconnect gracefully from account server. // Stop gameserver to prevent inconsistencies. exit(EXIT_DB_EXCEPTION); } else { LOG_DEBUG("Local item database is " "in sync with account server."); } if (msg.readInt16() != PASSWORD_OK) { LOG_ERROR("This game server sent a invalid password"); stop(); exit(EXIT_BAD_CONFIG_PARAMETER); } // read world state variables while (msg.getUnreadLength()) { std::string key = msg.readString(); std::string value = msg.readString(); if (!key.empty() && !value.empty()) { GameState::setVariableFromDbserver(key, value); } } } break; case AGMSG_PLAYER_ENTER: { std::string token = msg.readString(MAGIC_TOKEN_LENGTH); Character *ptr = new Character(msg); gameHandler->addPendingCharacter(token, ptr); } break; case AGMSG_ACTIVE_MAP: { int mapId = msg.readInt16(); if (MapManager::activateMap(mapId)) { // Set map variables MapComposite *m = MapManager::getMap(mapId); int mapVarsNumber = msg.readInt16(); for(int i = 0; i < mapVarsNumber; ++i) { std::string key = msg.readString(); std::string value = msg.readString(); if (!key.empty() && !value.empty()) m->setVariableFromDbserver(key, value); } // Recreate potential persistent floor items LOG_DEBUG("Recreate persistant items on map " << mapId); int floorItemsNumber = msg.readInt16(); for (int i = 0; i < floorItemsNumber; ++i) { int itemId = msg.readInt32(); int amount = msg.readInt16(); int posX = msg.readInt16(); int posY = msg.readInt16(); if (ItemClass *ic = itemManager->getItem(itemId)) { Item *item = new Item(ic, amount); item->setMap(m); Point dst(posX, posY); item->setPosition(dst); if (!GameState::insertOrDelete(item)) { // The map is full. LOG_WARN("Couldn't add floor item(s) " << itemId << " into map " << mapId); return; } } } } } break; case AGMSG_SET_VAR_WORLD: { std::string key = msg.readString(); std::string value = msg.readString(); GameState::setVariableFromDbserver(key, value); LOG_DEBUG("Global variable \"" << key << "\" has changed to \"" << value << "\""); } break; case AGMSG_REDIRECT_RESPONSE: { int id = msg.readInt32(); std::string token = msg.readString(MAGIC_TOKEN_LENGTH); std::string address = msg.readString(); int port = msg.readInt16(); gameHandler->completeServerChange(id, token, address, port); } break; case AGMSG_GET_VAR_CHR_RESPONSE: { int id = msg.readInt32(); std::string name = msg.readString(); std::string value = msg.readString(); recoveredQuestVar(id, name, value); } break; case CGMSG_CHANGED_PARTY: { // Character DB id int charid = msg.readInt32(); // Party id, 0 for none int partyid = msg.readInt32(); gameHandler->updateCharacter(charid, partyid); } break; case CGMSG_POST_RESPONSE: { // get the character Character *character = postMan->getCharacter(msg.readInt32()); // check character is still valid if (!character) { break; } std::string sender = msg.readString(); std::string letter = msg.readString(); postMan->gotPost(character, sender, letter); } break; case CGMSG_STORE_POST_RESPONSE: { // get character Character *character = postMan->getCharacter(msg.readInt32()); // check character is valid if (!character) { break; } // TODO: Get NPC to tell character if the sending of post // was successful or not } break; default: LOG_WARN("Invalid message type"); break; } }
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 localChatTab->chatLog(_("Guild created.")); joinedGuild(msg); } else { localChatTab->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 localChatTab->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 localChatTab->chatLog(_("Member was promoted successfully.")); } else { // promotion failed localChatTab->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) { Channel *channel = channelManager->findByName(guild->getName()); channelManager->removeChannel(channel); guildWindow->removeTab(guildId); player_node->removeGuild(guildId); } } } break; } }
void AccountHandler::handleCharacterCreateMessage(AccountClient &client, MessageIn &msg) { std::string name = msg.readString(); int hairStyle = msg.readInt8(); int hairColor = msg.readInt8(); int gender = msg.readInt8(); // Avoid creation of character from old clients. int slot = -1; if (msg.getUnreadLength() > 7) slot = msg.readInt8(); MessageOut reply(APMSG_CHAR_CREATE_RESPONSE); Account *acc = client.getAccount(); if (!acc) { reply.writeInt8(ERRMSG_NO_LOGIN); } else if (!stringFilter->filterContent(name)) { reply.writeInt8(ERRMSG_INVALID_ARGUMENT); } else if (stringFilter->findDoubleQuotes(name)) { reply.writeInt8(ERRMSG_INVALID_ARGUMENT); } else if (hairStyle > mNumHairStyles) { reply.writeInt8(CREATE_INVALID_HAIRSTYLE); } else if (hairColor > mNumHairColors) { reply.writeInt8(CREATE_INVALID_HAIRCOLOR); } else if (gender > mNumGenders) { reply.writeInt8(CREATE_INVALID_GENDER); } else if ((name.length() < mMinNameLength) || (name.length() > mMaxNameLength)) { reply.writeInt8(ERRMSG_INVALID_ARGUMENT); } else { if (storage->doesCharacterNameExist(name)) { reply.writeInt8(CREATE_EXISTS_NAME); client.send(reply); return; } // An account shouldn't have more // than <account_maxCharacters> characters. Characters &chars = acc->getCharacters(); if (slot < 1 || slot > mMaxCharacters || !acc->isSlotEmpty((unsigned int) slot)) { reply.writeInt8(CREATE_INVALID_SLOT); client.send(reply); return; } if ((int)chars.size() >= mMaxCharacters) { reply.writeInt8(CREATE_TOO_MUCH_CHARACTERS); client.send(reply); return; } // TODO: Add race, face and maybe special attributes. // Customization of character's attributes... std::vector<int> attributes = std::vector<int>(mModifiableAttributes.size(), 0); for (unsigned int i = 0; i < mModifiableAttributes.size(); ++i) attributes[i] = msg.readInt16(); int totalAttributes = 0; for (unsigned int i = 0; i < mModifiableAttributes.size(); ++i) { // For good total attributes check. totalAttributes += attributes.at(i); // For checking if all stats are >= min and <= max. if (attributes.at(i) < mAttributeMinimum || attributes.at(i) > mAttributeMaximum) { reply.writeInt8(CREATE_ATTRIBUTES_OUT_OF_RANGE); client.send(reply); return; } } if (totalAttributes > mStartingPoints) { reply.writeInt8(CREATE_ATTRIBUTES_TOO_HIGH); } else if (totalAttributes < mStartingPoints) { reply.writeInt8(CREATE_ATTRIBUTES_TOO_LOW); } else { Character *newCharacter = new Character(name); // Set the initial attributes provided by the client for (unsigned int i = 0; i < mModifiableAttributes.size(); ++i) { newCharacter->mAttributes.insert( std::make_pair(mModifiableAttributes.at(i), attributes[i])); } newCharacter->mAttributes.insert(mDefaultAttributes.begin(), mDefaultAttributes.end()); newCharacter->setAccount(acc); newCharacter->setCharacterSlot(slot); newCharacter->setLevel(1); // Init GP value to avoid flawed ones. AttributeMap::iterator itr = newCharacter->mAttributes.find(ATTR_GP); if (itr != newCharacter->mAttributes.end()) { itr->second.base = 0; itr->second.modified = 0; } newCharacter->setCharacterPoints(0); newCharacter->setCorrectionPoints(0); newCharacter->setGender(gender); newCharacter->setHairStyle(hairStyle); newCharacter->setHairColor(hairColor); newCharacter->setMapId(Configuration::getValue("char_startMap", 1)); Point startingPos(Configuration::getValue("char_startX", 1024), Configuration::getValue("char_startY", 1024)); newCharacter->setPosition(startingPos); acc->addCharacter(newCharacter); LOG_INFO("Character " << name << " was created for " << acc->getName() << "'s account."); storage->flush(acc); // flush changes // log transaction Transaction trans; trans.mCharacterId = newCharacter->getDatabaseID(); trans.mAction = TRANS_CHAR_CREATE; trans.mMessage = acc->getName() + " created character "; trans.mMessage.append("called " + name); storage->addTransaction(trans); reply.writeInt8(ERRMSG_OK); client.send(reply); // Send new characters infos back to client sendCharacterData(client, *chars[slot]); return; } } client.send(reply); }