// Stored packets void PlayerDataProvider::parseIncomingPacket(PacketReader &packet) { int32_t playerid = packet.get<int32_t>(); bool fromCashOrMts = packet.getBool(); size_t psize = packet.getBufferLength(); unsigned char *buf = new unsigned char[psize]; // Prevent the packet memory from being freed by external sources memcpy(buf, packet.getBuffer(), psize); m_packets[playerid].reset(new PacketReader(buf, psize)); SyncPacket::playerBuffsTransferred(ChannelServer::Instance()->getWorldConnection(), playerid, fromCashOrMts); }
void WorldServerConnectHandler::connect(WorldServerConnection *player, PacketReader &packet) { bool canHandle = packet.getBool(); if (canHandle) { uint16_t port = packet.get<uint16_t>(); CashServer::Instance()->setPort(port); CashServer::Instance()->setConnected(true); CashServer::Instance()->listen(); std::cout << "Handling cash server for world " << (int32_t)CashServer::Instance()->getWorld() << " on port " << port << std::endl; CashServer::Instance()->displayLaunchTime(); } else { std::cout << "Error: No cash server to handle" << std::endl; CashServer::Instance()->shutdown(); } }
void InventoryHandler::useScroll(Player *player, PacketReader &packet) { if (!player->updateTickCount(packet.get<int32_t>())) { // Tickcount was the same or less than 100 of the difference. return; } int16_t slot = packet.get<int16_t>(); int16_t eslot = packet.get<int16_t>(); bool wscroll = (packet.get<int16_t>() == 2); bool legendarySpirit = packet.getBool(); Item *item = player->getInventory()->getItem(Inventories::UseInventory, slot); Item *equip = player->getInventory()->getItem(Inventories::EquipInventory, eslot); if (item == nullptr || equip == nullptr) { // Most likely hacking return; } int32_t itemid = item->getId(); int8_t succeed = -1; bool cursed = false; ItemDataProvider::Instance()->scrollItem(itemid, equip, succeed, cursed, wscroll); if (succeed != -1) { if (wscroll) { Inventory::takeItem(player, Items::WhiteScroll, 1); } Inventory::takeItemSlot(player, Inventories::UseInventory, slot, 1); InventoryPacket::useScroll(player, succeed, cursed, legendarySpirit); if (!cursed) { player->getStats()->setEquip(eslot, equip); InventoryPacket::addNewItem(player, Inventories::EquipInventory, eslot, equip, true); } else { InventoryPacket::moveItem(player, Inventories::EquipInventory, eslot, 0); player->getInventory()->deleteItem(Inventories::EquipInventory, eslot); } InventoryPacket::updatePlayer(player); } else { if (legendarySpirit) { InventoryPacket::useScroll(player, succeed, cursed, legendarySpirit); } InventoryPacket::blankUpdate(player); } }
void Maps::usePortal(Player *player, PacketReader &packet) { packet.skipBytes(1); int32_t opcode = packet.get<int32_t>(); switch (opcode) { case 0: // Dead if (player->getStats()->getHp() == 0) { packet.getString(); // Useless packet.skipBytes(1); // Useless bool wheel = packet.getBool(); if (wheel && player->getInventory()->getItemAmount(Items::WheelOfDestiny) <= 0) { player->acceptDeath(false); return; } Inventory::takeItem(player, Items::WheelOfDestiny, 1); player->acceptDeath(wheel); } break; case -1: { string portalname = packet.getString(); Map *tomap = getMap(player->getMap()); if (tomap == nullptr) return; PortalInfo *portal = tomap->getPortal(portalname); if (portal == nullptr) // Exit the function if portal is not found return; usePortal(player, portal); break; } default: { // GM Map change (command "/m") if (player->isGm() && getMap(opcode)) { player->setMap(opcode); } } } }
void MobHandler::monsterControl(Player *player, PacketReader &packet) { int32_t mobid = packet.get<int32_t>(); Mob *mob = Maps::getMap(player->getMap())->getMob(mobid); if (mob == nullptr || mob->getControlStatus() == Mobs::ControlStatus::ControlNone) { return; } int16_t moveid = packet.get<int16_t>(); bool useskill = packet.getBool(); int8_t skill = packet.get<int8_t>(); uint8_t realskill = 0; uint8_t level = 0; Pos projectiletarget = packet.getPos(); packet.skipBytes(5); // 1 byte of always 0?, 4 bytes of always 1 or always 0? Pos spot = packet.getPos(); MovementHandler::parseMovement(mob, packet); if (useskill && (skill == -1 || skill == 0)) { if (!(mob->hasStatus(StatusEffects::Mob::Freeze) || mob->hasStatus(StatusEffects::Mob::Stun) || mob->hasStatus(StatusEffects::Mob::ShadowWeb))) { uint8_t size = mob->getSkillCount(); bool used = false; if (size) { bool stop = false; uint8_t rand = Randomizer::Instance()->randChar(size - 1); MobSkillInfo *info = MobDataProvider::Instance()->getMobSkill(mob->getMobId(), rand); realskill = info->skillId; level = info->level; MobSkillLevelInfo *mobskill = SkillDataProvider::Instance()->getMobSkill(realskill, level); switch (realskill) { case MobSkills::WeaponAttackUp: case MobSkills::WeaponAttackUpAoe: stop = mob->hasStatus(StatusEffects::Mob::Watk); break; case MobSkills::MagicAttackUp: case MobSkills::MagicAttackUpAoe: stop = mob->hasStatus(StatusEffects::Mob::Matk); break; case MobSkills::WeaponDefenseUp: case MobSkills::WeaponDefenseUpAoe: stop = mob->hasStatus(StatusEffects::Mob::Wdef); break; case MobSkills::MagicDefenseUp: case MobSkills::MagicDefenseUpAoe: stop = mob->hasStatus(StatusEffects::Mob::Mdef); break; case MobSkills::WeaponImmunity: case MobSkills::MagicImmunity: case MobSkills::WeaponDamageReflect: case MobSkills::MagicDamageReflect: stop = mob->hasImmunity(); break; case MobSkills::McSpeedUp: stop = mob->hasStatus(StatusEffects::Mob::Speed); break; case MobSkills::Summon: { int16_t limit = mobskill->limit; if (limit == 5000) // Custom limit based on number of players on map limit = 30 + Maps::getMap(mob->getMapId())->getNumPlayers() * 2; if (mob->getSpawnCount() >= limit) stop = true; break; } } if (!stop) { time_t now = time(0); time_t ls = mob->getLastSkillUse(realskill); if (ls == 0 || ((int32_t)(now - ls) > mobskill->interval)) { mob->setLastSkillUse(realskill, now); int64_t reqhp = mob->getHp() * 100; reqhp /= mob->getMaxHp(); if ((uint8_t)(reqhp) <= mobskill->hp) { if (info->effectAfter == 0) { handleMobSkill(mob, realskill, level, mobskill); } else { new Timer::Timer(bind(&MobHandler::handleMobSkill, mob, realskill, level, mobskill), Timer::Id(Timer::Types::MobSkillTimer, mob->getMobId(), mob->getCounter()), mob->getTimers(), Timer::Time::fromNow(info->effectAfter)); } used = true; } } } } if (!used) { realskill = 0; level = 0; } } } MobsPacket::moveMobResponse(player, mobid, moveid, useskill, mob->getMp(), realskill, level); packet.reset(19); MobsPacket::moveMob(player, mobid, useskill, skill, projectiletarget, packet.getBuffer(), packet.getBufferLength()); }
void InventoryHandler::useCashItem(Player *player, PacketReader &packet) { packet.get<int8_t>(); // Type packet.skipBytes(1); int32_t itemid = packet.get<int32_t>(); if (!player->getInventory()->getItemAmount(itemid)) { // Hacking return; } bool used = false; if (GameLogicUtilities::getItemType(itemid) == Items::Types::WeatherCash) { string message = packet.getString(); if (!player->updateTickCount(packet.get<int32_t>())) { // Tickcount was the same or less than 100 of the difference. return; } if (message.length() <= 35) { Map *map = Maps::getMap(player->getMap()); message = player->getName() + " 's message : " + message; used = map->createWeather(player, false, Items::WeatherTime, itemid, message); } } else if (GameLogicUtilities::getItemType(itemid) == Items::Types::CashPetFood) { // Pet food. Pet *pet = player->getPets()->getSummoned(0); if (pet != nullptr) { if (pet->getFullness() < Stats::MaxFullness) { PetsPacket::showAnimation(player, pet, 1); pet->modifyFullness(Stats::MaxFullness, false); pet->addCloseness(100); // All cash pet food gives 100 closeness. used = true; } } } else { switch (itemid) { case Items::TeleportRock: case Items::TeleportCoke: case Items::VipRock: // Only occurs when you actually try to move somewhere used = handleRockTeleport(player, itemid, packet); break; case Items::FirstJobSpReset: case Items::SecondJobSpReset: case Items::ThirdJobSpReset: case Items::FourthJobSpReset: { int32_t toskill = packet.get<int32_t>(); int32_t fromskill = packet.get<int32_t>(); if (!player->getSkills()->addSkillLevel(fromskill, -1, true)) { // Hacking return; } if (!player->getSkills()->addSkillLevel(toskill, 1, true)) { // Hacking return; } used = true; break; } case Items::ApReset: { int32_t tostat = packet.get<int32_t>(); int32_t fromstat = packet.get<int32_t>(); player->getStats()->addStat(tostat, 1, true); player->getStats()->addStat(fromstat, -1, true); used = true; break; } case Items::Megaphone: { string msg = player->getMedalName() + " : " + packet.getString(); InventoryPacket::showMegaphone(player, msg); used = true; break; } case Items::SuperMegaphone: { string msg = player->getMedalName() + " : " + packet.getString(); bool whisper = packet.getBool(); InventoryPacket::showSuperMegaphone(player, msg, whisper); used = true; break; } case Items::DiabloMessenger: case Items::Cloud9Messenger: case Items::LoveholicMessenger: { string msg = packet.getString(); string msg2 = packet.getString(); string msg3 = packet.getString(); string msg4 = packet.getString(); InventoryPacket::showMessenger(player, msg, msg2, msg3, msg4, packet.getBuffer(), packet.getBufferLength(), itemid); used = true; break; } case Items::ItemMegaphone: { string msg = player->getMedalName() + " : " + packet.getString(); bool whisper = packet.getBool(); Item *item = nullptr; if (packet.getBool()) { int8_t inv = (int8_t) packet.get<int32_t>(); int16_t slot = (int16_t) packet.get<int32_t>(); item = player->getInventory()->getItem(inv, slot); if (item == nullptr) { // Hacking return; } } InventoryPacket::showItemMegaphone(player, msg, whisper, item); used = true; break; } case Items::ArtMegaphone: { int8_t lines = packet.get<int8_t>(); if (lines < 1 || lines > 3) { // Hacking return; } string text[3]; for (int8_t i = 0; i < lines; i++) { text[i] = player->getMedalName() + " : " + packet.getString(); } bool whisper = packet.getBool(); InventoryPacket::showTripleMegaphone(player, lines, text[0], text[1], text[2], whisper); used = true; break; } case Items::PetNameTag: { string name = packet.getString(); PetHandler::changeName(player, name); used = true; break; } case Items::ItemNameTag: { int16_t slot = packet.get<int16_t>(); if (slot != 0) { Item *item = player->getInventory()->getItem(Inventories::EquipInventory, slot); if (item == nullptr) { // Hacking or failure, dunno return; } item->setName(player->getName()); InventoryPacket::addNewItem(player, Inventories::EquipInventory, slot, item, true); used = true; } break; } case Items::ItemLock: case Items::ScissorsOfKarma: { int8_t inventory = (int8_t) packet.get<int32_t>(); int16_t slot = (int16_t) packet.get<int32_t>(); if (slot != 0) { Item *item = player->getInventory()->getItem(inventory, slot); if (item == nullptr || (itemid == Items::ItemLock && item->hasLock()) || item->hasTradeBlock() || (itemid == Items::ScissorsOfKarma && item->hasKarma())) { // Hacking or failure, dunno return; } ItemInfo *info = ItemDataProvider::Instance()->getItemInfo(item->getId()); if (itemid == Items::ScissorsOfKarma && info->karmascissors) { // Hacking return; } switch (itemid) { case Items::ItemLock: item->setLock(true); break; case Items::ScissorsOfKarma: item->setKarma(true); break; } InventoryPacket::addNewItem(player, inventory, slot, item, true); used = true; } break; } case Items::MapleTvMessenger: case Items::Megassenger: { bool hasreceiver = (packet.get<int8_t>() == 3); bool show_whisper = (itemid == Items::Megassenger ? packet.getBool() : false); Player *receiver = PlayerDataProvider::Instance()->getPlayer(packet.getString()); int32_t time = 15; if ((hasreceiver && receiver != nullptr) || (!hasreceiver && receiver == nullptr)) { string msg = packet.getString(); string msg2 = packet.getString(); string msg3 = packet.getString(); string msg4 = packet.getString(); string msg5 = packet.getString(); if (!player->updateTickCount(packet.get<int32_t>())) { // Tickcount was the same or less than 100 of the difference. return; } MapleTvs::Instance()->addMessage(player, receiver, msg, msg2, msg3, msg4, msg5, itemid - (itemid == Items::Megassenger ? 3 : 0), time); if (itemid == Items::Megassenger) { InventoryPacket::showSuperMegaphone(player, player->getMedalName() + " : " + msg + msg2 + msg3 + msg4 + msg5, show_whisper); } used = true; } break; } case Items::MapleTvStarMessenger: case Items::StarMegassenger: { int32_t time = 30; bool show_whisper = (itemid == Items::StarMegassenger ? packet.getBool() : false); string msg = packet.getString(); string msg2 = packet.getString(); string msg3 = packet.getString(); string msg4 = packet.getString(); string msg5 = packet.getString(); if (!player->updateTickCount(packet.get<int32_t>())) { // Tickcount was the same or less than 100 of the difference. return; } MapleTvs::Instance()->addMessage(player, nullptr, msg, msg2, msg3, msg4, msg5, itemid - (itemid == Items::StarMegassenger ? 3 : 0), time); if (itemid == Items::StarMegassenger) { InventoryPacket::showSuperMegaphone(player, player->getMedalName() + " : " + msg + msg2 + msg3 + msg4 + msg5, show_whisper); } used = true; break; } case Items::MapleTvHeartMessenger: case Items::HeartMegassenger: { bool show_whisper = (itemid == Items::HeartMegassenger ? packet.getBool() : false); string name = packet.getString(); Player *receiver = PlayerDataProvider::Instance()->getPlayer(name); int32_t time = 60; if (receiver != nullptr) { string msg = packet.getString(); string msg2 = packet.getString(); string msg3 = packet.getString(); string msg4 = packet.getString(); string msg5 = packet.getString(); if (!player->updateTickCount(packet.get<int32_t>())) { // Tickcount was the same or less than 100 of the difference. return; } MapleTvs::Instance()->addMessage(player, receiver, msg, msg2, msg3, msg4, msg5, itemid - (itemid == Items::HeartMegassenger ? 3 : 0), time); if (itemid == Items::HeartMegassenger) { InventoryPacket::showSuperMegaphone(player, player->getMedalName() + " : " + msg + msg2 + msg3 + msg4 + msg5, show_whisper); } used = true; } break; } case Items::BronzeSackOfMesos: case Items::SilverSackOfMesos: case Items::GoldSackOfMesos: { int32_t mesos = ItemDataProvider::Instance()->getMesoBonus(itemid); if (!player->getInventory()->modifyMesos(mesos)) { InventoryPacket::sendMesobagFailed(player); } else { InventoryPacket::sendMesobagSucceed(player, mesos); used = true; } break; } case Items::Chalkboard: case Items::Chalkboard2: { string msg = packet.getString(); player->setChalkboard(msg); InventoryPacket::sendChalkboardUpdate(player, msg); break; } case Items::FungusScroll: case Items::OinkerDelight: case Items::ZetaNightmare: Inventory::useItem(player, itemid); used = true; break; case Items::ViciousHammer: { int8_t inventory = (int8_t) packet.get<int32_t>(); // How pointless... int16_t slot = (int16_t) packet.get<int32_t>(); Item *f = player->getInventory()->getItem(inventory, slot); if (f == nullptr || f->getHammers() == Items::MaxHammers) { // Hacking, probably return; } f->incHammers(); f->incSlots(); InventoryPacket::sendHammerSlots(player, f->getHammers()); player->getInventory()->setHammerSlot(slot); used = true; break; } case Items::CongratulatorySong: if (!player->updateTickCount(packet.get<int32_t>())) { // Tickcount was the same or less than 100 of the difference. return; } used = Maps::getMap(player->getMap())->playJukebox(player, itemid, 60 * 5); // 5 minutes is enough! break; case Items::KoreanKite: case Items::HeartBalloon: case Items::GraduationBanner: case Items::AdmissionBanner: { string message = packet.getString(); if (!player->updateTickCount(packet.get<int32_t>())) { // Tickcount was the same or less than 100 of the difference. return; } used = Maps::getMap(player->getMap())->createKite(player, itemid, message); if (!used) { InventoryPacket::sendCannotFlyHere(player); } break; } default: { packet.reset(); std::stringstream x; x << "Unknown cash item! ItemID: " << itemid << "; Player ID: " << player->getId() << "; Packet: " << packet; ChannelServer::Instance()->log(LogTypes::Info, x.str()); break; } } } if (used) { Inventory::takeItem(player, itemid, 1); } else { InventoryPacket::blankUpdate(player); } }
void WorldServerConnectHandler::updateCoupon(PacketReader &packet) { CouponInfo *info = CashDataProvider::Instance()->getCouponInfo(packet.getString()); if (info != nullptr) { info->used = packet.getBool(); } }