void ChangeStatsHandler::handle(InPacket& recv) const { recv.read_bool(); // 'itemreaction' int32_t updatemask = recv.read_int(); Player& player = Stage::get().getplayer(); bool recalculate = false; for (auto it = Maplestat::it(); it.hasnext(); it.increment()) { Maplestat::Value stat = it.get(); if (Maplestat::compare(stat, updatemask)) { bool updatesingle = false; switch (stat) { case Maplestat::SKIN: player.changelook(stat, recv.read_short()); break; case Maplestat::FACE: case Maplestat::HAIR: player.changelook(stat, recv.read_int()); break; case Maplestat::LEVEL: player.changelevel(recv.read_byte()); updatesingle = true; break; case Maplestat::JOB: player.changejob(recv.read_short()); updatesingle = true; break; case Maplestat::EXP: player.getstats().set_exp(recv.read_int()); break; case Maplestat::MESO: player.getinvent().setmeso(recv.read_int()); break; default: player.getstats().set_stat(stat, recv.read_short()); recalculate = true; break; } if (updatesingle) { UI::get().with_element<UIStatsinfo>([&stat](auto& si) { si.updatestat(stat); }); } } } if (recalculate) { player.recalcstats(false); } UI::get().enable(); }
void UpdateskillsHandler::handle(InPacket& recv) const { recv.skip(3); int32_t skillid = recv.read_int(); int32_t level = recv.read_int(); int32_t masterlevel = recv.read_int(); int64_t expire = recv.read_long(); Stage::get().getplayer().getskills().set_skill(skillid, level, masterlevel, expire); }
void ApplyBuffHandler::handlebuff(InPacket& recv, Buff::Stat bs) const { int16_t value = recv.read_short(); int32_t skillid = recv.read_int(); int32_t duration = recv.read_int(); Stage::get().getplayer().givebuff({ bs, value, skillid, duration }); UI::get().with_element<UIBuffList>([&skillid, &duration](auto& bl) { bl.add_buff(skillid, duration); }); }
void SetfieldHandler::parsetelerock(InPacket& recv, Telerock& trock) const { for (size_t i = 0; i < 5; i++) { trock.addlocation(recv.read_int()); } for (size_t i = 0; i < 10; i++) { trock.addviplocation(recv.read_int()); } }
void SkillMacrosHandler::handle(InPacket& recv) const { uint8_t size = recv.read_byte(); for (uint8_t i = 0; i < size; i++) { recv.read_string(); // name recv.read_byte(); // 'shout' byte recv.read_int(); // skill 1 recv.read_int(); // skill 2 recv.read_int(); // skill 3 } }
void SetfieldHandler::parsering1(InPacket& recv) const { int16_t rsize = recv.read_short(); for (int16_t i = 0; i < rsize; i++) { recv.read_int(); recv.read_padded_string(13); recv.read_int(); recv.read_int(); recv.read_int(); recv.read_int(); } }
void DeleteCharResponseHandler::handle(InPacket& recv) const { // Read the character id and if deletion was successfull (pic was correct). int32_t cid = recv.read_int(); uint8_t state = recv.read_byte(); // Extract information from the state byte. if (state) { UILoginNotice::Message message; switch (state) { case 10: message = UILoginNotice::BIRTHDAY_INCORRECT; break; case 20: message = UILoginNotice::SECOND_PASSWORD_INCORRECT; break; default: message = UILoginNotice::UNKNOWN_ERROR; } UI::get().emplace<UILoginNotice>(message); } else { if (auto charselect = UI::get().get_element<UICharSelect>()) charselect->remove_char(cid); } UI::get().enable(); }
void ServerIPHandler::handle(InPacket& recv) const { recv.skip(2); // Read the ipv4 adress in a string. std::string addrstr; for (int i = 0; i < 4; i++) { uint8_t num = static_cast<uint8_t>(recv.read_byte()); addrstr.append(std::to_string(num)); if (i < 3) { addrstr.push_back('.'); } } // Read the port adress in a string. std::string portstr = std::to_string(recv.read_short()); int32_t cid = recv.read_int(); // Attempt to reconnect to the server and if successfull, login to the game. Session::get().reconnect(addrstr.c_str(), portstr.c_str()); PlayerLoginPacket(cid).dispatch(); }
World LoginParser::parse_world(InPacket& recv) { int8_t wid = recv.read_byte(); if (wid == -1) return{ {}, {}, {}, 0, 0, wid }; std::string name = recv.read_string(); uint8_t flag = recv.read_byte(); std::string message = recv.read_string(); recv.skip(5); std::vector<int32_t> chloads; uint8_t channelcount = recv.read_byte(); for (uint8_t i = 0; i < channelcount; ++i) { recv.read_string(); // channel name chloads.push_back(recv.read_int()); recv.skip(1); recv.skip(2); } recv.skip(2); return{ name, message, chloads, channelcount, flag, wid }; }
void AddCooldownHandler::handle(InPacket& recv) const { int32_t skillid = recv.read_int(); int16_t time = recv.read_short(); int32_t seconds = Timer::get().seconds() + time; Stage::get().getplayer().getskills().set_cd(skillid, seconds); }
void SetfieldHandler::change_map(InPacket& recv, int32_t) const { recv.skip(3); int32_t mapid = recv.read_int(); int8_t portalid = recv.read_byte(); stagetransition(portalid, mapid); }
void KeymapHandler::handle(InPacket& recv) const { recv.skip(1); for (uint8_t i = 0; i < 90; i++) { uint8_t type = recv.read_byte(); int32_t action = recv.read_int(); UI::get().addkeymapping(i, type, action); } }
void SetfieldHandler::parse_skillbook(InPacket& recv, Skillbook& skills) const { int16_t size = recv.read_short(); for (int16_t i = 0; i < size; i++) { int32_t skillid = recv.read_int(); int32_t level = recv.read_int(); int64_t expiration = recv.read_long(); bool fourthtjob = ((skillid % 100000) / 10000 == 2); int32_t masterlevel = fourthtjob ? recv.read_int() : -1; skills.set_skill(skillid, level, masterlevel, expiration); } size = recv.read_short(); for (int16_t i = 0; i < size; i++) { int32_t skillid = recv.read_int(); int32_t cooldown = recv.read_short(); skills.set_cd(skillid, cooldown); } }
LookEntry LoginParser::parse_look(InPacket& recv) { LookEntry look; look.female = recv.read_bool(); look.skin = recv.read_byte(); look.faceid = recv.read_int(); recv.read_bool(); //megaphone look.hairid = recv.read_int(); uint8_t eqslot = recv.read_byte(); while (eqslot != 0xFF) { look.equips[eqslot] = recv.read_int(); eqslot = recv.read_byte(); } uint8_t mskeqslot = recv.read_byte(); while (mskeqslot != 0xFF) { look.maskedequips[mskeqslot] = recv.read_int(); mskeqslot = recv.read_byte(); } look.maskedequips[-111] = recv.read_int(); for (uint8_t i = 0; i < 3; i++) { look.petids.push_back(recv.read_int()); } return look; }
void LoginResultHandler::handle(InPacket& recv) const { // Remove login information. UI::get().remove(UIElement::LOGINNOTICE); UI::get().remove(UIElement::LOGINWAIT); // The packet should contain a 'reason' integer which can signify various things. int32_t reason = recv.read_int(); if (reason != 0) { // Login unsuccessfull. The LoginNotice displayed will contain the specific information. switch (reason) { case 2: UI::get().add(ElementTag<UILoginNotice, int8_t>(16)); break; case 7: UI::get().add(ElementTag<UILoginNotice, int8_t>(17)); break; case 23: // The server sends a request to accept the terms of service. For convenience, just auto-accept. TOSPacket().dispatch(); break; default: // Other reasons. if (reason > 0) { auto reasonbyte = static_cast<int8_t>(reason - 1); UI::get().add(ElementTag<UILoginNotice, int8_t>(reasonbyte)); } } UI::get().enable(); } else { // Login successfull. The packet contains information on the account, so we initialise the account with it. Session::get().getlogin().parseaccount(recv); // Save the Login ID if the box for it on the login panel is checked. bool savelogin = Setting<SaveLogin>::get().load(); if (savelogin) { std::string name = Session::get().getlogin().getaccount().name; Setting<DefaultAccount>::get().save(name); } // Request the list of worlds and channels online. ServerRequestPacket() .dispatch(); } }
CharEntry LoginParser::parse_charentry(InPacket& recv) { int32_t cid = recv.read_int(); StatsEntry stats = parse_stats(recv); LookEntry look = parse_look(recv); recv.read_bool(); // 'rankinfo' bool if (recv.read_bool()) { int32_t currank = recv.read_int(); int32_t rankmv = recv.read_int(); int32_t curjobrank = recv.read_int(); int32_t jobrankmv = recv.read_int(); int8_t rankmc = (rankmv > 0) ? '+' : (rankmv < 0) ? '-' : '='; int8_t jobrankmc = (jobrankmv > 0) ? '+' : (jobrankmv < 0) ? '-' : '='; stats.rank = std::make_pair(currank, rankmc); stats.jobrank = std::make_pair(curjobrank, jobrankmc); } return{ stats, look, cid }; }
StatsEntry LoginParser::parse_stats(InPacket& recv) { StatsEntry statsentry; statsentry.name = recv.read_padded_string(13); recv.read_bool(); //gender recv.read_byte(); //skin recv.read_int(); //face recv.read_int(); //hair for (size_t i = 0; i < 3; i++) { statsentry.petids.push_back(recv.read_long()); } statsentry.stats[Maplestat::LEVEL] = recv.read_byte(); statsentry.stats[Maplestat::JOB] = recv.read_short(); statsentry.stats[Maplestat::STR] = recv.read_short(); statsentry.stats[Maplestat::DEX] = recv.read_short(); statsentry.stats[Maplestat::INT] = recv.read_short(); statsentry.stats[Maplestat::LUK] = recv.read_short(); statsentry.stats[Maplestat::HP] = recv.read_short(); statsentry.stats[Maplestat::MAXHP] = recv.read_short(); statsentry.stats[Maplestat::MP] = recv.read_short(); statsentry.stats[Maplestat::MAXMP] = recv.read_short(); statsentry.stats[Maplestat::AP] = recv.read_short(); statsentry.stats[Maplestat::SP] = recv.read_short(); statsentry.exp = recv.read_int(); statsentry.stats[Maplestat::FAME] = recv.read_short(); recv.skip(4); //gachaexp statsentry.mapid = recv.read_int(); statsentry.portal = recv.read_byte(); recv.skip(4); //timestamp return statsentry; }
void SetfieldHandler::handle(InPacket& recv) const { int32_t channel = recv.read_int(); int8_t mode1 = recv.read_byte(); int8_t mode2 = recv.read_byte(); if (mode1 == 0 && mode2 == 0) { change_map(recv, channel); } else { set_field(recv); } }
void SetfieldHandler::parsemonsterbook(InPacket& recv, Monsterbook& monsterbook) const { monsterbook.setcover(recv.read_int()); recv.skip(1); int16_t size = recv.read_short(); for (int16_t i = 0; i < size; i++) { int16_t cid = recv.read_short(); int8_t mblv = recv.read_byte(); monsterbook.addcard(cid, mblv); } }
void SetfieldHandler::set_field(InPacket& recv) const { recv.skip(23); int32_t cid = recv.read_int(); const CharEntry& playerentry = Session::get().getlogin().getcharbyid(cid); if (playerentry.cid != cid) { Console::get().print("Nonexisting cid: " + std::to_string(cid)); } Stage::get().loadplayer(playerentry); Session::get().getlogin().parsestats(recv); Player& player = Stage::get().getplayer(); recv.read_byte(); // 'buddycap' if (recv.read_bool()) { recv.read_string(); // 'linkedname' } parse_inventory(recv, player.getinvent()); parse_skillbook(recv, player.getskills()); parse_questlog(recv, player.getquests()); parseminigame(recv); parsering1(recv); parsering2(recv); parsering3(recv); parsetelerock(recv, player.gettrock()); parsemonsterbook(recv, player.getmonsterbook()); parsenewyear(recv); parseareainfo(recv); recv.skip(10); player.recalcstats(true); stagetransition(player.getstats().getportal(), player.getstats().getmapid()); Sound(Sound::GAMESTART).play(); UI::get().changestate(UI::GAME); }
void DeleteCharResponseHandler::handle(InPacket& recv) const { // Read the character id and if deletion was successfull (pic was correct). recv.read_int(); // charid bool success = recv.read_bool(); // Show the result to the user. UILoginNotice::Message message; if (success) { message = UILoginNotice::CASH_ITEMS_CONFIRM_DELETION; } else { message = UILoginNotice::BIRTHDAY_INCORRECT; } UI::get().add(ElementTag<UILoginNotice, int8_t>(message)); }
Account LoginParser::parse_account(InPacket & recv) { Account account; recv.skip(2); account.accid = recv.read_int(); account.female = recv.read_bool(); recv.read_bool(); //is admin account.gmlevel = recv.read_byte(); recv.skip(1); account.name = recv.read_string(); recv.skip(1); account.muted = recv.read_bool(); recv.read_long(); //muted until recv.read_long(); //creation date recv.skip(4); account.pin = recv.read_short(); return account; }
void SetfieldHandler::parse_inventory(InPacket& recv, Inventory& invent) const { invent.setmeso(recv.read_int()); invent.setslots(Inventory::EQUIP, recv.read_byte()); invent.setslots(Inventory::USE, recv.read_byte()); invent.setslots(Inventory::SETUP, recv.read_byte()); invent.setslots(Inventory::ETC, recv.read_byte()); invent.setslots(Inventory::CASH, recv.read_byte()); recv.skip(8); for (size_t i = 0; i < 3; i++) { Inventory::Type inv = (i == 0) ? Inventory::EQUIPPED : Inventory::EQUIP; int16_t pos = recv.read_short(); while (pos != 0) { int16_t slot = (i == 1) ? -pos : pos; ItemParser::parseitem(recv, inv, slot, invent); pos = recv.read_short(); } } recv.skip(2); Inventory::Type toparse[4] = { Inventory::USE, Inventory::SETUP, Inventory::ETC, Inventory::CASH }; for (size_t i = 0; i < 4; i++) { Inventory::Type inv = toparse[i]; int8_t pos = recv.read_byte(); while (pos != 0) { ItemParser::parseitem(recv, inv, pos, invent); pos = recv.read_byte(); } } }
void CharlistHandler::handle(InPacket& recv) const { uint8_t channel_id = recv.read_byte(); // Parse all characters. std::vector<CharEntry> characters; uint8_t charcount = recv.read_byte(); for (uint8_t i = 0; i < charcount; ++i) { characters.emplace_back( LoginParser::parse_charentry(recv) ); } int8_t pic = recv.read_byte(); uint8_t slots = (uint8_t)recv.read_int(); // Remove previous UIs. UI::get().remove(UIElement::WORLDSELECT); UI::get().remove(UIElement::CHARCREATION); // Add the character selection screen. UI::get().emplace<UICharSelect>(characters, charcount, slots, channel_id, pic); UI::get().enable(); }