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 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 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 CharServerHandler::processCharLogin(Net::MessageIn &msg) { msg.skip(2); // Length word const int slots = msg.readInt16(); if (slots > 0 && slots < 30) loginData.characterSlots = static_cast<uint16_t>(slots); msg.skip(18); // 0 Unused delete_all(mCharacters); mCharacters.clear(); // Derive number of characters from message length const int count = (msg.getLength() - 24) / 106; for (int i = 0; i < count; ++i) { Net::Character *const character = new Net::Character; readPlayerData(msg, character, false); 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 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 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 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 GuildHandler::processGuildEmblem(Net::MessageIn &msg) const { const int length = msg.readInt16(); msg.readInt32(); // Guild ID msg.readInt32(); // Emblem ID if (length < 12) return; msg.skip(length - 12); // Emblem data (unknown format) }
void GuildHandler::processGuildExpulsion(Net::MessageIn &msg) const { msg.skip(2); // size (can be many explusions in list) const std::string nick = msg.readString(24); // Name (of expulsed?) msg.skip(24); // acc msg.readString(44); // Message if (taGuild) taGuild->removeMember(nick); if (!player_node) return; if (nick == player_node->getName()) { if (taGuild) { taGuild->removeFromMembers(); taGuild->clearMembers(); } NotifyManager::notify(NotifyManager::GUILD_KICKED); delete guildTab; guildTab = nullptr; if (socialWindow && taGuild) socialWindow->removeTab(taGuild); if (actorManager) actorManager->updatePlayerColors(); } else { NotifyManager::notify(NotifyManager::GUILD_USER_KICKED, nick); if (actorManager) { Being *const b = actorManager->findBeingByName( nick, Being::PLAYER); if (b) b->clearGuilds(); if (taGuild) taGuild->removeMember(nick); } } }
void GuildHandler::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 master = msg.readString(24, "master name"); std::string castle = msg.readString(16, "castles"); msg.readInt32("unused"); if (guildTab && showBasicInfo) { showBasicInfo = false; // TRANSLATORS: guild info message guildTab->chatLog(strprintf(_("Guild name: %s"), name.c_str()), ChatMsgType::BY_SERVER); // TRANSLATORS: guild info message guildTab->chatLog(strprintf(_("Guild master: %s"), master.c_str()), ChatMsgType::BY_SERVER); // TRANSLATORS: guild info message guildTab->chatLog(strprintf(_("Guild level: %d"), level), ChatMsgType::BY_SERVER); // TRANSLATORS: guild info message guildTab->chatLog(strprintf(_("Online members: %d"), members), ChatMsgType::BY_SERVER); // TRANSLATORS: guild info message guildTab->chatLog(strprintf(_("Max members: %d"), maxMembers), ChatMsgType::BY_SERVER); // TRANSLATORS: guild info message guildTab->chatLog(strprintf(_("Average level: %d"), avgLevel), ChatMsgType::BY_SERVER); // TRANSLATORS: guild info message guildTab->chatLog(strprintf(_("Guild exp: %d"), exp), ChatMsgType::BY_SERVER); // TRANSLATORS: guild info message guildTab->chatLog(strprintf(_("Guild next exp: %d"), nextExp), ChatMsgType::BY_SERVER); // TRANSLATORS: guild info message guildTab->chatLog(strprintf(_("Guild castle: %s"), castle.c_str()), ChatMsgType::BY_SERVER); } Guild *const g = Guild::getGuild(static_cast<int16_t>(guildId)); if (!g) return; g->setName(name); g->setEmblemId(emblem); }
void CharServerRecv::processCharLogin2(Net::MessageIn &msg) { // ignored msg.readInt16("len"); msg.readUInt8("char slots"); msg.readUInt8("left slots"); msg.readUInt8("left slots"); msg.readUInt8("char slots"); msg.readUInt8("char slots"); msg.skip(20, "unused"); }
void GuildRecv::processGuildEmblemData(Net::MessageIn &msg) { UNIMPLEMENTEDPACKET; const int length = msg.readInt16("len"); msg.readInt32("guild id"); msg.readInt32("emblem id"); if (length < 12) return; msg.skip(length - 12, "emblem data"); }
void LoginHandler::processLoginData(Net::MessageIn &msg) { // Skip the length word msg.skip(2); // size clearWorlds(); const int worldCount = (msg.getLength() - 47) / 32; mToken.session_ID1 = msg.readInt32(); mToken.account_ID = msg.readInt32(); mToken.session_ID2 = msg.readInt32(); msg.skip(4); // old ip loginData.lastLogin = msg.readString(24); msg.skip(2); // 0 unused bytes // msg.skip(30); // unknown // reserve bits for future usage mToken.sex = Being::intToGender(static_cast<uint8_t>( msg.readUInt8() & 3U)); for (int i = 0; i < worldCount; i++) { WorldInfo *const world = new WorldInfo; world->address = msg.readInt32(); world->port = msg.readInt16(); world->name = msg.readString(20); world->online_users = msg.readInt16(); config.setValue("updatehost", mUpdateHost); world->updateHost = mUpdateHost; msg.skip(2); // maintenance msg.skip(2); // new 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); }
void PlayerHandler::processPlayerShortcuts(Net::MessageIn &msg) { // +++ player shortcuts ignored. It also disabled on server side. // may be in future better use it? msg.readUInt8("unused?"); for (int f = 0; f < 27; f ++) { msg.readUInt8("type 0: item, 1: skill"); msg.readInt32("item or skill id"); msg.readInt16("skill level"); } msg.skip(77, "unused"); }
void GuildHandler::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(16); // 0 unused std::string name = msg.readString(24); // Name std::string master = msg.readString(24); // Master's name std::string castle = msg.readString(20); // Castles // (ie: "Six Castles" or "None Taken") if (guildTab && showBasicInfo) { showBasicInfo = false; // TRANSLATORS: guild info message guildTab->chatLog(strprintf(_("Guild name: %s"), name.c_str()), BY_SERVER); // TRANSLATORS: guild info message guildTab->chatLog(strprintf(_("Guild master: %s"), master.c_str()), BY_SERVER); // TRANSLATORS: guild info message guildTab->chatLog(strprintf(_("Guild level: %d"), level), BY_SERVER); // TRANSLATORS: guild info message guildTab->chatLog(strprintf(_("Online members: %d"), members), BY_SERVER); // TRANSLATORS: guild info message guildTab->chatLog(strprintf(_("Max members: %d"), maxMembers), BY_SERVER); // TRANSLATORS: guild info message guildTab->chatLog(strprintf(_("Average level: %d"), avgLevel), BY_SERVER); // TRANSLATORS: guild info message guildTab->chatLog(strprintf(_("Guild exp: %d"), exp), BY_SERVER); // TRANSLATORS: guild info message guildTab->chatLog(strprintf(_("Guild next exp: %d"), nextExp), BY_SERVER); // TRANSLATORS: guild info message guildTab->chatLog(strprintf(_("Guild castle: %s"), castle.c_str()), BY_SERVER); } Guild *const g = Guild::getGuild(static_cast<int16_t>(guildId)); if (!g) return; g->setName(name); }
void GuildHandler::processGuildSkillInfo(Net::MessageIn &msg) const { const int length = msg.readInt16(); const int count = (length - 6) / 37; msg.readInt16(); // 'Skill point' if (length < 6) return; for (int i = 0; i < count; i++) { msg.readInt16(); // ID msg.readInt16(); // 'Info' (unknown atm) msg.readInt16(); // 0 unused msg.readInt16(); // Level msg.readInt16(); // SP msg.readInt16(); // 'Range' msg.skip(24); // 0 unused msg.readInt8(); // Can be increased } }
void SkillRecv::processPlayerSkills(Net::MessageIn &msg) { msg.readInt16("len"); const int skillCount = (msg.getLength() - 4) / 37; int updateSkill = 0; for (int k = 0; k < skillCount; k++) { const int skillId = msg.readInt16("skill id"); const SkillType::SkillType inf = static_cast<SkillType::SkillType>( msg.readInt16("inf")); msg.readInt16("skill pool flags"); const int level = msg.readInt16("skill level"); const int sp = msg.readInt16("sp"); const int range = msg.readInt16("range"); msg.skip(24, "unused"); const Modifiable up = fromBool(msg.readUInt8("up flag"), Modifiable); const int oldLevel = PlayerInfo::getSkillLevel(skillId); if (oldLevel && oldLevel != level) updateSkill = skillId; PlayerInfo::setSkillLevel(skillId, level); if (skillDialog) { if (!skillDialog->updateSkill(skillId, range, up, inf, sp)) { skillDialog->addSkill(SkillOwner::Player, skillId, "", level, range, up, inf, sp); } } } if (skillDialog) { skillDialog->update(); if (updateSkill) skillDialog->playUpdateEffect(updateSkill); } }
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 actorSpriteManager->createItem(id, itemId, x, y); } break; case SMSG_ITEM_REMOVE: if (FloorItem *item = actorSpriteManager->findItem(msg.readInt32())) actorSpriteManager->destroy(item); break; } }
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 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 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 CharServerHandler::readPlayerData(Net::MessageIn &msg, Net::Character *const character, const bool withColors) const { if (!character) return; const Token &token = static_cast<LoginHandler*>(loginHandler)->getToken(); LocalPlayer *const tempPlayer = new LocalPlayer( msg.readBeingId("account id"), BeingTypeId_zero); tempPlayer->setGender(token.sex); PlayerInfoBackend &data = character->data; data.mAttributes[Attributes::EXP] = msg.readInt32("exp"); data.mAttributes[Attributes::MONEY] = msg.readInt32("money"); Stat &jobStat = data.mStats[Attributes::JOB]; jobStat.exp = msg.readInt32("job"); const int temp = msg.readInt32("job level"); jobStat.base = temp; jobStat.mod = temp; const int shoes = msg.readInt16("shoes"); const int gloves = msg.readInt16("gloves"); const int cape = msg.readInt16("cape"); const int misc1 = msg.readInt16("misc1"); msg.readInt32("option"); tempPlayer->setKarma(msg.readInt32("karma")); tempPlayer->setManner(msg.readInt32("manner")); msg.readInt16("character points left"); data.mAttributes[Attributes::HP] = msg.readInt16("hp"); data.mAttributes[Attributes::MAX_HP] = msg.readInt16("max hp"); data.mAttributes[Attributes::MP] = msg.readInt16("mp"); data.mAttributes[Attributes::MAX_MP] = msg.readInt16("max mp"); msg.readInt16("speed"); const uint16_t race = msg.readInt16("class"); const uint8_t hairStyle = msg.readUInt8("hair style"); const uint16_t look = msg.readUInt8("look"); tempPlayer->setSubtype(fromInt(race, BeingTypeId), look); const uint16_t weapon = msg.readInt16("weapon"); tempPlayer->setSprite(SPRITE_BODY, weapon, "", 1, true); data.mAttributes[Attributes::LEVEL] = msg.readInt16("level"); msg.readInt16("skill point"); const int bottomClothes = msg.readInt16("bottom clothes"); const int shield = msg.readInt16("shield"); const int hat = msg.readInt16("hat"); const int topClothes = msg.readInt16("top clothes"); const uint8_t hairColor = msg.readUInt8("hair color"); msg.readUInt8("unused"); tempPlayer->setSprite(SPRITE_HAIR_COLOR, hairStyle * -1, ItemDB::get(-hairStyle).getDyeColorsString(hairColor)); tempPlayer->setHairColor(static_cast<unsigned char>(hairColor)); const int misc2 = msg.readInt16("misc2"); tempPlayer->setName(msg.readString(24, "name")); character->dummy = tempPlayer; character->data.mStats[Attributes::STR].base = msg.readUInt8("str"); character->data.mStats[Attributes::AGI].base = msg.readUInt8("agi"); character->data.mStats[Attributes::VIT].base = msg.readUInt8("vit"); character->data.mStats[Attributes::INT].base = msg.readUInt8("int"); character->data.mStats[Attributes::DEX].base = msg.readUInt8("dex"); character->data.mStats[Attributes::LUK].base = msg.readUInt8("luk"); if (withColors) { tempPlayer->setSprite(SPRITE_HAIR, shoes, "", msg.readUInt8("shoes color")); tempPlayer->setSprite(SPRITE_SHOES, gloves, "", msg.readUInt8("gloves color")); tempPlayer->setSprite(SPRITE_SHIELD, cape, "", msg.readUInt8("cape color")); tempPlayer->setSprite(SPRITE_HEAD_TOP, misc1, "", msg.readUInt8("misc1 color")); tempPlayer->setSprite(SPRITE_WEAPON, bottomClothes, "", msg.readUInt8("bottom clothes color")); tempPlayer->setSprite(SPRITE_FLOOR, shield, "", msg.readUInt8("shield color")); tempPlayer->setSprite(SPRITE_CLOTHES_COLOR, hat, "", msg.readUInt8("head option top color")); tempPlayer->setSprite(SPRITE_HEAD_BOTTOM, topClothes, "", msg.readUInt8("top clothes color")); tempPlayer->setSprite(SPRITE_HEAD_MID, misc2, "", msg.readUInt8("misc2 color")); msg.skip(5, "unused"); } else { tempPlayer->setSprite(SPRITE_HAIR, shoes); tempPlayer->setSprite(SPRITE_SHOES, gloves); tempPlayer->setSprite(SPRITE_SHIELD, cape); tempPlayer->setSprite(SPRITE_HEAD_TOP, misc1); tempPlayer->setSprite(SPRITE_WEAPON, bottomClothes); tempPlayer->setSprite(SPRITE_FLOOR, shield); tempPlayer->setSprite(SPRITE_CLOTHES_COLOR, hat); // head option top tempPlayer->setSprite(SPRITE_HEAD_BOTTOM, topClothes); tempPlayer->setSprite(SPRITE_HEAD_MID, misc2); } character->slot = msg.readUInt8("slot"); msg.readUInt8("unused"); }
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); }
void GuildHandler::processGuildMemberList(Net::MessageIn &msg) const { const int length = msg.readInt16(); 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 int id = msg.readInt32(); // 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); // 0 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, Being::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); }
void SpecialHandler::handleMessage(Net::MessageIn &msg) { int skillCount; int skillId; switch (msg.getId()) { case SMSG_PLAYER_SKILLS: msg.readInt16(); // length skillCount = (msg.getLength() - 4) / 37; for (int k = 0; k < skillCount; k++) { skillId = msg.readInt16(); msg.readInt16(); // target type msg.skip(2); // unused int level = msg.readInt16(); msg.readInt16(); // sp msg.readInt16(); // range msg.skip(24); // unused int up = msg.readInt8(); PlayerInfo::setStatBase(skillId, level); if (skillDialog) skillDialog->setModifiable(skillId, up); } break; case SMSG_PLAYER_SKILL_UP: { skillId = msg.readInt16(); int level = msg.readInt16(); msg.readInt16(); // sp msg.readInt16(); // range int up = msg.readInt8(); PlayerInfo::setStatBase(skillId, level); skillDialog->setModifiable(skillId, up); } break; case SMSG_SKILL_FAILED: // Action failed (ex. sit because you have not reached the // right level) skillId = msg.readInt16(); short bskill = msg.readInt16(); msg.readInt16(); // unknown char success = msg.readInt8(); char reason = msg.readInt8(); if (success != SKILL_FAILED && bskill == BSKILL_EMOTE) { logger->log("Action: %d/%d", bskill, success); } std::string msg; if (success == SKILL_FAILED && skillId == SKILL_BASIC) { switch (bskill) { case BSKILL_TRADE: msg = _("Trade failed!"); break; case BSKILL_EMOTE: msg = _("Emote failed!"); break; case BSKILL_SIT: msg = _("Sit failed!"); break; case BSKILL_CREATECHAT: msg = _("Chat creating failed!"); break; case BSKILL_JOINPARTY: msg = _("Could not join party!"); break; case BSKILL_SHOUT: msg = _("Cannot shout!"); break; } msg += " "; switch (reason) { case RFAIL_SKILLDEP: msg += _("You have not yet reached a high enough lvl!"); break; case RFAIL_INSUFHP: msg += _("Insufficient HP!"); break; case RFAIL_INSUFSP: msg += _("Insufficient SP!"); break; case RFAIL_NOMEMO: msg += _("You have no memos!"); break; case RFAIL_SKILLDELAY: msg += _("You cannot do that right now!"); break; case RFAIL_ZENY: msg += _("Seems you need more money... ;-)"); break; case RFAIL_WEAPON: msg += _("You cannot use this skill with that kind of weapon!"); break; case RFAIL_REDGEM: msg += _("You need another red gem!"); break; case RFAIL_BLUEGEM: msg += _("You need another blue gem!"); break; case RFAIL_OVERWEIGHT: msg += _("You're carrying to much to do this!"); break; default: msg += _("Huh? What's that?"); break; } } else { switch (skillId) { case SKILL_WARP : msg = _("Warp failed..."); break; case SKILL_STEAL : msg = _("Could not steal anything..."); break; case SKILL_ENVENOM : msg = _("Poison had no effect..."); break; } } SERVER_NOTICE(msg) break; } }
void CharServerHandler::readPlayerData(Net::MessageIn &msg, Net::Character *character, bool withColors) { if (!character) return; const Token &token = static_cast<LoginHandler*>(Net::getLoginHandler())->getToken(); LocalPlayer *tempPlayer = new LocalPlayer(msg.readInt32(), 0); tempPlayer->setGender(token.sex); PlayerInfoBackend &data = character->data; data.mAttributes[EXP] = msg.readInt32(); data.mAttributes[MONEY] = msg.readInt32(); data.mStats[JOB].exp = msg.readInt32(); int temp = msg.readInt32(); data.mStats[JOB].base = temp; data.mStats[JOB].mod = temp; int shoes = msg.readInt16(); int gloves = msg.readInt16(); int cape = msg.readInt16(); int misc1 = msg.readInt16(); msg.readInt32(); // option msg.readInt32(); // karma msg.readInt32(); // manner msg.readInt16(); // character points left data.mAttributes[HP] = msg.readInt16(); data.mAttributes[MAX_HP] = msg.readInt16(); data.mAttributes[MP] = msg.readInt16(); data.mAttributes[MAX_MP] = msg.readInt16(); msg.readInt16(); // speed tempPlayer->setSubtype(msg.readInt16()); // class (used for race) int hairStyle = msg.readInt16(); uint16_t weapon = msg.readInt16(); // server not used it. may be need use? tempPlayer->setSprite(SPRITE_WEAPON, weapon, "", 1, true); data.mAttributes[LEVEL] = msg.readInt16(); msg.readInt16(); // skill point int bottomClothes = msg.readInt16(); int shield = msg.readInt16(); int hat = msg.readInt16(); // head option top int topClothes = msg.readInt16(); tempPlayer->setSprite(SPRITE_HAIR, hairStyle * -1, ItemDB::get(-hairStyle).getDyeColorsString(msg.readInt16())); 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.readInt8(); if (withColors) { tempPlayer->setSprite(SPRITE_SHOE, shoes, "", msg.readInt8()); tempPlayer->setSprite(SPRITE_GLOVES, gloves, "", msg.readInt8()); tempPlayer->setSprite(SPRITE_CAPE, cape, "", msg.readInt8()); tempPlayer->setSprite(SPRITE_MISC1, misc1, "", msg.readInt8()); tempPlayer->setSprite(SPRITE_BOTTOMCLOTHES, bottomClothes, "", msg.readInt8()); //to avoid show error (error.xml) need remove this sprite if (!config.getBoolValue("hideShield")) tempPlayer->setSprite(SPRITE_SHIELD, shield, "", msg.readInt8()); else msg.readInt8(); tempPlayer->setSprite(SPRITE_HAT, hat, "", msg.readInt8()); // head option top tempPlayer->setSprite(SPRITE_TOPCLOTHES, topClothes, "", msg.readInt8()); tempPlayer->setSprite(SPRITE_MISC2, misc2, "", msg.readInt8()); msg.skip(5); character->slot = msg.readInt8(); // character slot } else { 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.readInt8(); // character slot } msg.readInt8(); // unknown }