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 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 PartyHandler::processPartyLeave(Net::MessageIn &msg) { int id = msg.readInt32(); std::string nick = msg.readString(24); msg.readInt8(); // fail if (!player_node) return; if (id == player_node->getId()) { if (Ea::taParty) { Ea::taParty->removeFromMembers(); Ea::taParty->clearMembers(); } SERVER_NOTICE(_("You have left the party.")) delete Ea::partyTab; Ea::partyTab = nullptr; if (socialWindow && Ea::taParty) socialWindow->removeTab(Ea::taParty); player_node->setPartyName(""); } else { if (Ea::partyTab) { Ea::partyTab->chatLog(strprintf( _("%s has left your party."), nick.c_str()), BY_SERVER); } if (actorSpriteManager) { Being *b = actorSpriteManager->findBeing(id); if (b && b->getType() == Being::PLAYER) { b->setParty(nullptr); b->setPartyName(""); } } if (Ea::taParty) Ea::taParty->removeMember(id); } }
void PlayerHandler::processPlayerGetExp(Net::MessageIn &msg) { if (!localPlayer) return; const BeingId id = msg.readBeingId("player id"); const int exp = msg.readInt32("exp amount"); const int stat = msg.readInt16("exp type"); const bool fromQuest = msg.readInt16("is from quest"); if (!fromQuest && id == localPlayer->getId()) { if (stat == 1) localPlayer->addXpMessage(exp); else if (stat == 2) localPlayer->addJobMessage(exp); else UNIMPLIMENTEDPACKET; } // need show particle depend on isQuest flag, for now ignored }
void PartyHandler::processPartyInvited(Net::MessageIn &msg) { int id = msg.readInt32(); std::string partyName = msg.readString(24); std::string nick(""); Being *being; if (actorSpriteManager) { if ((being = actorSpriteManager->findBeing(id))) { if (being && being->getType() == Being::PLAYER) nick = being->getName(); } } if (socialWindow) socialWindow->showPartyInvite(partyName, nick); }
void FamilyRecv::processAskForChildReply(Net::MessageIn &msg) { const int type = msg.readInt32("type"); switch (type) { case 0: NotifyManager::notify(NotifyTypes::ADOPT_CHILD_ERROR_HAVE_BABY); break; case 1: NotifyManager::notify(NotifyTypes::ADOPT_CHILD_ERROR_LEVEL); break; case 2: NotifyManager::notify(NotifyTypes::ADOPT_CHILD_ERROR_BABY_MARRIED); break; default: UNIMPLEMENTEDPACKETFIELD(type); break; } }
void BuyingStoreRecv::processBuyingStoreCreateFailed(Net::MessageIn &msg) { const int16_t result = msg.readInt16("result"); const int weight = msg.readInt32("weight"); switch (result) { case 1: default: NotifyManager::notify(NotifyTypes::BUYING_STORE_CREATE_FAILED); break; case 2: NotifyManager::notify( NotifyTypes::BUYING_STORE_CREATE_FAILED_WEIGHT, weight); break; case 8: NotifyManager::notify(NotifyTypes::BUYING_STORE_CREATE_EMPTY); break; } }
void GuildRecv::processGuildPosNameList(Net::MessageIn &msg) { if (taGuild == nullptr) { logger->log1("!taGuild"); return; } const int length = msg.readInt16("len"); if (length < 4) return; const int count = (length - 4) / 28; for (int i = 0; i < count; i++) { const int id = msg.readInt32("position id"); const std::string name = msg.readString(24, "position name"); taGuild->addPos(id, name); } }
void BuyingStoreRecv::processBuyingStoreDeleteItem(Net::MessageIn &msg) { Inventory *const inventory = localPlayer ? PlayerInfo::getInventory() : nullptr; const int index = msg.readInt16("index") - INVENTORY_OFFSET; const int amount = msg.readInt16("amount"); msg.readInt32("price"); if (inventory) { if (Item *const item = inventory->getItem(index)) { item->increaseQuantity(-amount); if (item->getQuantity() == 0) inventory->removeItemAt(index); ArrowsListener::distributeEvent(); } } }
void GuildHandler::processGuildPosNameList(Net::MessageIn &msg) const { if (!taGuild) { logger->log1("!taGuild"); return; } const int length = msg.readInt16(); if (length < 4) return; const int count = (length - 4) / 28; for (int i = 0; i < count; i++) { const int id = msg.readInt32(); // ID const std::string name = msg.readString(24); // Position name taGuild->addPos(id, name); } }
void AchievementRecv::processAchievementUpdate(Net::MessageIn &msg) { UNIMPLEMENTEDPACKET; msg.readInt32("total points"); msg.readInt16("rank level"); msg.readInt32("rank points"); msg.readInt32("rank points need"); msg.readInt32("ach id"); msg.readUInt8("completed"); for (int d = 0; d < 10; d ++) msg.readInt32("objective"); msg.readInt32("completed at"); msg.readUInt8("reward"); }
void AchievementRecv::processAchievementList(Net::MessageIn &msg) { UNIMPLEMENTEDPACKET; const int count = (msg.readInt16("len") - 22) / 50; msg.readInt32("total achievements"); msg.readInt32("total points"); msg.readInt16("rank level"); msg.readInt32("rank points"); msg.readInt32("rank points need"); for (int f = 0; f < count; f ++) { msg.readInt32("ach id"); msg.readUInt8("completed"); for (int d = 0; d < 10; d ++) msg.readInt32("objective"); msg.readInt32("completed at"); msg.readUInt8("reward"); } }
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); } }
void GameRecv::processMapLogin(Net::MessageIn &msg) { unsigned char direction; uint16_t x; uint16_t y; msg.readInt32("tick"); msg.readCoordinates(x, y, direction, "position"); msg.readInt16("unknown?"); logger->log("Protocol: Player start position: (%d, %d)," " Direction: %d", x, y, direction); 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 PartyHandler::processPartyUpdateHp(Net::MessageIn &msg) { int id = msg.readInt32(); int hp = msg.readInt16(); int maxhp = msg.readInt16(); PartyMember *m = nullptr; if (Ea::taParty) m = Ea::taParty->getMember(id); if (m) { m->setHp(hp); m->setMaxHp(maxhp); } // The server only sends this when the member is in range, so // lets make sure they get the party hilight. if (actorSpriteManager && Ea::taParty) { if (Being *b = actorSpriteManager->findBeing(id)) b->setParty(Ea::taParty); } }
void PartyRecv::processPartySettings(Net::MessageIn &msg) { if (partyTab == nullptr) { if (chatWindow == nullptr) return; Ea::PartyRecv::createTab(); } const PartyShareT exp = static_cast<PartyShareT>( msg.readInt32("party exp")); Ea::PartyRecv::processPartyExpSettingsContinue(msg, exp); if (msg.getVersion() >= 20090603) { const PartyShareT item = static_cast<PartyShareT>( msg.readInt8("pickup item share (&1)")); Ea::PartyRecv::processPartyItemSettingsContinue(msg, item); const PartyShareT autoItem = static_cast<PartyShareT>( msg.readInt8("get auto item share (&2)")); processPartyAutoItemSettingsContinue(msg, autoItem); } }
void PartyHandler::processPartyMessage(Net::MessageIn &msg) { int msgLength = msg.readInt16() - 8; if (msgLength <= 0) return; int id = msg.readInt32(); std::string chatMsg = msg.readString(msgLength); if (Ea::taParty && Ea::partyTab) { PartyMember *member = Ea::taParty->getMember(id); if (member) { Ea::partyTab->chatLog(member->getName(), chatMsg); } else { Ea::partyTab->chatLog(strprintf( _("An unknown member tried to say: %s"), chatMsg.c_str()), BY_SERVER); } } }
void GuildRecv::processGuildBasicInfo(Net::MessageIn &msg) { const int guildId = msg.readInt32("guild id"); const int level = msg.readInt32("guild level"); const int members = msg.readInt32("connect member"); const int maxMembers = msg.readInt32("max member"); const int avgLevel = msg.readInt32("average level"); const int exp = msg.readInt32("exp"); const int nextExp = msg.readInt32("next exp"); msg.skip(12, "unused"); const int emblem = msg.readInt32("emblem id"); std::string name = msg.readString(24, "guild name"); std::string castle; std::string master; if (msg.getVersion() >= 20160622) { castle = msg.readString(16, "castles"); msg.readInt32("money, unused"); msg.readBeingId("leader char id"); } else { master = msg.readString(24, "master name"); castle = msg.readString(16, "castles"); msg.readInt32("money, unused"); } if (guildTab != nullptr && showBasicInfo) { showBasicInfo = false; // TRANSLATORS: guild info message guildTab->chatLog(strprintf(_("Guild name: %s"), name.c_str()), ChatMsgType::BY_SERVER, IgnoreRecord_false, TryRemoveColors_true); if (!master.empty()) { // TRANSLATORS: guild info message guildTab->chatLog(strprintf(_("Guild master: %s"), master.c_str()), ChatMsgType::BY_SERVER, IgnoreRecord_false, TryRemoveColors_true); } // TRANSLATORS: guild info message guildTab->chatLog(strprintf(_("Guild level: %d"), level), ChatMsgType::BY_SERVER, IgnoreRecord_false, TryRemoveColors_true); // TRANSLATORS: guild info message guildTab->chatLog(strprintf(_("Online members: %d"), members), ChatMsgType::BY_SERVER, IgnoreRecord_false, TryRemoveColors_true); // TRANSLATORS: guild info message guildTab->chatLog(strprintf(_("Max members: %d"), maxMembers), ChatMsgType::BY_SERVER, IgnoreRecord_false, TryRemoveColors_true); // TRANSLATORS: guild info message guildTab->chatLog(strprintf(_("Average level: %d"), avgLevel), ChatMsgType::BY_SERVER, IgnoreRecord_false, TryRemoveColors_true); // TRANSLATORS: guild info message guildTab->chatLog(strprintf(_("Guild exp: %d"), exp), ChatMsgType::BY_SERVER, IgnoreRecord_false, TryRemoveColors_true); // TRANSLATORS: guild info message guildTab->chatLog(strprintf(_("Guild next exp: %d"), nextExp), ChatMsgType::BY_SERVER, IgnoreRecord_false, TryRemoveColors_true); // TRANSLATORS: guild info message guildTab->chatLog(strprintf(_("Guild castle: %s"), castle.c_str()), ChatMsgType::BY_SERVER, IgnoreRecord_false, TryRemoveColors_true); } Guild *const g = Guild::getGuild(CAST_S16(guildId)); if (g == nullptr) return; g->setName(name); g->setEmblemId(emblem); }
void PlayerHandler::handleMessage(Net::MessageIn &msg) { if (!player_node) return; switch (msg.getId()) { case SMSG_WALK_RESPONSE: /* * This client assumes that all walk messages succeed, * and that the server will send a correction notice * otherwise. */ break; case SMSG_PLAYER_WARP: { std::string mapPath = msg.readString(16); int x = msg.readInt16(); int y = msg.readInt16(); logger->log("Warping to %s (%d, %d)", mapPath.c_str(), x, y); /* * We must clear the local player's target *before* the call * to changeMap, as it deletes all beings. */ player_node->stopAttack(); Game *game = Game::instance(); const std::string ¤tMapName = game->getCurrentMapName(); bool sameMap = (currentMapName == mapPath); // Switch the actual map, deleting the previous one if necessary mapPath = mapPath.substr(0, mapPath.rfind(".")); game->changeMap(mapPath); float scrollOffsetX = 0.0f; float scrollOffsetY = 0.0f; /* Scroll if necessary */ Map *map = game->getCurrentMap(); int tileX = player_node->getTileX(); int tileY = player_node->getTileY(); if (!sameMap || (abs(x - tileX) > MAP_TELEPORT_SCROLL_DISTANCE) || (abs(y - tileY) > MAP_TELEPORT_SCROLL_DISTANCE)) { scrollOffsetX = (x - tileX) * map->getTileWidth(); scrollOffsetY = (y - tileY) * map->getTileHeight(); } player_node->setAction(Being::STAND); Vector pos = map->getTileCenter(x, y); player_node->setPosition(pos); // Stop movement player_node->setDestination(pos.x, pos.y); logger->log("Adjust scrolling by %d:%d", (int) scrollOffsetX, (int) scrollOffsetY); viewport->scrollBy(scrollOffsetX, scrollOffsetY); } break; case SMSG_PLAYER_STAT_UPDATE_1: { if (!player_node) break; int type = msg.readInt16(); int value = msg.readInt32(); switch (type) { case 0x0000: player_node->setMoveSpeed(Vector(value / 10, value / 10, 0)); break; case 0x0004: break; // manner case 0x0005: PlayerInfo::setAttribute(HP, value); break; case 0x0006: PlayerInfo::setAttribute(MAX_HP, value); break; case 0x0007: PlayerInfo::setAttribute(MP, value); break; case 0x0008: PlayerInfo::setAttribute(MAX_MP, value); break; case 0x0009: PlayerInfo::setAttribute(CHAR_POINTS, value); break; case 0x000b: PlayerInfo::setAttribute(LEVEL, value); break; case 0x000c: PlayerInfo::setAttribute(SKILL_POINTS, value); break; case 0x0018: if (value >= PlayerInfo::getAttribute(MAX_WEIGHT) / 2 && PlayerInfo::getAttribute(TOTAL_WEIGHT) < PlayerInfo::getAttribute(MAX_WEIGHT) / 2) { weightNotice = new OkDialog(_("Message"), _("You are carrying more than " "half your weight. You are " "unable to regain health.")); weightNotice->addActionListener( &weightListener); } PlayerInfo::setAttribute(TOTAL_WEIGHT, value); break; case 0x0019: PlayerInfo::setAttribute(MAX_WEIGHT, value); break; case 0x0029: PlayerInfo::setStatBase(ATK, value); break; case 0x002a: PlayerInfo::setStatMod(ATK, value); break; case 0x002b: PlayerInfo::setStatBase(MATK, value); break; case 0x002c: PlayerInfo::setStatMod(MATK, value); break; case 0x002d: PlayerInfo::setStatBase(DEF, value); break; case 0x002e: PlayerInfo::setStatMod(DEF, value); break; case 0x002f: PlayerInfo::setStatBase(MDEF, value); break; case 0x0030: PlayerInfo::setStatMod(MDEF, value); break; case 0x0031: PlayerInfo::setStatBase(HIT, value); break; case 0x0032: PlayerInfo::setStatBase(FLEE, value); break; case 0x0033: PlayerInfo::setStatMod(FLEE, value); break; case 0x0034: PlayerInfo::setStatBase(CRIT, value); break; case 0x0035: player_node->setAttackSpeed(value); break; case 0x0037: PlayerInfo::setStatBase(JOB, value); break; case 500: player_node->setGMLevel(value); break; } if (PlayerInfo::getAttribute(HP) == 0 && !deathNotice) { viewport->shakeScreen(100); deathNotice = new OkDialog(_("Message"), randomDeathMessage(), false); deathNotice->addActionListener(&deathListener); player_node->setAction(Being::DEAD); } } if (statusWindow) statusWindow->updateAttrs(); break; case SMSG_PLAYER_STAT_UPDATE_2: switch (msg.readInt16()) { case 0x0001: PlayerInfo::setAttribute(EXP, msg.readInt32()); break; case 0x0002: PlayerInfo::setStatExperience(JOB, msg.readInt32(), PlayerInfo::getStatExperience(JOB).second); break; case 0x0014: { int oldMoney = PlayerInfo::getAttribute(MONEY); int newMoney = msg.readInt32(); std::string money = Units::formatCurrency( newMoney - oldMoney); PlayerInfo::setAttribute(MONEY, newMoney); if (newMoney > oldMoney) { if (config.getBoolValue("showpickupchat")) SERVER_NOTICE(strprintf(_("You picked up %s."), Units::formatCurrency(newMoney - oldMoney).c_str())) if (config.getBoolValue("showpickupparticle")) player_node->addMessageToQueue(money, UserPalette::PICKUP_INFO); } } break; case 0x0016: PlayerInfo::setAttribute(EXP_NEEDED, msg.readInt32()); break; case 0x0017: PlayerInfo::setStatExperience(JOB, PlayerInfo::getStatExperience(JOB).first, msg.readInt32()); break; } break; case SMSG_PLAYER_STAT_UPDATE_3: // Update a base attribute { int type = msg.readInt32(); int base = msg.readInt32(); int bonus = msg.readInt32(); PlayerInfo::setStatBase(type, base, false); PlayerInfo::setStatMod(type, bonus); } break; case SMSG_PLAYER_STAT_UPDATE_4: // Attribute increase ack { int type = msg.readInt16(); int ok = msg.readInt8(); int value = msg.readInt8(); if (ok != 1) { SERVER_NOTICE(_("Cannot raise skill!")) } PlayerInfo::setStatBase(type, value); } break; // Updates stats and status points case SMSG_PLAYER_STAT_UPDATE_5: PlayerInfo::setAttribute(CHAR_POINTS, msg.readInt16()); { int val = msg.readInt8(); PlayerInfo::setStatBase(STR, val); if (val >= 99) { statusWindow->setPointsNeeded(STR, 0); msg.readInt8(); } else { statusWindow->setPointsNeeded(STR, msg.readInt8()); } val = msg.readInt8(); PlayerInfo::setStatBase(AGI, val); if (val >= 99) { statusWindow->setPointsNeeded(AGI, 0); msg.readInt8(); } else { statusWindow->setPointsNeeded(AGI, msg.readInt8()); } val = msg.readInt8(); PlayerInfo::setStatBase(VIT, val); if (val >= 99) { statusWindow->setPointsNeeded(VIT, 0); msg.readInt8(); } else { statusWindow->setPointsNeeded(VIT, msg.readInt8()); } val = msg.readInt8(); PlayerInfo::setStatBase(INT, val); if (val >= 99) { statusWindow->setPointsNeeded(INT, 0); msg.readInt8(); } else { statusWindow->setPointsNeeded(INT, msg.readInt8()); } val = msg.readInt8(); PlayerInfo::setStatBase(DEX, val); if (val >= 99) { statusWindow->setPointsNeeded(DEX, 0); msg.readInt8(); } else { statusWindow->setPointsNeeded(DEX, msg.readInt8()); } val = msg.readInt8(); PlayerInfo::setStatBase(LUK, val); if (val >= 99) { statusWindow->setPointsNeeded(LUK, 0); msg.readInt8(); } else { statusWindow->setPointsNeeded(LUK, msg.readInt8()); } PlayerInfo::setStatBase(ATK, msg.readInt16(), false); PlayerInfo::setStatMod(ATK, msg.readInt16()); PlayerInfo::setStatBase(MATK, msg.readInt16(), false); PlayerInfo::setStatMod(MATK, msg.readInt16()); PlayerInfo::setStatBase(DEF, msg.readInt16(), false); PlayerInfo::setStatMod(DEF, msg.readInt16()); PlayerInfo::setStatBase(MDEF, msg.readInt16(), false); PlayerInfo::setStatMod(MDEF, msg.readInt16()); PlayerInfo::setStatBase(HIT, msg.readInt16()); PlayerInfo::setStatBase(FLEE, msg.readInt16(), false); PlayerInfo::setStatMod(FLEE, msg.readInt16()); PlayerInfo::setStatBase(CRIT, msg.readInt16()); } msg.readInt16(); // manner break; case SMSG_PLAYER_STAT_UPDATE_6: switch (msg.readInt16()) { case 0x0020: statusWindow->setPointsNeeded(STR, msg.readInt8()); break; case 0x0021: statusWindow->setPointsNeeded(AGI, msg.readInt8()); break; case 0x0022: statusWindow->setPointsNeeded(VIT, msg.readInt8()); break; case 0x0023: statusWindow->setPointsNeeded(INT, msg.readInt8()); break; case 0x0024: statusWindow->setPointsNeeded(DEX, msg.readInt8()); break; case 0x0025: statusWindow->setPointsNeeded(LUK, msg.readInt8()); break; } break; case SMSG_PLAYER_ARROW_MESSAGE: { int type = msg.readInt16(); switch (type) { case 0: { SERVER_NOTICE(_("Equip arrows first.")) } break; default: logger->log("0x013b: Unhandled message %i", type); break; } } break; } }
void GuildRecv::processGuildMemberList(Net::MessageIn &msg) { if (actorManager == nullptr) return; const int length = msg.readInt16("len"); if (length < 4) return; int guildSize = 0; if (msg.getVersion() >= 20161026) { guildSize = 34; } else { guildSize = 104; } const int count = (length - 4) / guildSize; if (taGuild == nullptr) { logger->log1("!taGuild"); return; } taGuild->clearMembers(); int onlineNum = 0; int totalNum = 0; for (int i = 0; i < count; i++) { const BeingId id = msg.readBeingId("account id"); const int charId = msg.readInt32("char id"); msg.readInt16("hair"); msg.readInt16("hair color"); const int gender = msg.readInt16("gender"); const int race = msg.readInt16("class"); const int level = msg.readInt16("level"); const int exp = msg.readInt32("exp"); const int online = msg.readInt32("online"); const int pos = msg.readInt32("position"); std::string name; if (msg.getVersion() < 20161026) { msg.skip(50, "unused"); name = msg.readString(24, "name"); } else { msg.readInt32("last login"); // for now unused name = actorManager->findCharById(charId); if (name.empty()) { beingHandler->requestNameByCharId(charId); } } GuildMember *const m = taGuild->addMember(id, charId, name); if (m != nullptr) { m->setOnline(online != 0); m->setID(id); m->setCharId(charId); m->setGender(Being::intToGender(CAST_U8(gender))); m->setLevel(level); m->setExp(exp); m->setPos(pos); m->setRace(race); Being *const being = actorManager->findBeingByName( name, ActorType::Player); if (being != nullptr) { being->setGuildName(taGuild->getName()); if (being->getLevel() != level) { being->setLevel(level); being->updateName(); } } if (online != 0) onlineNum ++; totalNum ++; } } taGuild->sort(); actorManager->updatePlayerGuild(); actorManager->updatePlayerColors(); if (socialWindow != nullptr) socialWindow->updateGuildCounter(onlineNum, totalNum); }
void CharServerHandler::readPlayerData(Net::MessageIn &msg, Net::Character *const character, const bool) const { if (!character) return; const Token &token = static_cast<LoginHandler*>(Net::getLoginHandler())->getToken(); LocalPlayer *const tempPlayer = new LocalPlayer(msg.readInt32(), 0); tempPlayer->setGender(token.sex); PlayerInfoBackend &data = character->data; data.mAttributes[Attributes::EXP] = msg.readInt32(); data.mAttributes[Attributes::MONEY] = msg.readInt32(); Stat &jobStat = data.mStats[JOB]; jobStat.exp = msg.readInt32(); const int temp = msg.readInt32(); jobStat.base = temp; jobStat.mod = temp; const int shoes = msg.readInt16(); const int gloves = msg.readInt16(); const int cape = msg.readInt16(); const int misc1 = msg.readInt16(); msg.readInt32(); // option msg.readInt32(); // karma msg.readInt32(); // manner msg.readInt16(); // character points left data.mAttributes[Attributes::HP] = msg.readInt16(); data.mAttributes[Attributes::MAX_HP] = msg.readInt16(); data.mAttributes[Attributes::MP] = msg.readInt16(); data.mAttributes[Attributes::MAX_MP] = msg.readInt16(); msg.readInt16(); // speed tempPlayer->setSubtype(msg.readInt16(), 0); // class (used for race) const int hairStyle = msg.readInt16(); const uint16_t weapon = msg.readInt16(); tempPlayer->setSprite(SPRITE_WEAPON, weapon, "", 1, true); data.mAttributes[Attributes::LEVEL] = msg.readInt16(); msg.readInt16(); // skill point const int bottomClothes = msg.readInt16(); const int shield = msg.readInt16(); const int hat = msg.readInt16(); // head option top const int topClothes = msg.readInt16(); tempPlayer->setSprite(SPRITE_HAIR, hairStyle * -1, ItemDB::get(-hairStyle).getDyeColorsString(msg.readInt16())); const int misc2 = msg.readInt16(); tempPlayer->setName(msg.readString(24)); character->dummy = tempPlayer; for (int i = 0; i < 6; i++) character->data.mStats[i + STR].base = msg.readUInt8(); tempPlayer->setSprite(SPRITE_SHOE, shoes); tempPlayer->setSprite(SPRITE_GLOVES, gloves); tempPlayer->setSprite(SPRITE_CAPE, cape); tempPlayer->setSprite(SPRITE_MISC1, misc1); tempPlayer->setSprite(SPRITE_BOTTOMCLOTHES, bottomClothes); // to avoid show error (error.xml) need remove this sprite if (!config.getBoolValue("hideShield")) tempPlayer->setSprite(SPRITE_SHIELD, shield); tempPlayer->setSprite(SPRITE_HAT, hat); // head option top tempPlayer->setSprite(SPRITE_TOPCLOTHES, topClothes); tempPlayer->setSprite(SPRITE_MISC2, misc2); character->slot = msg.readUInt8(); // character slot msg.readUInt8(); // unknown }
void TradeHandler::handleMessage(Net::MessageIn &msg) { switch (msg.getId()) { case GPMSG_TRADE_REQUEST: { Being *being = actorSpriteManager->findBeing(msg.readInt16()); if (!being || !mAcceptTradeRequests) { respond(false); break; } mTrading = true; tradePartnerName = being->getName(); tradePartnerID = being->getId(); ConfirmDialog *dlg = new ConfirmDialog(_("Request for Trade"), strprintf(_("%s wants to trade with you, do you accept?"), tradePartnerName.c_str())); 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(strprintf(_("Trading with %s"), tradePartnerName.c_str())); tradeWindow->setVisible(true); break; case GPMSG_TRADE_BOTH_CONFIRM: tradeWindow->receivedOk(false); break; case GPMSG_TRADE_AGREED: tradeWindow->receivedOk(false); break; case GPMSG_TRADE_CANCEL: SERVER_NOTICE(_("Trade canceled.")) tradeWindow->setVisible(false); tradeWindow->reset(); mTrading = false; break; case GPMSG_TRADE_COMPLETE: SERVER_NOTICE(_("Trade completed.")) tradeWindow->setVisible(false); tradeWindow->reset(); mTrading = false; break; } }
void TradeHandler::handleMessage(Net::MessageIn &msg) { switch (msg.getId()) { case SMSG_TRADE_REQUEST: { // If a trade window or request window is already open, send a // trade cancel to any other trade request. // // 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. std::string tradePartnerNameTemp = msg.readString(24); if (player_relations.hasPermission(tradePartnerName, PlayerRelation::TRADE)) { if (PlayerInfo::isTrading() || confirmDlg) { Net::getTradeHandler()->respond(false); break; } tradePartnerName = tradePartnerNameTemp; PlayerInfo::setTrading(true); confirmDlg = new ConfirmDialog(_("Request for Trade"), strprintf(_("%s wants to trade with you, do you " "accept?"), tradePartnerName.c_str())); confirmDlg->addActionListener(&listener); } else { Net::getTradeHandler()->respond(false); break; } } break; case SMSG_TRADE_RESPONSE: switch (msg.readInt8()) { case 0: // Too far away SERVER_NOTICE(_("Trading isn't possible. Trade " "partner is too far away.")) break; case 1: // Character doesn't exist SERVER_NOTICE(_("Trading isn't possible. Character " "doesn't exist.")) break; case 2: // Invite request check failed... SERVER_NOTICE(_("Trade cancelled due to an unknown " "reason.")) break; case 3: // Trade accepted tradeWindow->reset(); tradeWindow->setCaption(strprintf(_("Trade: You and %s"), tradePartnerName.c_str())); tradeWindow->setVisible(true); break; case 4: // Trade cancelled if (player_relations.hasPermission(tradePartnerName, PlayerRelation::SPEECH_LOG)) SERVER_NOTICE(strprintf(_("Trade with %s cancelled."), tradePartnerName.c_str())) // otherwise ignore silently tradeWindow->setVisible(false); PlayerInfo::setTrading(false); break; default: // Shouldn't happen as well, but to be sure SERVER_NOTICE(_("Unhandled trade cancel packet.")) break; } break; 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) // TODO: handle also identified, etc if (type == 0) tradeWindow->setMoney(amount); else tradeWindow->addItem(type, false, amount); } break; case SMSG_TRADE_ITEM_ADD_RESPONSE: // Trade: New Item add response (was 0x00ea, now 01b1) { const int index = msg.readInt16() - INVENTORY_OFFSET; Item *item = PlayerInfo::getInventory()->getItem(index); if (!item) { tradeWindow->receivedOk(true); return; } int quantity = msg.readInt16(); switch (msg.readInt8()) { case 0: // Successfully added item if (item->isEquippable() && item->isEquipped()) { item->doEvent(Event::DoUnequip); } tradeWindow->addItem(item->getId(), true, quantity); item->increaseQuantity(-quantity); break; case 1: // Add item failed - player overweighted SERVER_NOTICE(_("Failed adding item. Trade " "partner is over weighted.")) break; case 2: // Add item failed - player has no free slot SERVER_NOTICE(_("Failed adding item. Trade " "partner has no free slot.")) break; default: SERVER_NOTICE(_("Failed adding item for " "unknown reason.")) break; } } break; case SMSG_TRADE_OK: // 0 means ok from myself, 1 means ok from other; tradeWindow->receivedOk(msg.readInt8() == 0); break; case SMSG_TRADE_CANCEL: SERVER_NOTICE(_("Trade canceled.")) tradeWindow->setVisible(false); tradeWindow->reset(); PlayerInfo::setTrading(false); break; case SMSG_TRADE_COMPLETE: SERVER_NOTICE(_("Trade completed.")) tradeWindow->setVisible(false); tradeWindow->reset(); PlayerInfo::setTrading(false); break; } }
void LoginHandler::handleMessage(Net::MessageIn &msg) { int code, worldCount; switch (msg.getId()) { case SMSG_CHAR_PASSWORD_RESPONSE: { // 0: acc not found, 1: success, 2: password mismatch, 3: pass too short int errMsg = msg.readInt8(); // Successful pass change if (errMsg == 1) { Client::setState(STATE_CHANGEPASSWORD_SUCCESS); } // pass change failed else { switch (errMsg) { case 0: errorMessage = _("Account was not found. Please re-login."); break; case 2: errorMessage = _("Old password incorrect."); break; case 3: errorMessage = _("New password too short."); break; default: errorMessage = _("Unknown error."); break; } Client::setState(STATE_ACCOUNTCHANGE_ERROR); } } break; case SMSG_UPDATE_HOST: int len; len = msg.readInt16() - 4; mUpdateHost = msg.readString(len); loginData.updateHost = mUpdateHost; logger->log("Received update host \"%s\" from login server.", mUpdateHost.c_str()); break; case SMSG_LOGIN_DATA: // Skip the length word msg.skip(2); clearWorlds(); worldCount = (msg.getLength() - 47) / 32; mToken.session_ID1 = msg.readInt32(); mToken.account_ID = msg.readInt32(); mToken.session_ID2 = msg.readInt32(); msg.skip(30); // unknown mToken.sex = msg.readInt8() ? GENDER_MALE : GENDER_FEMALE; for (int i = 0; i < worldCount; i++) { WorldInfo *world = new WorldInfo; world->address = msg.readInt32(); world->port = msg.readInt16(); world->name = msg.readString(20); world->online_users = msg.readInt32(); world->updateHost = mUpdateHost; msg.skip(2); // unknown logger->log("Network: Server: %s (%s:%d)", world->name.c_str(), ipToString(world->address), world->port); mWorlds.push_back(world); } Client::setState(STATE_WORLD_SELECT); break; case SMSG_LOGIN_ERROR: code = msg.readInt8(); logger->log("Login::error code: %i", code); switch (code) { case 0: errorMessage = _("Unregistered ID."); break; case 1: errorMessage = _("Wrong password."); break; case 2: errorMessage = _("Account expired."); break; case 3: errorMessage = _("Rejected from server."); break; case 4: errorMessage = _("You have been permanently banned from " "the game. Please contact the GM team."); break; case 5: errorMessage = _("Client too old."); break; case 6: errorMessage = strprintf(_("You have been temporarily " "banned from the game until " "%s.\nPlease contact the GM " "team via the forums."), msg.readString(20).c_str()); break; case 7: errorMessage = _("Server overpopulated."); break; case 9: errorMessage = _("This user name is already taken."); break; case 99: errorMessage = _("Username permanently erased."); break; default: errorMessage = _("Unknown error."); break; } Client::setState(STATE_ERROR); break; case SMSG_SERVER_VERSION_RESPONSE: { // TODO: verify these! msg.readInt8(); // -1 msg.readInt8(); // T msg.readInt8(); // M msg.readInt8(); // W unsigned int options = msg.readInt32(); mRegistrationEnabled = (options & 1); // Leave this last mVersionResponse = true; } break; } }
void CharServerHandler::handleMessage(Net::MessageIn &msg) { switch (msg.getId()) { case SMSG_CHAR_LOGIN: { msg.skip(2); // Length word msg.skip(20); // Unused // Derive number of characters from message length const int count = (msg.getLength() - 24) / 106; for (int i = 0; i < count; ++i) { Net::Character *character = new Net::Character; readPlayerData(msg, character); mCharacters.push_back(character); logger->log("CharServer: Player: %s (%d)", character->dummy->getName().c_str(), character->slot); } Client::setState(STATE_CHAR_SELECT); } break; case SMSG_CHAR_LOGIN_ERROR: switch (msg.readInt8()) { case 0: errorMessage = _("Access denied. Most likely, there are " "too many players on this server."); break; case 1: errorMessage = _("Cannot use this ID."); break; default: errorMessage = _("Unknown char-server failure."); break; } Client::setState(STATE_ERROR); break; case SMSG_CHAR_CREATE_SUCCEEDED: { Net::Character *character = new Net::Character; readPlayerData(msg, character); mCharacters.push_back(character); updateCharSelectDialog(); // Close the character create dialog if (mCharCreateDialog) { mCharCreateDialog->scheduleDelete(); mCharCreateDialog = 0; } } break; case SMSG_CHAR_CREATE_FAILED: new OkDialog(_("Error"), _("Failed to create character. Most " "likely the name is already taken.")); if (mCharCreateDialog) mCharCreateDialog->unlock(); break; case SMSG_CHAR_DELETE_SUCCEEDED: delete mSelectedCharacter; mCharacters.remove(mSelectedCharacter); mSelectedCharacter = 0; updateCharSelectDialog(); unlockCharSelectDialog(); new OkDialog(_("Info"), _("Character deleted.")); break; case SMSG_CHAR_DELETE_FAILED: unlockCharSelectDialog(); new OkDialog(_("Error"), _("Failed to delete character.")); break; case SMSG_CHAR_MAP_INFO: { msg.skip(4); // CharID, must be the same as player_node->charID GameHandler *gh = static_cast<GameHandler*>(Net::getGameHandler()); gh->setMap(msg.readString(16)); mapServer.hostname = ipToString(msg.readInt32()); mapServer.port = msg.readInt16(); // Prevent the selected local player from being deleted player_node = mSelectedCharacter->dummy; PlayerInfo::setBackend(mSelectedCharacter->data); mSelectedCharacter->dummy = 0; delete_all(mCharacters); mCharacters.clear(); updateCharSelectDialog(); mNetwork->disconnect(); Client::setState(STATE_CONNECT_GAME); } break; case SMSG_CHANGE_MAP_SERVER: { GameHandler *gh = static_cast<GameHandler*>(Net::getGameHandler()); gh->setMap(msg.readString(16)); int x = msg.readInt16(); int y = msg.readInt16(); mapServer.hostname = ipToString(msg.readInt32()); mapServer.port = msg.readInt16(); mNetwork->disconnect(); Client::setState(STATE_CHANGE_MAP); player_node->setTileCoords(x, y); player_node->setMap(0); } break; } }
void LoginRecv::processLoginData(Net::MessageIn &msg) { msg.readInt16("len"); loginHandler->clearWorlds(); int offset = 0; int serverLen = 0; if (msg.getVersion() >= 20170315) { offset = 47 + 17; serverLen = 32 + 128; } else { offset = 47; serverLen = 32; } const int worldCount = (msg.getLength() - offset) / serverLen; Ea::LoginRecv::mToken.session_ID1 = msg.readInt32("session id1"); Ea::LoginRecv::mToken.account_ID = msg.readBeingId("accound id"); Ea::LoginRecv::mToken.session_ID2 = msg.readInt32("session id2"); msg.readInt32("old ip"); loginData.lastLogin = msg.readString(24, "last login"); msg.readInt16("unused"); // reserve bits for future usage Ea::LoginRecv::mToken.sex = Being::intToGender(CAST_U8( msg.readUInt8("gender") & 3U)); if (msg.getVersion() >= 20170315) { msg.readString(16, "twitter auth token"); msg.readUInt8("twitter flag"); } for (int i = 0; i < worldCount; i++) { WorldInfo *const world = new WorldInfo; world->address = msg.readInt32("ip address"); world->port = msg.readInt16("port"); world->name = msg.readString(20, "name"); world->online_users = msg.readInt16("online number"); config.setValue("updatehost", Ea::LoginRecv::mUpdateHost); world->updateHost = Ea::LoginRecv::mUpdateHost; msg.readInt16("maintenance"); msg.readInt16("new"); if (msg.getVersion() >= 20170315) { for (int f = 0; f < 32; f ++) msg.readInt32("unused2"); } logger->log("Network: Server: %s (%s:%d)", world->name.c_str(), ipToString(world->address), world->port); Ea::LoginRecv::mWorlds.push_back(world); } client->setState(State::WORLD_SELECT); }
void PartyHandler::processPartyInfo(Net::MessageIn &msg) { bool oldParty = false; std::set<std::string> names; if (!Ea::taParty) { logger->log1("error: party empty in SMSG_PARTY_INFO"); Ea::taParty = Party::getParty(1); } if (Ea::taParty) { if (Ea::taParty->getNumberOfElements() > 1) { oldParty = true; Ea::taParty->getNamesSet(names); } } if (!player_node) logger->log1("error: player_node==0 in SMSG_PARTY_INFO"); if (Ea::taParty) Ea::taParty->clearMembers(); int length = msg.readInt16(); if (Ea::taParty) Ea::taParty->setName(msg.readString(24)); int count = (length - 28) / 46; if (player_node && Ea::taParty) { player_node->setParty(Ea::taParty); player_node->setPartyName(Ea::taParty->getName()); } for (int i = 0; i < count; i++) { int id = msg.readInt32(); std::string nick = msg.readString(24); std::string map = msg.readString(16); bool leader = msg.readInt8() == 0; bool online = msg.readInt8() == 0; if (Ea::taParty) { PartyMember *member = nullptr; if (oldParty) { //member = Ea::taParty->getMember(id); if (Ea::partyTab && names.find(nick) == names.end()) { Ea::partyTab->chatLog(strprintf( _("%s has joined your party."), nick.c_str()), BY_SERVER); } } member = Ea::taParty->addMember(id, nick); if (member) { member->setLeader(leader); member->setOnline(online); member->setMap(map); } } } if (Ea::taParty) Ea::taParty->sort(); if (player_node && Ea::taParty) { player_node->setParty(Ea::taParty); player_node->setPartyName(Ea::taParty->getName()); } }
void CashShopHandler::processCashShopPoints(Net::MessageIn &msg) { UNIMPLIMENTEDPACKET; msg.readInt32("cash points"); msg.readInt32("kafra points"); }
void AchievementRecv::processAchievementGetReward(Net::MessageIn &msg) { UNIMPLEMENTEDPACKET; msg.readUInt8("received"); msg.readInt32("ach id"); }
void GuildHandler::processGuildMemberList(Net::MessageIn &msg) { const int length = msg.readInt16("len"); if (length < 4) return; const int count = (length - 4) / 104; if (!taGuild) { logger->log1("!taGuild"); return; } taGuild->clearMembers(); int onlineNum = 0; int totalNum = 0; for (int i = 0; i < count; i++) { const BeingId id = msg.readBeingId("account id"); const int charId = msg.readInt32("char id"); msg.readInt16("hair"); msg.readInt16("hair color"); const int gender = msg.readInt16("gender"); const int race = msg.readInt16("class"); const int level = msg.readInt16("level"); const int exp = msg.readInt32("exp"); const int online = msg.readInt32("online"); const int pos = msg.readInt32("position"); msg.skip(50, "unused"); std::string name = msg.readString(24, "name"); GuildMember *const m = taGuild->addMember(id, charId, name); if (m) { m->setOnline(online); m->setID(id); m->setCharId(charId); m->setGender(Being::intToGender(static_cast<uint8_t>(gender))); m->setLevel(level); m->setExp(exp); m->setPos(pos); m->setRace(race); if (actorManager) { Being *const being = actorManager->findBeingByName( name, ActorType::Player); if (being) { being->setGuildName(taGuild->getName()); if (being->getLevel() != level) { being->setLevel(level); being->updateName(); } } } if (online) onlineNum ++; totalNum ++; } } taGuild->sort(); if (actorManager) { actorManager->updatePlayerGuild(); actorManager->updatePlayerColors(); } if (socialWindow) socialWindow->updateGuildCounter(onlineNum, totalNum); }