void CharServerHandler::processCharLogin(Net::MessageIn &msg) { msg.skip(2, "packet len"); const int slots = msg.readInt8("MAX_CHARS"); msg.readInt8("sd->char_slots"); msg.readInt8("MAX_CHARS"); loginData.characterSlots = static_cast<uint16_t>(slots); msg.skip(20, "unused 0"); delete_all(mCharacters); mCharacters.clear(); // Derive number of characters from message length const int count = (msg.getLength() - 27) / (106 + 4 + 2 + 16 + 4 + 4 + 4 + 4); for (int i = 0; i < count; ++i) { Net::Character *const character = new Net::Character; readPlayerData(msg, character); mCharacters.push_back(character); if (character->dummy) { logger->log("CharServer: Player: %s (%d)", character->dummy->getName().c_str(), character->slot); } } client->setState(STATE_CHAR_SELECT); }
void InventoryHandler::handleMessage(Net::MessageIn &msg) { switch (msg.getId()) { case GPMSG_INVENTORY_FULL: player_node->clearInventory(); player_node->mEquipment->setBackend(&mEqiups); // no break! case GPMSG_INVENTORY: while (msg.getUnreadLength()) { unsigned int slot = msg.readInt8(); if (slot == 255) { player_node->setMoney(msg.readInt32()); continue; } int id = msg.readInt16(); if (slot < EQUIPMENT_SIZE) { mEqiups.setEquipment(slot, id); } else if (slot >= 32 && slot < 32 + getSize(INVENTORY)) { int amount = id ? msg.readInt8() : 0; player_node->setInvItem(slot - 32, id, amount); } }; break; } }
void PartyHandler::processPartyMove(Net::MessageIn &msg) { int id = msg.readInt32(); // id PartyMember *m = nullptr; if (Ea::taParty) m = Ea::taParty->getMember(id); if (m) { msg.skip(4); // 0 m->setX(msg.readInt16()); // x m->setY(msg.readInt16()); // y m->setOnline(msg.readInt8()); // online (if 0) msg.readString(24); // party msg.readString(24); // nick m->setMap(msg.readString(16)); // map } else { msg.skip(4); // 0 msg.readInt16(); // x msg.readInt16(); // y msg.readInt8(); // online (if 0) msg.readString(24); // party msg.readString(24); // nick msg.readString(16); // map } }
void PartyRecv::processPartyMemberInfo(Net::MessageIn &msg) { const BeingId id = msg.readBeingId("account id"); const bool leader = msg.readInt32("leader") == 0U; const int x = msg.readInt16("x"); const int y = msg.readInt16("y"); const bool online = msg.readInt8("online") == 0U; msg.readString(24, "party name"); const std::string nick = msg.readString(24, "player name"); const std::string map = msg.readString(16, "map name"); msg.readInt8("party.item&1"); msg.readInt8("party.item&2"); if (!Ea::taParty) return; PartyMember *const member = Ea::taParty->addMember(id, nick); if (member) { if (partyTab && member->getOnline() != online) partyTab->showOnline(nick, fromBool(online, Online)); member->setLeader(leader); member->setOnline(online); member->setMap(map); member->setX(x); member->setY(y); } }
void CharServerHandler::readPlayerData(Net::MessageIn &msg, Net::Character *character) { const Token &token = static_cast<LoginHandler*>(Net::getLoginHandler())->getToken(); LocalPlayer *tempPlayer = new LocalPlayer(msg.readInt32(), 0); tempPlayer->setGender(token.sex); character->data.mAttributes[EXP] = msg.readInt32(); character->data.mAttributes[MONEY] = msg.readInt32(); character->data.mStats[JOB].exp = msg.readInt32(); int temp = msg.readInt32(); character->data.mStats[JOB].base = temp; character->data.mStats[JOB].mod = temp; tempPlayer->setSprite(SPRITE_SHOE, msg.readInt16()); tempPlayer->setSprite(SPRITE_GLOVES, msg.readInt16()); tempPlayer->setSprite(SPRITE_CAPE, msg.readInt16()); tempPlayer->setSprite(SPRITE_MISC1, msg.readInt16()); msg.readInt32(); // option msg.readInt32(); // karma msg.readInt32(); // manner msg.skip(2); // unknown character->data.mAttributes[HP] = msg.readInt16(); character->data.mAttributes[MAX_HP] = msg.readInt16(); character->data.mAttributes[MP] = msg.readInt16(); character->data.mAttributes[MAX_MP] = msg.readInt16(); msg.readInt16(); // speed tempPlayer->setSubtype(msg.readInt16()); // class (used for race) int hairStyle = msg.readInt16(); Uint16 weapon = msg.readInt16(); tempPlayer->setSprite(SPRITE_WEAPON, weapon, "", true); character->data.mAttributes[LEVEL] = msg.readInt16(); msg.readInt16(); // skill point tempPlayer->setSprite(SPRITE_BOTTOMCLOTHES, msg.readInt16()); // head bottom tempPlayer->setSprite(SPRITE_SHIELD, msg.readInt16()); tempPlayer->setSprite(SPRITE_HAT, msg.readInt16()); // head option top tempPlayer->setSprite(SPRITE_TOPCLOTHES, msg.readInt16()); // head option mid tempPlayer->setSprite(SPRITE_HAIR, hairStyle * -1, hairDB.getHairColor(msg.readInt16())); tempPlayer->setSprite(SPRITE_MISC2, msg.readInt16()); tempPlayer->setName(msg.readString(24)); character->dummy = tempPlayer; for (int i = 0; i < 6; i++) character->data.mStats[i + STRENGTH].base = msg.readInt8(); character->slot = msg.readInt8(); // character slot msg.readInt8(); // unknown }
void InventoryHandler::handleMessage(Net::MessageIn &msg) { switch (msg.getId()) { case GPMSG_INVENTORY_FULL: { PlayerInfo::clearInventory(); PlayerInfo::getEquipment()->setBackend(&mEquips); int count = msg.readInt16(); while (count--) { unsigned int slot = msg.readInt16(); int id = msg.readInt16(); unsigned int amount = msg.readInt16(); PlayerInfo::setInventoryItem(slot, id, amount); } while (msg.getUnreadLength()) { unsigned int slot = msg.readInt8(); unsigned int ref = msg.readInt16(); mEquips.addEquipment(slot, ref); } } break; case GPMSG_INVENTORY: while (msg.getUnreadLength()) { unsigned int slot = msg.readInt16(); int id = msg.readInt16(); unsigned int amount = id ? msg.readInt16() : 0; PlayerInfo::setInventoryItem(slot, id, amount); } break; case GPMSG_EQUIP: while (msg.getUnreadLength()) { unsigned int ref = msg.readInt16(); int count = msg.readInt8(); while (count--) { unsigned int slot = msg.readInt8(); unsigned int used = msg.readInt8(); mEquips.setEquipment(slot, used, ref); } } break; } }
void BeingHandler::handleBeingAttackMessage(Net::MessageIn &msg) { Being *being = actorSpriteManager->findBeing(msg.readInt16()); const BeingDirection direction = (BeingDirection) msg.readInt8(); const int attackType = msg.readInt8(); if (!being) return; being->setDirection(direction); being->setAction(Being::ATTACK, attackType); }
void PlayerHandler::processPlayerStatUpdate4(Net::MessageIn &msg) { int type = msg.readInt16(); int ok = msg.readInt8(); int value = msg.readInt8(); if (ok != 1) { int oldValue = PlayerInfo::getStatBase(type); int points = PlayerInfo::getAttribute(CHAR_POINTS); points += oldValue - value; PlayerInfo::setAttribute(CHAR_POINTS, points); SERVER_NOTICE(_("Cannot raise skill!")) }
void LoginHandler::processServerVersion(Net::MessageIn &msg) { msg.readInt8(); msg.readInt8(); msg.readInt8(); msg.readInt8(); msg.readInt32(); mRegistrationEnabled = true; serverVersion = 0; if (Client::getState() != STATE_LOGIN) Client::setState(STATE_LOGIN); // Leave this last mVersionResponse = true; }
void SkillHandler::processPlayerSkills(Net::MessageIn &msg) const { msg.readInt16(); // length const int skillCount = (msg.getLength() - 4) / 37; int updateSkill = 0; for (int k = 0; k < skillCount; k++) { const int skillId = msg.readInt16(); msg.readInt16(); // target type msg.skip(2); // skill pool flags const int level = msg.readInt16(); msg.readInt16(); // sp const int range = msg.readInt16(); msg.skip(24); // 0 unused const int up = msg.readInt8(); const int oldLevel = PlayerInfo::getSkillLevel(skillId); if (oldLevel && oldLevel != level) updateSkill = skillId; PlayerInfo::setSkillLevel(skillId, level); if (skillDialog) { if (!skillDialog->updateSkill(skillId, range, up)) skillDialog->addSkill(skillId, level, range, up); } } if (updateSkill && skillDialog) skillDialog->playUpdateEffect(updateSkill); }
void ItemRecv::processItemDropped2(Net::MessageIn &msg) { const BeingId id = msg.readBeingId("id"); const int itemId = msg.readInt16("item id"); const ItemTypeT itemType = static_cast<ItemTypeT>(msg.readUInt8("type")); const Identified identified = fromInt( msg.readUInt8("identify"), Identified); const Damaged damaged = fromBool(msg.readUInt8("attribute"), Damaged); const uint8_t refine = msg.readUInt8("refine"); int cards[maxCards]; for (int f = 0; f < maxCards; f++) cards[f] = msg.readInt16("card"); const int x = msg.readInt16("x"); const int y = msg.readInt16("y"); const int amount = msg.readInt16("amount"); const int subX = CAST_S32(msg.readInt8("subx")); const int subY = CAST_S32(msg.readInt8("suby")); if (actorManager) { actorManager->createItem(id, itemId, x, y, itemType, amount, refine, ItemColorManager::getColorFromCards(&cards[0]), identified, damaged, subX, subY, &cards[0]); } }
void CharServerHandler::processCharLogin(Net::MessageIn &msg) { msg.skip(2); // Length word int slots = msg.readInt16(); if (slots > 0 && slots < 30) loginData.characterSlots = static_cast<short unsigned int>(slots); bool version = msg.readInt8() == 1 && serverVersion > 0; msg.skip(17); // 0 Unused delete_all(mCharacters); mCharacters.clear(); // Derive number of characters from message length int count = (msg.getLength() - 24); if (version) count /= 120; else count /= 106; for (int i = 0; i < count; ++i) { Net::Character *character = new Net::Character; readPlayerData(msg, character, version); mCharacters.push_back(character); if (character && character->dummy) { logger->log("CharServer: Player: %s (%d)", character->dummy->getName().c_str(), character->slot); } } Client::setState(STATE_CHAR_SELECT); }
void LoginHandler::procecessCharPasswordResponse(Net::MessageIn &msg) const { // 0: acc not found, 1: success, 2: password mismatch, 3: pass too short const int errMsg = msg.readInt8(); // Successful pass change if (errMsg == 1) { client->setState(STATE_CHANGEPASSWORD_SUCCESS); } // pass change failed else { switch (errMsg) { case 0: errorMessage = // TRANSLATORS: error message _("Account was not found. Please re-login."); break; case 2: // TRANSLATORS: error message errorMessage = _("Old password incorrect."); break; case 3: // TRANSLATORS: error message errorMessage = _("New password too short."); break; default: // TRANSLATORS: error message errorMessage = _("Unknown error."); break; } client->setState(STATE_ACCOUNTCHANGE_ERROR); } }
static void handleLooks(Being *being, Net::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] = { SPRITE_WEAPON, SPRITE_HAT, SPRITE_TOPCLOTHES, SPRITE_BOTTOMCLOTHES }; 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,"", (slots[i] == SPRITE_WEAPON)); } }
void ChatHandler::handleEnterChannelResponse(Net::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 ItemRecv::processItemDropped(Net::MessageIn &msg) { const BeingId id = msg.readBeingId("id"); const int itemId = msg.readInt16("item id"); ItemTypeT itemType = ItemType::Unknown; if (msg.getVersion() >= 20130000) itemType = static_cast<ItemTypeT>(msg.readInt16("type")); const Identified identified = fromInt( msg.readUInt8("identify"), Identified); const int x = msg.readInt16("x"); const int y = msg.readInt16("y"); const int subX = CAST_S32(msg.readInt8("subx")); const int subY = CAST_S32(msg.readInt8("suby")); const int amount = msg.readInt16("count"); if (actorManager) { actorManager->createItem(id, itemId, x, y, itemType, amount, 0, ItemColor_one, identified, Damaged_false, subX, subY, nullptr); } }
void GuildHandler::processGuildInviteAck(Net::MessageIn &msg) const { const int flag = msg.readInt8(); if (!guildTab) return; switch (flag) { case 0: NotifyManager::notify(NotifyManager::GUILD_INVITE_FAILED); break; case 1: NotifyManager::notify(NotifyManager::GUILD_INVITE_REJECTED); break; case 2: NotifyManager::notify(NotifyManager::GUILD_INVITE_JOINED); break; case 3: NotifyManager::notify(NotifyManager::GUILD_INVITE_FULL); break; default: NotifyManager::notify(NotifyManager::GUILD_INVITE_ERROR); break; } }
void GameRecv::processMapLogin(Net::MessageIn &msg) { unsigned char direction; uint16_t x; uint16_t y; msg.readInt32("start time"); msg.readCoordinates(x, y, direction, "position"); msg.readInt8("x size"); msg.readInt8("y size"); logger->log("Protocol: Player start position: " "(%d, %d), Direction: %d", x, y, direction); if (msg.getVersion() >= 20080102) msg.readInt16("font"); if (msg.getVersion() >= 20141022 && msg.getVersion() < 20160330) msg.readUInt8("sex"); mLastHost &= 0xffffff; Network *const network = Network::mInstance; if (network != nullptr) network->pauseDispatch(); // Switch now or we'll have problems client->setState(State::GAME); if (localPlayer != nullptr) localPlayer->setTileCoords(x, y); }
void ItemRecv::processItemVisible(Net::MessageIn &msg) { const BeingId id = msg.readBeingId("item object id"); const int itemId = msg.readInt16("item id"); const Identified identified = fromInt( msg.readUInt8("identify"), Identified); const int x = msg.readInt16("x"); const int y = msg.readInt16("y"); const int amount = msg.readInt16("amount"); const int subX = static_cast<int>(msg.readInt8("sub x")); const int subY = static_cast<int>(msg.readInt8("sub y")); if (actorManager) { actorManager->createItem(id, itemId, x, y, 0, amount, 0, ItemColor_one, identified, Damaged_false, subX, subY, nullptr); } }
void GuildHandler::processGuildCreateResponse(Net::MessageIn &msg) const { const int flag = msg.readInt8(); switch (flag) { case 0: // Success NotifyManager::notify(NotifyManager::GUILD_CREATED); break; case 1: // Already in a guild NotifyManager::notify(NotifyManager::GUILD_ALREADY); break; case 2: // Unable to make (likely name already in use) NotifyManager::notify(NotifyManager::GUILD_ALREADY); break; case 3: // Emperium check failed NotifyManager::notify(NotifyManager::GUILD_EMPERIUM_CHECK_FAILED); break; default: // Unknown response NotifyManager::notify(NotifyManager::GUILD_ERROR); break; } }
void CharServerHandler::processCharCreateFailed(Net::MessageIn &msg) { switch (msg.readInt8()) { case 1: case 0: default: errorMessage = _("Failed to create character. Most " "likely the name is already taken."); break; case 2: errorMessage = _("Wrong name."); break; case 3: errorMessage = _("Incorrect stats."); break; case 4: errorMessage = _("Incorrect hair."); break; case 5: errorMessage = _("Incorrect slot."); break; case 6: errorMessage = _("Incorrect race."); break; } new OkDialog(_("Error"), errorMessage, DIALOG_ERROR); if (mCharCreateDialog) mCharCreateDialog->unlock(); }
void PartyHandler::processPartyCreate(Net::MessageIn &msg) { if (msg.readInt8()) SERVER_NOTICE(_("Could not create party.")) else SERVER_NOTICE(_("Party successfully created.")) }
void ItemHandler::handleMessage(Net::MessageIn &msg) { switch (msg.getId()) { case SMSG_ITEM_VISIBLE: case SMSG_ITEM_DROPPED: { int id = msg.readInt32(); int itemId = msg.readInt16(); msg.readInt8(); // identify flag int x = msg.readInt16(); int y = msg.readInt16(); msg.skip(4); // amount,subX,subY / subX,subY,amount Game *game = Game::instance(); if (!game) break; if (Map *map = game->getCurrentMap()) actorSpriteManager->createItem(id, itemId, map->getTileCenter(x, y)); } break; case SMSG_ITEM_REMOVE: if (FloorItem *item = actorSpriteManager->findItem(msg.readInt32())) actorSpriteManager->destroy(item); break; } }
void GuildHandler::processGuildSkillUp(Net::MessageIn &msg) const { msg.readInt16(); // Skill ID msg.readInt16(); // Level msg.readInt16(); // SP msg.readInt16(); // 'Range' msg.readInt8(); // unused? (always 1) }
void PartyRecv::processPartySettings(Net::MessageIn &msg) { if (!partyTab) { if (!chatWindow) return; Ea::PartyRecv::createTab(); } msg.readInt32("party exp"); const PartyShareT exp = static_cast<PartyShareT>( msg.readInt8("share exp")); const PartyShareT item = static_cast<PartyShareT>( msg.readInt8("share item")); Ea::PartyRecv::processPartySettingsContinue(msg, exp, item); }
void ItemHandler::processItemDropped(Net::MessageIn &msg) const { const int id = msg.readInt32(); const int itemId = msg.readInt16(); const unsigned char identify = msg.readInt8(); // identify flag const int x = msg.readInt16(); const int y = msg.readInt16(); const int subX = msg.readInt8(); const int subY = msg.readInt8(); const int amount = msg.readInt16(); if (actorManager) { actorManager->createItem(id, itemId, x, y, amount, identify, subX, subY); } }
void ChatHandler::handleQuitChannelResponse(Net::MessageIn &msg) { if(msg.readInt8() == ERRMSG_OK) { short channelId = msg.readInt16(); Channel *channel = channelManager->findById(channelId); channelManager->removeChannel(channel); } }
void BeingHandler::handleBeingDirChangeMessage(Net::MessageIn &msg) { Being *being = actorSpriteManager->findBeing(msg.readInt16()); if (!being) return; int data = msg.readInt8(); // The direction for the player's character is handled on client side. if (being != player_node) being->setDirection((BeingDirection) data); }
void ChatHandler::handleChannelEvent(Net::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: channel->getTab()->chatLog(strprintf(_("%s entered the " "channel."), line.c_str()), BY_CHANNEL); break; case CHAT_EVENT_LEAVING_PLAYER: channel->getTab()->chatLog(strprintf(_("%s left the channel."), line.c_str()), BY_CHANNEL); break; case CHAT_EVENT_TOPIC_CHANGE: channel->getTab()->chatLog(strprintf(_("Topic: %s"), line.c_str()), BY_CHANNEL); 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()); channel->getTab()->chatLog(strprintf(_("%s has set mode %s " "on user %s."), user1.c_str(), mode.c_str(), user2.c_str()), BY_CHANNEL); } 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()); channel->getTab()->chatLog(strprintf(_("%s has kicked %s."), user1.c_str(), user2.c_str()), BY_CHANNEL); } break; default: channel->getTab()->chatLog(_("Unknown channel event."), BY_CHANNEL); } } }
void PartyRecv::processPartyMemberInfo(Net::MessageIn &msg) { const BeingId id = msg.readBeingId("account id"); if (msg.getVersion() >= 20171207) msg.readBeingId("char id"); const bool leader = msg.readInt32("leader") == 0U; int level = 0; if (msg.getVersionMain() >= 20170524 || msg.getVersionRe() >= 20170502 || packets_zero == true) { msg.readInt16("class"); level = msg.readInt16("level"); } const int x = msg.readInt16("x"); const int y = msg.readInt16("y"); const bool online = msg.readInt8("online") == 0U; msg.readString(24, "party name"); const std::string nick = msg.readString(24, "player name"); const std::string map = msg.readString(16, "map name"); msg.readInt8("pickup item share (&1)"); msg.readInt8("get item share (&2)"); if (Ea::taParty == nullptr) return; PartyMember *const member = Ea::taParty->addMember(id, nick); if (member != nullptr) { if ((partyTab != nullptr) && member->getOnline() != online) partyTab->showOnline(nick, fromBool(online, Online)); member->setLeader(leader); member->setOnline(online); member->setMap(map); member->setX(x); member->setY(y); if (level != 0) member->setLevel(level); } }