From 8267b4f324db66d0c74eb3c7d96f7d497b109f1d Mon Sep 17 00:00:00 2001 From: sruon Date: Tue, 14 Apr 2026 23:54:42 -0600 Subject: [PATCH] Fold PacketGuard into the general C2S system - Size checks are enforced for all packets in the handlers and automatically determined from structures - Adds missing padding to a handful of packets - Introduce a flag-driven BlockedState mechanism for packet validation - Rate limit values loaded from settings and handled by PacketSystem - PacketHandlers global array is no longer accessible --- modules/custom/cpp/ah_announcement.cpp | 168 ++++---- modules/renamer/README.md | 1 - modules/renamer/cpp/renamer.cpp | 99 ----- modules/renamer/lua/list.lua | 9 - settings/default/map.lua | 4 - src/map/CMakeLists.txt | 2 - src/map/enums/blocked_state.h | 51 +++ src/map/map_engine.cpp | 6 - src/map/map_networking.cpp | 87 ++-- src/map/map_networking.h | 4 + src/map/packet_guard.cpp | 198 --------- src/map/packet_system.cpp | 394 +++++++++--------- src/map/packet_system.h | 22 +- src/map/packets/c2s/0x00a_login.cpp | 4 +- src/map/packets/c2s/0x00c_gameok.cpp | 2 +- src/map/packets/c2s/0x00d_netend.cpp | 2 +- src/map/packets/c2s/0x00f_clstat.cpp | 2 +- src/map/packets/c2s/0x011_zone_transition.cpp | 2 +- src/map/packets/c2s/0x011_zone_transition.h | 5 +- src/map/packets/c2s/0x015_pos.cpp | 14 +- src/map/packets/c2s/0x015_pos.h | 1 + src/map/packets/c2s/0x016_charreq.cpp | 12 +- src/map/packets/c2s/0x017_charreq2.cpp | 5 +- src/map/packets/c2s/0x01a_action.cpp | 188 ++++----- src/map/packets/c2s/0x01b_friendpass.cpp | 9 +- src/map/packets/c2s/0x01c_unknown.cpp | 5 +- src/map/packets/c2s/0x01e_gm.cpp | 7 +- src/map/packets/c2s/0x01e_gm.h | 4 +- src/map/packets/c2s/0x01f_gmcommand.cpp | 7 +- src/map/packets/c2s/0x01f_gmcommand.h | 6 +- src/map/packets/c2s/0x028_item_dump.cpp | 23 +- src/map/packets/c2s/0x029_item_move.cpp | 63 +-- src/map/packets/c2s/0x02b_translate.cpp | 3 +- src/map/packets/c2s/0x02b_translate.h | 10 +- src/map/packets/c2s/0x02c_itemsearch.cpp | 9 +- src/map/packets/c2s/0x02c_itemsearch.h | 8 +- src/map/packets/c2s/0x032_trade_req.cpp | 14 +- src/map/packets/c2s/0x033_trade_res.cpp | 16 +- src/map/packets/c2s/0x034_trade_list.cpp | 52 +-- src/map/packets/c2s/0x036_item_transfer.cpp | 4 +- src/map/packets/c2s/0x037_item_use.cpp | 4 +- src/map/packets/c2s/0x03a_item_stack.cpp | 6 +- src/map/packets/c2s/0x03b_subcontainer.cpp | 27 +- src/map/packets/c2s/0x03c_black_list.cpp | 3 +- src/map/packets/c2s/0x03d_black_edit.cpp | 9 +- src/map/packets/c2s/0x041_trophy_entry.cpp | 9 +- src/map/packets/c2s/0x042_trophy_absence.cpp | 9 +- src/map/packets/c2s/0x04b_fragments.cpp | 24 +- src/map/packets/c2s/0x04d_pbx.cpp | 168 ++++---- src/map/packets/c2s/0x04e_auc.cpp | 47 ++- src/map/packets/c2s/0x050_equip_set.cpp | 10 +- src/map/packets/c2s/0x051_equipset_set.cpp | 16 +- src/map/packets/c2s/0x052_equipset_check.cpp | 3 +- src/map/packets/c2s/0x053_lockstyle.cpp | 12 +- src/map/packets/c2s/0x058_recipe.cpp | 32 +- src/map/packets/c2s/0x059_effectend.cpp | 3 +- src/map/packets/c2s/0x05a_reqconquest.cpp | 2 +- src/map/packets/c2s/0x05b_eventend.cpp | 12 +- src/map/packets/c2s/0x05c_eventendxzy.cpp | 18 +- src/map/packets/c2s/0x05d_motion.cpp | 17 +- src/map/packets/c2s/0x05e_maprect.cpp | 3 +- src/map/packets/c2s/0x060_passwards.cpp | 6 +- src/map/packets/c2s/0x061_clistatus.cpp | 4 +- src/map/packets/c2s/0x061_clistatus.h | 5 +- src/map/packets/c2s/0x063_dig.cpp | 3 +- src/map/packets/c2s/0x064_scenarioitem.cpp | 13 +- .../packets/c2s/0x06e_group_solicit_req.cpp | 15 +- src/map/packets/c2s/0x06f_group_leave.cpp | 7 +- src/map/packets/c2s/0x070_group_breakup.cpp | 13 +- src/map/packets/c2s/0x071_group_strike.cpp | 21 +- .../packets/c2s/0x074_group_solicit_res.cpp | 9 +- src/map/packets/c2s/0x074_group_solicit_res.h | 4 +- src/map/packets/c2s/0x076_group_list_req.cpp | 5 +- src/map/packets/c2s/0x077_group_change2.cpp | 33 +- src/map/packets/c2s/0x078_group_checkid.cpp | 3 +- src/map/packets/c2s/0x083_shop_buy.cpp | 3 +- src/map/packets/c2s/0x084_shop_sell_req.cpp | 4 +- src/map/packets/c2s/0x085_shop_sell_set.cpp | 6 +- src/map/packets/c2s/0x085_shop_sell_set.h | 3 +- src/map/packets/c2s/0x096_combine_ask.cpp | 9 +- src/map/packets/c2s/0x096_combine_ask.h | 1 + .../packets/c2s/0x09b_chocobo_race_req.cpp | 11 +- src/map/packets/c2s/0x0a0_switch_proposal.cpp | 9 +- src/map/packets/c2s/0x0a0_switch_proposal.h | 6 +- src/map/packets/c2s/0x0a1_switch_vote.cpp | 7 +- src/map/packets/c2s/0x0a2_dice.cpp | 3 +- src/map/packets/c2s/0x0aa_guild_buy.cpp | 21 +- src/map/packets/c2s/0x0ab_guild_buylist.cpp | 3 +- src/map/packets/c2s/0x0ac_guild_sell.cpp | 18 +- src/map/packets/c2s/0x0ad_guild_selllist.cpp | 3 +- src/map/packets/c2s/0x0b5_chat_std.cpp | 12 +- src/map/packets/c2s/0x0b5_chat_std.h | 8 +- src/map/packets/c2s/0x0b6_chat_name.cpp | 12 +- src/map/packets/c2s/0x0b6_chat_name.h | 10 +- src/map/packets/c2s/0x0b7_assist_channel.cpp | 9 +- src/map/packets/c2s/0x0be_merits.cpp | 21 +- .../packets/c2s/0x0bf_job_points_spend.cpp | 9 +- src/map/packets/c2s/0x0c0_job_points_req.cpp | 4 +- .../packets/c2s/0x0c1_alter_ego_points.cpp | 8 +- .../packets/c2s/0x0c3_group_comlink_make.cpp | 11 +- .../c2s/0x0c4_group_comlink_active.cpp | 19 +- src/map/packets/c2s/0x0cb_myroom_is.cpp | 15 +- src/map/packets/c2s/0x0d2_map_group.cpp | 5 +- src/map/packets/c2s/0x0d3_faq_gmcall.cpp | 3 +- src/map/packets/c2s/0x0d3_faq_gmcall.h | 16 +- src/map/packets/c2s/0x0d4_faq_gmparam.cpp | 3 +- src/map/packets/c2s/0x0d5_ack_gmmsg.cpp | 3 +- src/map/packets/c2s/0x0d8_dungeon_param.cpp | 15 +- src/map/packets/c2s/0x0db_config_language.cpp | 24 +- src/map/packets/c2s/0x0dc_config.cpp | 25 +- src/map/packets/c2s/0x0dd_equip_inspect.cpp | 15 +- src/map/packets/c2s/0x0de_inspect_message.cpp | 6 +- src/map/packets/c2s/0x0e0_set_usermsg.cpp | 8 +- src/map/packets/c2s/0x0e1_get_lsmsg.cpp | 9 +- src/map/packets/c2s/0x0e2_set_lsmsg.cpp | 13 +- src/map/packets/c2s/0x0e4_get_lspriv.cpp | 11 +- src/map/packets/c2s/0x0e7_reqlogout.cpp | 16 +- src/map/packets/c2s/0x0e8_camp.cpp | 15 +- src/map/packets/c2s/0x0ea_sit.cpp | 10 +- src/map/packets/c2s/0x0eb_reqsubmapnum.cpp | 3 +- src/map/packets/c2s/0x0f0_rescue.cpp | 10 +- src/map/packets/c2s/0x0f1_buffcancel.cpp | 7 +- src/map/packets/c2s/0x0f2_submapchange.cpp | 8 +- src/map/packets/c2s/0x0f4_tracking_list.cpp | 5 +- src/map/packets/c2s/0x0f5_tracking_start.cpp | 7 +- src/map/packets/c2s/0x0f6_tracking_end.cpp | 3 +- src/map/packets/c2s/0x0fa_myroom_layout.cpp | 3 +- src/map/packets/c2s/0x0fb_myroom_bankin.cpp | 3 +- .../packets/c2s/0x0fc_myroom_plant_add.cpp | 39 +- .../packets/c2s/0x0fd_myroom_plant_check.cpp | 13 +- .../packets/c2s/0x0fe_myroom_plant_crop.cpp | 17 +- .../packets/c2s/0x0ff_myroom_plant_stop.cpp | 17 +- src/map/packets/c2s/0x100_myroom_job.cpp | 27 +- src/map/packets/c2s/0x100_myroom_job.h | 5 +- src/map/packets/c2s/0x102_extended_job.cpp | 35 +- src/map/packets/c2s/0x104_bazaar_exit.cpp | 3 +- src/map/packets/c2s/0x105_bazaar_list.cpp | 7 +- src/map/packets/c2s/0x106_bazaar_buy.cpp | 3 +- src/map/packets/c2s/0x109_bazaar_open.cpp | 3 +- src/map/packets/c2s/0x10a_bazaar_itemset.cpp | 19 +- src/map/packets/c2s/0x10b_bazaar_close.cpp | 5 +- src/map/packets/c2s/0x10c_roe_start.cpp | 3 +- src/map/packets/c2s/0x10d_roe_remove.cpp | 7 +- src/map/packets/c2s/0x10e_roe_claim.cpp | 7 +- src/map/packets/c2s/0x10f_currencies_1.cpp | 3 +- src/map/packets/c2s/0x110_fishing_2.cpp | 31 +- src/map/packets/c2s/0x112_battlefield_req.cpp | 6 +- src/map/packets/c2s/0x112_battlefield_req.h | 4 +- src/map/packets/c2s/0x113_sitchair.cpp | 14 +- src/map/packets/c2s/0x114_map_markers.cpp | 2 +- src/map/packets/c2s/0x115_currencies_2.cpp | 3 +- src/map/packets/c2s/0x116_unity_menu.cpp | 5 +- src/map/packets/c2s/0x117_unity_quest.cpp | 5 +- src/map/packets/c2s/0x118_unity_toggle.cpp | 6 +- src/map/packets/c2s/0x119_emote_list.cpp | 3 +- src/map/packets/c2s/0x11b_mastery_display.cpp | 8 +- src/map/packets/c2s/0x11c_party_request.cpp | 11 +- src/map/packets/c2s/0x11c_party_request.h | 1 + src/map/packets/c2s/0x11d_jump.cpp | 9 +- src/map/packets/c2s/0x11d_jump.h | 6 +- src/map/packets/c2s/CMakeLists.txt | 2 + src/map/packets/c2s/base.h | 47 ++- src/map/packets/c2s/rate_limiter.cpp | 66 +++ .../c2s/rate_limiter.h} | 26 +- src/map/packets/c2s/validation.cpp | 199 ++++----- src/map/packets/c2s/validation.h | 136 +++--- .../lua_client_entity_pair_actions.cpp | 29 +- .../helpers/lua_client_entity_pair_events.cpp | 3 +- .../lua_client_entity_pair_packets.cpp | 9 +- .../helpers/lua_client_entity_pair_packets.h | 14 +- tools/ci/sanity_checks/cpp.sh | 1 + 171 files changed, 1641 insertions(+), 1806 deletions(-) delete mode 100644 modules/renamer/README.md delete mode 100644 modules/renamer/cpp/renamer.cpp delete mode 100644 modules/renamer/lua/list.lua create mode 100644 src/map/enums/blocked_state.h delete mode 100644 src/map/packet_guard.cpp create mode 100644 src/map/packets/c2s/rate_limiter.cpp rename src/map/{packet_guard.h => packets/c2s/rate_limiter.h} (62%) diff --git a/modules/custom/cpp/ah_announcement.cpp b/modules/custom/cpp/ah_announcement.cpp index 2b3b4deb636..dd8d3b2938c 100644 --- a/modules/custom/cpp/ah_announcement.cpp +++ b/modules/custom/cpp/ah_announcement.cpp @@ -1,4 +1,4 @@ -/************************************************************************ +/************************************************************************ * Auction House Announcements * * This will send a message to the seller of an item when it is bought, @@ -10,7 +10,6 @@ #include "map/ipc_client.h" #include "map/map_session.h" -#include "map/packet_system.h" #include "map/packets/basic.h" #include "map/utils/itemutils.h" #include "map/utils/moduleutils.h" @@ -20,101 +19,102 @@ #include #include -extern uint8 PacketSize[512]; - -extern std::function PacketParser[512]; - class AHAnnouncementModule : public CPPModule { void OnInit() override + { + } + + auto OnIncomingPacket(MapSession* PSession, CCharEntity* PChar, CBasicPacket& data) -> bool override { TracyZoneScoped; - const auto originalHandler = PacketParser[0x04E]; + // Only intercept AUC packets (0x04E) + if (data.getType() != static_cast(PacketC2S::GP_CLI_COMMAND_AUC)) + { + return false; + } - const auto newHandler = [originalHandler](MapSession* const PSession, CCharEntity* const PChar, CBasicPacket& data) -> void + // Only intercept for action 0x0E: Purchasing Items + const auto* packet = data.as(); + if (packet->Command != GP_CLI_COMMAND_AUC_COMMAND::Bid) { - TracyZoneScoped; + return false; + } - // Only intercept for action 0x0E: Purchasing Items - const auto action = data.ref(0x04); - if (action == 0x0E) - { - const uint32 price = data.ref(0x08); - const uint16 itemid = data.ref(0x0C); - const uint8 quantity = data.ref(0x10); + const uint32 price = packet->Param.Bid.BidPrice; + const uint16 itemid = packet->Param.Bid.ItemNo; + const uint8 quantity = packet->Param.Bid.ItemStacks; - CItem* PItem = itemutils::GetItemPointer(itemid); - if (PItem) - { - const GP_AUC_PARAM_BID payload{ - .BidPrice = price, - .ItemNo = itemid, - .ItemStacks = quantity, - }; - - if (auctionutils::PurchasingItems(PChar, payload)) - { - const auto sellerId = [&]() -> uint32 - { - uint32 sellerId = 0; - - const auto rset = db::preparedStmt("SELECT seller " - "FROM auction_house WHERE " - "buyer_name = ? AND " - "sale = ? AND " - "itemid = ? AND " - "stack = ? " - "ORDER BY sell_date DESC LIMIT 1", - PChar->getName(), - price, - itemid, - quantity == 0); - - FOR_DB_SINGLE_RESULT(rset) - { - sellerId = rset->get("seller"); - } - - return sellerId; - }(); - - if (sellerId) - { - // Sanitize name - std::string name = PItem->getName(); - auto parts = split(name, "_"); - name = ""; - name += std::accumulate( - std::begin(parts), - std::end(parts), - std::string(), - [](const std::string& ss, const std::string& s) - { - return ss.empty() ? s : ss + " " + s; - }); - - // Capitalize first letter - name[0] = std::toupper(name[0]); - - // Send message to seller! - message::send(ipc::ChatMessageCustom{ - .recipientId = sellerId, - .senderName = "", - .message = fmt::format("Your '{}' has sold to {} for {} gil!", name, PChar->getName(), price), - .messageType = MESSAGE_SYSTEM_3, - }); - } - } - } - } - else // Otherwise, call original handler + CItem* PItem = itemutils::GetItemPointer(itemid); + if (!PItem) + { + return false; + } + + const GP_AUC_PARAM_BID payload{ + .BidPrice = price, + .ItemNo = itemid, + .ItemStacks = quantity, + }; + + if (!auctionutils::PurchasingItems(PChar, payload)) + { + return false; + } + + const auto sellerId = [&]() -> uint32 + { + uint32 id = 0; + + const auto rset = db::preparedStmt("SELECT seller " + "FROM auction_house WHERE " + "buyer_name = ? AND " + "sale = ? AND " + "itemid = ? AND " + "stack = ? " + "ORDER BY sell_date DESC LIMIT 1", + PChar->getName(), + price, + itemid, + quantity == 0); + + FOR_DB_SINGLE_RESULT(rset) { - originalHandler(PSession, PChar, data); + id = rset->get("seller"); } - }; - PacketParser[0x04E] = newHandler; + return id; + }(); + + if (sellerId) + { + // Sanitize name + std::string name = PItem->getName(); + auto parts = split(name, "_"); + name = ""; + name += std::accumulate( + std::begin(parts), + std::end(parts), + std::string(), + [](const std::string& ss, const std::string& s) + { + return ss.empty() ? s : ss + " " + s; + }); + + // Capitalize first letter + name[0] = std::toupper(name[0]); + + // Send message to seller! + message::send(ipc::ChatMessageCustom{ + .recipientId = sellerId, + .senderName = "", + .message = fmt::format("Your '{}' has sold to {} for {} gil!", name, PChar->getName(), price), + .messageType = MESSAGE_SYSTEM_3, + }); + } + + return true; } }; diff --git a/modules/renamer/README.md b/modules/renamer/README.md deleted file mode 100644 index cf92c4f8b8c..00000000000 --- a/modules/renamer/README.md +++ /dev/null @@ -1 +0,0 @@ -# Renamer Readme diff --git a/modules/renamer/cpp/renamer.cpp b/modules/renamer/cpp/renamer.cpp deleted file mode 100644 index c6b4b03e89a..00000000000 --- a/modules/renamer/cpp/renamer.cpp +++ /dev/null @@ -1,99 +0,0 @@ -#include "map/packet_guard.h" -#include "map/utils/moduleutils.h" -#include "map/zone.h" - -extern uint8 PacketSize[512]; -extern std::function PacketParser[512]; - -class RenamerModule : public CPPModule -{ - void SendListPacket(CCharEntity* PChar, const std::string& data) - { - if (data.empty()) - { - // Nothing to do, bail out - return; - } - - auto customPacket = std::unique_ptr(); - customPacket->setType(0x1FF); - customPacket->setSize(0x100); - for (std::size_t i = 0; i < data.size(); ++i) - { - customPacket->ref(0x04 + i) = data[i]; - } - PChar->pushPacket(std::move(customPacket)); - } - - void OnInit() override - { - TracyZoneScoped; - - ShowInfo("Renamer: Loading ./modules/renamer/lua/list.lua"); - - auto result = lua.safe_script_file("./modules/renamer/lua/list.lua", &sol::script_pass_on_error); - if (!result.valid()) - { - sol::error err = result; - ShowError("Load error: %s", err.what()); - return; - } - - if (!result.return_count()) - { - ShowError("No returned renamer list object"); - return; - } - - // NOTE: If we don't attach the result to something global, it will not be - // : correclty captured by the packet handling lambda. - lua[sol::create_if_nil]["xi"]["renamerTable"] = result; - - // Add a custom packet handler to the PacketParser array for id 0x01 - PacketParser[0x01] = [&](MapSession* const, CCharEntity* const PChar, CBasicPacket&) - { - ShowInfo(fmt::format("{} requested renamer list for {}", PChar->getName(), PChar->loc.zone->getName())); - - auto zoneId = PChar->getZone(); - auto renamerTable = lua["xi"]["renamerTable"].get(); - - auto zoneTable = renamerTable[zoneId].get_or(sol::lua_nil); - if (zoneTable == sol::lua_nil) - { - return; - } - - std::string dataString; - for (const auto& [key, value] : zoneTable) - { - auto entryTable = value.as(); - - // convert entityId to targid - auto entityCodedName = entryTable[1].get(); - auto entityDisplayName = entryTable[2].get(); - auto packedString = fmt::format("{},{}.", entityCodedName, entityDisplayName); - - // If the dataString gets too large, send a packet with what we've - // already prepared so we don't exceed the target size of 0x100. - if (0x04 + dataString.size() + packedString.size() > 0x100) - { - SendListPacket(PChar, dataString); - dataString.clear(); - } - else - { - dataString += packedString; - } - } - - SendListPacket(PChar, dataString); - }; - - // Add new possible packet to PacketGuard allow list - auto& allowList = PacketGuard::GetPacketAllowList(); - - allowList[SUBSTATE_IN_CS][0x01] = true; - } -}; - -REGISTER_CPP_MODULE(RenamerModule); diff --git a/modules/renamer/lua/list.lua b/modules/renamer/lua/list.lua deleted file mode 100644 index 7837d421f96..00000000000 --- a/modules/renamer/lua/list.lua +++ /dev/null @@ -1,9 +0,0 @@ -local list = -{ - [xi.zone.KUFTAL_TUNNEL] = - { - { 'Robber Crab', 'I HAVE BEEN RENAMED!' }, - { 'Cave Worm', 'IMMA WORM!' }, - }, -} -return list diff --git a/settings/default/map.lua b/settings/default/map.lua index 46114b9b3d6..11c886effe2 100644 --- a/settings/default/map.lua +++ b/settings/default/map.lua @@ -29,10 +29,6 @@ xi.settings.map = -- Game settings -- -------------------------------- - -- PacketGuard will block and report any packets that aren't in the allow-list for a - -- player's current state. - PACKETGUARD_ENABLED = true, - -- Minimal number of 0x3A packets which uses for detect lightluggage (set 0 for disable) LIGHTLUGGAGE_BLOCK = 4, diff --git a/src/map/CMakeLists.txt b/src/map/CMakeLists.txt index 187f5d70a99..b9ad56643a1 100644 --- a/src/map/CMakeLists.txt +++ b/src/map/CMakeLists.txt @@ -123,8 +123,6 @@ set(SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/ximesh.h ${CMAKE_CURRENT_SOURCE_DIR}/notoriety_container.cpp ${CMAKE_CURRENT_SOURCE_DIR}/notoriety_container.h - ${CMAKE_CURRENT_SOURCE_DIR}/packet_guard.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/packet_guard.h ${CMAKE_CURRENT_SOURCE_DIR}/packet_system.cpp ${CMAKE_CURRENT_SOURCE_DIR}/packet_system.h ${CMAKE_CURRENT_SOURCE_DIR}/party.cpp diff --git a/src/map/enums/blocked_state.h b/src/map/enums/blocked_state.h new file mode 100644 index 00000000000..4a73766c582 --- /dev/null +++ b/src/map/enums/blocked_state.h @@ -0,0 +1,51 @@ +/* +=========================================================================== + + Copyright (c) 2026 LandSandBoat Dev Teams + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see http://www.gnu.org/licenses/ + +=========================================================================== +*/ + +#pragma once + +#include "magic_enum/magic_enum.hpp" + +enum class BlockedState : uint16_t +{ + Jailed = 0x00000001, // PC must not be jailed + Dead = 0x00000002, // PC must not be dead + Crafting = 0x00000004, // PC must not be crafting + Healing = 0x00000008, // PC must not be healing (incl. logging out) + Fishing = 0x00000010, // PC must not be fishing + Sitting = 0x00000020, // PC must not be using /sit or /sitchair + Mounted = 0x00000040, // PC must not be mounted + Charmed = 0x00000080, // PC must not be charmed + PreventAction = 0x00000100, // PC must not be prevented from acting (Charm, Sleep, Stun, Terror, Petrified) + InEvent = 0x00000200, // PC must not be in a cutscene/event + Engaged = 0x00000400, // PC must not be engaged + AbnormalStatus = 0x00000800, // Any status != NORMAL + Monstrosity = 0x00001000, // PC cannot be assuming a Monstrosity form +}; + +template <> +struct magic_enum::customize::enum_range +{ + static constexpr bool is_flags = true; +}; + +#include "magic_enum/magic_enum_containers.hpp" + +using namespace magic_enum::bitwise_operators; diff --git a/src/map/map_engine.cpp b/src/map/map_engine.cpp index be7772b7be2..7bbb000d0bb 100644 --- a/src/map/map_engine.cpp +++ b/src/map/map_engine.cpp @@ -44,8 +44,6 @@ #include "map_statistics.h" #include "mob_spell_list.h" #include "monstrosity.h" -#include "packet_guard.h" -#include "packet_system.h" #include "roe.h" #include "spell.h" #include "status_effect_container.h" @@ -148,8 +146,6 @@ auto MapEngine::init() -> Task luautils::init(mapIPP, config_.inCI); // Also calls moduleutils::LoadLuaModules(); - PacketParserInitialize(); - // Delete sessions that are associated with this map process, but leave others alone db::preparedStmt("DELETE FROM accounts_sessions WHERE IF(? = 0 AND ? = 0, true, server_addr = ? AND server_port = ?)", mapIPP.getIP(), @@ -251,8 +247,6 @@ auto MapEngine::init() -> Task db::preparedStmt("DELETE FROM char_vars WHERE expiry > 0 AND expiry <= ?", currentTimestamp); db::preparedStmt("DELETE FROM server_variables WHERE expiry > 0 AND expiry <= ?", currentTimestamp); - PacketGuard::Init(); - moduleutils::OnInit(); luautils::OnServerStart(); diff --git a/src/map/map_networking.cpp b/src/map/map_networking.cpp index 27ad856e7bf..6136f17a9e7 100644 --- a/src/map/map_networking.cpp +++ b/src/map/map_networking.cpp @@ -37,9 +37,8 @@ #include "job_points.h" #include "latent_effect_container.h" #include "map_engine.h" +#include "map_session.h" #include "map_statistics.h" -#include "packet_guard.h" -#include "packet_system.h" #include "roe.h" #include "status_effect_container.h" #include "transport.h" @@ -423,67 +422,34 @@ int32 MapNetworking::parse(uint8* buff, size_t* buffsize, MapSession* PSession) SmallPD_Size = (ref(SmallPD_ptr, 1) & 0x0FE); SmallPD_Type = (ref(SmallPD_ptr, 0) & 0x1FF); - if (PacketSize[SmallPD_Type] == SmallPD_Size || PacketSize[SmallPD_Type] == 0) // Tests incoming packets for the correct size prior to processing + if ((ref(SmallPD_ptr, 2) <= PSession->client_packet_id) || (ref(SmallPD_ptr, 2) > SmallPD_Code)) { - // Google Translate: - // if the code of the current package is less than or equal to the last received - // or more global then ignore the package - - if ((ref(SmallPD_ptr, 2) <= PSession->client_packet_id) || (ref(SmallPD_ptr, 2) > SmallPD_Code)) - { - continue; - } - - if (SmallPD_Type != 0x15) - { - DebugPackets("parse: %03hX | %04hX %04hX %02hX from user: %s", - SmallPD_Type, - ref(SmallPD_ptr, 2), - ref(buff, 2), - SmallPD_Size, - PChar->getName()); - } - - if (settings::get("map.PACKETGUARD_ENABLED") && PacketGuard::IsRateLimitedPacket(PChar, SmallPD_Type)) - { - ShowWarning("[PacketGuard] Rate-limiting packet: Player: %s - Packet: %03hX", PChar->getName(), SmallPD_Type); - continue; // skip this packet - } - - if (settings::get("map.PACKETGUARD_ENABLED") && !PacketGuard::PacketIsValidForPlayerState(PChar, SmallPD_Type)) - { - ShowWarning("[PacketGuard] Caught mismatch between player substate and recieved packet: Player: %s - Packet: %03hX", - PChar->getName(), - SmallPD_Type); - continue; // skip this packet - } + continue; + } - if (settings::get("map.PACKETGUARD_ENABLED") && !PacketGuard::PacketsArrivingInCorrectOrder(PChar, SmallPD_Type)) - { - ShowWarning("[PacketGuard] Caught out-of-order packet: Player: %s - Packet: %03hX", PChar->getName(), SmallPD_Type); - continue; // skip this packet - } + if (SmallPD_Type != static_cast(PacketC2S::GP_CLI_COMMAND_POS)) + { + DebugPackets("parse: %03hX | %04hX %04hX %02hX from user: %s", + SmallPD_Type, + ref(SmallPD_ptr, 2), + ref(buff, 2), + SmallPD_Size, + PChar->getName()); + } - if (PChar->loc.zone == nullptr && SmallPD_Type != 0x0A) - { - // Packets aren't unexpected from the old key under BLOWFISH_PENDING_ZONE - if (PSession->blowfish.status != BLOWFISH_PENDING_ZONE) - { - ShowWarning("This packet is unexpected from %s - Received %03hX earlier without matching 0x0A", PChar->getName(), SmallPD_Type); - } - } - else + if (PChar->loc.zone == nullptr && SmallPD_Type != static_cast(PacketC2S::GP_CLI_COMMAND_LOGIN)) + { + // Packets aren't unexpected from the old key under BLOWFISH_PENDING_ZONE + if (PSession->blowfish.status != BLOWFISH_PENDING_ZONE) { - // TODO: We should be passing a non-modifyable span of the packet data into the parser - // : instead of creating a new packet here. - auto basicPacket = CBasicPacket::createFromBuffer(reinterpret_cast(SmallPD_ptr)); - ShowTraceFmt("map::parse: Char: {} ({}): {}", PChar->getName(), PChar->id, hex16ToString(basicPacket->getType())); - PacketParser[SmallPD_Type](PSession, PChar, *basicPacket); + ShowWarning("This packet is unexpected from %s - Received %03hX earlier without matching 0x0A", PChar->getName(), SmallPD_Type); } } else { - ShowWarning("Bad packet size %03hX | %04hX %04hX %02hX from user: %s", SmallPD_Type, ref(SmallPD_ptr, 2), ref(buff, 2), SmallPD_Size, PChar->getName()); + auto basicPacket = CBasicPacket::createFromBuffer(SmallPD_ptr); + ShowTraceFmt("map::parse: Char: {} ({}): {}", PChar->getName(), PChar->id, hex16ToString(basicPacket->getType())); + packetSystem_.dispatch(SmallPD_Type, PSession, PChar, *basicPacket); } } @@ -512,7 +478,7 @@ int32 MapNetworking::parse(uint8* buff, size_t* buffsize, MapSession* PSession) { // If the client and server have become out of sync, then caching takes place. However, caching // zone packets will result in the client never properly connecting. Ignore those specifically. - if (SmallPD_Type == 0x0A) + if (SmallPD_Type == static_cast(PacketC2S::GP_CLI_COMMAND_LOGIN)) { return 0; } @@ -554,10 +520,6 @@ int32 MapNetworking::send_parse(uint8* buff, size_t* buffsize, MapSession* PSess mapStatistics_.increment(MapStatistics::Key::TotalPacketsToSendPerTick, static_cast(PChar->getPacketCount())); -#ifdef LOG_OUTGOING_PACKETS - PacketGuard::PrintPacketList(PChar); -#endif - do { do @@ -813,3 +775,8 @@ auto MapNetworking::socket() -> MapSocket& { return *mapSocket_; } + +auto MapNetworking::packetSystem() -> PacketSystem& +{ + return packetSystem_; +} diff --git a/src/map/map_networking.h b/src/map/map_networking.h index 3ab7bcd9357..b83da379662 100644 --- a/src/map/map_networking.h +++ b/src/map/map_networking.h @@ -32,6 +32,7 @@ #include "map_session_container.h" #include "map_socket.h" #include "map_statistics.h" +#include "packet_system.h" class CBasicPacket; @@ -93,6 +94,7 @@ class MapNetworking auto sessions() -> MapSessionContainer&; auto scheduler() -> Scheduler&; auto socket() -> MapSocket&; + auto packetSystem() -> PacketSystem&; private: Scheduler& scheduler_; @@ -108,4 +110,6 @@ class MapNetworking NetworkBuffer PBuff; // Global packet clipboard NetworkBuffer PBuffCopy; // Copy of above, used to decrypt a second time if necessary. NetworkBuffer PScratchBuffer; // Temporary packet clipboard + + PacketSystem packetSystem_; }; diff --git a/src/map/packet_guard.cpp b/src/map/packet_guard.cpp deleted file mode 100644 index cdd6a0c3369..00000000000 --- a/src/map/packet_guard.cpp +++ /dev/null @@ -1,198 +0,0 @@ -/* -=========================================================================== - - Copyright (c) 2025 LandSandBoat Dev Teams - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see http://www.gnu.org/licenses/ - -=========================================================================== -*/ - -#include "packet_guard.h" - -#include "common/timer.h" - -// #define PACKETGUARD_CAP_ENABLED 1 - -#include // Lookup - -#ifdef PACKETGUARD_CAP_ENABLED -#include // Capture -#endif - -namespace PacketGuard -{ - -#ifdef PACKETGUARD_CAP_ENABLED -std::unordered_map> regular_client_packets; -#endif - -std::unordered_map> allowList; - -// Time in seconds (double) -std::unordered_map ratelimitList; - -void Init() -{ - // Allow all non-substate packets - for (uint16 i = 0; i < 512; ++i) - { - allowList[SUBSTATE_NONE][i] = true; - } - - // In Cutscene - allowList[SUBSTATE_IN_CS][0x00A] = true; // Log In To Zone - allowList[SUBSTATE_IN_CS][0x00C] = true; // Event Update (String Update) - allowList[SUBSTATE_IN_CS][0x00D] = true; // Player Leaving Zone(Dezone) - allowList[SUBSTATE_IN_CS][0x00F] = true; // Player Information Request - allowList[SUBSTATE_IN_CS][0x011] = true; // Player Zone Transition Confirmation - allowList[SUBSTATE_IN_CS][0x015] = true; // Player Sync - allowList[SUBSTATE_IN_CS][0x016] = true; // Entity Information Request - allowList[SUBSTATE_IN_CS][0x01A] = true; // Player Action - allowList[SUBSTATE_IN_CS][0x03A] = true; // Sort Inventory - allowList[SUBSTATE_IN_CS][0x04B] = true; // Fish Ranking Packet - allowList[SUBSTATE_IN_CS][0x053] = true; // LockStyleSet - allowList[SUBSTATE_IN_CS][0x058] = true; // Synthesis Suggestion - allowList[SUBSTATE_IN_CS][0x05A] = true; // Map Update (Conquest, Besieged, Campaign) - allowList[SUBSTATE_IN_CS][0x05B] = true; // Event Update (Completion or Update) - allowList[SUBSTATE_IN_CS][0x05C] = true; // Event Update (Update Player Position) - allowList[SUBSTATE_IN_CS][0x060] = true; // Event Update (String Update) - allowList[SUBSTATE_IN_CS][0x061] = true; // Full Char Update - allowList[SUBSTATE_IN_CS][0x0B5] = true; // Chat Message - allowList[SUBSTATE_IN_CS][0x0B6] = true; // Tell Message - allowList[SUBSTATE_IN_CS][0x0DB] = true; // Set Preferred Language - allowList[SUBSTATE_IN_CS][0x0E0] = true; // Set Search Message - allowList[SUBSTATE_IN_CS][0x0F2] = true; // Update Player Zone Boundary - allowList[SUBSTATE_IN_CS][0x112] = true; // Roe Quest Log Request - allowList[SUBSTATE_IN_CS][0x114] = true; // Map Marker Request - allowList[SUBSTATE_IN_CS][0x118] = true; // Not Impl - allowList[SUBSTATE_IN_CS][0x11B] = true; // Not Impl - - // Rate limiting - // NOTE: You should rate limit any packet that a player can - // : send at will that results in an immediate database hit - // : or generates logs or results in file or network io. - ratelimitList[0x017] = 1s; // Invalid NPC Information Response - ratelimitList[0x03B] = 1s; // Mannequin Equip - ratelimitList[0x05D] = 2s; // Emotes - ratelimitList[0x083] = 250ms; // Vendor Shop Purchase - ratelimitList[0x0AA] = 250ms; // Guild Shop Purchase - ratelimitList[0x0B7] = 1s; // Assist Channel - ratelimitList[0x0F4] = 1s; // Wide Scan - ratelimitList[0x0F5] = 1s; // Wide Scan Track - ratelimitList[0x11B] = 2s; // Set Job Master Display - ratelimitList[0x11D] = 2s; // Jump -} - -bool PacketIsValidForPlayerState(CCharEntity* PChar, uint16 SmallPD_Type) -{ - TracyZoneScoped; -#if PACKETGUARD_CAP_ENABLED == 1 - regular_client_packets[PChar->m_Substate].insert(SmallPD_Type); - for (uint8 state = SUBSTATE_IN_CS; state < SUBSTATE_LAST; ++state) - { - fmt::print("Substate {}: ", state); - for (auto& entry : regular_client_packets[(CHAR_SUBSTATE)state]) - { - fmt::print("{:#04x}, ", entry); - } - fmt::print("\n"); - } - return true; -#endif - - return allowList[PChar->m_Substate][SmallPD_Type]; -} - -bool IsRateLimitedPacket(CCharEntity* PChar, uint16 SmallPD_Type) -{ - TracyZoneScoped; - auto timeNow = timer::now(); - auto lastPacketRecieved = PChar->m_PacketRecievedTimestamps.emplace(SmallPD_Type, timeNow); - - if (lastPacketRecieved.second || ratelimitList.count(SmallPD_Type) == 0) - { - return false; - } - auto lastPacketRecievedTime = lastPacketRecieved.first->second; - auto ratelimitTime = ratelimitList[SmallPD_Type]; - - PChar->m_PacketRecievedTimestamps[SmallPD_Type] = timeNow; - - return timeNow < lastPacketRecievedTime + ratelimitTime; -} - -bool PacketsArrivingInCorrectOrder(CCharEntity* PChar, uint16 SmallPD_Type) -{ - TracyZoneScoped; - - const auto currentPacketId = SmallPD_Type; - const auto previousPacketId = PChar->m_LastPacketType; - - // Update the last packet type now that we've cached it - PChar->m_LastPacketType = currentPacketId; - - // 0x084 (vendor appraise) should always lead into 0x085 (vendor sell) - if (currentPacketId == 0x085 && previousPacketId != 0x084) - { - return false; - } - - return true; -} - -void PrintPacketList(CCharEntity* PChar) -{ - // Count packets in queue - std::map packetCounterMap; - for (auto& entry : PChar->getPacketListCopy()) - { - auto packetStr = fmt::format("0x{:4X}", entry->getType()); - packetCounterMap[packetStr]++; - } - - // Sort - using pair_t = std::pair; - std::vector sortedVec; - sortedVec.reserve(packetCounterMap.size()); - for (auto& entry : packetCounterMap) - { - sortedVec.emplace_back(entry); - } - - std::sort( - sortedVec.begin(), - sortedVec.end(), - [](pair_t& a, pair_t& b) - { - return a.second < b.second; - }); - - // Print - std::string output; - output += "\n=======================================\n"; - for (auto& entry : packetCounterMap) - { - output += fmt::format("{} : {}\n", entry.first, entry.second); - } - output += "=======================================\n"; - ShowInfo(output); -} - -auto GetPacketAllowList() -> std::unordered_map>& -{ - return allowList; -} - -} // namespace PacketGuard diff --git a/src/map/packet_system.cpp b/src/map/packet_system.cpp index 4de109de54b..25575be0bcb 100644 --- a/src/map/packet_system.cpp +++ b/src/map/packet_system.cpp @@ -1,7 +1,7 @@ -/* +/* =========================================================================== - Copyright (c) 2010-2015 Darkstar Dev Teams + Copyright (c) 2026 LandSandBoat Dev Teams This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -19,22 +19,13 @@ =========================================================================== */ -#include "common/database.h" -#include "common/logging.h" -#include "common/mmo.h" -#include "common/timer.h" -#include "common/utils.h" - -#include -#include - -#include "ipc_client.h" -#include "map_networking.h" -#include "map_session.h" #include "packet_system.h" -#include "entities/charentity.h" +#include "common/logging.h" +#include "common/tracy.h" +#include "entities/charentity.h" +#include "map_session.h" #include "packets/basic.h" #include "packets/c2s/0x00a_login.h" #include "packets/c2s/0x00c_gameok.h" @@ -44,6 +35,7 @@ #include "packets/c2s/0x015_pos.h" #include "packets/c2s/0x016_charreq.h" #include "packets/c2s/0x017_charreq2.h" +#include "packets/c2s/0x01a_action.h" #include "packets/c2s/0x01b_friendpass.h" #include "packets/c2s/0x01c_unknown.h" #include "packets/c2s/0x01e_gm.h" @@ -167,60 +159,53 @@ #include "packets/c2s/0x11d_jump.h" #include "utils/moduleutils.h" -uint8 PacketSize[512]; - -std::function PacketParser[512]; +namespace +{ -/************************************************************************ - * * - * Display the contents of the incoming packet to the console. * - * * - ************************************************************************/ +using PacketHandler = void (*)(MapSession* const, CCharEntity* const, CBasicPacket&); -void PrintPacket(CBasicPacket& packet) +template +constexpr auto packetSizeRange() -> std::pair { - std::string message; - - for (std::size_t idx = 0U; idx < packet.getSize(); idx++) + if constexpr (requires { T::getMinSize(); }) { - uint8 byte = *packet[idx]; - message.append(fmt::format("{:02x} ", byte)); - - if (((idx + 1U) % 16U) == 0U) - { - message += "\n"; - ShowDebug(message.c_str()); - message.clear(); - } + return { T::getMinSize(), sizeof(T) }; } - - if (!message.empty()) + else { - message += "\n"; - ShowDebug(message.c_str()); + return { sizeof(T), sizeof(T) }; } } -/************************************************************************ - * * - * Unknown Packet * - * * - ************************************************************************/ - -void SmallPacket0x000(MapSession* const PSession, CCharEntity* const PChar, CBasicPacket& data) -{ - ShowWarning("parse: Unhandled game packet %03hX from user: %s", (data.ref(0) & 0x1FF), PChar->getName()); -} - template void ValidatedPacketHandler(MapSession* const PSession, CCharEntity* const PChar, CBasicPacket& data) { TracyZoneScoped; + constexpr auto packetId = static_cast(T::packetId); + constexpr auto sizeRange = packetSizeRange(); + constexpr auto minSize = sizeRange.first; + constexpr auto maxSize = sizeRange.second; + const auto actualSize = data.getSize(); + + if (actualSize < minSize || actualSize > maxSize) + { + ShowWarningFmt("Bad packet size for {} ({:#05x}) from {}: got {}, expected [{}, {}]", + T::name, + packetId, + PChar->getName(), + actualSize, + minSize, + maxSize); + return; + } + const T* packet = data.as(); if (const auto result = packet->validate(PSession, PChar); result.valid()) { + PChar->m_LastPacketType = packetId; + // Modules can optionally block processing of packets by returning true from OnIncomingPacket if (moduleutils::OnIncomingPacket(PSession, PChar, data)) { @@ -231,156 +216,175 @@ void ValidatedPacketHandler(MapSession* const PSession, CCharEntity* const PChar } else { - ShowWarningFmt("Invalid {} packet from {}: {} ", packet->getName(), PChar->name, result.errorString()); + ShowWarningFmt("Invalid {} packet from {}: {} ", T::name, PChar->getName(), result.errorString()); } } -/************************************************************************ - * * - * Packet Array Initialization * - * * - ************************************************************************/ +template +constexpr void registerPacket(std::array& handlers) +{ + handlers[static_cast(T::packetId)] = &ValidatedPacketHandler; +} -void PacketParserInitialize() +consteval auto buildPacketHandlers() -> std::array { - TracyZoneScoped; + std::array handlers{}; + + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + registerPacket(handlers); + + return handlers; +} - for (uint16 i = 0; i < 512; ++i) +constexpr auto packetHandlers_ = buildPacketHandlers(); + +} // namespace + +void PacketSystem::dispatch(uint16 packetId, MapSession* PSession, CCharEntity* PChar, CBasicPacket& data) +{ + if (const auto handler = packetHandlers_[packetId]) { - PacketSize[i] = 0; - PacketParser[i] = &SmallPacket0x000; - } + if (rateLimiter_.isLimited(PChar, packetId)) + { + ShowWarningFmt("Rate-limiting packet {} ({:#05x}) from {}", + magic_enum::enum_name(static_cast(packetId)), + packetId, + PChar->getName()); + return; + } - // clang-format off - PacketSize[0x00A] = 0x2E; PacketParser[0x00A] = &ValidatedPacketHandler; - PacketSize[0x00C] = 0x00; PacketParser[0x00C] = &ValidatedPacketHandler; - PacketSize[0x00D] = 0x04; PacketParser[0x00D] = &ValidatedPacketHandler; - PacketSize[0x00F] = 0x00; PacketParser[0x00F] = &ValidatedPacketHandler; - PacketSize[0x011] = 0x00; PacketParser[0x011] = &ValidatedPacketHandler; - PacketSize[0x015] = 0x10; PacketParser[0x015] = &ValidatedPacketHandler; - PacketSize[0x016] = 0x04; PacketParser[0x016] = &ValidatedPacketHandler; - PacketSize[0x017] = 0x00; PacketParser[0x017] = &ValidatedPacketHandler; - PacketSize[0x01A] = 0x0E; PacketParser[0x01A] = &ValidatedPacketHandler; - PacketSize[0x01B] = 0x00; PacketParser[0x01B] = &ValidatedPacketHandler; - PacketSize[0x01C] = 0x00; PacketParser[0x01C] = &ValidatedPacketHandler; - PacketSize[0x01E] = 0x00; PacketParser[0x01E] = &ValidatedPacketHandler; - PacketSize[0x01F] = 0x00; PacketParser[0x01F] = &ValidatedPacketHandler; - PacketSize[0x028] = 0x06; PacketParser[0x028] = &ValidatedPacketHandler; - PacketSize[0x029] = 0x06; PacketParser[0x029] = &ValidatedPacketHandler; - PacketSize[0x02B] = 0x00; PacketParser[0x02B] = &ValidatedPacketHandler; - PacketSize[0x02C] = 0x00; PacketParser[0x02C] = &ValidatedPacketHandler; - PacketSize[0x032] = 0x06; PacketParser[0x032] = &ValidatedPacketHandler; - PacketSize[0x033] = 0x06; PacketParser[0x033] = &ValidatedPacketHandler; - PacketSize[0x034] = 0x06; PacketParser[0x034] = &ValidatedPacketHandler; - PacketSize[0x036] = 0x20; PacketParser[0x036] = &ValidatedPacketHandler; - PacketSize[0x037] = 0x0A; PacketParser[0x037] = &ValidatedPacketHandler; - PacketSize[0x03A] = 0x04; PacketParser[0x03A] = &ValidatedPacketHandler; - PacketSize[0x03B] = 0x10; PacketParser[0x03B] = &ValidatedPacketHandler; - PacketSize[0x03C] = 0x00; PacketParser[0x03C] = &ValidatedPacketHandler; - PacketSize[0x03D] = 0x00; PacketParser[0x03D] = &ValidatedPacketHandler; - PacketSize[0x041] = 0x00; PacketParser[0x041] = &ValidatedPacketHandler; - PacketSize[0x042] = 0x00; PacketParser[0x042] = &ValidatedPacketHandler; - PacketSize[0x04B] = 0x00; PacketParser[0x04B] = &ValidatedPacketHandler; - PacketSize[0x04D] = 0x00; PacketParser[0x04D] = &ValidatedPacketHandler; - PacketSize[0x04E] = 0x1E; PacketParser[0x04E] = &ValidatedPacketHandler; - PacketSize[0x050] = 0x04; PacketParser[0x050] = &ValidatedPacketHandler; - PacketSize[0x051] = 0x24; PacketParser[0x051] = &ValidatedPacketHandler; - PacketSize[0x052] = 0x26; PacketParser[0x052] = &ValidatedPacketHandler; - PacketSize[0x053] = 0x44; PacketParser[0x053] = &ValidatedPacketHandler; - PacketSize[0x058] = 0x0A; PacketParser[0x058] = &ValidatedPacketHandler; - PacketSize[0x059] = 0x00; PacketParser[0x059] = &ValidatedPacketHandler; - PacketSize[0x05A] = 0x02; PacketParser[0x05A] = &ValidatedPacketHandler; - PacketSize[0x05B] = 0x0A; PacketParser[0x05B] = &ValidatedPacketHandler; - PacketSize[0x05C] = 0x00; PacketParser[0x05C] = &ValidatedPacketHandler; - PacketSize[0x05D] = 0x08; PacketParser[0x05D] = &ValidatedPacketHandler; - PacketSize[0x05E] = 0x0C; PacketParser[0x05E] = &ValidatedPacketHandler; - PacketSize[0x060] = 0x00; PacketParser[0x060] = &ValidatedPacketHandler; - PacketSize[0x061] = 0x04; PacketParser[0x061] = &ValidatedPacketHandler; - PacketSize[0x063] = 0x00; PacketParser[0x063] = &ValidatedPacketHandler; - PacketSize[0x064] = 0x26; PacketParser[0x064] = &ValidatedPacketHandler; - PacketSize[0x066] = 0x0A; PacketParser[0x066] = &ValidatedPacketHandler; - PacketSize[0x06E] = 0x06; PacketParser[0x06E] = &ValidatedPacketHandler; - PacketSize[0x06F] = 0x00; PacketParser[0x06F] = &ValidatedPacketHandler; - PacketSize[0x070] = 0x00; PacketParser[0x070] = &ValidatedPacketHandler; - PacketSize[0x071] = 0x00; PacketParser[0x071] = &ValidatedPacketHandler; - PacketSize[0x074] = 0x00; PacketParser[0x074] = &ValidatedPacketHandler; - PacketSize[0x076] = 0x00; PacketParser[0x076] = &ValidatedPacketHandler; - PacketSize[0x077] = 0x00; PacketParser[0x077] = &ValidatedPacketHandler; - PacketSize[0x078] = 0x00; PacketParser[0x078] = &ValidatedPacketHandler; - PacketSize[0x083] = 0x08; PacketParser[0x083] = &ValidatedPacketHandler; - PacketSize[0x084] = 0x06; PacketParser[0x084] = &ValidatedPacketHandler; - PacketSize[0x085] = 0x04; PacketParser[0x085] = &ValidatedPacketHandler; - PacketSize[0x096] = 0x12; PacketParser[0x096] = &ValidatedPacketHandler; - PacketSize[0x09B] = 0x00; PacketParser[0x09B] = &ValidatedPacketHandler; - PacketSize[0x0A0] = 0x00; PacketParser[0x0A0] = &ValidatedPacketHandler; - PacketSize[0x0A1] = 0x00; PacketParser[0x0A1] = &ValidatedPacketHandler; - PacketSize[0x0A2] = 0x00; PacketParser[0x0A2] = &ValidatedPacketHandler; - PacketSize[0x0AA] = 0x00; PacketParser[0x0AA] = &ValidatedPacketHandler; - PacketSize[0x0AB] = 0x00; PacketParser[0x0AB] = &ValidatedPacketHandler; - PacketSize[0x0AC] = 0x00; PacketParser[0x0AC] = &ValidatedPacketHandler; - PacketSize[0x0AD] = 0x00; PacketParser[0x0AD] = &ValidatedPacketHandler; - PacketSize[0x0B5] = 0x00; PacketParser[0x0B5] = &ValidatedPacketHandler; - PacketSize[0x0B6] = 0x00; PacketParser[0x0B6] = &ValidatedPacketHandler; - PacketSize[0x0B7] = 0x00; PacketParser[0x0B7] = &ValidatedPacketHandler; - PacketSize[0x0BE] = 0x00; PacketParser[0x0BE] = &ValidatedPacketHandler; - PacketSize[0x0BF] = 0x04; PacketParser[0x0BF] = &ValidatedPacketHandler; - PacketSize[0x0C0] = 0x00; PacketParser[0x0C0] = &ValidatedPacketHandler; - PacketSize[0x0C1] = 0x04; PacketParser[0x0C1] = &ValidatedPacketHandler; - PacketSize[0x0C3] = 0x00; PacketParser[0x0C3] = &ValidatedPacketHandler; - PacketSize[0x0C4] = 0x0E; PacketParser[0x0C4] = &ValidatedPacketHandler; - PacketSize[0x0CB] = 0x04; PacketParser[0x0CB] = &ValidatedPacketHandler; - PacketSize[0x0D2] = 0x04; PacketParser[0x0D2] = &ValidatedPacketHandler; - PacketSize[0x0D3] = 0x00; PacketParser[0x0D3] = &ValidatedPacketHandler; - PacketSize[0x0D4] = 0x04; PacketParser[0x0D4] = &ValidatedPacketHandler; - PacketSize[0x0D5] = 0x06; PacketParser[0x0D5] = &ValidatedPacketHandler; - PacketSize[0x0D8] = 0x00; PacketParser[0x0D8] = &ValidatedPacketHandler; - PacketSize[0x0DB] = 0x00; PacketParser[0x0DB] = &ValidatedPacketHandler; - PacketSize[0x0DC] = 0x0A; PacketParser[0x0DC] = &ValidatedPacketHandler; - PacketSize[0x0DD] = 0x08; PacketParser[0x0DD] = &ValidatedPacketHandler; - PacketSize[0x0DE] = 0x40; PacketParser[0x0DE] = &ValidatedPacketHandler; - PacketSize[0x0E0] = 0x00; PacketParser[0x0E0] = &ValidatedPacketHandler; - PacketSize[0x0E1] = 0x00; PacketParser[0x0E1] = &ValidatedPacketHandler; - PacketSize[0x0E2] = 0x00; PacketParser[0x0E2] = &ValidatedPacketHandler; - PacketSize[0x0E4] = 0x00; PacketParser[0x0E4] = &ValidatedPacketHandler; - PacketSize[0x0E7] = 0x04; PacketParser[0x0E7] = &ValidatedPacketHandler; - PacketSize[0x0E8] = 0x04; PacketParser[0x0E8] = &ValidatedPacketHandler; - PacketSize[0x0EA] = 0x04; PacketParser[0x0EA] = &ValidatedPacketHandler; - PacketSize[0x0EB] = 0x00; PacketParser[0x0EB] = &ValidatedPacketHandler; - PacketSize[0x0F0] = 0x04; PacketParser[0x0F0] = &ValidatedPacketHandler; - PacketSize[0x0F1] = 0x04; PacketParser[0x0F1] = &ValidatedPacketHandler; - PacketSize[0x0F2] = 0x04; PacketParser[0x0F2] = &ValidatedPacketHandler; - PacketSize[0x0F4] = 0x04; PacketParser[0x0F4] = &ValidatedPacketHandler; - PacketSize[0x0F5] = 0x00; PacketParser[0x0F5] = &ValidatedPacketHandler; - PacketSize[0x0F6] = 0x00; PacketParser[0x0F6] = &ValidatedPacketHandler; - PacketSize[0x0FA] = 0x00; PacketParser[0x0FA] = &ValidatedPacketHandler; - PacketSize[0x0FB] = 0x00; PacketParser[0x0FB] = &ValidatedPacketHandler; - PacketSize[0x0FC] = 0x00; PacketParser[0x0FC] = &ValidatedPacketHandler; - PacketSize[0x0FD] = 0x00; PacketParser[0x0FD] = &ValidatedPacketHandler; - PacketSize[0x0FE] = 0x00; PacketParser[0x0FE] = &ValidatedPacketHandler; - PacketSize[0x0FF] = 0x00; PacketParser[0x0FF] = &ValidatedPacketHandler; - PacketSize[0x100] = 0x04; PacketParser[0x100] = &ValidatedPacketHandler; - PacketSize[0x102] = 0x52; PacketParser[0x102] = &ValidatedPacketHandler; - PacketSize[0x104] = 0x02; PacketParser[0x104] = &ValidatedPacketHandler; - PacketSize[0x105] = 0x06; PacketParser[0x105] = &ValidatedPacketHandler; - PacketSize[0x106] = 0x06; PacketParser[0x106] = &ValidatedPacketHandler; - PacketSize[0x109] = 0x00; PacketParser[0x109] = &ValidatedPacketHandler; - PacketSize[0x10A] = 0x06; PacketParser[0x10A] = &ValidatedPacketHandler; - PacketSize[0x10B] = 0x00; PacketParser[0x10B] = &ValidatedPacketHandler; - PacketSize[0x10C] = 0x04; PacketParser[0x10C] = &ValidatedPacketHandler; - PacketSize[0x10D] = 0x04; PacketParser[0x10D] = &ValidatedPacketHandler; - PacketSize[0x10E] = 0x04; PacketParser[0x10E] = &ValidatedPacketHandler; - PacketSize[0x10F] = 0x02; PacketParser[0x10F] = &ValidatedPacketHandler; - PacketSize[0x110] = 0x0A; PacketParser[0x110] = &ValidatedPacketHandler; - PacketSize[0x112] = 0x00; PacketParser[0x112] = &ValidatedPacketHandler; - PacketSize[0x113] = 0x06; PacketParser[0x113] = &ValidatedPacketHandler; - PacketSize[0x114] = 0x00; PacketParser[0x114] = &ValidatedPacketHandler; - PacketSize[0x115] = 0x02; PacketParser[0x115] = &ValidatedPacketHandler; - PacketSize[0x116] = 0x00; PacketParser[0x116] = &ValidatedPacketHandler; - PacketSize[0x117] = 0x00; PacketParser[0x117] = &ValidatedPacketHandler; - PacketSize[0x118] = 0x00; PacketParser[0x118] = &ValidatedPacketHandler; - PacketSize[0x119] = 0x00; PacketParser[0x119] = &ValidatedPacketHandler; - PacketSize[0x11B] = 0x00; PacketParser[0x11B] = &ValidatedPacketHandler; - PacketSize[0x11C] = 0x08; PacketParser[0x11C] = &ValidatedPacketHandler; - PacketSize[0x11D] = 0x00; PacketParser[0x11D] = &ValidatedPacketHandler; - // clang-format on + handler(PSession, PChar, data); + } + else + { + ShowWarningFmt("parse: Unhandled game packet {:#05x} from user: {}", packetId, PChar->getName()); + } } diff --git a/src/map/packet_system.h b/src/map/packet_system.h index 501c77f133f..a9a130b8913 100644 --- a/src/map/packet_system.h +++ b/src/map/packet_system.h @@ -1,7 +1,7 @@ -/* +/* =========================================================================== - Copyright (c) 2010-2015 Darkstar Dev Teams + Copyright (c) 2026 LandSandBoat Dev Teams This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -19,21 +19,21 @@ =========================================================================== */ -#ifndef _PACKETSYSTEM_H -#define _PACKETSYSTEM_H +#pragma once #include "common/cbasetypes.h" #include "packets/basic.h" +#include "packets/c2s/rate_limiter.h" #include "entities/charentity.h" struct MapSession; -extern uint8 PacketSize[512]; +class PacketSystem +{ +public: + void dispatch(uint16 packetId, MapSession* PSession, CCharEntity* PChar, CBasicPacket& data); -extern std::function PacketParser[512]; - -void PrintPacket(CBasicPacket& data); -void PacketParserInitialize(); - -#endif +private: + PacketRateLimiter rateLimiter_; +}; diff --git a/src/map/packets/c2s/0x00a_login.cpp b/src/map/packets/c2s/0x00a_login.cpp index 1ff96f56258..efff5808d80 100644 --- a/src/map/packets/c2s/0x00a_login.cpp +++ b/src/map/packets/c2s/0x00a_login.cpp @@ -36,8 +36,8 @@ auto GP_CLI_COMMAND_LOGIN::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() - .mustEqual(PChar->id, UniqueNo, "Player ID mismatch") + return PacketValidator(PChar) + .mustEqual(PChar->id, this->UniqueNo, "Player ID mismatch") .mustNotEqual(PSession->blowfish.status == BLOWFISH_ACCEPTED && PChar->status == STATUS_TYPE::NORMAL, true, "Player already logged in."); } diff --git a/src/map/packets/c2s/0x00c_gameok.cpp b/src/map/packets/c2s/0x00c_gameok.cpp index adaf1afeead..e8c7989e5b4 100644 --- a/src/map/packets/c2s/0x00c_gameok.cpp +++ b/src/map/packets/c2s/0x00c_gameok.cpp @@ -46,7 +46,7 @@ auto GP_CLI_COMMAND_GAMEOK::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() + return PacketValidator(PChar) .mustEqual(ClientState, 0, "ClientState not 0") .mustEqual(DebugClientFlg, 0, "DebugClientFlg not 0"); } diff --git a/src/map/packets/c2s/0x00d_netend.cpp b/src/map/packets/c2s/0x00d_netend.cpp index d266a238bf7..d79867bda70 100644 --- a/src/map/packets/c2s/0x00d_netend.cpp +++ b/src/map/packets/c2s/0x00d_netend.cpp @@ -24,7 +24,7 @@ auto GP_CLI_COMMAND_NETEND::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { // Packet explicitly ignored. - return PacketValidator(); + return PacketValidator(PChar); } void GP_CLI_COMMAND_NETEND::process(MapSession* PSession, CCharEntity* PChar) const diff --git a/src/map/packets/c2s/0x00f_clstat.cpp b/src/map/packets/c2s/0x00f_clstat.cpp index 2ce3dc4ca31..a685b9766e8 100644 --- a/src/map/packets/c2s/0x00f_clstat.cpp +++ b/src/map/packets/c2s/0x00f_clstat.cpp @@ -27,7 +27,7 @@ auto GP_CLI_COMMAND_CLSTAT::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { // No parameter to validate for this packet. - return PacketValidator(); + return PacketValidator(PChar); } void GP_CLI_COMMAND_CLSTAT::process(MapSession* PSession, CCharEntity* PChar) const diff --git a/src/map/packets/c2s/0x011_zone_transition.cpp b/src/map/packets/c2s/0x011_zone_transition.cpp index f5583efe8b4..b0e1a162f74 100644 --- a/src/map/packets/c2s/0x011_zone_transition.cpp +++ b/src/map/packets/c2s/0x011_zone_transition.cpp @@ -29,7 +29,7 @@ auto GP_CLI_COMMAND_ZONE_TRANSITION::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() + return PacketValidator(PChar) .mustEqual(unknown00, 2, "unknown00 not 2") .mustEqual(unknown01, 0, "unknown01 not 0"); } diff --git a/src/map/packets/c2s/0x011_zone_transition.h b/src/map/packets/c2s/0x011_zone_transition.h index 2312fd580a0..8ee2f163797 100644 --- a/src/map/packets/c2s/0x011_zone_transition.h +++ b/src/map/packets/c2s/0x011_zone_transition.h @@ -26,6 +26,7 @@ // https://github.com/atom0s/XiPackets/tree/main/world/client/0x0011 // This packet is sent by the client when it has successfully entered the requested zone, confirming it has entered the new area. GP_CLI_PACKET(GP_CLI_COMMAND_ZONE_TRANSITION, - uint8_t unknown00; // PS2: (New; did not exist.) - uint8_t unknown01; // PS2: (New; did not exist.) + uint8_t unknown00; // PS2: (New; did not exist.) + uint8_t unknown01; // PS2: (New; did not exist.) + uint16_t padding00; // PS2: (New; did not exist.) ); diff --git a/src/map/packets/c2s/0x015_pos.cpp b/src/map/packets/c2s/0x015_pos.cpp index 34ac3e9e940..ed4783a04e3 100644 --- a/src/map/packets/c2s/0x015_pos.cpp +++ b/src/map/packets/c2s/0x015_pos.cpp @@ -26,7 +26,7 @@ auto GP_CLI_COMMAND_POS::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() + return PacketValidator(PChar) .mustNotEqual(PChar->status, STATUS_TYPE::DISAPPEAR, "Character is disappearing") .mustNotEqual(PChar->status, STATUS_TYPE::SHUTDOWN, "Character is shutting down"); } @@ -38,11 +38,11 @@ void GP_CLI_COMMAND_POS::process(MapSession* PSession, CCharEntity* PChar) const return; } - const float newX = x; - const float newY = z; // Not a typo. - const float newZ = y; // Not a typo. - const uint16 newTargID = facetarget; - const uint8 newRotation = dir; + const float newX = this->x; + const float newY = this->z; // Not a typo. + const float newZ = this->y; // Not a typo. + const uint16 newTargID = this->facetarget; + const uint8 newRotation = this->dir; // clang-format off const bool moved = @@ -62,7 +62,7 @@ void GP_CLI_COMMAND_POS::process(MapSession* PSession, CCharEntity* PChar) const PChar->loc.p.y = newY; PChar->loc.p.z = newZ; - PChar->loc.p.moving = MoveFlame; + PChar->loc.p.moving = this->MoveFlame; PChar->loc.p.rotation = newRotation; PChar->m_TargID = newTargID; diff --git a/src/map/packets/c2s/0x015_pos.h b/src/map/packets/c2s/0x015_pos.h index 710a6d2a807..1fffba52ed5 100644 --- a/src/map/packets/c2s/0x015_pos.h +++ b/src/map/packets/c2s/0x015_pos.h @@ -38,4 +38,5 @@ GP_CLI_PACKET(GP_CLI_COMMAND_POS, uint8_t unused : 5; // PS2: dummy uint16_t facetarget; // PS2: facetarget uint32_t TimeNow; // PS2: TimeNow + uint32_t padding00; // PS2: (padding) ); diff --git a/src/map/packets/c2s/0x016_charreq.cpp b/src/map/packets/c2s/0x016_charreq.cpp index cc7bc0896a0..92e400bf6bf 100644 --- a/src/map/packets/c2s/0x016_charreq.cpp +++ b/src/map/packets/c2s/0x016_charreq.cpp @@ -28,25 +28,25 @@ auto GP_CLI_COMMAND_CHARREQ::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator(); + return PacketValidator(PChar); } void GP_CLI_COMMAND_CHARREQ::process(MapSession* PSession, CCharEntity* PChar) const { // Requesting self-update - if (ActIndex == PChar->targid) + if (this->ActIndex == PChar->targid) { PChar->updateEntityPacket(PChar, ENTITY_SPAWN, UPDATE_ALL_CHAR); PChar->pushPacket(PChar); return; } - CBaseEntity* PEntity = PChar->GetEntity(ActIndex, TYPE_NPC | TYPE_PC); + CBaseEntity* PEntity = PChar->GetEntity(this->ActIndex, TYPE_NPC | TYPE_PC); if (!PEntity) { - const auto fullId = ((4096 + PChar->getZone()) << 12) + ActIndex; + const auto fullId = ((4096 + PChar->getZone()) << 12) + this->ActIndex; ShowWarningFmt("Could not look up entity <{}, {}> in zone <{} ({})>", - ActIndex, + this->ActIndex, fullId, zoneutils::GetZone(PChar->getZone())->getName(), PChar->getZone()); @@ -60,7 +60,7 @@ void GP_CLI_COMMAND_CHARREQ::process(MapSession* PSession, CCharEntity* PChar) c { if (PCharEntity->m_isGMHidden) { - ShowErrorFmt("Player {} requested information about a hidden GM ({}) using targid {}", PChar->getName(), PCharEntity->getName(), ActIndex); + ShowErrorFmt("Player {} requested information about a hidden GM ({}) using targid {}", PChar->getName(), PCharEntity->getName(), this->ActIndex); return; } diff --git a/src/map/packets/c2s/0x017_charreq2.cpp b/src/map/packets/c2s/0x017_charreq2.cpp index 8a1a9a5abcc..1fd070d3695 100644 --- a/src/map/packets/c2s/0x017_charreq2.cpp +++ b/src/map/packets/c2s/0x017_charreq2.cpp @@ -26,10 +26,11 @@ auto GP_CLI_COMMAND_CHARREQ2::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { // Not implemented. - return PacketValidator(); + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }); } void GP_CLI_COMMAND_CHARREQ2::process(MapSession* PSession, CCharEntity* PChar) const { - ShowWarning("GP_CLI_COMMAND_CHARREQ2: Incorrect NPC(%u,%u) type(%u)", ActIndex, UniqueNo2, Flg); + ShowWarning("GP_CLI_COMMAND_CHARREQ2: Incorrect NPC(%u,%u) type(%u)", this->ActIndex, this->UniqueNo2, this->Flg); } diff --git a/src/map/packets/c2s/0x01a_action.cpp b/src/map/packets/c2s/0x01a_action.cpp index 4acf833069c..cf0887140f9 100644 --- a/src/map/packets/c2s/0x01a_action.cpp +++ b/src/map/packets/c2s/0x01a_action.cpp @@ -53,115 +53,101 @@ const auto actionToStr = [](const GP_CLI_COMMAND_ACTION_ACTIONID actionIn) auto GP_CLI_COMMAND_ACTION::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() + return PacketValidator(PChar) .oneOf(this->ActionID) - .custom([&](PacketValidator& pv) + .custom( + [&](PacketValidator& pv) + { + switch (this->ActionID) { - switch (this->ActionID) + // Assist, /blockaid and /help are almost never blocked. + case GP_CLI_COMMAND_ACTION_ACTIONID::Assist: + case GP_CLI_COMMAND_ACTION_ACTIONID::Blockaid: + case GP_CLI_COMMAND_ACTION_ACTIONID::Help: + { + break; + } + case GP_CLI_COMMAND_ACTION_ACTIONID::Talk: + { + // Talking to NPC has several blocked states checked a little later as they send a release packet. + break; + } + case GP_CLI_COMMAND_ACTION_ACTIONID::AttackOff: + { + // You can disengage while slept. + pv.blockedBy({ BlockedState::Charmed }) + .isEngaged(); + break; + } + case GP_CLI_COMMAND_ACTION_ACTIONID::ChangeTarget: + { + pv.blockedBy({ BlockedState::PreventAction }) + .isEngaged(); + break; + } + case GP_CLI_COMMAND_ACTION_ACTIONID::HomepointMenu: + case GP_CLI_COMMAND_ACTION_ACTIONID::RaiseMenu: + case GP_CLI_COMMAND_ACTION_ACTIONID::TractorMenu: + { + pv.mustEqual(PChar->isDead(), true, "Character is not dead."); + break; + } + case GP_CLI_COMMAND_ACTION_ACTIONID::Attack: + { + // Note: It is possible to attack while fishing on retail and is disabled here on purpose. + pv.blockedBy({ BlockedState::Healing, BlockedState::Sitting, BlockedState::Crafting, BlockedState::Fishing, BlockedState::PreventAction }); + break; + } + case GP_CLI_COMMAND_ACTION_ACTIONID::CastMagic: + case GP_CLI_COMMAND_ACTION_ACTIONID::JobAbility: + case GP_CLI_COMMAND_ACTION_ACTIONID::Shoot: + case GP_CLI_COMMAND_ACTION_ACTIONID::Weaponskill: + case GP_CLI_COMMAND_ACTION_ACTIONID::MonsterSkill: // MonsterSkill is entirely assumed { - // Assist, /blockaid and /help are almost never blocked. - case GP_CLI_COMMAND_ACTION_ACTIONID::Assist: - case GP_CLI_COMMAND_ACTION_ACTIONID::Blockaid: - case GP_CLI_COMMAND_ACTION_ACTIONID::Help: - { - break; - } - case GP_CLI_COMMAND_ACTION_ACTIONID::Talk: - { - // Talking to NPC has several blocked states checked a little later as they send a release packet. - break; - } - case GP_CLI_COMMAND_ACTION_ACTIONID::AttackOff: - { - // You can disengage while slept. - pv.isEngaged(PChar) - .isNotCharmed(PChar); - break; - } - case GP_CLI_COMMAND_ACTION_ACTIONID::ChangeTarget: - { - pv.isEngaged(PChar) - .isNotPreventedAction(PChar); - break; - } - case GP_CLI_COMMAND_ACTION_ACTIONID::HomepointMenu: - case GP_CLI_COMMAND_ACTION_ACTIONID::RaiseMenu: - case GP_CLI_COMMAND_ACTION_ACTIONID::TractorMenu: - { - pv.mustEqual(PChar->isDead(), true, "Character is not dead."); - break; - } - case GP_CLI_COMMAND_ACTION_ACTIONID::Attack: - { - pv.isNotResting(PChar) - .isNotSitting(PChar) - .isNotCrafting(PChar) - .isNotFishing(PChar) // Note: It is possible to attack while fishing on retail and is disabled here on purpose. - .isNotPreventedAction(PChar); - break; - } - case GP_CLI_COMMAND_ACTION_ACTIONID::CastMagic: - case GP_CLI_COMMAND_ACTION_ACTIONID::JobAbility: - case GP_CLI_COMMAND_ACTION_ACTIONID::Shoot: - case GP_CLI_COMMAND_ACTION_ACTIONID::Weaponskill: - case GP_CLI_COMMAND_ACTION_ACTIONID::MonsterSkill: // MonsterSkill is entirely assumed - { - pv.isNotResting(PChar) - .isNotCrafting(PChar) - .isNotFishing(PChar) - .isNotPreventedAction(PChar) - .isNotMounted(PChar) - .mustEqual(PChar->animation == ANIMATION_NONE || PChar->animation == ANIMATION_ATTACK, true, "Character in invalid animation state."); - break; - } - case GP_CLI_COMMAND_ACTION_ACTIONID::Fish: - { - pv.isNotResting(PChar) - .isNotSitting(PChar) - .isNotCrafting(PChar) - .isNotFishing(PChar) - .isNotPreventedAction(PChar) - .isNotMounted(PChar); - break; - } - case GP_CLI_COMMAND_ACTION_ACTIONID::Mount: - { - pv.isNotResting(PChar) - .isNotSitting(PChar) - .isNotCrafting(PChar) - .isNotFishing(PChar); - break; - } - case GP_CLI_COMMAND_ACTION_ACTIONID::Dismount: - { - pv.isNotPreventedAction(PChar) - .mustEqual(PChar->isMounted(), true, "Character is not mounted."); - break; - } - case GP_CLI_COMMAND_ACTION_ACTIONID::ChocoboDig: - { - pv.isNotPreventedAction(PChar) - .mustEqual(PChar->isMounted(), true, "Character is not mounted."); - break; - } - case GP_CLI_COMMAND_ACTION_ACTIONID::SendResRdy: - { - break; - } - // Unimplemented Ballista actions - case GP_CLI_COMMAND_ACTION_ACTIONID::Quarry: - case GP_CLI_COMMAND_ACTION_ACTIONID::Sprint: - case GP_CLI_COMMAND_ACTION_ACTIONID::Scout: - { - break; - } + pv.blockedBy({ BlockedState::Healing, BlockedState::Crafting, BlockedState::Fishing, BlockedState::PreventAction, BlockedState::Mounted }) + .mustEqual(PChar->animation == ANIMATION_NONE || PChar->animation == ANIMATION_ATTACK, true, "Character in invalid animation state."); + break; } - }); + case GP_CLI_COMMAND_ACTION_ACTIONID::Fish: + { + pv.blockedBy({ BlockedState::Healing, BlockedState::Sitting, BlockedState::Crafting, BlockedState::Fishing, BlockedState::PreventAction, BlockedState::Mounted }); + break; + } + case GP_CLI_COMMAND_ACTION_ACTIONID::Mount: + { + pv.blockedBy({ BlockedState::Healing, BlockedState::Sitting, BlockedState::Crafting, BlockedState::Fishing }); + break; + } + case GP_CLI_COMMAND_ACTION_ACTIONID::Dismount: + { + pv.blockedBy({ BlockedState::PreventAction }) + .mustEqual(PChar->isMounted(), true, "Character is not mounted."); + break; + } + case GP_CLI_COMMAND_ACTION_ACTIONID::ChocoboDig: + { + pv.blockedBy({ BlockedState::PreventAction }) + .mustEqual(PChar->isMounted(), true, "Character is not mounted."); + break; + } + case GP_CLI_COMMAND_ACTION_ACTIONID::SendResRdy: + { + break; + } + // Unimplemented Ballista actions + case GP_CLI_COMMAND_ACTION_ACTIONID::Quarry: + case GP_CLI_COMMAND_ACTION_ACTIONID::Sprint: + case GP_CLI_COMMAND_ACTION_ACTIONID::Scout: + { + break; + } + } + }); } void GP_CLI_COMMAND_ACTION::process(MapSession* PSession, CCharEntity* PChar) const { - const auto actionStr = fmt::format("Player Action: {}: {} -> ActIndex: {}", PChar->getName(), actionToStr(static_cast(ActionID)), ActIndex); + const auto actionStr = fmt::format("Player Action: {}: {} -> ActIndex: {}", PChar->getName(), actionToStr(static_cast(this->ActionID)), this->ActIndex); ShowTrace(actionStr); DebugActions(actionStr); diff --git a/src/map/packets/c2s/0x01b_friendpass.cpp b/src/map/packets/c2s/0x01b_friendpass.cpp index 91b91638464..1cfb7c3f41e 100644 --- a/src/map/packets/c2s/0x01b_friendpass.cpp +++ b/src/map/packets/c2s/0x01b_friendpass.cpp @@ -27,13 +27,14 @@ auto GP_CLI_COMMAND_FRIENDPASS::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { // Not implemented. - return PacketValidator() - .oneOf(Para); + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }) + .oneOf(this->Para); } void GP_CLI_COMMAND_FRIENDPASS::process(MapSession* PSession, CCharEntity* PChar) const { - switch (static_cast(Para)) + switch (static_cast(this->Para)) { case GP_CLI_COMMAND_FRIENDPASS_PARA::BeginPurchase: break; @@ -45,5 +46,5 @@ void GP_CLI_COMMAND_FRIENDPASS::process(MapSession* PSession, CCharEntity* PChar break; } - PChar->pushPacket(Para & 1 ? static_cast(xirand::GetRandomNumber(9999999999)) : 0); + PChar->pushPacket(this->Para & 1 ? static_cast(xirand::GetRandomNumber(9999999999)) : 0); } diff --git a/src/map/packets/c2s/0x01c_unknown.cpp b/src/map/packets/c2s/0x01c_unknown.cpp index 2c9cc63abfa..9a6f4d746d1 100644 --- a/src/map/packets/c2s/0x01c_unknown.cpp +++ b/src/map/packets/c2s/0x01c_unknown.cpp @@ -26,11 +26,12 @@ auto GP_CLI_COMMAND_UNKNOWN::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { // Not implemented. - return PacketValidator(); + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }); } void GP_CLI_COMMAND_UNKNOWN::process(MapSession* PSession, CCharEntity* PChar) const { // Purpose of this packet is currently unknown - ShowDebug("GP_CLI_COMMAND_UNKNOWN: unknown00=%u padding00=%u unknown01=%u", unknown00, padding00, unknown01); + ShowDebug("GP_CLI_COMMAND_UNKNOWN: unknown00=%u padding00=%u unknown01=%u", this->unknown00, this->padding00, this->unknown01); } diff --git a/src/map/packets/c2s/0x01e_gm.cpp b/src/map/packets/c2s/0x01e_gm.cpp index 4ecbf30e72e..2da0fa252a6 100644 --- a/src/map/packets/c2s/0x01e_gm.cpp +++ b/src/map/packets/c2s/0x01e_gm.cpp @@ -27,7 +27,8 @@ auto GP_CLI_COMMAND_GM::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { // No parameter to validate for this packet. - return PacketValidator(); + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }); } void GP_CLI_COMMAND_GM::process(MapSession* PSession, CCharEntity* PChar) const @@ -37,8 +38,8 @@ void GP_CLI_COMMAND_GM::process(MapSession* PSession, CCharEntity* PChar) const // Extremely important to figure out the message length here. // Depending on alignment, the message may not be NULL-terminated. // Start with reported size and skip the first 4 bytes (header). - const auto messageLength = std::min((header.size * 4) - 0x4, sizeof(Command)); - const auto rawCommand = asStringFromUntrustedSource(Command, messageLength); + const auto messageLength = std::min((header.size * 4) - 0x4, sizeof(this->Command)); + const auto rawCommand = asStringFromUntrustedSource(this->Command, messageLength); luautils::OnPlayerVolunteer(PChar, rawCommand); } diff --git a/src/map/packets/c2s/0x01e_gm.h b/src/map/packets/c2s/0x01e_gm.h index 20d314b9a7e..5699c91f017 100644 --- a/src/map/packets/c2s/0x01e_gm.h +++ b/src/map/packets/c2s/0x01e_gm.h @@ -27,6 +27,6 @@ // This packet is sent by the client when using GM commands. // Note: The system to actually make use of this packet is no longer implemented in the retail client. However, the functions that send this packet still exist. // Note: /volunteer is what generates this packet. -GP_CLI_PACKET(GP_CLI_COMMAND_GM, - uint8_t Command[115]; // PS2: Command +GP_CLI_PACKET_VLA(GP_CLI_COMMAND_GM, Command, + uint8_t Command[115]; // PS2: Command ); diff --git a/src/map/packets/c2s/0x01f_gmcommand.cpp b/src/map/packets/c2s/0x01f_gmcommand.cpp index d2b4e7ae1fe..d331cdb2942 100644 --- a/src/map/packets/c2s/0x01f_gmcommand.cpp +++ b/src/map/packets/c2s/0x01f_gmcommand.cpp @@ -26,13 +26,14 @@ auto GP_CLI_COMMAND_GMCOMMAND::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { // Not implemented. - return PacketValidator(); + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }); } void GP_CLI_COMMAND_GMCOMMAND::process(MapSession* PSession, CCharEntity* PChar) const { - auto commandStr = asStringFromUntrustedSource(Command, sizeof(Command)); + auto commandStr = asStringFromUntrustedSource(this->Command, sizeof(this->Command)); ShowDebugFmt("GP_CLI_COMMAND_GMCOMMAND: Not implemented. GMUniqueNo: {}, Command: '{}'", - GMUniqueNo, + this->GMUniqueNo, commandStr); } diff --git a/src/map/packets/c2s/0x01f_gmcommand.h b/src/map/packets/c2s/0x01f_gmcommand.h index 0cb9d8b3779..c77da356a2f 100644 --- a/src/map/packets/c2s/0x01f_gmcommand.h +++ b/src/map/packets/c2s/0x01f_gmcommand.h @@ -25,7 +25,7 @@ // https://github.com/atom0s/XiPackets/tree/main/world/client/0x001F // This packet is sent by the client in response to a remote GM command execution request. -GP_CLI_PACKET(GP_CLI_COMMAND_GMCOMMAND, - uint32_t GMUniqueNo; // PS2: GMUniqueNo - uint8_t Command[128]; // PS2: Command -- unknown max size +GP_CLI_PACKET_VLA(GP_CLI_COMMAND_GMCOMMAND, Command, + uint32_t GMUniqueNo; // PS2: GMUniqueNo + uint8_t Command[128]; // PS2: Command -- unknown max size ); diff --git a/src/map/packets/c2s/0x028_item_dump.cpp b/src/map/packets/c2s/0x028_item_dump.cpp index 52e0fbccdb4..0985761de6c 100644 --- a/src/map/packets/c2s/0x028_item_dump.cpp +++ b/src/map/packets/c2s/0x028_item_dump.cpp @@ -56,31 +56,32 @@ const std::set validContainers = { auto GP_CLI_COMMAND_ITEM_DUMP::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() - .oneOf("Category", static_cast(Category), validContainers) - .range("ItemNum", ItemNum, 0, 99); // Retail honors 0 quantity. + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }) + .oneOf("Category", static_cast(this->Category), validContainers) + .range("ItemNum", this->ItemNum, 0, 99); // Retail honors 0 quantity. } void GP_CLI_COMMAND_ITEM_DUMP::process(MapSession* PSession, CCharEntity* PChar) const { // Gil cannot be dropped. - if (Category == LOC_INVENTORY && ItemIndex == 0) + if (this->Category == LOC_INVENTORY && this->ItemIndex == 0) { PChar->pushPacket(ITEMID::GIL, MsgStd::UnableToThrowAway); return; } - CItem* PItem = PChar->getStorage(Category)->GetItem(ItemIndex); + CItem* PItem = PChar->getStorage(this->Category)->GetItem(this->ItemIndex); if (!PItem || PItem->isSubType(ITEM_LOCKED)) { - ShowWarning("GP_CLI_COMMAND_ITEM_DUMP: Attempt of removal of invalid item from slot %u", ItemIndex); + ShowWarning("GP_CLI_COMMAND_ITEM_DUMP: Attempt of removal of invalid item from slot %u", this->ItemIndex); return; } - if (PItem->getQuantity() - PItem->getReserve() < ItemNum) + if (PItem->getQuantity() - PItem->getReserve() < this->ItemNum) { - ShowWarning("GP_CLI_COMMAND_ITEM_DUMP: Trying to drop too much quantity from location %u slot %u", Category, ItemIndex); + ShowWarning("GP_CLI_COMMAND_ITEM_DUMP: Trying to drop too much quantity from location %u slot %u", this->Category, this->ItemIndex); return; } @@ -118,13 +119,13 @@ void GP_CLI_COMMAND_ITEM_DUMP::process(MapSession* PSession, CCharEntity* PChar) // Retail accurate: Any item dropped from a container other than inventory skips the recycle bin. // Items with the NoRecycle flag bypass the recycle bin entirely (e.g. linkshells). - if (!settings::get("map.ENABLE_ITEM_RECYCLE_BIN") || Category != CONTAINER_ID::LOC_INVENTORY || PItem->hasFlag(ItemFlag::NoRecycle)) + if (!settings::get("map.ENABLE_ITEM_RECYCLE_BIN") || this->Category != CONTAINER_ID::LOC_INVENTORY || PItem->hasFlag(ItemFlag::NoRecycle)) { - charutils::DropItem(PChar, Category, ItemIndex, ItemNum, PItem->getID()); + charutils::DropItem(PChar, this->Category, this->ItemIndex, this->ItemNum, PItem->getID()); return; } // Otherwise, to the recycle bin! // Note: AddItemToRecycleBin moves the whole item without using ItemNum which is not retail accurate. - charutils::AddItemToRecycleBin(PChar, Category, ItemIndex, ItemNum); + charutils::AddItemToRecycleBin(PChar, this->Category, this->ItemIndex, this->ItemNum); } diff --git a/src/map/packets/c2s/0x029_item_move.cpp b/src/map/packets/c2s/0x029_item_move.cpp index 7ce0e9023ee..df96be2d785 100644 --- a/src/map/packets/c2s/0x029_item_move.cpp +++ b/src/map/packets/c2s/0x029_item_move.cpp @@ -150,45 +150,46 @@ auto GP_CLI_COMMAND_ITEM_MOVE::validate(MapSession* PSession, const CCharEntity* { const auto validContainersForChar = validContainers(PChar); - return PacketValidator() - .oneOf("Category1", static_cast(Category1), validContainersForChar) - .oneOf("Category2", static_cast(Category2), validContainersForChar) + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }) + .oneOf("Category1", static_cast(this->Category1), validContainersForChar) + .oneOf("Category2", static_cast(this->Category2), validContainersForChar) .mustEqual(isValidMovement(PChar, - static_cast(Category1), - static_cast(Category2), - ItemIndex1), + static_cast(this->Category1), + static_cast(this->Category2), + this->ItemIndex1), true, "Illegal movement"); } void GP_CLI_COMMAND_ITEM_MOVE::process(MapSession* PSession, CCharEntity* PChar) const { - CItem* PItem = PChar->getStorage(Category1)->GetItem(ItemIndex1); + CItem* PItem = PChar->getStorage(this->Category1)->GetItem(this->ItemIndex1); if (!PItem) { return; } - if (PItem->getQuantity() - PItem->getReserve() < ItemNum) + if (PItem->getQuantity() - PItem->getReserve() < this->ItemNum) { - ShowWarning("GP_CLI_COMMAND_ITEM_MOVE: Trying to move too much quantity from location %u slot %u", Category1, ItemIndex1); + ShowWarning("GP_CLI_COMMAND_ITEM_MOVE: Trying to move too much quantity from location %u slot %u", this->Category1, this->ItemIndex1); return; } - if (const uint32 newQty = PItem->getQuantity() - ItemNum; newQty != 0) // split item stack + if (const uint32 newQty = PItem->getQuantity() - this->ItemNum; newQty != 0) // split item stack { - if (charutils::AddItem(PChar, Category2, PItem->getID(), ItemNum) != ERROR_SLOTID) + if (charutils::AddItem(PChar, this->Category2, PItem->getID(), this->ItemNum) != ERROR_SLOTID) { - charutils::UpdateItem(PChar, Category1, ItemIndex1, -static_cast(ItemNum)); + charutils::UpdateItem(PChar, this->Category1, this->ItemIndex1, -static_cast(this->ItemNum)); } } else // move stack / combine items into stack { - if (ItemIndex2 < 82) // 80 + 1 + if (this->ItemIndex2 < 82) // 80 + 1 { - ShowDebug("GP_CLI_COMMAND_ITEM_MOVE: Trying to unite items", Category1, ItemIndex1); - const CItem* PItem2 = PChar->getStorage(Category2)->GetItem(ItemIndex2); + ShowDebug("GP_CLI_COMMAND_ITEM_MOVE: Trying to unite items", this->Category1, this->ItemIndex1); + const CItem* PItem2 = PChar->getStorage(this->Category2)->GetItem(this->ItemIndex2); if (!PItem2 || PItem2->getID() != PItem->getID() || PItem2->isSubType(ITEM_LOCKED) || @@ -196,8 +197,8 @@ void GP_CLI_COMMAND_ITEM_MOVE::process(MapSession* PSession, CCharEntity* PChar) { ShowWarning("GP_CLI_COMMAND_ITEM_MOVE: Trying to unite items with invalid item %i at location %u slot %u", PItem2 ? PItem2->getID() : 0, - Category2, - ItemIndex2); + this->Category2, + this->ItemIndex2); return; } @@ -216,51 +217,51 @@ void GP_CLI_COMMAND_ITEM_MOVE::process(MapSession* PSession, CCharEntity* PChar) } if (moveQty > 0) { - charutils::UpdateItem(PChar, Category2, ItemIndex2, moveQty); - charutils::UpdateItem(PChar, Category1, ItemIndex1, -static_cast(moveQty)); + charutils::UpdateItem(PChar, this->Category2, this->ItemIndex2, moveQty); + charutils::UpdateItem(PChar, this->Category1, this->ItemIndex1, -static_cast(moveQty)); } } return; } - if (uint8 newSlotId = PChar->getStorage(Category2)->InsertItem(PItem); newSlotId != ERROR_SLOTID) + if (uint8 newSlotId = PChar->getStorage(this->Category2)->InsertItem(PItem); newSlotId != ERROR_SLOTID) { const auto rset = db::preparedStmt("UPDATE char_inventory SET location = ?, slot = ? WHERE charid = ? AND location = ? AND slot = ?", - Category2, + this->Category2, newSlotId, PChar->id, - Category1, - ItemIndex1); + this->Category1, + this->ItemIndex1); if (rset && rset->rowsAffected()) { - PChar->getStorage(Category1)->InsertItem(nullptr, ItemIndex1); + PChar->getStorage(this->Category1)->InsertItem(nullptr, this->ItemIndex1); - PChar->pushPacket(nullptr, static_cast(Category1), ItemIndex1, PItem); - PChar->pushPacket(PItem, static_cast(Category2), newSlotId); + PChar->pushPacket(nullptr, static_cast(this->Category1), this->ItemIndex1, PItem); + PChar->pushPacket(PItem, static_cast(this->Category2), newSlotId); } else { - PChar->getStorage(Category2)->InsertItem(nullptr, newSlotId); - PChar->getStorage(Category1)->InsertItem(PItem, ItemIndex1); + PChar->getStorage(this->Category2)->InsertItem(nullptr, newSlotId); + PChar->getStorage(this->Category1)->InsertItem(PItem, this->ItemIndex1); } } else { // Client assumed the location was not full when it is // Resend the packets to inform the client of the storage sizes - const uint8 size = PChar->getStorage(Category2)->GetSize(); + const uint8 size = PChar->getStorage(this->Category2)->GetSize(); for (uint8 slotID = 0; slotID <= size; ++slotID) { if (CItem* PSlotItem = PChar->getStorage(Category2)->GetItem(slotID); PSlotItem != nullptr) { - PChar->pushPacket(PSlotItem, static_cast(Category2), slotID); + PChar->pushPacket(PSlotItem, static_cast(this->Category2), slotID); } } PChar->pushPacket(PChar); - ShowError("GP_CLI_COMMAND_ITEM_MOVE: Location %u Slot %u is full", Category2, ItemIndex2); + ShowError("GP_CLI_COMMAND_ITEM_MOVE: Location %u Slot %u is full", this->Category2, this->ItemIndex2); return; } } diff --git a/src/map/packets/c2s/0x02b_translate.cpp b/src/map/packets/c2s/0x02b_translate.cpp index 6eb6e822819..25fbb4f9cad 100644 --- a/src/map/packets/c2s/0x02b_translate.cpp +++ b/src/map/packets/c2s/0x02b_translate.cpp @@ -27,7 +27,8 @@ auto GP_CLI_COMMAND_TRANSLATE::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }) .oneOf(this->FromIndex) .oneOf(this->ToIndex); } diff --git a/src/map/packets/c2s/0x02b_translate.h b/src/map/packets/c2s/0x02b_translate.h index b8960db7267..0ecbb32c457 100644 --- a/src/map/packets/c2s/0x02b_translate.h +++ b/src/map/packets/c2s/0x02b_translate.h @@ -31,9 +31,9 @@ enum class GP_CLI_COMMAND_TRANSLATE_INDEX : uint8_t // https://github.com/atom0s/XiPackets/tree/main/world/client/0x002B // This packet is sent by the client when using the /translate command. -GP_CLI_PACKET(GP_CLI_COMMAND_TRANSLATE, - GP_CLI_COMMAND_TRANSLATE_INDEX FromIndex; - GP_CLI_COMMAND_TRANSLATE_INDEX ToIndex; - uint16_t padding00; - uint8_t Name[64]; // Variable length +GP_CLI_PACKET_VLA(GP_CLI_COMMAND_TRANSLATE, Name, + GP_CLI_COMMAND_TRANSLATE_INDEX FromIndex; + GP_CLI_COMMAND_TRANSLATE_INDEX ToIndex; + uint16_t padding00; + uint8_t Name[64]; // Variable length ); diff --git a/src/map/packets/c2s/0x02c_itemsearch.cpp b/src/map/packets/c2s/0x02c_itemsearch.cpp index 3d2eec6a805..2011919905e 100644 --- a/src/map/packets/c2s/0x02c_itemsearch.cpp +++ b/src/map/packets/c2s/0x02c_itemsearch.cpp @@ -26,13 +26,14 @@ auto GP_CLI_COMMAND_ITEMSEARCH::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { // Not implemented. - return PacketValidator() - .oneOf(Language); + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }) + .oneOf(this->Language); } void GP_CLI_COMMAND_ITEMSEARCH::process(MapSession* PSession, CCharEntity* PChar) const { ShowDebugFmt("GP_CLI_COMMAND_ITEMSEARCH: Not implemented. Language: {}, Name: {}", - Language, - asStringFromUntrustedSource(Name, sizeof(Name))); + this->Language, + asStringFromUntrustedSource(this->Name, sizeof(this->Name))); } diff --git a/src/map/packets/c2s/0x02c_itemsearch.h b/src/map/packets/c2s/0x02c_itemsearch.h index 67ed5012a14..e4cce6ce75a 100644 --- a/src/map/packets/c2s/0x02c_itemsearch.h +++ b/src/map/packets/c2s/0x02c_itemsearch.h @@ -31,8 +31,8 @@ enum class GP_CLI_COMMAND_ITEMSEARCH_LANGUAGE : uint8_t // https://github.com/atom0s/XiPackets/tree/main/world/client/0x002C // This packet is sent by the client when using the /itemsearch command. -GP_CLI_PACKET(GP_CLI_COMMAND_ITEMSEARCH, - uint8_t Language; - uint8_t padding00[3]; - uint8_t Name[64]; // Variable length +GP_CLI_PACKET_VLA(GP_CLI_COMMAND_ITEMSEARCH, Name, + uint8_t Language; + uint8_t padding00[3]; + uint8_t Name[64]; // Variable length ); diff --git a/src/map/packets/c2s/0x032_trade_req.cpp b/src/map/packets/c2s/0x032_trade_req.cpp index c802bc130af..0c894e610c4 100644 --- a/src/map/packets/c2s/0x032_trade_req.cpp +++ b/src/map/packets/c2s/0x032_trade_req.cpp @@ -33,15 +33,15 @@ auto GP_CLI_COMMAND_TRADE_REQ::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() - .mustNotEqual(PChar->id, UniqueNo, "Character trading with itself") - .isNotMonstrosity(PChar); + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent, BlockedState::Monstrosity }) + .mustNotEqual(PChar->id, this->UniqueNo, "Character trading with itself"); } void GP_CLI_COMMAND_TRADE_REQ::process(MapSession* PSession, CCharEntity* PChar) const { - auto* PTarget = static_cast(PChar->GetEntity(ActIndex, TYPE_PC)); - if (!PTarget || PTarget->id != UniqueNo) + auto* PTarget = static_cast(PChar->GetEntity(this->ActIndex, TYPE_PC)); + if (!PTarget || PTarget->id != this->UniqueNo) { return; } @@ -119,8 +119,8 @@ void GP_CLI_COMMAND_TRADE_REQ::process(MapSession* PSession, CCharEntity* PChar) } PChar->lastTradeInvite = currentTime; - PChar->TradePending.id = UniqueNo; - PChar->TradePending.targid = ActIndex; + PChar->TradePending.id = this->UniqueNo; + PChar->TradePending.targid = this->ActIndex; PTarget->lastTradeInvite = currentTime; PTarget->TradePending.id = PChar->id; diff --git a/src/map/packets/c2s/0x033_trade_res.cpp b/src/map/packets/c2s/0x033_trade_res.cpp index 839cfa99e0a..c39c47c96ef 100644 --- a/src/map/packets/c2s/0x033_trade_res.cpp +++ b/src/map/packets/c2s/0x033_trade_res.cpp @@ -39,10 +39,10 @@ const auto cleanTradeTargets = [](CCharEntity* PChar, CCharEntity* PTarget) auto GP_CLI_COMMAND_TRADE_RES::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() - .oneOf(Kind) - .mustNotEqual(PChar->TradePending.targid, 0, "No pending trade target") - .isNotMonstrosity(PChar); + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent, BlockedState::Monstrosity }) + .oneOf(this->Kind) + .mustNotEqual(PChar->TradePending.targid, 0, "No pending trade target"); } void GP_CLI_COMMAND_TRADE_RES::process(MapSession* PSession, CCharEntity* PChar) const @@ -57,7 +57,7 @@ void GP_CLI_COMMAND_TRADE_RES::process(MapSession* PSession, CCharEntity* PChar) return; } - switch (static_cast(Kind)) + switch (static_cast(this->Kind)) { case GP_CLI_COMMAND_TRADE_RES_KIND::Start: // request accepted { @@ -82,10 +82,10 @@ void GP_CLI_COMMAND_TRADE_RES::process(MapSession* PSession, CCharEntity* PChar) } PChar->UContainer->SetType(UCONTAINER_TRADE); - PChar->pushPacket(PTarget, static_cast(Kind)); + PChar->pushPacket(PTarget, static_cast(this->Kind)); PTarget->UContainer->SetType(UCONTAINER_TRADE); - PTarget->pushPacket(PChar, static_cast(Kind)); + PTarget->pushPacket(PChar, static_cast(this->Kind)); } break; case GP_CLI_COMMAND_TRADE_RES_KIND::Cancell: // trade cancelled @@ -104,7 +104,7 @@ void GP_CLI_COMMAND_TRADE_RES::process(MapSession* PSession, CCharEntity* PChar) cleanTradeTargets(PChar, PTarget); // TODO: Verify exact sequence of packets sent here. - PTarget->pushPacket(PChar, static_cast(Kind)); + PTarget->pushPacket(PChar, static_cast(this->Kind)); } break; case GP_CLI_COMMAND_TRADE_RES_KIND::Make: // trade accepted diff --git a/src/map/packets/c2s/0x034_trade_list.cpp b/src/map/packets/c2s/0x034_trade_list.cpp index 8512baf98d1..62e5cca920c 100644 --- a/src/map/packets/c2s/0x034_trade_list.cpp +++ b/src/map/packets/c2s/0x034_trade_list.cpp @@ -57,10 +57,10 @@ const auto auditTrade = [](Scheduler& scheduler, CCharEntity* PChar, CCharEntity auto GP_CLI_COMMAND_TRADE_LIST::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent, BlockedState::Monstrosity }) .mustNotEqual(PChar->TradePending.id, 0, "No trade target") - .range("TradeIndex", TradeIndex, 0, 8) - .isNotMonstrosity(PChar); + .range("TradeIndex", this->TradeIndex, 0, 8); } void GP_CLI_COMMAND_TRADE_LIST::process(MapSession* PSession, CCharEntity* PChar) const @@ -76,43 +76,43 @@ void GP_CLI_COMMAND_TRADE_LIST::process(MapSession* PSession, CCharEntity* PChar } // If updating a filled slot, remove the pending item. - if (!PChar->UContainer->IsSlotEmpty(TradeIndex)) + if (!PChar->UContainer->IsSlotEmpty(this->TradeIndex)) { - CItem* PCurrentSlotItem = PChar->UContainer->GetItem(TradeIndex); - if (ItemNum != 0) + CItem* PCurrentSlotItem = PChar->UContainer->GetItem(this->TradeIndex); + if (this->ItemNum != 0) { ShowError("GP_CLI_COMMAND_TRADE_LIST: Player %s trying to update trade quantity of a RESERVED item! [Item: %i | Trade Slot: %i] ", PChar->getName(), PCurrentSlotItem->getID(), - TradeIndex); + this->TradeIndex); } PCurrentSlotItem->setReserve(0); - PChar->UContainer->ClearSlot(TradeIndex); + PChar->UContainer->ClearSlot(this->TradeIndex); } - CItem* PItem = PChar->getStorage(LOC_INVENTORY)->GetItem(ItemIndex); + CItem* PItem = PChar->getStorage(LOC_INVENTORY)->GetItem(this->ItemIndex); // Validate that the item exists in sufficient quantity, is not reserved, and is not an EX item. if (!PItem || - PItem->getID() != ItemNo || + PItem->getID() != this->ItemNo || PItem->hasFlag(ItemFlag::Exclusive) || - ItemNum + PItem->getReserve() > PItem->getQuantity() || + this->ItemNum + PItem->getReserve() > PItem->getQuantity() || PItem->isSubType(ITEM_LOCKED)) { ShowErrorFmt("GP_CLI_COMMAND_TRADE_LIST: {} trying to add an invalid item/quantity [Item: {} | Trade Slot: {}] ", PChar->getName(), - ItemNo, - TradeIndex); + this->ItemNo, + this->TradeIndex); return; } // If item count is zero remove from container - if (ItemNum == 0) + if (this->ItemNum == 0) { - ShowInfo("GP_CLI_COMMAND_TRADE_LIST: %s->%s trade updating trade slot id %d with item %s, quantity 0", PChar->getName(), PTarget->getName(), TradeIndex, PItem->getName()); + ShowInfo("GP_CLI_COMMAND_TRADE_LIST: %s->%s trade updating trade slot id %d with item %s, quantity 0", PChar->getName(), PTarget->getName(), this->TradeIndex, PItem->getName()); PItem->setReserve(0); - PChar->UContainer->SetItem(TradeIndex, nullptr); + PChar->UContainer->SetItem(this->TradeIndex, nullptr); } if (PItem->isType(ITEM_LINKSHELL)) @@ -125,30 +125,30 @@ void GP_CLI_COMMAND_TRADE_LIST::process(MapSession* PSession, CCharEntity* PChar { PChar->pushPacket(MsgStd::LinkshellEquipBeforeUsing); PItem->setReserve(0); - PChar->UContainer->SetItem(TradeIndex, nullptr); + PChar->UContainer->SetItem(this->TradeIndex, nullptr); } else { - ShowInfo("GP_CLI_COMMAND_TRADE_LIST: %s->%s trade updating trade slot id %d with item %s, quantity %d", PChar->getName(), PTarget->getName(), TradeIndex, PItem->getName(), ItemNum); - PItem->setReserve(ItemNum + PItem->getReserve()); - PChar->UContainer->SetItem(TradeIndex, PItem); + ShowInfo("GP_CLI_COMMAND_TRADE_LIST: %s->%s trade updating trade slot id %d with item %s, quantity %d", PChar->getName(), PTarget->getName(), this->TradeIndex, PItem->getName(), this->ItemNum); + PItem->setReserve(this->ItemNum + PItem->getReserve()); + PChar->UContainer->SetItem(this->TradeIndex, PItem); } } else { - ShowInfo("GP_CLI_COMMAND_TRADE_LIST: %s->%s trade updating trade slot id %d with item %s, quantity %d", PChar->getName(), PTarget->getName(), TradeIndex, PItem->getName(), ItemNum); - PItem->setReserve(ItemNum + PItem->getReserve()); - PChar->UContainer->SetItem(TradeIndex, PItem); + ShowInfo("GP_CLI_COMMAND_TRADE_LIST: %s->%s trade updating trade slot id %d with item %s, quantity %d", PChar->getName(), PTarget->getName(), this->TradeIndex, PItem->getName(), this->ItemNum); + PItem->setReserve(this->ItemNum + PItem->getReserve()); + PChar->UContainer->SetItem(this->TradeIndex, PItem); } // TODO: Don't pass around Scheduler& through PSession - auditTrade(*PSession->scheduler, PChar, PTarget, PItem, ItemNum); + auditTrade(*PSession->scheduler, PChar, PTarget, PItem, this->ItemNum); ShowDebug("GP_CLI_COMMAND_TRADE_LIST: %s->%s trade pushing packet to %s", PChar->getName(), PTarget->getName(), PChar->getName()); - PChar->pushPacket(PItem, TradeIndex); + PChar->pushPacket(PItem, this->TradeIndex); ShowDebug("GP_CLI_COMMAND_TRADE_LIST: %s->%s trade pushing packet to %s", PChar->getName(), PTarget->getName(), PTarget->getName()); - PTarget->pushPacket(PItem, TradeIndex); + PTarget->pushPacket(PItem, this->TradeIndex); PChar->UContainer->UnLock(); PTarget->UContainer->UnLock(); diff --git a/src/map/packets/c2s/0x036_item_transfer.cpp b/src/map/packets/c2s/0x036_item_transfer.cpp index a885be836e6..3af79a44e2f 100644 --- a/src/map/packets/c2s/0x036_item_transfer.cpp +++ b/src/map/packets/c2s/0x036_item_transfer.cpp @@ -58,8 +58,8 @@ const auto auditTrade = [](Scheduler& scheduler, CCharEntity* PChar, CBaseEntity auto GP_CLI_COMMAND_ITEM_TRANSFER::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() - .isNotMonstrosity(PChar) + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent, BlockedState::Monstrosity }) .range("ItemNum", this->ItemNum, 1, 9); } diff --git a/src/map/packets/c2s/0x037_item_use.cpp b/src/map/packets/c2s/0x037_item_use.cpp index 1293c99e21e..a5a7cd8ac3f 100644 --- a/src/map/packets/c2s/0x037_item_use.cpp +++ b/src/map/packets/c2s/0x037_item_use.cpp @@ -46,8 +46,8 @@ const std::set validContainers = { auto GP_CLI_COMMAND_ITEM_USE::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() - .isNotMonstrosity(PChar) + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent, BlockedState::Monstrosity }) .mustEqual(PChar->inMogHouse(), false, "Player is in moghouse") .mustEqual(this->ItemNum, 0, "ItemNum not 0") .oneOf("Category", static_cast(this->Category), validContainers); diff --git a/src/map/packets/c2s/0x03a_item_stack.cpp b/src/map/packets/c2s/0x03a_item_stack.cpp index cec44f31a4a..82048197854 100644 --- a/src/map/packets/c2s/0x03a_item_stack.cpp +++ b/src/map/packets/c2s/0x03a_item_stack.cpp @@ -27,13 +27,13 @@ auto GP_CLI_COMMAND_ITEM_STACK::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() - .oneOf(Category); // Retail honors _every_ container, even if you don't presently have access. + return PacketValidator(PChar) + .oneOf(this->Category); // Retail honors _every_ container, even if you don't presently have access. } void GP_CLI_COMMAND_ITEM_STACK::process(MapSession* PSession, CCharEntity* PChar) const { - CItemContainer* PItemContainer = PChar->getStorage(Category); + CItemContainer* PItemContainer = PChar->getStorage(this->Category); const uint8 size = PItemContainer->GetSize(); diff --git a/src/map/packets/c2s/0x03b_subcontainer.cpp b/src/map/packets/c2s/0x03b_subcontainer.cpp index 7db75a84654..b5e07368b8a 100644 --- a/src/map/packets/c2s/0x03b_subcontainer.cpp +++ b/src/map/packets/c2s/0x03b_subcontainer.cpp @@ -67,19 +67,20 @@ const auto validContainers = [](const CCharEntity* PChar) -> std::set PacketValidationResult { - return PacketValidator() + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }) .mustEqual(PChar->m_moghouseID, PChar->id, "Character not in their mog house") - .oneOf(Kind) - .oneOf(ContainerIndex) - .oneOf("Category1", static_cast(Category1), validContainers(PChar)); + .oneOf(this->Kind) + .oneOf(this->ContainerIndex) + .oneOf("Category1", static_cast(this->Category1), validContainers(PChar)); } void GP_CLI_COMMAND_SUBCONTAINER::process(MapSession* PSession, CCharEntity* PChar) const { - auto* PItem = PChar->getStorage(Category1)->GetItem(ItemIndex1); + auto* PItem = PChar->getStorage(this->Category1)->GetItem(this->ItemIndex1); if (PItem == nullptr) { - ShowWarning("GP_CLI_COMMAND_SUBCONTAINER: Unable to load mannequin from slot %u in location %u by %s", ItemIndex1, Category1, PChar->getName()); + ShowWarning("GP_CLI_COMMAND_SUBCONTAINER: Unable to load mannequin from slot %u in location %u by %s", this->ItemIndex1, this->Category1, PChar->getName()); return; } @@ -111,13 +112,13 @@ void GP_CLI_COMMAND_SUBCONTAINER::process(MapSession* PSession, CCharEntity* PCh } }; - switch (static_cast(Kind)) + switch (static_cast(this->Kind)) { case GP_CLI_COMMAND_SUBCONTAINER_KIND::Equip: { - if (Category2 != LOC_STORAGE) // Only valid for direct equip/unequip + if (this->Category2 != LOC_STORAGE) // Only valid for direct equip/unequip { - ShowWarning("GP_CLI_COMMAND_SUBCONTAINER: Invalid item location passed to Mannequin Equip packet %u by %s", Category2, PChar->getName()); + ShowWarning("GP_CLI_COMMAND_SUBCONTAINER: Invalid item location passed to Mannequin Equip packet %u by %s", this->Category2, PChar->getName()); return; } @@ -161,13 +162,13 @@ void GP_CLI_COMMAND_SUBCONTAINER::process(MapSession* PSession, CCharEntity* PCh "extra = ? " "WHERE location = ? AND slot = ? AND charid = ?", PItem->m_extra, - Category1, - ItemIndex1, + this->Category1, + this->ItemIndex1, PChar->id); if (rset) { - PChar->pushPacket(PFurnishing, static_cast(Category1), ItemIndex1); - PChar->pushPacket(PChar, static_cast(Category1), ItemIndex1, mannequin); + PChar->pushPacket(PFurnishing, static_cast(this->Category1), this->ItemIndex1); + PChar->pushPacket(PChar, static_cast(this->Category1), this->ItemIndex1, mannequin); PChar->pushPacket(PChar); } else diff --git a/src/map/packets/c2s/0x03c_black_list.cpp b/src/map/packets/c2s/0x03c_black_list.cpp index abe39793955..c28040bea33 100644 --- a/src/map/packets/c2s/0x03c_black_list.cpp +++ b/src/map/packets/c2s/0x03c_black_list.cpp @@ -26,7 +26,8 @@ auto GP_CLI_COMMAND_BLACK_LIST::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { // No parameter to validate for this packet. - return PacketValidator(); + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }); } void GP_CLI_COMMAND_BLACK_LIST::process(MapSession* PSession, CCharEntity* PChar) const diff --git a/src/map/packets/c2s/0x03d_black_edit.cpp b/src/map/packets/c2s/0x03d_black_edit.cpp index 1c6be2a64a9..96012672edd 100644 --- a/src/map/packets/c2s/0x03d_black_edit.cpp +++ b/src/map/packets/c2s/0x03d_black_edit.cpp @@ -38,13 +38,14 @@ const auto sendFailPacket = [](CCharEntity* PChar) auto GP_CLI_COMMAND_BLACK_EDIT::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() - .oneOf(Mode); + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }) + .oneOf(this->Mode); } void GP_CLI_COMMAND_BLACK_EDIT::process(MapSession* PSession, CCharEntity* PChar) const { - const auto name = db::escapeString(asStringFromUntrustedSource(Data.Name, 15)); + const auto name = db::escapeString(asStringFromUntrustedSource(this->Data.Name, 15)); const auto [charid, accid] = charutils::getCharIdAndAccountIdFromName(name); if (!charid) @@ -53,7 +54,7 @@ void GP_CLI_COMMAND_BLACK_EDIT::process(MapSession* PSession, CCharEntity* PChar return; } - switch (static_cast(Mode)) + switch (static_cast(this->Mode)) { case GP_CLI_COMMAND_BLACK_EDIT_MODE::Add: { diff --git a/src/map/packets/c2s/0x041_trophy_entry.cpp b/src/map/packets/c2s/0x041_trophy_entry.cpp index ddcc169991b..96f42e6c00f 100644 --- a/src/map/packets/c2s/0x041_trophy_entry.cpp +++ b/src/map/packets/c2s/0x041_trophy_entry.cpp @@ -26,15 +26,16 @@ auto GP_CLI_COMMAND_TROPHY_ENTRY::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }) .mustNotEqual(PChar->PTreasurePool, nullptr, "Character does not have a treasure pool") - .range("TrophyItemIndex", TrophyItemIndex, 0, TREASUREPOOL_SIZE - 1); + .range("TrophyItemIndex", this->TrophyItemIndex, 0, TREASUREPOOL_SIZE - 1); } void GP_CLI_COMMAND_TROPHY_ENTRY::process(MapSession* PSession, CCharEntity* PChar) const { - if (!PChar->PTreasurePool->hasLottedItem(PChar, TrophyItemIndex)) + if (!PChar->PTreasurePool->hasLottedItem(PChar, this->TrophyItemIndex)) { - PChar->PTreasurePool->lotItem(PChar, TrophyItemIndex, xirand::GetRandomNumber(1, 1000)); // 1 ~ 998+1 + PChar->PTreasurePool->lotItem(PChar, this->TrophyItemIndex, xirand::GetRandomNumber(1, 1000)); // 1 ~ 998+1 } } diff --git a/src/map/packets/c2s/0x042_trophy_absence.cpp b/src/map/packets/c2s/0x042_trophy_absence.cpp index 5a3c0181837..ea67d6375ed 100644 --- a/src/map/packets/c2s/0x042_trophy_absence.cpp +++ b/src/map/packets/c2s/0x042_trophy_absence.cpp @@ -26,15 +26,16 @@ auto GP_CLI_COMMAND_TROPHY_ABSENCE::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }) .mustNotEqual(PChar->PTreasurePool, nullptr, "Character does not have a treasure pool") - .range("TrophyItemIndex", TrophyItemIndex, 0, TREASUREPOOL_SIZE - 1); + .range("TrophyItemIndex", this->TrophyItemIndex, 0, TREASUREPOOL_SIZE - 1); } void GP_CLI_COMMAND_TROPHY_ABSENCE::process(MapSession* PSession, CCharEntity* PChar) const { - if (!PChar->PTreasurePool->hasPassedItem(PChar, TrophyItemIndex)) + if (!PChar->PTreasurePool->hasPassedItem(PChar, this->TrophyItemIndex)) { - PChar->PTreasurePool->passItem(PChar, TrophyItemIndex); + PChar->PTreasurePool->passItem(PChar, this->TrophyItemIndex); } } diff --git a/src/map/packets/c2s/0x04b_fragments.cpp b/src/map/packets/c2s/0x04b_fragments.cpp index c609c1f2e3d..1776cd378d9 100644 --- a/src/map/packets/c2s/0x04b_fragments.cpp +++ b/src/map/packets/c2s/0x04b_fragments.cpp @@ -33,32 +33,32 @@ auto GP_CLI_COMMAND_FRAGMENTS::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { // TODO: Document field values and validate. - return PacketValidator(); + return PacketValidator(PChar); } void GP_CLI_COMMAND_FRAGMENTS::process(MapSession* PSession, CCharEntity* PChar) const { // TODO: Verify all of this - uint8 msgChunk = Command; // The current chunk of the message to send (1 = start, 2 = rest of message) - const uint8 msgType = value1; // 1 = Server message, 2 = Fishing Rank - uint8 msgLanguage = value2; // Language request id (2 = English, 4 = French) + uint8 msgChunk = this->Command; // The current chunk of the message to send (1 = start, 2 = rest of message) + const uint8 msgType = this->value1; // 1 = Server message, 2 = Fishing Rank + uint8 msgLanguage = this->value2; // Language request id (2 = English, 4 = French) if (msgType == 1) // Standard Server Message { // Deduplicate fragment retries caused by slow zone-in response times. - if (PChar->servmesLastOffset_ == offset) + if (PChar->servmesLastOffset_ == this->offset) { return; } std::string loginMessage = luautils::GetServerMessage(msgLanguage); - PChar->pushPacket(loginMessage, msgLanguage, timestamp, offset); - PChar->servmesLastOffset_ = offset; + PChar->pushPacket(loginMessage, msgLanguage, this->timestamp, this->offset); + PChar->servmesLastOffset_ = this->offset; // Reset tracking after the final fragment so /servmes works later const auto msgSize = loginMessage.length() + 1; - const auto sndLength = msgSize - offset > 236 ? 236 : (msgSize - offset); - if (offset + sndLength >= msgSize) + const auto sndLength = msgSize - this->offset > 236 ? 236 : (msgSize - this->offset); + if (this->offset + sndLength >= msgSize) { PChar->servmesLastOffset_ = std::nullopt; } @@ -131,11 +131,11 @@ void GP_CLI_COMMAND_FRAGMENTS::process(MapSession* PSession, CCharEntity* PChar) // Add the next five blocks until we are out of entries if (msgChunk == 1 || msgChunk == 2) { - while (entries.size() <= (data_size / blockSize)) + while (entries.size() <= (this->data_size / blockSize)) { // Create a copy of the ranking entry and hold it in the local entry vector // This vector is cleared once the packets are sent - const uint8 position = offset / blockSize + entryVal++; + const uint8 position = this->offset / blockSize + entryVal++; FishingContestEntry* packetEntry = fishingcontest::GetFishRankEntry(position); if (packetEntry != nullptr) { @@ -149,7 +149,7 @@ void GP_CLI_COMMAND_FRAGMENTS::process(MapSession* PSession, CCharEntity* PChar) } } - PChar->pushPacket(entries, msgLanguage, timestamp, offset, totalEntries, msgChunk); + PChar->pushPacket(entries, msgLanguage, this->timestamp, this->offset, totalEntries, msgChunk); entries.clear(); } } diff --git a/src/map/packets/c2s/0x04d_pbx.cpp b/src/map/packets/c2s/0x04d_pbx.cpp index aa264123e8a..0f2ec9245cb 100644 --- a/src/map/packets/c2s/0x04d_pbx.cpp +++ b/src/map/packets/c2s/0x04d_pbx.cpp @@ -29,150 +29,148 @@ auto GP_CLI_COMMAND_PBX::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - auto pv = PacketValidator() - .oneOf(Command) - .isNotCrafting(PChar) - .isNotFishing(PChar) - .mustEqual(jailutils::InPrison(PChar), false, "Cannot use delivery box while jailed") - .mustEqual(Result, 0, "Result not 0") - .mustEqual(ResParam1, 0, "ResParam1 not 0") - .mustEqual(ResParam2, 0, "ResParam2 not 0") - .mustEqual(ResParam3, 0, "ResParam3 not 0"); + auto pv = PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent, BlockedState::Crafting, BlockedState::Fishing, BlockedState::Jailed }) + .oneOf(this->Command) + .mustEqual(this->Result, 0, "Result not 0") + .mustEqual(this->ResParam1, 0, "ResParam1 not 0") + .mustEqual(this->ResParam2, 0, "ResParam2 not 0") + .mustEqual(this->ResParam3, 0, "ResParam3 not 0"); - switch (static_cast(Command)) + switch (static_cast(this->Command)) { case GP_CLI_COMMAND_PBX_COMMAND::Work: { pv - .range("BoxNo", BoxNo, GP_CLI_COMMAND_PBX_BOXNO::Incoming, GP_CLI_COMMAND_PBX_BOXNO::Outgoing) - .range("PostWorkNo", PostWorkNo, -1, 8) - .mustEqual(ItemWorkNo, -1, "ItemWorkNo not -1") - .mustEqual(ItemStacks, -1, "ItemStacks not -1"); + .range("BoxNo", this->BoxNo, GP_CLI_COMMAND_PBX_BOXNO::Incoming, GP_CLI_COMMAND_PBX_BOXNO::Outgoing) + .range("PostWorkNo", this->PostWorkNo, -1, 8) + .mustEqual(this->ItemWorkNo, -1, "ItemWorkNo not -1") + .mustEqual(this->ItemStacks, -1, "ItemStacks not -1"); } break; case GP_CLI_COMMAND_PBX_COMMAND::Set: { pv - .mustEqual(BoxNo, GP_CLI_COMMAND_PBX_BOXNO::Outgoing, "BoxNo not Outgoing") - .range("PostWorkNo", PostWorkNo, 0, 8) - .range("ItemStacks", ItemStacks, 0, 999999999); + .mustEqual(this->BoxNo, GP_CLI_COMMAND_PBX_BOXNO::Outgoing, "BoxNo not Outgoing") + .range("PostWorkNo", this->PostWorkNo, 0, 8) + .range("ItemStacks", this->ItemStacks, 0, 999999999); } break; case GP_CLI_COMMAND_PBX_COMMAND::Send: { pv - .mustEqual(BoxNo, GP_CLI_COMMAND_PBX_BOXNO::Outgoing, "BoxNo not Outgoing") - .range("PostWorkNo", PostWorkNo, 0, 8) - .mustEqual(ItemWorkNo, -1, "ItemWorkNo not -1") - .mustEqual(ItemStacks, -1, "ItemStacks not -1"); + .mustEqual(this->BoxNo, GP_CLI_COMMAND_PBX_BOXNO::Outgoing, "BoxNo not Outgoing") + .range("PostWorkNo", this->PostWorkNo, 0, 8) + .mustEqual(this->ItemWorkNo, -1, "ItemWorkNo not -1") + .mustEqual(this->ItemStacks, -1, "ItemStacks not -1"); } break; case GP_CLI_COMMAND_PBX_COMMAND::Cancel: { pv - .mustEqual(BoxNo, GP_CLI_COMMAND_PBX_BOXNO::Outgoing, "BoxNo not Outgoing") - .range("PostWorkNo", PostWorkNo, 0, 8) - .mustEqual(ItemWorkNo, -1, "ItemWorkNo not -1") - .mustEqual(ItemStacks, -1, "ItemStacks not -1"); + .mustEqual(this->BoxNo, GP_CLI_COMMAND_PBX_BOXNO::Outgoing, "BoxNo not Outgoing") + .range("PostWorkNo", this->PostWorkNo, 0, 8) + .mustEqual(this->ItemWorkNo, -1, "ItemWorkNo not -1") + .mustEqual(this->ItemStacks, -1, "ItemStacks not -1"); } break; case GP_CLI_COMMAND_PBX_COMMAND::Check: { pv - .range("BoxNo", BoxNo, GP_CLI_COMMAND_PBX_BOXNO::Incoming, GP_CLI_COMMAND_PBX_BOXNO::Outgoing) - .mustEqual(PostWorkNo, -1, "PostWorkNo not -1") - .mustEqual(ItemWorkNo, -1, "ItemWorkNo not -1") - .mustEqual(ItemStacks, -1, "ItemStacks not -1"); + .range("BoxNo", this->BoxNo, GP_CLI_COMMAND_PBX_BOXNO::Incoming, GP_CLI_COMMAND_PBX_BOXNO::Outgoing) + .mustEqual(this->PostWorkNo, -1, "PostWorkNo not -1") + .mustEqual(this->ItemWorkNo, -1, "ItemWorkNo not -1") + .mustEqual(this->ItemStacks, -1, "ItemStacks not -1"); } break; case GP_CLI_COMMAND_PBX_COMMAND::Recv: { pv - .mustEqual(BoxNo, GP_CLI_COMMAND_PBX_BOXNO::Incoming, "BoxNo not Incoming") - .range("PostWorkNo", PostWorkNo, 0, 8) - .mustEqual(ItemWorkNo, 1, "ItemWorkNo not 1") - .mustEqual(ItemStacks, -1, "ItemStacks not -1"); + .mustEqual(this->BoxNo, GP_CLI_COMMAND_PBX_BOXNO::Incoming, "BoxNo not Incoming") + .range("PostWorkNo", this->PostWorkNo, 0, 8) + .mustEqual(this->ItemWorkNo, 1, "ItemWorkNo not 1") + .mustEqual(this->ItemStacks, -1, "ItemStacks not -1"); } break; case GP_CLI_COMMAND_PBX_COMMAND::Confirm: { pv - .mustEqual(BoxNo, GP_CLI_COMMAND_PBX_BOXNO::None, "BoxNo not None") - .mustEqual(PostWorkNo, -1, "PostWorkNo not -1") - .mustEqual(ItemWorkNo, -1, "ItemWorkNo not -1") - .mustEqual(ItemStacks, -1, "ItemStacks not -1"); + .mustEqual(this->BoxNo, GP_CLI_COMMAND_PBX_BOXNO::None, "BoxNo not None") + .mustEqual(this->PostWorkNo, -1, "PostWorkNo not -1") + .mustEqual(this->ItemWorkNo, -1, "ItemWorkNo not -1") + .mustEqual(this->ItemStacks, -1, "ItemStacks not -1"); } break; case GP_CLI_COMMAND_PBX_COMMAND::Accept: { pv - .mustEqual(BoxNo, GP_CLI_COMMAND_PBX_BOXNO::Incoming, "BoxNo not Incoming") - .range("PostWorkNo", PostWorkNo, 0, 8) - .mustEqual(ItemWorkNo, -1, "ItemWorkNo not -1") - .mustEqual(ItemStacks, -1, "ItemStacks not -1"); + .mustEqual(this->BoxNo, GP_CLI_COMMAND_PBX_BOXNO::Incoming, "BoxNo not Incoming") + .range("PostWorkNo", this->PostWorkNo, 0, 8) + .mustEqual(this->ItemWorkNo, -1, "ItemWorkNo not -1") + .mustEqual(this->ItemStacks, -1, "ItemStacks not -1"); } break; case GP_CLI_COMMAND_PBX_COMMAND::Reject: { pv - .mustEqual(BoxNo, GP_CLI_COMMAND_PBX_BOXNO::Incoming, "BoxNo not Incoming") - .range("PostWorkNo", PostWorkNo, 0, 8) - .mustEqual(ItemWorkNo, -1, "ItemWorkNo not -1") - .mustEqual(ItemStacks, -1, "ItemStacks not -1"); + .mustEqual(this->BoxNo, GP_CLI_COMMAND_PBX_BOXNO::Incoming, "BoxNo not Incoming") + .range("PostWorkNo", this->PostWorkNo, 0, 8) + .mustEqual(this->ItemWorkNo, -1, "ItemWorkNo not -1") + .mustEqual(this->ItemStacks, -1, "ItemStacks not -1"); } break; case GP_CLI_COMMAND_PBX_COMMAND::Get: { pv - .range("BoxNo", BoxNo, GP_CLI_COMMAND_PBX_BOXNO::Incoming, GP_CLI_COMMAND_PBX_BOXNO::Outgoing) - .range("PostWorkNo", PostWorkNo, 0, 8) - .mustEqual(ItemWorkNo, -1, "ItemWorkNo not -1") - .mustEqual(ItemStacks, -1, "ItemStacks not -1"); + .range("BoxNo", this->BoxNo, GP_CLI_COMMAND_PBX_BOXNO::Incoming, GP_CLI_COMMAND_PBX_BOXNO::Outgoing) + .range("PostWorkNo", this->PostWorkNo, 0, 8) + .mustEqual(this->ItemWorkNo, -1, "ItemWorkNo not -1") + .mustEqual(this->ItemStacks, -1, "ItemStacks not -1"); } break; case GP_CLI_COMMAND_PBX_COMMAND::Clear: { pv - .range("BoxNo", BoxNo, GP_CLI_COMMAND_PBX_BOXNO::Incoming, GP_CLI_COMMAND_PBX_BOXNO::Outgoing) - .range("PostWorkNo", PostWorkNo, 0, 8) - .mustEqual(ItemWorkNo, -1, "ItemWorkNo not -1") - .mustEqual(ItemStacks, -1, "ItemStacks not -1"); + .range("BoxNo", this->BoxNo, GP_CLI_COMMAND_PBX_BOXNO::Incoming, GP_CLI_COMMAND_PBX_BOXNO::Outgoing) + .range("PostWorkNo", this->PostWorkNo, 0, 8) + .mustEqual(this->ItemWorkNo, -1, "ItemWorkNo not -1") + .mustEqual(this->ItemStacks, -1, "ItemStacks not -1"); } break; case GP_CLI_COMMAND_PBX_COMMAND::Query: { pv - .mustEqual(BoxNo, GP_CLI_COMMAND_PBX_BOXNO::None, "BoxNo not None") - .mustEqual(PostWorkNo, -1, "PostWorkNo not -1") - .mustEqual(ItemWorkNo, -1, "ItemWorkNo not -1") - .mustEqual(ItemStacks, -1, "ItemStacks not -1"); + .mustEqual(this->BoxNo, GP_CLI_COMMAND_PBX_BOXNO::None, "BoxNo not None") + .mustEqual(this->PostWorkNo, -1, "PostWorkNo not -1") + .mustEqual(this->ItemWorkNo, -1, "ItemWorkNo not -1") + .mustEqual(this->ItemStacks, -1, "ItemStacks not -1"); } break; case GP_CLI_COMMAND_PBX_COMMAND::DeliOpen: { pv - .mustEqual(BoxNo, GP_CLI_COMMAND_PBX_BOXNO::None, "BoxNo not None") - .mustEqual(PostWorkNo, -1, "PostWorkNo not -1") - .mustEqual(ItemWorkNo, -1, "ItemWorkNo not -1") - .mustEqual(ItemStacks, -1, "ItemStacks not -1"); + .mustEqual(this->BoxNo, GP_CLI_COMMAND_PBX_BOXNO::None, "BoxNo not None") + .mustEqual(this->PostWorkNo, -1, "PostWorkNo not -1") + .mustEqual(this->ItemWorkNo, -1, "ItemWorkNo not -1") + .mustEqual(this->ItemStacks, -1, "ItemStacks not -1"); } break; case GP_CLI_COMMAND_PBX_COMMAND::PostOpen: { pv - .mustEqual(BoxNo, GP_CLI_COMMAND_PBX_BOXNO::None, "BoxNo not None") - .mustEqual(PostWorkNo, -1, "PostWorkNo not -1") - .mustEqual(ItemWorkNo, -1, "ItemWorkNo not -1") - .mustEqual(ItemStacks, -1, "ItemStacks not -1"); + .mustEqual(this->BoxNo, GP_CLI_COMMAND_PBX_BOXNO::None, "BoxNo not None") + .mustEqual(this->PostWorkNo, -1, "PostWorkNo not -1") + .mustEqual(this->ItemWorkNo, -1, "ItemWorkNo not -1") + .mustEqual(this->ItemStacks, -1, "ItemStacks not -1"); } break; case GP_CLI_COMMAND_PBX_COMMAND::PostClose: { pv - .mustEqual(BoxNo, GP_CLI_COMMAND_PBX_BOXNO::None, "BoxNo not None") - .mustEqual(PostWorkNo, -1, "PostWorkNo not -1") - .mustEqual(ItemWorkNo, -1, "ItemWorkNo not -1") - .mustEqual(ItemStacks, -1, "ItemStacks not -1"); + .mustEqual(this->BoxNo, GP_CLI_COMMAND_PBX_BOXNO::None, "BoxNo not None") + .mustEqual(this->PostWorkNo, -1, "PostWorkNo not -1") + .mustEqual(this->ItemWorkNo, -1, "ItemWorkNo not -1") + .mustEqual(this->ItemStacks, -1, "ItemStacks not -1"); } break; } @@ -190,71 +188,71 @@ void GP_CLI_COMMAND_PBX::process(MapSession* PSession, CCharEntity* PChar) const return; } - switch (static_cast(Command)) + switch (static_cast(this->Command)) { case GP_CLI_COMMAND_PBX_COMMAND::Work: { - dboxutils::SendOldItems(PChar, static_cast(BoxNo)); + dboxutils::SendOldItems(PChar, static_cast(this->BoxNo)); } break; case GP_CLI_COMMAND_PBX_COMMAND::Set: { - const auto receiverName = db::escapeString(asStringFromUntrustedSource(TargetName, 15)); + const auto receiverName = db::escapeString(asStringFromUntrustedSource(this->TargetName, 15)); - dboxutils::AddItemsToBeSent(PChar, static_cast(BoxNo), PostWorkNo, ItemWorkNo, ItemStacks, receiverName); + dboxutils::AddItemsToBeSent(PChar, static_cast(this->BoxNo), this->PostWorkNo, this->ItemWorkNo, this->ItemStacks, receiverName); } break; case GP_CLI_COMMAND_PBX_COMMAND::Send: { - dboxutils::SendConfirmation(PChar, static_cast(BoxNo), PostWorkNo); + dboxutils::SendConfirmation(PChar, static_cast(this->BoxNo), this->PostWorkNo); } break; case GP_CLI_COMMAND_PBX_COMMAND::Cancel: { - dboxutils::CancelSendingItem(PChar, static_cast(BoxNo), PostWorkNo); + dboxutils::CancelSendingItem(PChar, static_cast(this->BoxNo), this->PostWorkNo); } break; case GP_CLI_COMMAND_PBX_COMMAND::Check: { - dboxutils::SendClientNewItemCount(PChar, static_cast(BoxNo), PostWorkNo); + dboxutils::SendClientNewItemCount(PChar, static_cast(this->BoxNo), this->PostWorkNo); } break; case GP_CLI_COMMAND_PBX_COMMAND::Recv: { // TODO: Don't pass around Scheduler& through PSession - dboxutils::SendNewItems(*PSession->scheduler, PChar, static_cast(BoxNo), PostWorkNo); + dboxutils::SendNewItems(*PSession->scheduler, PChar, static_cast(this->BoxNo), this->PostWorkNo); } break; case GP_CLI_COMMAND_PBX_COMMAND::Confirm: { - dboxutils::RemoveDeliveredItemFromSendingBox(PChar, static_cast(BoxNo), PostWorkNo); + dboxutils::RemoveDeliveredItemFromSendingBox(PChar, static_cast(this->BoxNo), this->PostWorkNo); } break; case GP_CLI_COMMAND_PBX_COMMAND::Accept: { - dboxutils::UpdateDeliveryCellBeforeRemoving(PChar, static_cast(BoxNo), PostWorkNo); + dboxutils::UpdateDeliveryCellBeforeRemoving(PChar, static_cast(this->BoxNo), this->PostWorkNo); } break; case GP_CLI_COMMAND_PBX_COMMAND::Reject: { - dboxutils::ReturnToSender(PChar, static_cast(BoxNo), PostWorkNo); + dboxutils::ReturnToSender(PChar, static_cast(this->BoxNo), this->PostWorkNo); } break; case GP_CLI_COMMAND_PBX_COMMAND::Get: { - dboxutils::TakeItemFromCell(PChar, static_cast(BoxNo), PostWorkNo); + dboxutils::TakeItemFromCell(PChar, static_cast(this->BoxNo), this->PostWorkNo); } break; case GP_CLI_COMMAND_PBX_COMMAND::Clear: { - dboxutils::RemoveItemFromCell(PChar, static_cast(BoxNo), PostWorkNo); + dboxutils::RemoveItemFromCell(PChar, static_cast(this->BoxNo), this->PostWorkNo); } break; case GP_CLI_COMMAND_PBX_COMMAND::Query: { - const auto receiverName = db::escapeString(asStringFromUntrustedSource(TargetName, 15)); + const auto receiverName = db::escapeString(asStringFromUntrustedSource(this->TargetName, 15)); - dboxutils::ConfirmNameBeforeSending(PChar, static_cast(BoxNo), receiverName); + dboxutils::ConfirmNameBeforeSending(PChar, static_cast(this->BoxNo), receiverName); } break; case GP_CLI_COMMAND_PBX_COMMAND::DeliOpen: @@ -269,7 +267,7 @@ void GP_CLI_COMMAND_PBX::process(MapSession* PSession, CCharEntity* PChar) const break; case GP_CLI_COMMAND_PBX_COMMAND::PostClose: { - dboxutils::CloseMailWindow(PChar, static_cast(BoxNo)); + dboxutils::CloseMailWindow(PChar, static_cast(this->BoxNo)); } break; } diff --git a/src/map/packets/c2s/0x04e_auc.cpp b/src/map/packets/c2s/0x04e_auc.cpp index e1d6e9a8db9..6ff58b2db43 100644 --- a/src/map/packets/c2s/0x04e_auc.cpp +++ b/src/map/packets/c2s/0x04e_auc.cpp @@ -27,20 +27,21 @@ auto GP_CLI_COMMAND_AUC::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - auto pv = PacketValidator() - .hasZoneMiscFlag(PChar, MISC_AH) + auto pv = PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }) + .hasZoneMiscFlag(MISC_AH) .mustEqual(jailutils::InPrison(PChar), false, "Character in jail") - .oneOf(Command) - .mustEqual(Result, 0, "Result not 0") - .mustEqual(ResultStatus, 0, "Result status"); + .oneOf(this->Command) + .mustEqual(this->Result, 0, "Result not 0") + .mustEqual(this->ResultStatus, 0, "Result status"); - switch (Command) + switch (this->Command) { case GP_CLI_COMMAND_AUC_COMMAND::AskCommit: { pv - .range("Commission", Param.AskCommit.Commission, 1, 999999999) - .range("ItemStacks", Param.AskCommit.ItemStacks, 0, 1); + .range("Commission", this->Param.AskCommit.Commission, 1, 999999999) + .range("ItemStacks", this->Param.AskCommit.ItemStacks, 0, 1); } break; case GP_CLI_COMMAND_AUC_COMMAND::Info: @@ -50,33 +51,33 @@ auto GP_CLI_COMMAND_AUC::validate(MapSession* PSession, const CCharEntity* PChar break; case GP_CLI_COMMAND_AUC_COMMAND::WorkCheck: { - pv.mustEqual(AucWorkIndex, -1, "AucWorkIndex not -1"); + pv.mustEqual(this->AucWorkIndex, -1, "AucWorkIndex not -1"); } break; case GP_CLI_COMMAND_AUC_COMMAND::LotIn: { pv - .range("AucWorkIndex", AucWorkIndex, 0, 6) - .range("LimitPrice", Param.LotIn.LimitPrice, 1, 999999999) - .range("ItemStacks", Param.LotIn.ItemStacks, 0, 1); + .range("AucWorkIndex", this->AucWorkIndex, 0, 6) + .range("LimitPrice", this->Param.LotIn.LimitPrice, 1, 999999999) + .range("ItemStacks", this->Param.LotIn.ItemStacks, 0, 1); } break; case GP_CLI_COMMAND_AUC_COMMAND::Bid: { pv - .range("AucWorkIndex", AucWorkIndex, 0, 6) - .range("BidPrice", Param.Bid.BidPrice, 1, 999999999) - .range("ItemStacks", Param.Bid.ItemStacks, 0, 1); + .range("AucWorkIndex", this->AucWorkIndex, 0, 6) + .range("BidPrice", this->Param.Bid.BidPrice, 1, 999999999) + .range("ItemStacks", this->Param.Bid.ItemStacks, 0, 1); } break; case GP_CLI_COMMAND_AUC_COMMAND::LotCancel: { - pv.range("AucWorkIndex", AucWorkIndex, 0, 6); + pv.range("AucWorkIndex", this->AucWorkIndex, 0, 6); } break; case GP_CLI_COMMAND_AUC_COMMAND::LotCheck: { - pv.range("AucWorkIndex", AucWorkIndex, 0, 6); + pv.range("AucWorkIndex", this->AucWorkIndex, 0, 6); } break; default: @@ -90,11 +91,11 @@ void GP_CLI_COMMAND_AUC::process(MapSession* PSession, CCharEntity* PChar) const { const auto playerName = PChar->getName(); - switch (Command) + switch (this->Command) { case GP_CLI_COMMAND_AUC_COMMAND::AskCommit: { - auctionutils::SellingItems(PChar, Param.AskCommit); + auctionutils::SellingItems(PChar, this->Param.AskCommit); } break; case GP_CLI_COMMAND_AUC_COMMAND::Info: @@ -110,22 +111,22 @@ void GP_CLI_COMMAND_AUC::process(MapSession* PSession, CCharEntity* PChar) const break; case GP_CLI_COMMAND_AUC_COMMAND::LotIn: { - auctionutils::ProofOfPurchase(PChar, Param.LotIn); + auctionutils::ProofOfPurchase(PChar, this->Param.LotIn); } break; case GP_CLI_COMMAND_AUC_COMMAND::Bid: { - auctionutils::PurchasingItems(PChar, Param.Bid); + auctionutils::PurchasingItems(PChar, this->Param.Bid); } break; case GP_CLI_COMMAND_AUC_COMMAND::LotCancel: { - auctionutils::CancelSale(PChar, AucWorkIndex); + auctionutils::CancelSale(PChar, this->AucWorkIndex); } break; case GP_CLI_COMMAND_AUC_COMMAND::LotCheck: { - auctionutils::UpdateSaleListByPlayer(PChar, AucWorkIndex); + auctionutils::UpdateSaleListByPlayer(PChar, this->AucWorkIndex); } break; default: diff --git a/src/map/packets/c2s/0x050_equip_set.cpp b/src/map/packets/c2s/0x050_equip_set.cpp index cc0965bdc7a..7ba337da63d 100644 --- a/src/map/packets/c2s/0x050_equip_set.cpp +++ b/src/map/packets/c2s/0x050_equip_set.cpp @@ -77,15 +77,15 @@ const auto validContainers = [](const CCharEntity* PChar) -> std::set PacketValidationResult { - return PacketValidator() - .isNormalStatus(PChar) - .oneOf(EquipKind) - .oneOf("Category", static_cast(Category), validContainers(PChar)); + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent, BlockedState::AbnormalStatus }) + .oneOf(this->EquipKind) + .oneOf("Category", static_cast(this->Category), validContainers(PChar)); } void GP_CLI_COMMAND_EQUIP_SET::process(MapSession* PSession, CCharEntity* PChar) const { - charutils::EquipItem(PChar, PropertyItemIndex, EquipKind, Category); + charutils::EquipItem(PChar, this->PropertyItemIndex, this->EquipKind, this->Category); PChar->RequestPersist(CHAR_PERSIST::EQUIP); luautils::CheckForGearSet(PChar); // check for gear set on gear change PChar->UpdateHealth(); diff --git a/src/map/packets/c2s/0x051_equipset_set.cpp b/src/map/packets/c2s/0x051_equipset_set.cpp index d4957463762..c3e0d26a4a2 100644 --- a/src/map/packets/c2s/0x051_equipset_set.cpp +++ b/src/map/packets/c2s/0x051_equipset_set.cpp @@ -79,15 +79,15 @@ auto GP_CLI_COMMAND_EQUIPSET_SET::validate(MapSession* PSession, const CCharEnti { const auto allowedContainers = validContainers(PChar); - auto pv = PacketValidator() - .isNormalStatus(PChar) - .range("Count", Count, 1, 16); + auto pv = PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent, BlockedState::AbnormalStatus }) + .range("Count", this->Count, 1, 16); - if (Count <= 16) + if (this->Count <= 16) { - for (uint8 i = 0; i < Count; i++) + for (uint8 i = 0; i < this->Count; i++) { - const auto& equipment = Equipment[i]; + const auto& equipment = this->Equipment[i]; pv .oneOf(equipment.EquipKind) .oneOf("equipment.Category", static_cast(equipment.Category), allowedContainers); @@ -99,9 +99,9 @@ auto GP_CLI_COMMAND_EQUIPSET_SET::validate(MapSession* PSession, const CCharEnti void GP_CLI_COMMAND_EQUIPSET_SET::process(MapSession* PSession, CCharEntity* PChar) const { - for (uint8 i = 0; i < Count; i++) + for (uint8 i = 0; i < this->Count; i++) { - charutils::EquipItem(PChar, Equipment[i].ItemIndex, Equipment[i].EquipKind, Equipment[i].Category); + charutils::EquipItem(PChar, this->Equipment[i].ItemIndex, this->Equipment[i].EquipKind, this->Equipment[i].Category); } PChar->RequestPersist(CHAR_PERSIST::EQUIP); diff --git a/src/map/packets/c2s/0x052_equipset_check.cpp b/src/map/packets/c2s/0x052_equipset_check.cpp index 9b987b1e7f0..7dd8570f2a0 100644 --- a/src/map/packets/c2s/0x052_equipset_check.cpp +++ b/src/map/packets/c2s/0x052_equipset_check.cpp @@ -27,7 +27,8 @@ auto GP_CLI_COMMAND_EQUIPSET_CHECK::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { // Not implemented. - return PacketValidator(); + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }); } void GP_CLI_COMMAND_EQUIPSET_CHECK::process(MapSession* PSession, CCharEntity* PChar) const diff --git a/src/map/packets/c2s/0x053_lockstyle.cpp b/src/map/packets/c2s/0x053_lockstyle.cpp index 8279fcfbee9..eb37c78c9db 100644 --- a/src/map/packets/c2s/0x053_lockstyle.cpp +++ b/src/map/packets/c2s/0x053_lockstyle.cpp @@ -42,14 +42,14 @@ const auto updateClientAppearance = [](CCharEntity* PChar) auto GP_CLI_COMMAND_LOCKSTYLE::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() - .oneOf(Mode) - .range("Count", Count, 0, 16); + return PacketValidator(PChar) + .oneOf(this->Mode) + .range("Count", this->Count, 0, 16); } void GP_CLI_COMMAND_LOCKSTYLE::process(MapSession* PSession, CCharEntity* PChar) const { - switch (static_cast(Mode)) + switch (static_cast(this->Mode)) { case GP_CLI_COMMAND_LOCKSTYLE_MODE::Disable: { @@ -78,9 +78,9 @@ void GP_CLI_COMMAND_LOCKSTYLE::process(MapSession* PSession, CCharEntity* PChar) charutils::SetStyleLock(PChar, true); // Build new lockstyle - for (int i = 0; i < Count; i++) + for (int i = 0; i < this->Count; i++) { - const auto& item = Items[i]; + const auto& item = this->Items[i]; uint16_t itemId = item.ItemNo; // Skip non-visible items diff --git a/src/map/packets/c2s/0x058_recipe.cpp b/src/map/packets/c2s/0x058_recipe.cpp index f7a5472d4a1..bebe885d259 100644 --- a/src/map/packets/c2s/0x058_recipe.cpp +++ b/src/map/packets/c2s/0x058_recipe.cpp @@ -27,25 +27,25 @@ auto GP_CLI_COMMAND_RECIPE::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() - .range("skill", skill, 0x01, 0x08) // Fishing 0x00 to Digging 0x0A. 0x00, 0x09, and 0x0A are not implemented - .range("level", level, 0, 110) - .range("Mode", Mode, // 1-5 but only 1-3 are implemented + return PacketValidator(PChar) + .range("skill", this->skill, 0x01, 0x08) // Fishing 0x00 to Digging 0x0A. 0x00, 0x09, and 0x0A are not implemented + .range("level", this->level, 0, 110) + .range("Mode", this->Mode, // 1-5 but only 1-3 are implemented GP_CLI_COMMAND_RECIPE_MODE::RequestAvailableRankList, GP_CLI_COMMAND_RECIPE_MODE::RequestRecipeMaterials) .custom([&](PacketValidator& v) { // clang-format off - switch (static_cast(Mode)) + switch (static_cast(this->Mode)) { case GP_CLI_COMMAND_RECIPE_MODE::RequestAvailableRecipeList: - v.range("Param4", Param4, 0, 11) // Skill 0 to 110 + v.range("Param4", this->Param4, 0, 11) // Skill 0 to 110 // The recipe pagenation values (Param1 & Param2) are used to walk the pages of recipes. The initial page will start with values 0 and 16. // Each page beyond that will step through the recipes, incrementing the values by 16. - .multipleOf("Param1", Param1, 16); + .multipleOf("Param1", this->Param1, 16); break; case GP_CLI_COMMAND_RECIPE_MODE::RequestRecipeMaterials: - v.range("Param4", Param4, 0, 11); + v.range("Param4", this->Param4, 0, 11); break; default: break; @@ -60,23 +60,23 @@ void GP_CLI_COMMAND_RECIPE::process(MapSession* PSession, CCharEntity* PChar) co uint16 pagination = 0; uint16 selectedRecipeIndex = 0; - switch (static_cast(Mode)) + switch (static_cast(this->Mode)) { case GP_CLI_COMMAND_RECIPE_MODE::RequestAvailableRankList: - PChar->pushPacket(GP_SERV_COMMAND_RECIPE_TYPE::RecipeDetail1, skill, level, skillRank, selectedRecipeIndex); + PChar->pushPacket(GP_SERV_COMMAND_RECIPE_TYPE::RecipeDetail1, this->skill, this->level, skillRank, selectedRecipeIndex); break; case GP_CLI_COMMAND_RECIPE_MODE::RequestAvailableRecipeList: // For pagination, the client sends the range in increments of 16. (0..0x10, 0x10..0x20, etc) - skillRank = Param4; - pagination = Param1; + skillRank = this->Param4; + pagination = this->Param1; - PChar->pushPacket(GP_SERV_COMMAND_RECIPE_TYPE::RecipeList, skill, level, skillRank, pagination); + PChar->pushPacket(GP_SERV_COMMAND_RECIPE_TYPE::RecipeList, this->skill, this->level, skillRank, pagination); break; case GP_CLI_COMMAND_RECIPE_MODE::RequestRecipeMaterials: - skillRank = Param4; - selectedRecipeIndex = Param3; + skillRank = this->Param4; + selectedRecipeIndex = this->Param3; - PChar->pushPacket(GP_SERV_COMMAND_RECIPE_TYPE::RecipeDetail2, skill, level, skillRank, selectedRecipeIndex); + PChar->pushPacket(GP_SERV_COMMAND_RECIPE_TYPE::RecipeDetail2, this->skill, this->level, skillRank, selectedRecipeIndex); break; default: break; diff --git a/src/map/packets/c2s/0x059_effectend.cpp b/src/map/packets/c2s/0x059_effectend.cpp index f46aaaf8fbc..b1998ebdf33 100644 --- a/src/map/packets/c2s/0x059_effectend.cpp +++ b/src/map/packets/c2s/0x059_effectend.cpp @@ -24,7 +24,8 @@ auto GP_CLI_COMMAND_EFFECTEND::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { // Packet explicitly ignored. - return PacketValidator(); + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }); } void GP_CLI_COMMAND_EFFECTEND::process(MapSession* PSession, CCharEntity* PChar) const diff --git a/src/map/packets/c2s/0x05a_reqconquest.cpp b/src/map/packets/c2s/0x05a_reqconquest.cpp index b0ec6109f55..a754bbae228 100644 --- a/src/map/packets/c2s/0x05a_reqconquest.cpp +++ b/src/map/packets/c2s/0x05a_reqconquest.cpp @@ -30,7 +30,7 @@ auto GP_CLI_COMMAND_REQCONQUEST::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { // No parameter to validate for this packet. - return PacketValidator(); + return PacketValidator(PChar); } void GP_CLI_COMMAND_REQCONQUEST::process(MapSession* PSession, CCharEntity* PChar) const diff --git a/src/map/packets/c2s/0x05b_eventend.cpp b/src/map/packets/c2s/0x05b_eventend.cpp index dcf3b86e9ce..8b3d0debf98 100644 --- a/src/map/packets/c2s/0x05b_eventend.cpp +++ b/src/map/packets/c2s/0x05b_eventend.cpp @@ -28,22 +28,22 @@ auto GP_CLI_COMMAND_EVENTEND::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() - .oneOf(Mode) - .isInEvent(PChar, EventPara); + return PacketValidator(PChar) + .oneOf(this->Mode) + .isInEvent(this->EventPara); } void GP_CLI_COMMAND_EVENTEND::process(MapSession* PSession, CCharEntity* PChar) const { - auto result = EndPara; - const auto eventId = EventPara; + auto result = this->EndPara; + const auto eventId = this->EventPara; if (PChar->currentEvent->option != 0) { result = PChar->currentEvent->option; } - switch (static_cast(Mode)) + switch (static_cast(this->Mode)) { case GP_CLI_COMMAND_EVENTEND_MODE::UpdatePending: { diff --git a/src/map/packets/c2s/0x05c_eventendxzy.cpp b/src/map/packets/c2s/0x05c_eventendxzy.cpp index 1a2ec33e00f..484003ed157 100644 --- a/src/map/packets/c2s/0x05c_eventendxzy.cpp +++ b/src/map/packets/c2s/0x05c_eventendxzy.cpp @@ -32,15 +32,15 @@ auto GP_CLI_COMMAND_EVENTENDXZY::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() - .mustEqual(Mode, 1, "Mode not 1") - .isInEvent(PChar, EventPara); + return PacketValidator(PChar) + .mustEqual(this->Mode, 1, "Mode not 1") + .isInEvent(this->EventPara); } void GP_CLI_COMMAND_EVENTENDXZY::process(MapSession* PSession, CCharEntity* PChar) const { - const auto result = EndPara; - const auto eventId = EventPara; + const auto result = this->EndPara; + const auto eventId = this->EventPara; bool updatePosition = false; @@ -58,11 +58,11 @@ void GP_CLI_COMMAND_EVENTENDXZY::process(MapSession* PSession, CCharEntity* PCha if (updatePosition) { newPos = { - x, - y, - z, + this->x, + this->y, + this->z, 0, - static_cast(dir), + static_cast(this->dir), }; PChar->pushPacket(PChar, newPos, POSMODE::EVENT); diff --git a/src/map/packets/c2s/0x05d_motion.cpp b/src/map/packets/c2s/0x05d_motion.cpp index 709b825a69f..fa438f013f1 100644 --- a/src/map/packets/c2s/0x05d_motion.cpp +++ b/src/map/packets/c2s/0x05d_motion.cpp @@ -42,9 +42,10 @@ const std::set validBells = { auto GP_CLI_COMMAND_MOTION::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() - .oneOf(Mode) - .range("Number", Number, Emote::Point, Emote::Aim); + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }) + .oneOf(this->Mode) + .range("Number", this->Number, Emote::Point, Emote::Aim); } void GP_CLI_COMMAND_MOTION::process(MapSession* PSession, CCharEntity* PChar) const @@ -56,7 +57,7 @@ void GP_CLI_COMMAND_MOTION::process(MapSession* PSession, CCharEntity* PChar) co } // Attempting to use bell emote without a bell. - if (static_cast(Number) == Emote::Bell) + if (static_cast(this->Number) == Emote::Bell) { // This is the actual observed behavior. Even with a different weapon type equipped, // having a bell in the lockstyle is sufficient. On the other hand, if any other @@ -78,19 +79,19 @@ void GP_CLI_COMMAND_MOTION::process(MapSession* PSession, CCharEntity* PChar) co return; } - if (Param < 0x06 || Param > 0x1e) + if (this->Param < 0x06 || this->Param > 0x1e) { // Invalid note. return; } } // Attempting to use locked job emote. - else if (static_cast(Number) == Emote::Job && Param && !(PChar->jobs.unlocked & (1 << (Param - 0x1E)))) + else if (static_cast(this->Number) == Emote::Job && this->Param && !(PChar->jobs.unlocked & (1 << (this->Param - 0x1E)))) { return; } - PChar->loc.zone->PushPacket(PChar, CHAR_INRANGE_SELF, std::make_unique(PChar, UniqueNo, ActIndex, static_cast(Number), static_cast(Mode), Param)); + PChar->loc.zone->PushPacket(PChar, CHAR_INRANGE_SELF, std::make_unique(PChar, this->UniqueNo, this->ActIndex, static_cast(this->Number), static_cast(this->Mode), this->Param)); - luautils::OnPlayerEmote(PChar, static_cast(Number)); + luautils::OnPlayerEmote(PChar, static_cast(this->Number)); } diff --git a/src/map/packets/c2s/0x05e_maprect.cpp b/src/map/packets/c2s/0x05e_maprect.cpp index 7ecd84b1436..527e3a1d921 100644 --- a/src/map/packets/c2s/0x05e_maprect.cpp +++ b/src/map/packets/c2s/0x05e_maprect.cpp @@ -53,7 +53,8 @@ const auto denyZone = [](CCharEntity* PChar) auto GP_CLI_COMMAND_MAPRECT::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }) .oneOf(this->MyRoomExitBit) .oneOf(this->MyRoomExitMode); } diff --git a/src/map/packets/c2s/0x060_passwards.cpp b/src/map/packets/c2s/0x060_passwards.cpp index bbcffadaea5..2f2f85d71ca 100644 --- a/src/map/packets/c2s/0x060_passwards.cpp +++ b/src/map/packets/c2s/0x060_passwards.cpp @@ -28,14 +28,14 @@ auto GP_CLI_COMMAND_PASSWARDS::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() - .isInEvent(PChar); + return PacketValidator(PChar) + .isInEvent(); } void GP_CLI_COMMAND_PASSWARDS::process(MapSession* PSession, CCharEntity* PChar) const { // !cs 199 in zone 245 - const auto updateString = asStringFromUntrustedSource(String); + const auto updateString = asStringFromUntrustedSource(this->String); luautils::OnEventUpdate(PChar, updateString); PChar->pushPacket(PChar, GP_SERV_COMMAND_EVENTUCOFF_MODE::EventRecvPending); diff --git a/src/map/packets/c2s/0x061_clistatus.cpp b/src/map/packets/c2s/0x061_clistatus.cpp index b79622692f9..9601a310668 100644 --- a/src/map/packets/c2s/0x061_clistatus.cpp +++ b/src/map/packets/c2s/0x061_clistatus.cpp @@ -27,8 +27,8 @@ auto GP_CLI_COMMAND_CLISTATUS::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() - .range("unknown00", unknown00, 0, 1); + return PacketValidator(PChar) + .range("unknown00", this->unknown00, 0, 1); } void GP_CLI_COMMAND_CLISTATUS::process(MapSession* PSession, CCharEntity* PChar) const diff --git a/src/map/packets/c2s/0x061_clistatus.h b/src/map/packets/c2s/0x061_clistatus.h index db8a7701e2a..9eb5dc9e377 100644 --- a/src/map/packets/c2s/0x061_clistatus.h +++ b/src/map/packets/c2s/0x061_clistatus.h @@ -26,6 +26,7 @@ // https://github.com/atom0s/XiPackets/tree/main/world/client/0x0061 // This packet is sent by the client when requesting the current clients local player information. GP_CLI_PACKET(GP_CLI_COMMAND_CLISTATUS, - uint8_t unknown00; // PS2: (New; did not exist.) - uint8_t padding00; // PS2: (New; did not exist.) + uint8_t unknown00; // PS2: (New; did not exist.) + uint8_t padding00; // PS2: (New; did not exist.) + uint16_t padding01; // PS2: (New; did not exist.) ); diff --git a/src/map/packets/c2s/0x063_dig.cpp b/src/map/packets/c2s/0x063_dig.cpp index 9c8d8dce6de..de15d67da7d 100644 --- a/src/map/packets/c2s/0x063_dig.cpp +++ b/src/map/packets/c2s/0x063_dig.cpp @@ -24,7 +24,8 @@ auto GP_CLI_COMMAND_DIG::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { // Packet explicitly ignored. - return PacketValidator(); + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }); } void GP_CLI_COMMAND_DIG::process(MapSession* PSession, CCharEntity* PChar) const diff --git a/src/map/packets/c2s/0x064_scenarioitem.cpp b/src/map/packets/c2s/0x064_scenarioitem.cpp index 3971abedce1..b2b79d5d0f6 100644 --- a/src/map/packets/c2s/0x064_scenarioitem.cpp +++ b/src/map/packets/c2s/0x064_scenarioitem.cpp @@ -26,21 +26,22 @@ auto GP_CLI_COMMAND_SCENARIOITEM::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() - .mustEqual(UniqueNo, PChar->id, "Character ID mismatch") - .mustEqual(ActIndex, PChar->targid, "Character targid mismatch") - .range("TableIndex", TableIndex, 0, PChar->keys.tables.size()); + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }) + .mustEqual(this->UniqueNo, PChar->id, "Character ID mismatch") + .mustEqual(this->ActIndex, PChar->targid, "Character targid mismatch") + .range("TableIndex", this->TableIndex, 0, PChar->keys.tables.size()); } void GP_CLI_COMMAND_SCENARIOITEM::process(MapSession* PSession, CCharEntity* PChar) const { for (int i = 0; i < 16; i++) { - const uint32_t flags = LookItemFlag[i]; + const uint32_t flags = this->LookItemFlag[i]; for (int bit = 0; bit < 32; bit++) { - const auto keyItemId = (TableIndex * 512) + (i * 32) + bit; + const auto keyItemId = (this->TableIndex * 512) + (i * 32) + bit; if ((flags >> bit) & 1) { diff --git a/src/map/packets/c2s/0x06e_group_solicit_req.cpp b/src/map/packets/c2s/0x06e_group_solicit_req.cpp index c1423ddb055..9e66e2438c0 100644 --- a/src/map/packets/c2s/0x06e_group_solicit_req.cpp +++ b/src/map/packets/c2s/0x06e_group_solicit_req.cpp @@ -35,10 +35,11 @@ auto GP_CLI_COMMAND_GROUP_SOLICIT_REQ::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - auto pv = PacketValidator() - .oneOf(Kind) - .mustNotEqual(PChar->id, UniqueNo, "Cannot invite yourself") - .mustEqual(blacklistutils::IsBlacklisted(UniqueNo, PChar->id), false, "Character has inviter blacklisted"); + auto pv = PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }) + .oneOf(this->Kind) + .mustNotEqual(PChar->id, this->UniqueNo, "Cannot invite yourself") + .mustEqual(blacklistutils::IsBlacklisted(this->UniqueNo, PChar->id), false, "Character has inviter blacklisted"); return pv; } @@ -47,8 +48,8 @@ void GP_CLI_COMMAND_GROUP_SOLICIT_REQ::process(MapSession* PSession, CCharEntity { auto* PInviter = PChar; - const uint32 inviteeCharId = UniqueNo; - const uint16 inviteeTargId = ActIndex; + const uint32 inviteeCharId = this->UniqueNo; + const uint16 inviteeTargId = this->ActIndex; if (jailutils::InPrison(PInviter)) { @@ -57,7 +58,7 @@ void GP_CLI_COMMAND_GROUP_SOLICIT_REQ::process(MapSession* PSession, CCharEntity return; } - switch (Kind) + switch (this->Kind) { case PartyKind::Party: { diff --git a/src/map/packets/c2s/0x06f_group_leave.cpp b/src/map/packets/c2s/0x06f_group_leave.cpp index 2473e00e86b..88b697c9824 100644 --- a/src/map/packets/c2s/0x06f_group_leave.cpp +++ b/src/map/packets/c2s/0x06f_group_leave.cpp @@ -26,14 +26,15 @@ auto GP_CLI_COMMAND_GROUP_LEAVE::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() - .oneOf(Kind) + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }) + .oneOf(this->Kind) .mustNotEqual(PChar->PParty, nullptr, "Character is not in a party"); } void GP_CLI_COMMAND_GROUP_LEAVE::process(MapSession* PSession, CCharEntity* PChar) const { - switch (Kind) + switch (this->Kind) { case PartyKind::Party: { diff --git a/src/map/packets/c2s/0x070_group_breakup.cpp b/src/map/packets/c2s/0x070_group_breakup.cpp index 54e8272e1b6..54dbee83047 100644 --- a/src/map/packets/c2s/0x070_group_breakup.cpp +++ b/src/map/packets/c2s/0x070_group_breakup.cpp @@ -28,11 +28,12 @@ auto GP_CLI_COMMAND_GROUP_BREAKUP::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - auto pv = PacketValidator() - .oneOf(Kind) - .isPartyLeader(PChar); + auto pv = PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }) + .oneOf(this->Kind) + .isPartyLeader(); - switch (Kind) + switch (this->Kind) { case PartyKind::Party: { @@ -41,7 +42,7 @@ auto GP_CLI_COMMAND_GROUP_BREAKUP::validate(MapSession* PSession, const CCharEnt break; case PartyKind::Alliance: { - pv.isAllianceLeader(PChar); + pv.isAllianceLeader(); } break; } @@ -51,7 +52,7 @@ auto GP_CLI_COMMAND_GROUP_BREAKUP::validate(MapSession* PSession, const CCharEnt void GP_CLI_COMMAND_GROUP_BREAKUP::process(MapSession* PSession, CCharEntity* PChar) const { - switch (Kind) + switch (this->Kind) { case PartyKind::Party: { diff --git a/src/map/packets/c2s/0x071_group_strike.cpp b/src/map/packets/c2s/0x071_group_strike.cpp index d8437bdf5aa..8c3ac9bd7d4 100644 --- a/src/map/packets/c2s/0x071_group_strike.cpp +++ b/src/map/packets/c2s/0x071_group_strike.cpp @@ -33,27 +33,28 @@ auto GP_CLI_COMMAND_GROUP_STRIKE::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - auto pv = PacketValidator() - .oneOf(Kind) - .mustEqual(ActIndex, 0, "ActIndex not 0") - .mustEqual(UniqueNo, 0, "UniqueNo not 0"); + auto pv = PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }) + .oneOf(this->Kind) + .mustEqual(this->ActIndex, 0, "ActIndex not 0") + .mustEqual(this->UniqueNo, 0, "UniqueNo not 0"); - switch (static_cast(Kind)) + switch (static_cast(this->Kind)) { case GP_CLI_COMMAND_GROUP_STRIKE_KIND::Party: { - pv.isPartyLeader(PChar); + pv.isPartyLeader(); } break; case GP_CLI_COMMAND_GROUP_STRIKE_KIND::Linkshell1: case GP_CLI_COMMAND_GROUP_STRIKE_KIND::Linkshell2: { - pv.hasLinkshellRank(PChar, Kind, LSTYPE_PEARLSACK); + pv.hasLinkshellRank(this->Kind, LSTYPE_PEARLSACK); } break; case GP_CLI_COMMAND_GROUP_STRIKE_KIND::Alliance: { - pv.isAllianceLeader(PChar); + pv.isAllianceLeader(); } break; } @@ -63,9 +64,9 @@ auto GP_CLI_COMMAND_GROUP_STRIKE::validate(MapSession* PSession, const CCharEnti void GP_CLI_COMMAND_GROUP_STRIKE::process(MapSession* PSession, CCharEntity* PChar) const { - const auto victimName = db::escapeString(asStringFromUntrustedSource(sName, sizeof(sName))); + const auto victimName = db::escapeString(asStringFromUntrustedSource(this->sName, sizeof(this->sName))); - switch (static_cast(Kind)) + switch (static_cast(this->Kind)) { case GP_CLI_COMMAND_GROUP_STRIKE_KIND::Party: { diff --git a/src/map/packets/c2s/0x074_group_solicit_res.cpp b/src/map/packets/c2s/0x074_group_solicit_res.cpp index 9c3a79ce0d6..6c6f80ce17d 100644 --- a/src/map/packets/c2s/0x074_group_solicit_res.cpp +++ b/src/map/packets/c2s/0x074_group_solicit_res.cpp @@ -32,8 +32,9 @@ auto GP_CLI_COMMAND_GROUP_SOLICIT_RES::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() - .oneOf(Res); + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }) + .oneOf(this->Res); } void GP_CLI_COMMAND_GROUP_SOLICIT_RES::process(MapSession* PSession, CCharEntity* PChar) const @@ -41,7 +42,7 @@ void GP_CLI_COMMAND_GROUP_SOLICIT_RES::process(MapSession* PSession, CCharEntity if (CCharEntity* PInviter = zoneutils::GetCharFromWorld(PChar->InvitePending.id, PChar->InvitePending.targid); PInviter != nullptr) { // This switch statement only occurs when both the invitee and inviter are on the same process - switch (static_cast(Res)) + switch (static_cast(this->Res)) { case GP_CLI_COMMAND_GROUP_SOLICIT_RES_RES::Decline: { @@ -136,7 +137,7 @@ void GP_CLI_COMMAND_GROUP_SOLICIT_RES::process(MapSession* PSession, CCharEntity .inviteeTargId = PChar->targid, .inviterId = PChar->InvitePending.id, .inviterTargId = PChar->InvitePending.targid, - .inviteAnswer = Res, + .inviteAnswer = this->Res, }); } diff --git a/src/map/packets/c2s/0x074_group_solicit_res.h b/src/map/packets/c2s/0x074_group_solicit_res.h index 9b2480a7a85..9ee2d2ce8a1 100644 --- a/src/map/packets/c2s/0x074_group_solicit_res.h +++ b/src/map/packets/c2s/0x074_group_solicit_res.h @@ -32,6 +32,6 @@ enum class GP_CLI_COMMAND_GROUP_SOLICIT_RES_RES : uint8_t // https://github.com/atom0s/XiPackets/tree/main/world/client/0x0074 // This packet is sent by the client when responding to a party or alliance invite. GP_CLI_PACKET(GP_CLI_COMMAND_GROUP_SOLICIT_RES, - uint8_t Res; // PS2: Res - uint8_t padding00; // PS2: (New; did not exist.) + uint8_t Res; // PS2: Res + uint8_t padding00[3]; // Padding; unused. ); diff --git a/src/map/packets/c2s/0x076_group_list_req.cpp b/src/map/packets/c2s/0x076_group_list_req.cpp index cb2be9e2c91..f5c61694285 100644 --- a/src/map/packets/c2s/0x076_group_list_req.cpp +++ b/src/map/packets/c2s/0x076_group_list_req.cpp @@ -26,8 +26,9 @@ auto GP_CLI_COMMAND_GROUP_LIST_REQ::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() - .mustEqual(Kind, 0, "Kind not 0"); + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }) + .mustEqual(this->Kind, 0, "Kind not 0"); } void GP_CLI_COMMAND_GROUP_LIST_REQ::process(MapSession* PSession, CCharEntity* PChar) const diff --git a/src/map/packets/c2s/0x077_group_change2.cpp b/src/map/packets/c2s/0x077_group_change2.cpp index f9d8288ce8d..7489a18bc5b 100644 --- a/src/map/packets/c2s/0x077_group_change2.cpp +++ b/src/map/packets/c2s/0x077_group_change2.cpp @@ -40,11 +40,12 @@ const std::set validLinkshellOperations = { auto GP_CLI_COMMAND_GROUP_CHANGE2::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - auto pv = PacketValidator() - .oneOf(Kind) - .oneOf(ChangeKind); + auto pv = PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }) + .oneOf(this->Kind) + .oneOf(this->ChangeKind); - switch (static_cast(ChangeKind)) + switch (static_cast(this->ChangeKind)) { case GP_CLI_COMMAND_GROUP_CHANGE2_CHANGEKIND::SetPartyLeader: case GP_CLI_COMMAND_GROUP_CHANGE2_CHANGEKIND::SetQuartermaster: @@ -53,23 +54,23 @@ auto GP_CLI_COMMAND_GROUP_CHANGE2::validate(MapSession* PSession, const CCharEnt case GP_CLI_COMMAND_GROUP_CHANGE2_CHANGEKIND::DisableLevelSync: { pv - .mustEqual(Kind, GP_CLI_COMMAND_GROUP_CHANGE2_KIND::Party, "Invalid operation") - .isPartyLeader(PChar); + .mustEqual(this->Kind, GP_CLI_COMMAND_GROUP_CHANGE2_KIND::Party, "Invalid operation") + .isPartyLeader(); } break; case GP_CLI_COMMAND_GROUP_CHANGE2_CHANGEKIND::PearlToSack: case GP_CLI_COMMAND_GROUP_CHANGE2_CHANGEKIND::SackToPearl: { pv - .oneOf("Kind", static_cast(Kind), validLinkshellOperations) - .hasLinkshellRank(PChar, Kind, LSTYPE_LINKSHELL); + .oneOf("Kind", static_cast(this->Kind), validLinkshellOperations) + .hasLinkshellRank(this->Kind, LSTYPE_LINKSHELL); } break; case GP_CLI_COMMAND_GROUP_CHANGE2_CHANGEKIND::SetAllianceLeader: { pv - .mustEqual(Kind, GP_CLI_COMMAND_GROUP_CHANGE2_KIND::Alliance, "Invalid operation") - .isAllianceLeader(PChar); + .mustEqual(this->Kind, GP_CLI_COMMAND_GROUP_CHANGE2_KIND::Alliance, "Invalid operation") + .isAllianceLeader(); } break; } @@ -79,13 +80,13 @@ auto GP_CLI_COMMAND_GROUP_CHANGE2::validate(MapSession* PSession, const CCharEnt void GP_CLI_COMMAND_GROUP_CHANGE2::process(MapSession* PSession, CCharEntity* PChar) const { - const auto memberName = db::escapeString(asStringFromUntrustedSource(sName, sizeof(sName))); - switch (static_cast(Kind)) + const auto memberName = db::escapeString(asStringFromUntrustedSource(this->sName, sizeof(this->sName))); + switch (static_cast(this->Kind)) { case GP_CLI_COMMAND_GROUP_CHANGE2_KIND::Party: { - ShowDebug(fmt::format("(Party) Altering permissions of {} to {}", memberName, ChangeKind)); - PChar->PParty->AssignPartyRole(memberName, static_cast(ChangeKind)); + ShowDebug(fmt::format("(Party) Altering permissions of {} to {}", memberName, this->ChangeKind)); + PChar->PParty->AssignPartyRole(memberName, static_cast(this->ChangeKind)); } break; case GP_CLI_COMMAND_GROUP_CHANGE2_KIND::Linkshell1: @@ -93,7 +94,7 @@ void GP_CLI_COMMAND_GROUP_CHANGE2::process(MapSession* PSession, CCharEntity* PC { CItemLinkshell* PItemLinkshell = nullptr; const CLinkshell* PLinkshell = nullptr; - switch (Kind) + switch (this->Kind) { case 1: { @@ -119,7 +120,7 @@ void GP_CLI_COMMAND_GROUP_CHANGE2::process(MapSession* PSession, CCharEntity* PC .requesterRank = PItemLinkshell->GetLSType(), .memberName = memberName, .linkshellId = PLinkshell->getID(), - .newRank = ChangeKind, + .newRank = this->ChangeKind, }); } } diff --git a/src/map/packets/c2s/0x078_group_checkid.cpp b/src/map/packets/c2s/0x078_group_checkid.cpp index 7d616580d13..92f4d054f56 100644 --- a/src/map/packets/c2s/0x078_group_checkid.cpp +++ b/src/map/packets/c2s/0x078_group_checkid.cpp @@ -27,7 +27,8 @@ auto GP_CLI_COMMAND_GROUP_CHECKID::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { // No parameter to validate. - return PacketValidator(); + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }); } void GP_CLI_COMMAND_GROUP_CHECKID::process(MapSession* PSession, CCharEntity* PChar) const diff --git a/src/map/packets/c2s/0x083_shop_buy.cpp b/src/map/packets/c2s/0x083_shop_buy.cpp index 0e91c510594..5791b431442 100644 --- a/src/map/packets/c2s/0x083_shop_buy.cpp +++ b/src/map/packets/c2s/0x083_shop_buy.cpp @@ -30,7 +30,8 @@ auto GP_CLI_COMMAND_SHOP_BUY::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }) .mustEqual(this->PropertyItemIndex, 0, "PropertyItemIndex not 0"); } diff --git a/src/map/packets/c2s/0x084_shop_sell_req.cpp b/src/map/packets/c2s/0x084_shop_sell_req.cpp index 9b7f262176d..812992fa944 100644 --- a/src/map/packets/c2s/0x084_shop_sell_req.cpp +++ b/src/map/packets/c2s/0x084_shop_sell_req.cpp @@ -27,8 +27,8 @@ auto GP_CLI_COMMAND_SHOP_SELL_REQ::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() - .isNotCrafting(PChar); + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent, BlockedState::Crafting }); } void GP_CLI_COMMAND_SHOP_SELL_REQ::process(MapSession* PSession, CCharEntity* PChar) const diff --git a/src/map/packets/c2s/0x085_shop_sell_set.cpp b/src/map/packets/c2s/0x085_shop_sell_set.cpp index b818821435a..e7474ff74d1 100644 --- a/src/map/packets/c2s/0x085_shop_sell_set.cpp +++ b/src/map/packets/c2s/0x085_shop_sell_set.cpp @@ -24,6 +24,7 @@ #include "common/settings.h" #include "entities/charentity.h" #include "enums/msg_std.h" +#include "enums/packet_c2s.h" #include "packets/s2c/0x009_message.h" #include "packets/s2c/0x01d_item_same.h" #include "trade_container.h" @@ -54,8 +55,9 @@ const auto auditSale = [](Scheduler& scheduler, CCharEntity* PChar, uint32_t ite auto GP_CLI_COMMAND_SHOP_SELL_SET::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() - .isNotCrafting(PChar) + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent, BlockedState::Crafting }) + .requiresPriorPacket(PacketC2S::GP_CLI_COMMAND_SHOP_SELL_REQ) .mustEqual(this->SellFlag, 1, "SellFlag not 1"); } diff --git a/src/map/packets/c2s/0x085_shop_sell_set.h b/src/map/packets/c2s/0x085_shop_sell_set.h index b64f93ff73b..b9424449a4a 100644 --- a/src/map/packets/c2s/0x085_shop_sell_set.h +++ b/src/map/packets/c2s/0x085_shop_sell_set.h @@ -26,5 +26,6 @@ // https://github.com/atom0s/XiPackets/tree/main/world/client/0x0085 // This packet is sent by the client when confirming the sale of an item to a shop. GP_CLI_PACKET(GP_CLI_COMMAND_SHOP_SELL_SET, - uint16_t SellFlag; // PS2: SellFlag + uint16_t SellFlag; // PS2: SellFlag + uint16_t padding00; // PS2: (New; did not exist.) ); diff --git a/src/map/packets/c2s/0x096_combine_ask.cpp b/src/map/packets/c2s/0x096_combine_ask.cpp index 67a325bab7f..a92c0294f18 100644 --- a/src/map/packets/c2s/0x096_combine_ask.cpp +++ b/src/map/packets/c2s/0x096_combine_ask.cpp @@ -66,13 +66,10 @@ const std::set validCrystals = { auto GP_CLI_COMMAND_COMBINE_ASK::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent, BlockedState::AbnormalStatus, BlockedState::Crafting, BlockedState::PreventAction, BlockedState::Monstrosity }) .oneOf("Crystal", static_cast(this->Crystal), validCrystals) - .range("Items", this->Items, 1, 8) - .isNotMonstrosity(PChar) - .isNotPreventedAction(PChar) - .isNormalStatus(PChar) - .isNotCrafting(PChar); + .range("Items", this->Items, 1, 8); } void GP_CLI_COMMAND_COMBINE_ASK::process(MapSession* PSession, CCharEntity* PChar) const diff --git a/src/map/packets/c2s/0x096_combine_ask.h b/src/map/packets/c2s/0x096_combine_ask.h index 9bd15186618..f6b41b9bd43 100644 --- a/src/map/packets/c2s/0x096_combine_ask.h +++ b/src/map/packets/c2s/0x096_combine_ask.h @@ -33,4 +33,5 @@ GP_CLI_PACKET(GP_CLI_COMMAND_COMBINE_ASK, uint8_t Items; // PS2: Items uint16_t ItemNo[8]; // PS2: ItemNo uint8_t TableNo[8]; // PS2: TableNo + uint16_t padding01; // PS2: (New; did not exist.) ); diff --git a/src/map/packets/c2s/0x09b_chocobo_race_req.cpp b/src/map/packets/c2s/0x09b_chocobo_race_req.cpp index 0a8dbafa3eb..1d36996d019 100644 --- a/src/map/packets/c2s/0x09b_chocobo_race_req.cpp +++ b/src/map/packets/c2s/0x09b_chocobo_race_req.cpp @@ -26,18 +26,19 @@ auto GP_CLI_COMMAND_CHOCOBO_RACE_REQ::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() - .oneOf(Param) - .oneOf(Kind); + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }) + .oneOf(this->Param) + .oneOf(this->Kind); } void GP_CLI_COMMAND_CHOCOBO_RACE_REQ::process(MapSession* PSession, CCharEntity* PChar) const { - ShowDebugFmt("GP_CLI_COMMAND_CHOCOBO_RACE_REQ: Not fully implemented. Param: {}, Kind: {}", Param, Kind); + ShowDebugFmt("GP_CLI_COMMAND_CHOCOBO_RACE_REQ: Not fully implemented. Param: {}, Kind: {}", this->Param, this->Kind); // NOTE: Can trigger with !cs 335 from Chocobo Circuit - switch (static_cast(Kind)) + switch (static_cast(this->Kind)) { case GP_CLI_COMMAND_CHOCOBO_RACE_REQ_KIND::Toteboard: { diff --git a/src/map/packets/c2s/0x0a0_switch_proposal.cpp b/src/map/packets/c2s/0x0a0_switch_proposal.cpp index b547420aba5..4bedf41ee5d 100644 --- a/src/map/packets/c2s/0x0a0_switch_proposal.cpp +++ b/src/map/packets/c2s/0x0a0_switch_proposal.cpp @@ -26,12 +26,13 @@ auto GP_CLI_COMMAND_SWITCH_PROPOSAL::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { // Not implemented. - return PacketValidator() - .oneOf(Kind); + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }) + .oneOf(this->Kind); } void GP_CLI_COMMAND_SWITCH_PROPOSAL::process(MapSession* PSession, CCharEntity* PChar) const { - auto str = asStringFromUntrustedSource(Str, sizeof(Str)); - ShowDebugFmt("GP_CLI_COMMAND_SWITCH_PROPOSAL: Not implemented. Kind: {}, Str: {}", Kind, str); + auto str = asStringFromUntrustedSource(this->Str, sizeof(this->Str)); + ShowDebugFmt("GP_CLI_COMMAND_SWITCH_PROPOSAL: Not implemented. Kind: {}, Str: {}", this->Kind, str); } diff --git a/src/map/packets/c2s/0x0a0_switch_proposal.h b/src/map/packets/c2s/0x0a0_switch_proposal.h index a2911329b4e..f793a8e95be 100644 --- a/src/map/packets/c2s/0x0a0_switch_proposal.h +++ b/src/map/packets/c2s/0x0a0_switch_proposal.h @@ -34,7 +34,7 @@ enum class GP_CLI_COMMAND_SWITCH_PROPOSAL_KIND : uint8_t // https://github.com/atom0s/XiPackets/tree/main/world/client/0x00A0 // This packet is sent by the client when making a proposal. (via /nominate or /propose) -GP_CLI_PACKET(GP_CLI_COMMAND_SWITCH_PROPOSAL, - uint8_t Kind; // PS2: Kind - uint8_t Str[128]; // PS2: Str +GP_CLI_PACKET_VLA(GP_CLI_COMMAND_SWITCH_PROPOSAL, Str, + uint8_t Kind; // PS2: Kind + uint8_t Str[128]; // PS2: Str ); diff --git a/src/map/packets/c2s/0x0a1_switch_vote.cpp b/src/map/packets/c2s/0x0a1_switch_vote.cpp index 84bc85c10c6..84c1a849f62 100644 --- a/src/map/packets/c2s/0x0a1_switch_vote.cpp +++ b/src/map/packets/c2s/0x0a1_switch_vote.cpp @@ -26,11 +26,12 @@ auto GP_CLI_COMMAND_SWITCH_VOTE::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { // Not implemented. - return PacketValidator(); + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }); } void GP_CLI_COMMAND_SWITCH_VOTE::process(MapSession* PSession, CCharEntity* PChar) const { - auto name = asStringFromUntrustedSource(Name, sizeof(Name)); - ShowDebugFmt("GP_CLI_COMMAND_SWITCH_VOTE: Not implemented. Index: {}, Name: {}", Index, name); + auto name = asStringFromUntrustedSource(this->Name, sizeof(this->Name)); + ShowDebugFmt("GP_CLI_COMMAND_SWITCH_VOTE: Not implemented. Index: {}, Name: {}", this->Index, name); } diff --git a/src/map/packets/c2s/0x0a2_dice.cpp b/src/map/packets/c2s/0x0a2_dice.cpp index a50e7531b74..c3c18e1a71f 100644 --- a/src/map/packets/c2s/0x0a2_dice.cpp +++ b/src/map/packets/c2s/0x0a2_dice.cpp @@ -28,7 +28,8 @@ auto GP_CLI_COMMAND_DICE::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { // No parameter to validate for this packet. - return PacketValidator(); + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }); } void GP_CLI_COMMAND_DICE::process(MapSession* PSession, CCharEntity* PChar) const diff --git a/src/map/packets/c2s/0x0aa_guild_buy.cpp b/src/map/packets/c2s/0x0aa_guild_buy.cpp index 6772cb870f5..e8e4b9a7f8b 100644 --- a/src/map/packets/c2s/0x0aa_guild_buy.cpp +++ b/src/map/packets/c2s/0x0aa_guild_buy.cpp @@ -31,28 +31,29 @@ auto GP_CLI_COMMAND_GUILD_BUY::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }) .mustNotEqual(PChar->PGuildShop, nullptr, "Character does not have a guild shop") - .range("ItemNum", ItemNum, 1, 99) - .mustEqual(PropertyItemIndex, 0, "PropertyItemIndex not 0"); + .range("ItemNum", this->ItemNum, 1, 99) + .mustEqual(this->PropertyItemIndex, 0, "PropertyItemIndex not 0"); } void GP_CLI_COMMAND_GUILD_BUY::process(MapSession* PSession, CCharEntity* PChar) const { - uint8 quantity = ItemNum; + uint8 quantity = this->ItemNum; - const CItem* PItem = itemutils::GetItemPointer(ItemNo); + const CItem* PItem = itemutils::GetItemPointer(this->ItemNo); if (!PItem) { ShowWarning("User '%s' attempting to buy an invalid item from guild vendor!", PChar->getName()); return; } - const uint8 shopSlotId = PChar->PGuildShop->SearchItem(ItemNo); + const uint8 shopSlotId = PChar->PGuildShop->SearchItem(this->ItemNo); if (shopSlotId == ERROR_SLOTID) { - ShowWarning("User '%s' attempting to buy an item not in guild vendor: %u", PChar->getName(), ItemNo); + ShowWarning("User '%s' attempting to buy an item not in guild vendor: %u", PChar->getName(), this->ItemNo); return; } @@ -74,12 +75,12 @@ void GP_CLI_COMMAND_GUILD_BUY::process(MapSession* PSession, CCharEntity* PChar) { if (gil->getQuantity() > (item->getBasePrice() * quantity)) { - if (charutils::AddItem(PChar, LOC_INVENTORY, ItemNo, quantity) != ERROR_SLOTID) + if (charutils::AddItem(PChar, LOC_INVENTORY, this->ItemNo, quantity) != ERROR_SLOTID) { charutils::UpdateItem(PChar, LOC_INVENTORY, 0, -static_cast(item->getBasePrice() * quantity)); - ShowInfo("GP_CLI_COMMAND_GUILD_BUY: Player '%s' purchased %u of itemID %u [from GUILD] ", PChar->getName(), quantity, ItemNo); + ShowInfo("GP_CLI_COMMAND_GUILD_BUY: Player '%s' purchased %u of itemID %u [from GUILD] ", PChar->getName(), quantity, this->ItemNo); PChar->PGuildShop->GetItem(shopSlotId)->setQuantity(PChar->PGuildShop->GetItem(shopSlotId)->getQuantity() - quantity); - PChar->pushPacket(PChar, PChar->PGuildShop->GetItem(PChar->PGuildShop->SearchItem(ItemNo))->getQuantity(), ItemNo, quantity); + PChar->pushPacket(PChar, PChar->PGuildShop->GetItem(PChar->PGuildShop->SearchItem(this->ItemNo))->getQuantity(), this->ItemNo, quantity); PChar->pushPacket(PChar); } } diff --git a/src/map/packets/c2s/0x0ab_guild_buylist.cpp b/src/map/packets/c2s/0x0ab_guild_buylist.cpp index d64b61c1e3c..ac9ea6a4442 100644 --- a/src/map/packets/c2s/0x0ab_guild_buylist.cpp +++ b/src/map/packets/c2s/0x0ab_guild_buylist.cpp @@ -26,7 +26,8 @@ auto GP_CLI_COMMAND_GUILD_BUYLIST::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }) .mustNotEqual(PChar->PGuildShop, nullptr, "Character does not have a guild shop"); } diff --git a/src/map/packets/c2s/0x0ac_guild_sell.cpp b/src/map/packets/c2s/0x0ac_guild_sell.cpp index bbd8d1b943f..c6893440336 100644 --- a/src/map/packets/c2s/0x0ac_guild_sell.cpp +++ b/src/map/packets/c2s/0x0ac_guild_sell.cpp @@ -59,16 +59,16 @@ const auto auditSale = [](Scheduler& scheduler, CCharEntity* PChar, uint32_t ite auto GP_CLI_COMMAND_GUILD_SELL::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() - .isNotCrafting(PChar) + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent, BlockedState::Crafting }) .mustNotEqual(PChar->PGuildShop, nullptr, "Character does not have a guild shop") - .range("ItemNum", ItemNum, 1, 99); + .range("ItemNum", this->ItemNum, 1, 99); } void GP_CLI_COMMAND_GUILD_SELL::process(MapSession* PSession, CCharEntity* PChar) const { - uint8 quantity = ItemNum; - const uint8 shopSlotId = PChar->PGuildShop->SearchItem(ItemNo); + uint8 quantity = this->ItemNum; + const uint8 shopSlotId = PChar->PGuildShop->SearchItem(this->ItemNo); if (shopSlotId == ERROR_SLOTID) { @@ -76,7 +76,7 @@ void GP_CLI_COMMAND_GUILD_SELL::process(MapSession* PSession, CCharEntity* PChar } auto* shopItem = static_cast(PChar->PGuildShop->GetItem(shopSlotId)); - const CItem* charItem = PChar->getStorage(LOC_INVENTORY)->GetItem(PropertyItemIndex); + const CItem* charItem = PChar->getStorage(LOC_INVENTORY)->GetItem(this->PropertyItemIndex); const uint32 basePrice = shopItem->getBasePrice(); if (!charItem || charItem->getID() != shopItem->getID()) @@ -93,16 +93,16 @@ void GP_CLI_COMMAND_GUILD_SELL::process(MapSession* PSession, CCharEntity* PChar // TODO: add all sellable items to guild table if (quantity != 0 && charItem->getQuantity() >= quantity) { - if (charutils::UpdateItem(PChar, LOC_INVENTORY, PropertyItemIndex, -quantity) == ItemNo) + if (charutils::UpdateItem(PChar, LOC_INVENTORY, this->PropertyItemIndex, -quantity) == this->ItemNo) { // TODO: Don't pass around Scheduler& through PSession auditSale(*PSession->scheduler, PChar, charItem->getID(), basePrice, quantity); charutils::UpdateItem(PChar, LOC_INVENTORY, 0, shopItem->getSellPrice() * quantity); - ShowInfo("GP_CLI_COMMAND_GUILD_SELL: Player '%s' sold %u of ItemNo %u [to GUILD] ", PChar->getName(), quantity, ItemNo); + ShowInfo("GP_CLI_COMMAND_GUILD_SELL: Player '%s' sold %u of ItemNo %u [to GUILD] ", PChar->getName(), quantity, this->ItemNo); PChar->PGuildShop->GetItem(shopSlotId)->setQuantity(PChar->PGuildShop->GetItem(shopSlotId)->getQuantity() + quantity); PChar->pushPacket( - PChar, PChar->PGuildShop->GetItem(PChar->PGuildShop->SearchItem(ItemNo))->getQuantity(), ItemNo, quantity); + PChar, PChar->PGuildShop->GetItem(PChar->PGuildShop->SearchItem(this->ItemNo))->getQuantity(), this->ItemNo, quantity); PChar->pushPacket(PChar); } } diff --git a/src/map/packets/c2s/0x0ad_guild_selllist.cpp b/src/map/packets/c2s/0x0ad_guild_selllist.cpp index f86299ca839..9fc0e4b1209 100644 --- a/src/map/packets/c2s/0x0ad_guild_selllist.cpp +++ b/src/map/packets/c2s/0x0ad_guild_selllist.cpp @@ -26,7 +26,8 @@ auto GP_CLI_COMMAND_GUILD_SELLLIST::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }) .mustNotEqual(PChar->PGuildShop, nullptr, "Character does not have a guild shop"); } diff --git a/src/map/packets/c2s/0x0b5_chat_std.cpp b/src/map/packets/c2s/0x0b5_chat_std.cpp index 11a83e8454b..54b6ff614de 100644 --- a/src/map/packets/c2s/0x0b5_chat_std.cpp +++ b/src/map/packets/c2s/0x0b5_chat_std.cpp @@ -104,8 +104,8 @@ const auto auditLinkshell = [](Scheduler& scheduler, CCharEntity* PChar, CLinksh auto GP_CLI_COMMAND_CHAT_STD::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() - .oneOf(Kind); + return PacketValidator(PChar) + .oneOf(this->Kind); } void GP_CLI_COMMAND_CHAT_STD::process(MapSession* PSession, CCharEntity* PChar) const @@ -113,8 +113,8 @@ void GP_CLI_COMMAND_CHAT_STD::process(MapSession* PSession, CCharEntity* PChar) // Extremely important to figure out the message length here. // Depending on alignment, the message may not be NULL-terminated. // Start with reported size and skip the first 6 bytes (4x header + 1x kind + 1x unknown). - const auto messageLength = std::min((header.size * 4) - 0x6, sizeof(Str)); - const auto rawMessage = asStringFromUntrustedSource(Str, messageLength); + const auto messageLength = std::min((header.size * 4) - 0x6, sizeof(this->Str)); + const auto rawMessage = asStringFromUntrustedSource(this->Str, messageLength); const auto firstChar = rawMessage[0]; const auto rawMessageWithoutFirstChar = rawMessage.substr(1); @@ -146,7 +146,7 @@ void GP_CLI_COMMAND_CHAT_STD::process(MapSession* PSession, CCharEntity* PChar) // If you're jailed, you can only use /say if (jailutils::InPrison(PChar)) { - if (Kind == static_cast(GP_CLI_COMMAND_CHAT_STD_KIND::Say)) + if (this->Kind == static_cast(GP_CLI_COMMAND_CHAT_STD_KIND::Say)) { // TODO: Don't pass around Scheduler& through PSession auditChat(*PSession->scheduler, PChar, "SAY", rawMessage); @@ -161,7 +161,7 @@ void GP_CLI_COMMAND_CHAT_STD::process(MapSession* PSession, CCharEntity* PChar) } // Now handle every other chat type - switch (static_cast(Kind)) + switch (static_cast(this->Kind)) { case GP_CLI_COMMAND_CHAT_STD_KIND::Say: { diff --git a/src/map/packets/c2s/0x0b5_chat_std.h b/src/map/packets/c2s/0x0b5_chat_std.h index e43178c810a..e56060cb6c7 100644 --- a/src/map/packets/c2s/0x0b5_chat_std.h +++ b/src/map/packets/c2s/0x0b5_chat_std.h @@ -40,8 +40,8 @@ enum class GP_CLI_COMMAND_CHAT_STD_KIND : uint8_t // https://github.com/atom0s/XiPackets/tree/main/world/client/0x00B5 // This packet is sent by the client when sending chat messages. -GP_CLI_PACKET(GP_CLI_COMMAND_CHAT_STD, - uint8_t Kind; // Kind - uint8_t unknown00; // Dammy - uint8_t Str[128]; // Str +GP_CLI_PACKET_VLA(GP_CLI_COMMAND_CHAT_STD, Str, + uint8_t Kind; // Kind + uint8_t unknown00; // Dammy + uint8_t Str[128]; // Str ); diff --git a/src/map/packets/c2s/0x0b6_chat_name.cpp b/src/map/packets/c2s/0x0b6_chat_name.cpp index aed371fdf5c..a1534576485 100644 --- a/src/map/packets/c2s/0x0b6_chat_name.cpp +++ b/src/map/packets/c2s/0x0b6_chat_name.cpp @@ -56,9 +56,9 @@ const auto auditTell = [](Scheduler& scheduler, CCharEntity* PChar, const std::s auto GP_CLI_COMMAND_CHAT_NAME::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() - .mustEqual(unknown00, 3, "unknown00 not 3") - .mustEqual(unknown01, 0, "unknown01 not 0"); + return PacketValidator(PChar) + .mustEqual(this->unknown00, 3, "unknown00 not 3") + .mustEqual(this->unknown01, 0, "unknown01 not 0"); } void GP_CLI_COMMAND_CHAT_NAME::process(MapSession* PSession, CCharEntity* PChar) const @@ -72,9 +72,9 @@ void GP_CLI_COMMAND_CHAT_NAME::process(MapSession* PSession, CCharEntity* PChar) // Extremely important to figure out the message length here. // Depending on alignment, the message may not be NULL-terminated. // Start with reported size and skip the first 21 bytes (4x header + 2x unknown + 15x name). - const auto messageLength = std::min((header.size * 4) - 0x15, sizeof(Mes)); - const auto recipientName = db::escapeString(asStringFromUntrustedSource(sName, sizeof(sName))); - const auto rawMessage = asStringFromUntrustedSource(Mes, messageLength); + const auto messageLength = std::min((header.size * 4) - 0x15, sizeof(this->Mes)); + const auto recipientName = db::escapeString(asStringFromUntrustedSource(this->sName, sizeof(this->sName))); + const auto rawMessage = asStringFromUntrustedSource(this->Mes, messageLength); if (strcmp(recipientName.c_str(), "_CUSTOM_MENU") == 0 && luautils::HasCustomMenuContext(PChar)) diff --git a/src/map/packets/c2s/0x0b6_chat_name.h b/src/map/packets/c2s/0x0b6_chat_name.h index 7413f8d1960..a1c01507020 100644 --- a/src/map/packets/c2s/0x0b6_chat_name.h +++ b/src/map/packets/c2s/0x0b6_chat_name.h @@ -25,9 +25,9 @@ // https://github.com/atom0s/XiPackets/tree/main/world/client/0x00B6 // This packet is sent by the client when sending tells to another player. -GP_CLI_PACKET(GP_CLI_COMMAND_CHAT_NAME, - uint8_t unknown00; - uint8_t unknown01; - uint8_t sName[15]; - uint8_t Mes[128]; // Variable length +GP_CLI_PACKET_VLA(GP_CLI_COMMAND_CHAT_NAME, Mes, + uint8_t unknown00; + uint8_t unknown01; + uint8_t sName[15]; + uint8_t Mes[128]; // Variable length ); diff --git a/src/map/packets/c2s/0x0b7_assist_channel.cpp b/src/map/packets/c2s/0x0b7_assist_channel.cpp index 9638c973427..864e51cd3c0 100644 --- a/src/map/packets/c2s/0x0b7_assist_channel.cpp +++ b/src/map/packets/c2s/0x0b7_assist_channel.cpp @@ -29,14 +29,15 @@ auto GP_CLI_COMMAND_ASSIST_CHANNEL::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() - .oneOf(Kind) + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }) + .oneOf(this->Kind) .mustEqual(settings::get("main.ASSIST_CHANNEL_ENABLED"), true, "Assist Channel is not enabled"); } void GP_CLI_COMMAND_ASSIST_CHANNEL::process(MapSession* PSession, CCharEntity* PChar) const { - const auto safeName = db::escapeString(asStringFromUntrustedSource(sName, sizeof(sName))); + const auto safeName = db::escapeString(asStringFromUntrustedSource(this->sName, sizeof(this->sName))); const auto victimId = charutils::getCharIdFromName(safeName); if (!victimId) @@ -46,7 +47,7 @@ void GP_CLI_COMMAND_ASSIST_CHANNEL::process(MapSession* PSession, CCharEntity* P } // TODO: If char is offline, this is an automatic fail. - switch (static_cast(Kind)) + switch (static_cast(this->Kind)) { case GP_CLI_COMMAND_ASSIST_CHANNEL_KIND::GiveThumbsUp: { diff --git a/src/map/packets/c2s/0x0be_merits.cpp b/src/map/packets/c2s/0x0be_merits.cpp index b08050b9ea9..0ae4d6aafe4 100644 --- a/src/map/packets/c2s/0x0be_merits.cpp +++ b/src/map/packets/c2s/0x0be_merits.cpp @@ -36,22 +36,23 @@ auto GP_CLI_COMMAND_MERITS::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() - .oneOf(Kind) - .oneOf(Param1); + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }) + .oneOf(this->Kind) + .oneOf(this->Param1); } void GP_CLI_COMMAND_MERITS::process(MapSession* PSession, CCharEntity* PChar) const { - switch (static_cast(Kind)) + switch (static_cast(this->Kind)) { case GP_CLI_COMMAND_MERITS_KIND::ChangeMode: { // Note: While the client restricts the ability to change mode during besieged and when level restricted // : Retail server will still honor an injected request and change the mode. - if (db::preparedStmt("UPDATE char_exp SET mode = ? WHERE charid = ? LIMIT 1", Param1, PChar->id)) + if (db::preparedStmt("UPDATE char_exp SET mode = ? WHERE charid = ? LIMIT 1", this->Param1, PChar->id)) { - PChar->MeritMode = Param1; + PChar->MeritMode = this->Param1; PChar->pushPacket(PChar); PChar->pushPacket(PChar); PChar->pushPacket(PChar); @@ -63,19 +64,19 @@ void GP_CLI_COMMAND_MERITS::process(MapSession* PSession, CCharEntity* PChar) co { if (PChar->inMogHouse()) // Note: This has been verified as allowed in a shared mog house. { - if (const auto merit = static_cast(Param2 << 1); PChar->PMeritPoints->IsMeritExist(merit)) + if (const auto merit = static_cast(this->Param2 << 1); PChar->PMeritPoints->IsMeritExist(merit)) { const Merit_t* PMerit = PChar->PMeritPoints->GetMerit(merit); - switch (static_cast(Param1)) + switch (static_cast(this->Param1)) { case GP_CLI_COMMAND_MERITS_PARAM1::Lower: PChar->PMeritPoints->LowerMerit(merit); - PChar->pushPacket(PChar, PChar, Param2, PMerit->count, MsgBasic::MeritDecrease); + PChar->pushPacket(PChar, PChar, this->Param2, PMerit->count, MsgBasic::MeritDecrease); break; case GP_CLI_COMMAND_MERITS_PARAM1::Raise: PChar->PMeritPoints->RaiseMerit(merit); - PChar->pushPacket(PChar, PChar, Param2, PMerit->count, MsgBasic::MeritIncrease); + PChar->pushPacket(PChar, PChar, this->Param2, PMerit->count, MsgBasic::MeritIncrease); break; } diff --git a/src/map/packets/c2s/0x0bf_job_points_spend.cpp b/src/map/packets/c2s/0x0bf_job_points_spend.cpp index a5ce2b761b5..485c8d80c37 100644 --- a/src/map/packets/c2s/0x0bf_job_points_spend.cpp +++ b/src/map/packets/c2s/0x0bf_job_points_spend.cpp @@ -28,18 +28,19 @@ auto GP_CLI_COMMAND_JOB_POINTS_SPEND::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }) .mustEqual(PChar->inMogHouse(), true, "Character not in a mog house.") // Has been verified to work in ANY Mog House. - .mustEqual(PChar->PJobPoints && PChar->PJobPoints->IsJobPointExist(static_cast(Index)), true, "Job point does not exist."); + .mustEqual(PChar->PJobPoints && PChar->PJobPoints->IsJobPointExist(static_cast(this->Index)), true, "Job point does not exist."); } void GP_CLI_COMMAND_JOB_POINTS_SPEND::process(MapSession* PSession, CCharEntity* PChar) const { - auto jpType = static_cast(Index); + auto jpType = static_cast(this->Index); PChar->PJobPoints->RaiseJobPoint(jpType); auto newLevel = PChar->PJobPoints->GetJobPointType(jpType)->value; PChar->pushPacket(PChar); PChar->pushPacket(PChar, jpType); - PChar->pushPacket(PChar, PChar, Index, newLevel, MsgBasic::JobPointsIncrease); + PChar->pushPacket(PChar, PChar, this->Index, newLevel, MsgBasic::JobPointsIncrease); } diff --git a/src/map/packets/c2s/0x0c0_job_points_req.cpp b/src/map/packets/c2s/0x0c0_job_points_req.cpp index e143de0f21d..bfbef633606 100644 --- a/src/map/packets/c2s/0x0c0_job_points_req.cpp +++ b/src/map/packets/c2s/0x0c0_job_points_req.cpp @@ -27,8 +27,8 @@ auto GP_CLI_COMMAND_JOB_POINTS_REQ::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - // No parameters to validate for this packet - return PacketValidator(); + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }); } void GP_CLI_COMMAND_JOB_POINTS_REQ::process(MapSession* PSession, CCharEntity* PChar) const diff --git a/src/map/packets/c2s/0x0c1_alter_ego_points.cpp b/src/map/packets/c2s/0x0c1_alter_ego_points.cpp index 3760bee1636..e7c21355dcd 100644 --- a/src/map/packets/c2s/0x0c1_alter_ego_points.cpp +++ b/src/map/packets/c2s/0x0c1_alter_ego_points.cpp @@ -28,11 +28,11 @@ auto GP_CLI_COMMAND_ALTER_EGO_POINTS::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent, BlockedState::AbnormalStatus }) .oneOf(this->CategoryIndex) - .isNormalStatus(PChar) - .isInMogHouse(PChar) - .hasKeyItem(PChar, KeyItem::CIPHER_BRACELET) + .isInMogHouse() + .hasKeyItem(KeyItem::CIPHER_BRACELET) .custom([&](PacketValidator& v) { if (PChar->GetMLevel() < 99) diff --git a/src/map/packets/c2s/0x0c3_group_comlink_make.cpp b/src/map/packets/c2s/0x0c3_group_comlink_make.cpp index 286b50f9033..750ddde33b3 100644 --- a/src/map/packets/c2s/0x0c3_group_comlink_make.cpp +++ b/src/map/packets/c2s/0x0c3_group_comlink_make.cpp @@ -29,17 +29,18 @@ auto GP_CLI_COMMAND_GROUP_COMLINK_MAKE::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() - .mustEqual(State, 0, "State not 0") - .oneOf(LinkshellId) - .hasLinkshellRank(PChar, LinkshellId, LSTYPE_PEARLSACK); + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }) + .mustEqual(this->State, 0, "State not 0") + .oneOf(this->LinkshellId) + .hasLinkshellRank(this->LinkshellId, LSTYPE_PEARLSACK); } void GP_CLI_COMMAND_GROUP_COMLINK_MAKE::process(MapSession* PSession, CCharEntity* PChar) const { const CItemLinkshell* PItemLinkshell = nullptr; - switch (static_cast(LinkshellId)) + switch (static_cast(this->LinkshellId)) { case GP_CLI_COMMAND_GROUP_COMLINK_MAKE_LINKSHELLID::Linkshell1: PItemLinkshell = reinterpret_cast(PChar->getEquip(SLOT_LINK1)); diff --git a/src/map/packets/c2s/0x0c4_group_comlink_active.cpp b/src/map/packets/c2s/0x0c4_group_comlink_active.cpp index 6628475203b..65525abf4b2 100644 --- a/src/map/packets/c2s/0x0c4_group_comlink_active.cpp +++ b/src/map/packets/c2s/0x0c4_group_comlink_active.cpp @@ -177,25 +177,26 @@ const auto unequipLinkshell = [](CCharEntity* PChar, CItemLinkshell* PItemLinksh auto GP_CLI_COMMAND_GROUP_COMLINK_ACTIVE::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() - .range("r", r, 0, 15) - .range("g", g, 0, 15) - .range("b", b, 0, 15) - .mustEqual(a, 15, "a not 15") - .oneOf(ActiveFlg) - .oneOf(LinkshellId); + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }) + .range("r", this->r, 0, 15) + .range("g", this->g, 0, 15) + .range("b", this->b, 0, 15) + .mustEqual(this->a, 15, "a not 15") + .oneOf(this->ActiveFlg) + .oneOf(this->LinkshellId); } void GP_CLI_COMMAND_GROUP_COMLINK_ACTIVE::process(MapSession* PSession, CCharEntity* PChar) const { - auto* PItemLinkshell = static_cast(PChar->getStorage(Category)->GetItem(ItemIndex)); + auto* PItemLinkshell = static_cast(PChar->getStorage(this->Category)->GetItem(this->ItemIndex)); if (!PItemLinkshell || !PItemLinkshell->isType(ITEM_LINKSHELL)) { return; } - switch (static_cast(ActiveFlg)) + switch (static_cast(this->ActiveFlg)) { case GP_CLI_COMMAND_GROUP_COMLINK_ACTIVE_ACTIVEFLG::EquipOrCreate: { diff --git a/src/map/packets/c2s/0x0cb_myroom_is.cpp b/src/map/packets/c2s/0x0cb_myroom_is.cpp index 03f1f02c802..e732aa604b0 100644 --- a/src/map/packets/c2s/0x0cb_myroom_is.cpp +++ b/src/map/packets/c2s/0x0cb_myroom_is.cpp @@ -53,10 +53,11 @@ const auto isRentARoom = [](const CCharEntity* PChar) auto GP_CLI_COMMAND_MYROOM_IS::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }) .mustEqual(PChar->m_moghouseID, PChar->id, "Character not in their mog house") - .oneOf(Kind) - .oneOf(Param2); + .oneOf(this->Kind) + .oneOf(this->Param2); } void GP_CLI_COMMAND_MYROOM_IS::process(MapSession* PSession, CCharEntity* PChar) const @@ -68,7 +69,7 @@ void GP_CLI_COMMAND_MYROOM_IS::process(MapSession* PSession, CCharEntity* PChar) ShowWarning(fmt::format("Player {} modifying Rent-a-Room state.", PChar->getName())); } - switch (static_cast(Kind)) + switch (static_cast(this->Kind)) { case GP_CLI_COMMAND_MYROOM_IS_KIND::Open: // Not implemented @@ -80,7 +81,7 @@ void GP_CLI_COMMAND_MYROOM_IS::process(MapSession* PSession, CCharEntity* PChar) break; case GP_CLI_COMMAND_MYROOM_IS_KIND::Remodel: { - auto newStyle = Param2; + auto newStyle = this->Param2; // Retail forces you to nation default style on invalid Param2. auto default2fStyle = GP_CLI_COMMAND_MYROOM_IS_PARAM2::SandorianStyle; @@ -94,7 +95,7 @@ void GP_CLI_COMMAND_MYROOM_IS::process(MapSession* PSession, CCharEntity* PChar) ShowWarning(fmt::format("Player {} remodeling MH2F without it unlocked.", PChar->getName())); } - if (Param2 == static_cast(GP_CLI_COMMAND_MYROOM_IS_PARAM2::MogPatio) && !charutils::hasKeyItem(PChar, KeyItem::MOG_PATIO_DESIGN_DOCUMENT)) + if (this->Param2 == static_cast(GP_CLI_COMMAND_MYROOM_IS_PARAM2::MogPatio) && !charutils::hasKeyItem(PChar, KeyItem::MOG_PATIO_DESIGN_DOCUMENT)) { ShowWarning(fmt::format("Player {} remodeling MH2F to Patio without owning the KI to unlock it.", PChar->getName())); newStyle = static_cast(default2fStyle); @@ -118,7 +119,7 @@ void GP_CLI_COMMAND_MYROOM_IS::process(MapSession* PSession, CCharEntity* PChar) PChar->pushPacket(MsgStd::SuccessfulRemodel); // If the model changes AND you're on MH2F; force a rezone so the model change can take effect. - if (Param2 != oldType && PChar->profile.mhflag & 0x0040) + if (this->Param2 != oldType && PChar->profile.mhflag & 0x0040) { const auto zoneid = PChar->getZone(); diff --git a/src/map/packets/c2s/0x0d2_map_group.cpp b/src/map/packets/c2s/0x0d2_map_group.cpp index aa488b3b23f..7bdd670c346 100644 --- a/src/map/packets/c2s/0x0d2_map_group.cpp +++ b/src/map/packets/c2s/0x0d2_map_group.cpp @@ -26,8 +26,9 @@ auto GP_CLI_COMMAND_MAP_GROUP::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() - .mustEqual(ZoneNo, PChar->getZone(), "ZoneNo does not match character zone"); + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }) + .mustEqual(this->ZoneNo, PChar->getZone(), "ZoneNo does not match character zone"); } void GP_CLI_COMMAND_MAP_GROUP::process(MapSession* PSession, CCharEntity* PChar) const diff --git a/src/map/packets/c2s/0x0d3_faq_gmcall.cpp b/src/map/packets/c2s/0x0d3_faq_gmcall.cpp index 4bf39a0857f..b5c247a476c 100644 --- a/src/map/packets/c2s/0x0d3_faq_gmcall.cpp +++ b/src/map/packets/c2s/0x0d3_faq_gmcall.cpp @@ -25,7 +25,8 @@ auto GP_CLI_COMMAND_FAQ_GMCALL::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }) .oneOf(this->type) .mustEqual(this->vers, 0, "vers not equal to 0") .range("eos", this->eos, 0, 1); diff --git a/src/map/packets/c2s/0x0d3_faq_gmcall.h b/src/map/packets/c2s/0x0d3_faq_gmcall.h index 328797b2d82..b634b7f7b8b 100644 --- a/src/map/packets/c2s/0x0d3_faq_gmcall.h +++ b/src/map/packets/c2s/0x0d3_faq_gmcall.h @@ -93,12 +93,12 @@ struct FFGpGMReportLobbyStruct // https://github.com/atom0s/XiPackets/tree/main/world/client/0x00D3 // This packet is sent by the client when interacting with the Help Desk system. More specifically, when selecting an option that will send a request to the server. -GP_CLI_PACKET(GP_CLI_COMMAND_FAQ_GMCALL, - uint16_t type : 4; // PS2: type - uint16_t vers : 4; // PS2: vers - uint16_t pktId : 8; // PS2: pktId - uint16_t seq : 7; // PS2: seq - uint16_t eos : 1; // PS2: eos - uint16_t blkNum : 8; // PS2: blkNum -- 9 max observed - uint8_t Data[256]; // PS2: (Non-specific structured data.) - Unknown max size +GP_CLI_PACKET_VLA(GP_CLI_COMMAND_FAQ_GMCALL, Data, + uint16_t type : 4; // PS2: type + uint16_t vers : 4; // PS2: vers + uint16_t pktId : 8; // PS2: pktId + uint16_t seq : 7; // PS2: seq + uint16_t eos : 1; // PS2: eos + uint16_t blkNum : 8; // PS2: blkNum -- 9 max observed + uint8_t Data[256]; // PS2: (Non-specific structured data.) - Unknown max size ); diff --git a/src/map/packets/c2s/0x0d4_faq_gmparam.cpp b/src/map/packets/c2s/0x0d4_faq_gmparam.cpp index 0081abd6a4a..096782aa926 100644 --- a/src/map/packets/c2s/0x0d4_faq_gmparam.cpp +++ b/src/map/packets/c2s/0x0d4_faq_gmparam.cpp @@ -26,7 +26,8 @@ auto GP_CLI_COMMAND_FAQ_GMPARAM::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }) .mustEqual(this->Option, 0, "Option not 0"); } diff --git a/src/map/packets/c2s/0x0d5_ack_gmmsg.cpp b/src/map/packets/c2s/0x0d5_ack_gmmsg.cpp index 7ab6f2f2dce..b2c9376cc12 100644 --- a/src/map/packets/c2s/0x0d5_ack_gmmsg.cpp +++ b/src/map/packets/c2s/0x0d5_ack_gmmsg.cpp @@ -26,7 +26,8 @@ auto GP_CLI_COMMAND_ACK_GMMSG::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator(); + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }); } void GP_CLI_COMMAND_ACK_GMMSG::process(MapSession* PSession, CCharEntity* PChar) const diff --git a/src/map/packets/c2s/0x0d8_dungeon_param.cpp b/src/map/packets/c2s/0x0d8_dungeon_param.cpp index 201b9acaade..5a7742ff2ab 100644 --- a/src/map/packets/c2s/0x0d8_dungeon_param.cpp +++ b/src/map/packets/c2s/0x0d8_dungeon_param.cpp @@ -26,16 +26,17 @@ auto GP_CLI_COMMAND_DUNGEON_PARAM::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { // Not implemented. - return PacketValidator() - .mustEqual(PChar->id, UniqueNo, "Character ID mismatch") - .mustEqual(PChar->targid, ActIndex, "Targid mismatch"); + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }) + .mustEqual(PChar->id, this->UniqueNo, "Character ID mismatch") + .mustEqual(PChar->targid, this->ActIndex, "Targid mismatch"); } void GP_CLI_COMMAND_DUNGEON_PARAM::process(MapSession* PSession, CCharEntity* PChar) const { ShowDebugFmt("GP_CLI_COMMAND_DUNGEON_PARAM: Not implemented. ActIndex: {}, Param1: {}, Param2: {}, UniqueNo: {}", - ActIndex, - Param1, - Param2, - UniqueNo); + this->ActIndex, + this->Param1, + this->Param2, + this->UniqueNo); } diff --git a/src/map/packets/c2s/0x0db_config_language.cpp b/src/map/packets/c2s/0x0db_config_language.cpp index 1ca821c4ec0..f341d4c4b54 100644 --- a/src/map/packets/c2s/0x0db_config_language.cpp +++ b/src/map/packets/c2s/0x0db_config_language.cpp @@ -28,10 +28,10 @@ auto GP_CLI_COMMAND_CONFIG_LANGUAGE::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() - .oneOf(Kind) - .mustEqual(unknown00, 0, "unknown00 must be 0") - .mustEqual(unknown01, 0, "unknown00 must be 0"); + return PacketValidator(PChar) + .oneOf(this->Kind) + .mustEqual(this->unknown00, 0, "unknown00 must be 0") + .mustEqual(this->unknown01, 0, "unknown00 must be 0"); } void GP_CLI_COMMAND_CONFIG_LANGUAGE::process(MapSession* PSession, CCharEntity* PChar) const @@ -44,21 +44,21 @@ void GP_CLI_COMMAND_CONFIG_LANGUAGE::process(MapSession* PSession, CCharEntity* std::memcpy(&oldChatFilter1, &PChar->playerConfig.MessageFilter, sizeof(uint32_t)); std::memcpy(&oldChatFilter2, &PChar->playerConfig.MessageFilter2, sizeof(uint32_t)); - switch (static_cast(Kind)) + switch (static_cast(this->Kind)) { case GP_CLI_COMMAND_CONFIG_LANGUAGE_KIND::SearchLanguage: { // Player is updating chat filters - if (oldPlayerConfig != ConfigSys[0]) + if (oldPlayerConfig != this->ConfigSys[0]) { - std::memcpy(&PChar->playerConfig, &ConfigSys[0], sizeof(uint32_t)); + std::memcpy(&PChar->playerConfig, &this->ConfigSys[0], sizeof(uint32_t)); charutils::SavePlayerSettings(PChar); } - if (oldChatFilter1 != ConfigSys[1] || oldChatFilter2 != ConfigSys[2]) + if (oldChatFilter1 != this->ConfigSys[1] || oldChatFilter2 != this->ConfigSys[2]) { - std::memcpy(&PChar->playerConfig.MessageFilter, &ConfigSys[1], sizeof(uint32_t)); - std::memcpy(&PChar->playerConfig.MessageFilter2, &ConfigSys[2], sizeof(uint32_t)); + std::memcpy(&PChar->playerConfig.MessageFilter, &this->ConfigSys[1], sizeof(uint32_t)); + std::memcpy(&PChar->playerConfig.MessageFilter2, &this->ConfigSys[2], sizeof(uint32_t)); // It's probably not necessary to save the flags as they are sent by the client on login. charutils::SaveChatFilterFlags(PChar); } @@ -67,9 +67,9 @@ void GP_CLI_COMMAND_CONFIG_LANGUAGE::process(MapSession* PSession, CCharEntity* case GP_CLI_COMMAND_CONFIG_LANGUAGE_KIND::PartyLanguages: { // Player is updating party search languages - if (PChar->search.language != Param) + if (PChar->search.language != this->Param) { - PChar->search.language = static_cast(Param); + PChar->search.language = static_cast(this->Param); charutils::SaveLanguages(PChar); } } diff --git a/src/map/packets/c2s/0x0dc_config.cpp b/src/map/packets/c2s/0x0dc_config.cpp index 05edebbabd0..286b802a808 100644 --- a/src/map/packets/c2s/0x0dc_config.cpp +++ b/src/map/packets/c2s/0x0dc_config.cpp @@ -34,32 +34,33 @@ auto GP_CLI_COMMAND_CONFIG::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() - .oneOf(SetFlg); + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }) + .oneOf(this->SetFlg); } void GP_CLI_COMMAND_CONFIG::process(MapSession* PSession, CCharEntity* PChar) const { - const bool value = SetFlg == static_cast(GP_CLI_COMMAND_CONFIG_SETFLG::On); + const bool value = this->SetFlg == static_cast(GP_CLI_COMMAND_CONFIG_SETFLG::On); bool updated = false; // Flag set if the client is looking for party. (/invite) - if (InviteFlg && PChar->playerConfig.InviteFlg != value) + if (this->InviteFlg && PChar->playerConfig.InviteFlg != value) { updated = true; PChar->playerConfig.InviteFlg = value; } // Flag set if the client is away. (/away) - if (AwayFlg && PChar->playerConfig.AwayFlg != value) + if (this->AwayFlg && PChar->playerConfig.AwayFlg != value) { updated = true; PChar->playerConfig.AwayFlg = value; } // Flag set if the client is anon. (/anon) - if (AnonymityFlg && PChar->playerConfig.AnonymityFlg != value) + if (this->AnonymityFlg && PChar->playerConfig.AnonymityFlg != value) { updated = true; PChar->playerConfig.AnonymityFlg = value; @@ -67,21 +68,21 @@ void GP_CLI_COMMAND_CONFIG::process(MapSession* PSession, CCharEntity* PChar) co } // Flag set if the client has auto-target disabled. (/autotarget) - if (AutoTargetOffFlg && PChar->playerConfig.AutoTargetOffFlg != value) + if (this->AutoTargetOffFlg && PChar->playerConfig.AutoTargetOffFlg != value) { updated = true; PChar->playerConfig.AutoTargetOffFlg = value; } // Flag set if the client is looking for party using the auto-group system. (/autogroup) - if (AutoPartyFlg && PChar->playerConfig.AutoPartyFlg != value) + if (this->AutoPartyFlg && PChar->playerConfig.AutoPartyFlg != value) { updated = true; PChar->playerConfig.AutoPartyFlg = value; } // Flag set if the client has enabled mentor status. (/mentor) - if (MentorFlg && PChar->playerConfig.MentorFlg != value) + if (this->MentorFlg && PChar->playerConfig.MentorFlg != value) { if (PChar->aman().hasMentorUnlocked()) { @@ -91,7 +92,7 @@ void GP_CLI_COMMAND_CONFIG::process(MapSession* PSession, CCharEntity* PChar) co } // Flag set if the client has disabled the 'New Adventurer' status. (Red question mark.) - if (NewAdventurerOffFlg && PChar->playerConfig.NewAdventurerOffFlg != value) + if (this->NewAdventurerOffFlg && PChar->playerConfig.NewAdventurerOffFlg != value) { if (!PChar->playerConfig.NewAdventurerOffFlg) // Can only turn it off, not on. { @@ -101,7 +102,7 @@ void GP_CLI_COMMAND_CONFIG::process(MapSession* PSession, CCharEntity* PChar) co } // Flag set if the client has disabled displaying headgear. (/displayhead) - if (DisplayHeadOffFlg && PChar->playerConfig.DisplayHeadOffFlg != value) + if (this->DisplayHeadOffFlg && PChar->playerConfig.DisplayHeadOffFlg != value) { updated = true; PChar->playerConfig.DisplayHeadOffFlg = value; @@ -116,7 +117,7 @@ void GP_CLI_COMMAND_CONFIG::process(MapSession* PSession, CCharEntity* PChar) co } // Flag set if the client has enabled recruitment requests. (/rec) - if (RecruitFlg && PChar->playerConfig.RecruitFlg != value) + if (this->RecruitFlg && PChar->playerConfig.RecruitFlg != value) { updated = true; PChar->playerConfig.RecruitFlg = value; diff --git a/src/map/packets/c2s/0x0dd_equip_inspect.cpp b/src/map/packets/c2s/0x0dd_equip_inspect.cpp index bc7944449a7..7965a8d050f 100644 --- a/src/map/packets/c2s/0x0dd_equip_inspect.cpp +++ b/src/map/packets/c2s/0x0dd_equip_inspect.cpp @@ -36,8 +36,9 @@ auto GP_CLI_COMMAND_EQUIP_INSPECT::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() - .oneOf(Kind); + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }) + .oneOf(this->Kind); } void GP_CLI_COMMAND_EQUIP_INSPECT::process(MapSession* PSession, CCharEntity* PChar) const @@ -48,7 +49,7 @@ void GP_CLI_COMMAND_EQUIP_INSPECT::process(MapSession* PSession, CCharEntity* PC return; } - CBaseEntity* PEntity = PChar->GetEntity(ActIndex, TYPE_MOB | TYPE_PC); + CBaseEntity* PEntity = PChar->GetEntity(this->ActIndex, TYPE_MOB | TYPE_PC); auto* PMobTarget = dynamic_cast(PEntity); auto* PCharTarget = dynamic_cast(PEntity); @@ -65,11 +66,11 @@ void GP_CLI_COMMAND_EQUIP_INSPECT::process(MapSession* PSession, CCharEntity* PC ShowWarning("GP_CLI_COMMAND_EQUIP_INSPECT: {} checking mob {} from too far away", PChar->getName(), PMobTarget->getName()); } - switch (static_cast(Kind)) + switch (static_cast(this->Kind)) { case GP_CLI_COMMAND_EQUIP_INSPECT_KIND::Check: { - if (!PEntity || PEntity->id != UniqueNo) + if (!PEntity || PEntity->id != this->UniqueNo) { return; } @@ -147,7 +148,7 @@ void GP_CLI_COMMAND_EQUIP_INSPECT::process(MapSession* PSession, CCharEntity* PC break; case GP_CLI_COMMAND_EQUIP_INSPECT_KIND::CheckParam: { - if (PChar->id == UniqueNo) + if (PChar->id == this->UniqueNo) { // /checkparam on self @@ -179,7 +180,7 @@ void GP_CLI_COMMAND_EQUIP_INSPECT::process(MapSession* PSession, CCharEntity* PC PChar->pushPacket(PChar, PChar, PChar->EVA(), PChar->DEF(), MsgBasic::CheckparamDefense); } - else if (PChar->PPet && PChar->PPet->id == UniqueNo) + else if (PChar->PPet && PChar->PPet->id == this->UniqueNo) { // /checkparam on pet diff --git a/src/map/packets/c2s/0x0de_inspect_message.cpp b/src/map/packets/c2s/0x0de_inspect_message.cpp index 0b6af8d5384..6844c1f6dc2 100644 --- a/src/map/packets/c2s/0x0de_inspect_message.cpp +++ b/src/map/packets/c2s/0x0de_inspect_message.cpp @@ -25,8 +25,8 @@ auto GP_CLI_COMMAND_INSPECT_MESSAGE::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - // No parameters to validate for this packet. - return PacketValidator(); + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }); } void GP_CLI_COMMAND_INSPECT_MESSAGE::process(MapSession* PSession, CCharEntity* PChar) const @@ -36,7 +36,7 @@ void GP_CLI_COMMAND_INSPECT_MESSAGE::process(MapSession* PSession, CCharEntity* // NOTE: We are NOT escaping this because the exact message needs to be stored to // : be correctly displayed in the bazaar. We're storing through a prepared statement so // : this is safe from injection. - const auto message = asStringFromUntrustedSource(sInspectMessage, sizeof(sInspectMessage) - 3); + const auto message = asStringFromUntrustedSource(this->sInspectMessage, sizeof(this->sInspectMessage) - 3); if (db::preparedStmt("UPDATE char_stats SET bazaar_message = ? WHERE charid = ? LIMIT 1", message, PChar->id)) { diff --git a/src/map/packets/c2s/0x0e0_set_usermsg.cpp b/src/map/packets/c2s/0x0e0_set_usermsg.cpp index dc16414717d..eb76d5bb5ca 100644 --- a/src/map/packets/c2s/0x0e0_set_usermsg.cpp +++ b/src/map/packets/c2s/0x0e0_set_usermsg.cpp @@ -26,8 +26,8 @@ auto GP_CLI_COMMAND_SET_USERMSG::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() - .oneOf(msgType); + return PacketValidator(PChar) + .oneOf(this->msgType); } void GP_CLI_COMMAND_SET_USERMSG::process(MapSession* PSession, CCharEntity* PChar) const @@ -35,9 +35,9 @@ void GP_CLI_COMMAND_SET_USERMSG::process(MapSession* PSession, CCharEntity* PCha // NOTE: As with the bazaar message, we aren't going to escape this because we need the // : exact message to be stored to be displayed correctly. We're storing through a prepared statement so // : this is safe from injection. - const auto message = asStringFromUntrustedSource(sMessage, sizeof(sMessage)); + const auto message = asStringFromUntrustedSource(this->sMessage, sizeof(this->sMessage)); - auto type = message.empty() ? GP_CLI_COMMAND_SET_USERMSG_MSGTYPE::Default : static_cast(msgType); + auto type = message.empty() ? GP_CLI_COMMAND_SET_USERMSG_MSGTYPE::Default : static_cast(this->msgType); if (static_cast(type) == PChar->search.messagetype && strcmp(message.c_str(), PChar->search.message.c_str()) == 0) { diff --git a/src/map/packets/c2s/0x0e1_get_lsmsg.cpp b/src/map/packets/c2s/0x0e1_get_lsmsg.cpp index bfcc1ec4d2e..2d985bfd01a 100644 --- a/src/map/packets/c2s/0x0e1_get_lsmsg.cpp +++ b/src/map/packets/c2s/0x0e1_get_lsmsg.cpp @@ -27,10 +27,11 @@ auto GP_CLI_COMMAND_GET_LSMSG::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - auto pv = PacketValidator() - .oneOf(LinkshellId); + auto pv = PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }) + .oneOf(this->LinkshellId); - switch (static_cast(LinkshellId)) + switch (static_cast(this->LinkshellId)) { case LinkshellSlot::LS1: pv.mustNotEqual(PChar->PLinkshell1, nullptr, "Character does not have Linkshell 1"); @@ -45,7 +46,7 @@ auto GP_CLI_COMMAND_GET_LSMSG::validate(MapSession* PSession, const CCharEntity* void GP_CLI_COMMAND_GET_LSMSG::process(MapSession* PSession, CCharEntity* PChar) const { - switch (static_cast(LinkshellId)) + switch (static_cast(this->LinkshellId)) { case LinkshellSlot::LS1: PChar->PLinkshell1->PushLinkshellMessage(PChar, LinkshellSlot::LS1); diff --git a/src/map/packets/c2s/0x0e2_set_lsmsg.cpp b/src/map/packets/c2s/0x0e2_set_lsmsg.cpp index 46ff41576c8..1828378b398 100644 --- a/src/map/packets/c2s/0x0e2_set_lsmsg.cpp +++ b/src/map/packets/c2s/0x0e2_set_lsmsg.cpp @@ -29,8 +29,9 @@ auto GP_CLI_COMMAND_SET_LSMSG::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { // TODO: Short-circuit the null check so we can check the permission level here - auto pv = PacketValidator() - .oneOf(writeLevel) + auto pv = PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }) + .oneOf(this->writeLevel) .mustNotEqual(PChar->PLinkshell1, nullptr, "Character does not have Linkshell 1"); return pv; @@ -62,23 +63,23 @@ void GP_CLI_COMMAND_SET_LSMSG::process(MapSession* PSession, CCharEntity* PChar) auto* PItemLinkshell = reinterpret_cast(PChar->getEquip(SLOT_LINK1)); if (PItemLinkshell != nullptr && PItemLinkshell->isType(ITEM_LINKSHELL)) { - if (unknown02) + if (this->unknown02) { // This flag is set when changing the linkshell message access level. if (PItemLinkshell->GetLSType() == LSTYPE_LINKSHELL) // Only Linkshell owner can change the access level { - PChar->PLinkshell1->setPostRights(static_cast(writeLevel)); + PChar->PLinkshell1->setPostRights(static_cast(this->writeLevel)); return; } PChar->pushPacket(MsgStd::LinkshellNoAccess); } - else if (unknown03) + else if (this->unknown03) { // This flag is set when changing the linkshell message. if (canEditLsMes(PItemLinkshell)) { - const auto lsMessage = asStringFromUntrustedSource(sMessage, sizeof(sMessage)); + const auto lsMessage = asStringFromUntrustedSource(this->sMessage, sizeof(this->sMessage)); PChar->PLinkshell1->setMessage(lsMessage, PChar->getName()); return; } diff --git a/src/map/packets/c2s/0x0e4_get_lspriv.cpp b/src/map/packets/c2s/0x0e4_get_lspriv.cpp index ce9dc007851..51c7271dc44 100644 --- a/src/map/packets/c2s/0x0e4_get_lspriv.cpp +++ b/src/map/packets/c2s/0x0e4_get_lspriv.cpp @@ -26,7 +26,8 @@ auto GP_CLI_COMMAND_GET_LSPRIV::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { // No parameter to validate as it is not implemented. - return PacketValidator(); + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }); } void GP_CLI_COMMAND_GET_LSPRIV::process(MapSession* PSession, CCharEntity* PChar) const @@ -41,8 +42,8 @@ void GP_CLI_COMMAND_GET_LSPRIV::process(MapSession* PSession, CCharEntity* PChar // - seqId:The linkshell message sequence id. // This sends a 0xCC response that prints "The linkshell message can be set by pearlsack owners" ShowDebugFmt("GP_CLI_COMMAND_GET_LSPRIV: Not implemented. unknown01 {}, unknown02 {}, unknown04 {}, seqId {}", - unknown01, - unknown02, - unknown04, - seqId); + this->unknown01, + this->unknown02, + this->unknown04, + this->seqId); } diff --git a/src/map/packets/c2s/0x0e7_reqlogout.cpp b/src/map/packets/c2s/0x0e7_reqlogout.cpp index 4dfc0fc92a1..3a083143557 100644 --- a/src/map/packets/c2s/0x0e7_reqlogout.cpp +++ b/src/map/packets/c2s/0x0e7_reqlogout.cpp @@ -27,12 +27,10 @@ auto GP_CLI_COMMAND_REQLOGOUT::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() - .isNotCrafting(PChar) - .isNormalStatus(PChar) - .isNotPreventedAction(PChar) - .oneOf(Mode) - .oneOf(Kind); + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent, BlockedState::AbnormalStatus, BlockedState::Crafting, BlockedState::PreventAction }) + .oneOf(this->Mode) + .oneOf(this->Kind); } void GP_CLI_COMMAND_REQLOGOUT::process(MapSession* PSession, CCharEntity* PChar) const @@ -62,10 +60,10 @@ void GP_CLI_COMMAND_REQLOGOUT::process(MapSession* PSession, CCharEntity* PChar) } }; - switch (static_cast(Kind)) + switch (static_cast(this->Kind)) { case GP_CLI_COMMAND_REQLOGOUT_KIND::Logout: - switch (static_cast(Mode)) + switch (static_cast(this->Mode)) { case GP_CLI_COMMAND_REQLOGOUT_MODE::Toggle: if (existingEffect) @@ -89,7 +87,7 @@ void GP_CLI_COMMAND_REQLOGOUT::process(MapSession* PSession, CCharEntity* PChar) } break; case GP_CLI_COMMAND_REQLOGOUT_KIND::Shutdown: - switch (static_cast(Mode)) + switch (static_cast(this->Mode)) { case GP_CLI_COMMAND_REQLOGOUT_MODE::Toggle: if (existingEffect) diff --git a/src/map/packets/c2s/0x0e8_camp.cpp b/src/map/packets/c2s/0x0e8_camp.cpp index 5ba33ea128e..636367d24c8 100644 --- a/src/map/packets/c2s/0x0e8_camp.cpp +++ b/src/map/packets/c2s/0x0e8_camp.cpp @@ -28,20 +28,17 @@ auto GP_CLI_COMMAND_CAMP::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() - .isNormalStatus(PChar) - .isNotPreventedAction(PChar) - .isNotCrafting(PChar) - .mustNotEqual(PChar->PAI->IsEngaged(), true, "Cannot heal while engaged in combat") - .oneOf(Mode) + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent, BlockedState::AbnormalStatus, BlockedState::Crafting, BlockedState::PreventAction, BlockedState::Engaged }) + .oneOf(this->Mode) .mustNotEqual( PChar->animation == ANIMATION_HEALING && - Mode == static_cast(GP_CLI_COMMAND_CAMP_MODE::On), + this->Mode == static_cast(GP_CLI_COMMAND_CAMP_MODE::On), true, "Requested healing when already healing") .mustNotEqual( PChar->animation != ANIMATION_HEALING && - Mode == static_cast(GP_CLI_COMMAND_CAMP_MODE::Off), + this->Mode == static_cast(GP_CLI_COMMAND_CAMP_MODE::Off), true, "Requested stop healing when not healing"); } @@ -65,7 +62,7 @@ void GP_CLI_COMMAND_CAMP::process(MapSession* PSession, CCharEntity* PChar) cons }; // Note: The status effect lua takes care of changing the animation. - switch (static_cast(Mode)) + switch (static_cast(this->Mode)) { case GP_CLI_COMMAND_CAMP_MODE::Toggle: if (PChar->animation == ANIMATION_HEALING) diff --git a/src/map/packets/c2s/0x0ea_sit.cpp b/src/map/packets/c2s/0x0ea_sit.cpp index f9f48f47240..77dc5027a4a 100644 --- a/src/map/packets/c2s/0x0ea_sit.cpp +++ b/src/map/packets/c2s/0x0ea_sit.cpp @@ -27,11 +27,9 @@ auto GP_CLI_COMMAND_SIT::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() - .isNotCrafting(PChar) - .isNormalStatus(PChar) - .isNotPreventedAction(PChar) - .oneOf(Mode); + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent, BlockedState::AbnormalStatus, BlockedState::Crafting, BlockedState::PreventAction }) + .oneOf(this->Mode); } void GP_CLI_COMMAND_SIT::process(MapSession* PSession, CCharEntity* PChar) const @@ -39,7 +37,7 @@ void GP_CLI_COMMAND_SIT::process(MapSession* PSession, CCharEntity* PChar) const // Retail accurate: Can inject /sit while healing/logging out, but it cancels the effect. PChar->StatusEffectContainer->DelStatusEffectSilent(EFFECT_HEALING); - switch (static_cast(Mode)) + switch (static_cast(this->Mode)) { case GP_CLI_COMMAND_SIT_MODE::Toggle: PChar->animation = PChar->animation == ANIMATION_SIT ? ANIMATION_NONE : ANIMATION_SIT; diff --git a/src/map/packets/c2s/0x0eb_reqsubmapnum.cpp b/src/map/packets/c2s/0x0eb_reqsubmapnum.cpp index 936bc900a07..95e43a64447 100644 --- a/src/map/packets/c2s/0x0eb_reqsubmapnum.cpp +++ b/src/map/packets/c2s/0x0eb_reqsubmapnum.cpp @@ -27,7 +27,8 @@ auto GP_CLI_COMMAND_REQSUBMAPNUM::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { // No parameter to validate. - return PacketValidator(); + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }); } void GP_CLI_COMMAND_REQSUBMAPNUM::process(MapSession* PSession, CCharEntity* PChar) const diff --git a/src/map/packets/c2s/0x0f0_rescue.cpp b/src/map/packets/c2s/0x0f0_rescue.cpp index 9122163f8d6..d2c39d5cc23 100644 --- a/src/map/packets/c2s/0x0f0_rescue.cpp +++ b/src/map/packets/c2s/0x0f0_rescue.cpp @@ -30,13 +30,9 @@ auto GP_CLI_COMMAND_RESCUE::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() - .mustEqual(State, 0, "State not 0") - .isNotJailed(PChar) - .isNotEngaged(PChar) - .isNotInEvent(PChar) - .isNotFishing(PChar) - .isNotCrafting(PChar); + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent, BlockedState::Crafting, BlockedState::Fishing, BlockedState::Jailed, BlockedState::Engaged }) + .mustEqual(this->State, 0, "State not 0"); } void GP_CLI_COMMAND_RESCUE::process(MapSession* PSession, CCharEntity* PChar) const diff --git a/src/map/packets/c2s/0x0f1_buffcancel.cpp b/src/map/packets/c2s/0x0f1_buffcancel.cpp index c9bc8eeaafa..a6625fd184a 100644 --- a/src/map/packets/c2s/0x0f1_buffcancel.cpp +++ b/src/map/packets/c2s/0x0f1_buffcancel.cpp @@ -27,11 +27,12 @@ auto GP_CLI_COMMAND_BUFFCANCEL::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { // TODO: Build a list of known cancellable buffs - return PacketValidator() - .range("BuffNo", BuffNo, 0, MAX_EFFECTID); + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }) + .range("BuffNo", this->BuffNo, 0, MAX_EFFECTID); } void GP_CLI_COMMAND_BUFFCANCEL::process(MapSession* PSession, CCharEntity* PChar) const { - PChar->StatusEffectContainer->DelStatusEffectsByIcon(BuffNo); + PChar->StatusEffectContainer->DelStatusEffectsByIcon(this->BuffNo); } diff --git a/src/map/packets/c2s/0x0f2_submapchange.cpp b/src/map/packets/c2s/0x0f2_submapchange.cpp index 0bc3297bf99..9867e252e43 100644 --- a/src/map/packets/c2s/0x0f2_submapchange.cpp +++ b/src/map/packets/c2s/0x0f2_submapchange.cpp @@ -27,10 +27,10 @@ auto GP_CLI_COMMAND_SUBMAPCHANGE::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { // TODO: List of valid submap numbers per zone - auto pv = PacketValidator() - .range("State", State, GP_CLI_COMMAND_SUBMAPCHANGE_STATE::General, GP_CLI_COMMAND_SUBMAPCHANGE_STATE::Event); + auto pv = PacketValidator(PChar) + .range("State", this->State, GP_CLI_COMMAND_SUBMAPCHANGE_STATE::General, GP_CLI_COMMAND_SUBMAPCHANGE_STATE::Event); - if (State == static_cast(GP_CLI_COMMAND_SUBMAPCHANGE_STATE::Event)) + if (this->State == static_cast(GP_CLI_COMMAND_SUBMAPCHANGE_STATE::Event)) { pv.mustNotEqual(PChar->currentEvent, nullptr, "Character not in event"); } @@ -40,7 +40,7 @@ auto GP_CLI_COMMAND_SUBMAPCHANGE::validate(MapSession* PSession, const CCharEnti void GP_CLI_COMMAND_SUBMAPCHANGE::process(MapSession* PSession, CCharEntity* PChar) const { - PChar->loc.boundary = SubMapNumber; + PChar->loc.boundary = this->SubMapNumber; charutils::SaveCharPosition(PChar); } diff --git a/src/map/packets/c2s/0x0f4_tracking_list.cpp b/src/map/packets/c2s/0x0f4_tracking_list.cpp index 7b2fd881153..b34a6c27afb 100644 --- a/src/map/packets/c2s/0x0f4_tracking_list.cpp +++ b/src/map/packets/c2s/0x0f4_tracking_list.cpp @@ -26,8 +26,9 @@ auto GP_CLI_COMMAND_TRACKING_LIST::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() - .mustEqual(SendFlg, 1, "SendFlg not equal to 1"); + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }) + .mustEqual(this->SendFlg, 1, "SendFlg not equal to 1"); } void GP_CLI_COMMAND_TRACKING_LIST::process(MapSession* PSession, CCharEntity* PChar) const diff --git a/src/map/packets/c2s/0x0f5_tracking_start.cpp b/src/map/packets/c2s/0x0f5_tracking_start.cpp index 176d8bf631b..b64ead71862 100644 --- a/src/map/packets/c2s/0x0f5_tracking_start.cpp +++ b/src/map/packets/c2s/0x0f5_tracking_start.cpp @@ -26,13 +26,14 @@ auto GP_CLI_COMMAND_TRACKING_START::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() - .range("ActIndex", ActIndex, 0x1, 0x1000); // 1 to 4096 + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }) + .range("ActIndex", this->ActIndex, 0x1, 0x1000); // 1 to 4096 } void GP_CLI_COMMAND_TRACKING_START::process(MapSession* PSession, CCharEntity* PChar) const { - CBaseEntity* target = PChar->GetEntity(ActIndex, TYPE_MOB | TYPE_NPC); + CBaseEntity* target = PChar->GetEntity(this->ActIndex, TYPE_MOB | TYPE_NPC); if (target == nullptr) { // Target not found diff --git a/src/map/packets/c2s/0x0f6_tracking_end.cpp b/src/map/packets/c2s/0x0f6_tracking_end.cpp index 8cf0e746f47..ccecc0a57b1 100644 --- a/src/map/packets/c2s/0x0f6_tracking_end.cpp +++ b/src/map/packets/c2s/0x0f6_tracking_end.cpp @@ -26,7 +26,8 @@ auto GP_CLI_COMMAND_TRACKING_END::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { // No parameter to validate. - return PacketValidator(); + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }); } void GP_CLI_COMMAND_TRACKING_END::process(MapSession* PSession, CCharEntity* PChar) const diff --git a/src/map/packets/c2s/0x0fa_myroom_layout.cpp b/src/map/packets/c2s/0x0fa_myroom_layout.cpp index 9e6e0cb7a44..81e7fbb62bc 100644 --- a/src/map/packets/c2s/0x0fa_myroom_layout.cpp +++ b/src/map/packets/c2s/0x0fa_myroom_layout.cpp @@ -138,7 +138,8 @@ auto anyInstalledFurnishing(CCharEntity* PChar, const uint8 selfCat, const uint8 auto GP_CLI_COMMAND_MYROOM_LAYOUT::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }) .range("MyroomFloorFlg", this->MyroomFloorFlg, 0, 1) // Flag indicating if 2nd floor .range("v", this->v, 0, 3) // Rotation of the item (0-3) .range("y", this->y, 0, 25); // Stacking elevation (parent height / 10) diff --git a/src/map/packets/c2s/0x0fb_myroom_bankin.cpp b/src/map/packets/c2s/0x0fb_myroom_bankin.cpp index d5308fb7aea..565a5b66f34 100644 --- a/src/map/packets/c2s/0x0fb_myroom_bankin.cpp +++ b/src/map/packets/c2s/0x0fb_myroom_bankin.cpp @@ -42,7 +42,8 @@ const std::set validContainers = { LOC_MOGSAFE, LOC_MOGSAFE2 }; auto GP_CLI_COMMAND_MYROOM_BANKIN::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }) .mustNotEqual(this->MyroomItemNo, 0, "MyroomItemNo must not equal 0") .oneOf("MyroomCategory", this->MyroomCategory, validContainers); } diff --git a/src/map/packets/c2s/0x0fc_myroom_plant_add.cpp b/src/map/packets/c2s/0x0fc_myroom_plant_add.cpp index 6f0dfb1aa5d..c432370943a 100644 --- a/src/map/packets/c2s/0x0fc_myroom_plant_add.cpp +++ b/src/map/packets/c2s/0x0fc_myroom_plant_add.cpp @@ -41,17 +41,18 @@ const std::set validPlantCategories = { LOC_MOGSAFE, LOC_MOGSAFE2 }; auto GP_CLI_COMMAND_MYROOM_PLANT_ADD::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() - .mustNotEqual(MyroomPlantItemNo, 0, "MyroomPlantItemNo must not be 0") - .mustNotEqual(MyroomAddItemNo, 0, "MyroomAddItemNo must not be 0") - .oneOf("MyroomPlantCategory", MyroomPlantCategory, validPlantCategories) - .oneOf("MyroomAddCategory", MyroomAddCategory, validPlantCategories); + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }) + .mustNotEqual(this->MyroomPlantItemNo, 0, "MyroomPlantItemNo must not be 0") + .mustNotEqual(this->MyroomAddItemNo, 0, "MyroomAddItemNo must not be 0") + .oneOf("MyroomPlantCategory", this->MyroomPlantCategory, validPlantCategories) + .oneOf("MyroomAddCategory", this->MyroomAddCategory, validPlantCategories); } void GP_CLI_COMMAND_MYROOM_PLANT_ADD::process(MapSession* PSession, CCharEntity* PChar) const { - CItemContainer* PPotItemContainer = PChar->getStorage(MyroomPlantCategory); - auto* PPotItem = static_cast(PPotItemContainer->GetItem(MyroomPlantItemIndex)); + CItemContainer* PPotItemContainer = PChar->getStorage(this->MyroomPlantCategory); + auto* PPotItem = static_cast(PPotItemContainer->GetItem(this->MyroomPlantItemIndex)); if (PPotItem == nullptr) { return; @@ -66,8 +67,8 @@ void GP_CLI_COMMAND_MYROOM_PLANT_ADD::process(MapSession* PSession, CCharEntity* return; } - CItemContainer* PItemContainer = PChar->getStorage(MyroomAddCategory); - const CItem* PItem = PItemContainer->GetItem(MyroomAddItemIndex); + CItemContainer* PItemContainer = PChar->getStorage(this->MyroomAddCategory); + const CItem* PItem = PItemContainer->GetItem(this->MyroomAddItemIndex); if (PItem == nullptr || PItem->getQuantity() < 1) { return; @@ -75,29 +76,29 @@ void GP_CLI_COMMAND_MYROOM_PLANT_ADD::process(MapSession* PSession, CCharEntity* bool updatedPot = false; - if (CItemFlowerpot::getPlantFromSeed(MyroomAddItemNo) != FLOWERPOT_PLANT_NONE) + if (CItemFlowerpot::getPlantFromSeed(this->MyroomAddItemNo) != FLOWERPOT_PLANT_NONE) { // Planting a seed in the flowerpot - PChar->pushPacket(MyroomAddItemNo, MsgStd::MooglePlantsSeeds); + PChar->pushPacket(this->MyroomAddItemNo, MsgStd::MooglePlantsSeeds); PPotItem->cleanPot(); - PPotItem->setPlant(CItemFlowerpot::getPlantFromSeed(MyroomAddItemNo)); + PPotItem->setPlant(CItemFlowerpot::getPlantFromSeed(this->MyroomAddItemNo)); PPotItem->setPlantTimestamp(earth_time::vanadiel_timestamp()); PPotItem->setStrength(xirand::GetRandomNumber(33)); gardenutils::GrowToNextStage(PPotItem); updatedPot = true; } - else if (MyroomAddItemNo >= FIRE_CRYSTAL && MyroomAddItemNo <= DARK_CLUSTER) + else if (this->MyroomAddItemNo >= FIRE_CRYSTAL && this->MyroomAddItemNo <= DARK_CLUSTER) { // Feeding the plant a crystal - PChar->pushPacket(MyroomAddItemNo, MsgStd::MoogleUsesItemOnPLant); + PChar->pushPacket(this->MyroomAddItemNo, MsgStd::MoogleUsesItemOnPLant); if (PPotItem->getStage() == FLOWERPOT_STAGE_FIRST_SPROUTS_CRYSTAL) { - PPotItem->setFirstCrystalFeed(CItemFlowerpot::getElementFromItem(MyroomAddItemNo)); + PPotItem->setFirstCrystalFeed(CItemFlowerpot::getElementFromItem(this->MyroomAddItemNo)); updatedPot = true; } else if (PPotItem->getStage() == FLOWERPOT_STAGE_SECOND_SPROUTS_CRYSTAL) { - PPotItem->setSecondCrystalFeed(CItemFlowerpot::getElementFromItem(MyroomAddItemNo)); + PPotItem->setSecondCrystalFeed(CItemFlowerpot::getElementFromItem(this->MyroomAddItemNo)); updatedPot = true; } if (updatedPot) @@ -115,11 +116,11 @@ void GP_CLI_COMMAND_MYROOM_PLANT_ADD::process(MapSession* PSession, CCharEntity* PPotItem->getLocationID(), PPotItem->getSlotID()); - PChar->pushPacket(PPotItem, static_cast(MyroomPlantCategory), MyroomPlantItemIndex); + PChar->pushPacket(PPotItem, static_cast(this->MyroomPlantCategory), this->MyroomPlantItemIndex); - PChar->pushPacket(PPotItem, static_cast(MyroomPlantCategory), MyroomPlantItemIndex); + PChar->pushPacket(PPotItem, static_cast(this->MyroomPlantCategory), this->MyroomPlantItemIndex); - charutils::UpdateItem(PChar, MyroomAddCategory, MyroomAddItemIndex, -1); + charutils::UpdateItem(PChar, this->MyroomAddCategory, this->MyroomAddItemIndex, -1); PChar->pushPacket(PChar); } } diff --git a/src/map/packets/c2s/0x0fd_myroom_plant_check.cpp b/src/map/packets/c2s/0x0fd_myroom_plant_check.cpp index 985e36f7183..1d333bf556c 100644 --- a/src/map/packets/c2s/0x0fd_myroom_plant_check.cpp +++ b/src/map/packets/c2s/0x0fd_myroom_plant_check.cpp @@ -36,15 +36,16 @@ const std::set validPlantCategories = { LOC_MOGSAFE, LOC_MOGSAFE2 }; auto GP_CLI_COMMAND_MYROOM_PLANT_CHECK::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() - .mustNotEqual(MyroomPlantItemNo, 0, "MyroomPlantItemNo must not be 0") - .oneOf("MyroomPlantCategory", MyroomPlantCategory, validPlantCategories); + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }) + .mustNotEqual(this->MyroomPlantItemNo, 0, "MyroomPlantItemNo must not be 0") + .oneOf("MyroomPlantCategory", this->MyroomPlantCategory, validPlantCategories); } void GP_CLI_COMMAND_MYROOM_PLANT_CHECK::process(MapSession* PSession, CCharEntity* PChar) const { - CItemContainer* PItemContainer = PChar->getStorage(MyroomPlantCategory); - auto* PItem = static_cast(PItemContainer->GetItem(MyroomPlantItemIndex)); + CItemContainer* PItemContainer = PChar->getStorage(this->MyroomPlantCategory); + auto* PItem = static_cast(PItemContainer->GetItem(this->MyroomPlantItemIndex)); if (PItem == nullptr) { return; @@ -91,5 +92,5 @@ void GP_CLI_COMMAND_MYROOM_PLANT_CHECK::process(MapSession* PSession, CCharEntit } } - PChar->pushPacket(PItem, static_cast(MyroomPlantCategory), MyroomPlantItemIndex); + PChar->pushPacket(PItem, static_cast(this->MyroomPlantCategory), this->MyroomPlantItemIndex); } diff --git a/src/map/packets/c2s/0x0fe_myroom_plant_crop.cpp b/src/map/packets/c2s/0x0fe_myroom_plant_crop.cpp index 034f415b93f..93fb7bb0a19 100644 --- a/src/map/packets/c2s/0x0fe_myroom_plant_crop.cpp +++ b/src/map/packets/c2s/0x0fe_myroom_plant_crop.cpp @@ -40,15 +40,16 @@ const std::set validPlantCategories = { LOC_MOGSAFE, LOC_MOGSAFE2 }; auto GP_CLI_COMMAND_MYROOM_PLANT_CROP::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() - .mustNotEqual(MyroomPlantItemNo, 0, "MyroomPlantItemNo must not be 0") - .oneOf("MyroomPlantCategory", MyroomPlantCategory, validPlantCategories); + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }) + .mustNotEqual(this->MyroomPlantItemNo, 0, "MyroomPlantItemNo must not be 0") + .oneOf("MyroomPlantCategory", this->MyroomPlantCategory, validPlantCategories); } void GP_CLI_COMMAND_MYROOM_PLANT_CROP::process(MapSession* PSession, CCharEntity* PChar) const { - CItemContainer* PItemContainer = PChar->getStorage(MyroomPlantCategory); - CItemFlowerpot* PItem = static_cast(PItemContainer->GetItem(MyroomPlantItemIndex)); + CItemContainer* PItemContainer = PChar->getStorage(this->MyroomPlantCategory); + CItemFlowerpot* PItem = static_cast(PItemContainer->GetItem(this->MyroomPlantItemIndex)); if (PItem == nullptr) { return; @@ -66,7 +67,7 @@ void GP_CLI_COMMAND_MYROOM_PLANT_CROP::process(MapSession* PSession, CCharEntity if (PItem->isPlanted()) { - if (CancellFlg == 0 && PItem->getStage() == FLOWERPOT_STAGE_MATURE_PLANT) + if (this->CancellFlg == 0 && PItem->getStage() == FLOWERPOT_STAGE_MATURE_PLANT) { // Harvesting plant uint16 resultID = 0; @@ -93,7 +94,7 @@ void GP_CLI_COMMAND_MYROOM_PLANT_CROP::process(MapSession* PSession, CCharEntity PChar->pushPacket(resultID, totalQuantity, 134); // Your moogle from the plant! } - PChar->pushPacket(PItem, static_cast(MyroomPlantCategory), MyroomPlantItemIndex); + PChar->pushPacket(PItem, static_cast(this->MyroomPlantCategory), this->MyroomPlantItemIndex); PItem->cleanPot(); db::preparedStmt("UPDATE char_inventory SET extra = ? WHERE charid = ? AND location = ? AND slot = ? LIMIT 1", @@ -102,7 +103,7 @@ void GP_CLI_COMMAND_MYROOM_PLANT_CROP::process(MapSession* PSession, CCharEntity PItem->getLocationID(), PItem->getSlotID()); - PChar->pushPacket(PItem, static_cast(MyroomPlantCategory), MyroomPlantItemIndex); + PChar->pushPacket(PItem, static_cast(this->MyroomPlantCategory), this->MyroomPlantItemIndex); PChar->pushPacket(PChar); } } diff --git a/src/map/packets/c2s/0x0ff_myroom_plant_stop.cpp b/src/map/packets/c2s/0x0ff_myroom_plant_stop.cpp index d7cff7b4423..6c8af2314f7 100644 --- a/src/map/packets/c2s/0x0ff_myroom_plant_stop.cpp +++ b/src/map/packets/c2s/0x0ff_myroom_plant_stop.cpp @@ -39,20 +39,21 @@ const std::set validPlantCategories = { LOC_MOGSAFE, LOC_MOGSAFE2 }; auto GP_CLI_COMMAND_MYROOM_PLANT_STOP::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() - .mustNotEqual(MyroomPlantItemNo, 0, "MyroomPlantItemNo must not be 0") - .oneOf("MyroomPlantCategory", MyroomPlantCategory, validPlantCategories); + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }) + .mustNotEqual(this->MyroomPlantItemNo, 0, "MyroomPlantItemNo must not be 0") + .oneOf("MyroomPlantCategory", this->MyroomPlantCategory, validPlantCategories); } void GP_CLI_COMMAND_MYROOM_PLANT_STOP::process(MapSession* PSession, CCharEntity* PChar) const { - CItemContainer* PItemContainer = PChar->getStorage(MyroomPlantCategory); - CItemFlowerpot* PItem = static_cast(PItemContainer->GetItem(MyroomPlantItemIndex)); + CItemContainer* PItemContainer = PChar->getStorage(this->MyroomPlantCategory); + CItemFlowerpot* PItem = static_cast(PItemContainer->GetItem(this->MyroomPlantItemIndex)); if (PItem != nullptr && PItem->isPlanted() && PItem->getStage() > FLOWERPOT_STAGE_INITIAL && PItem->getStage() < FLOWERPOT_STAGE_WILTED && !PItem->isDried()) { - PChar->pushPacket(MyroomPlantItemNo, MsgStd::MoogleDriesPlant); - PChar->pushPacket(PItem, static_cast(MyroomPlantCategory), MyroomPlantItemIndex); + PChar->pushPacket(this->MyroomPlantItemNo, MsgStd::MoogleDriesPlant); + PChar->pushPacket(PItem, static_cast(this->MyroomPlantCategory), this->MyroomPlantItemIndex); PItem->setDried(true); db::preparedStmt("UPDATE char_inventory SET extra = ? WHERE charid = ? AND location = ? AND slot = ? LIMIT 1", @@ -61,7 +62,7 @@ void GP_CLI_COMMAND_MYROOM_PLANT_STOP::process(MapSession* PSession, CCharEntity PItem->getLocationID(), PItem->getSlotID()); - PChar->pushPacket(PItem, static_cast(MyroomPlantCategory), MyroomPlantItemIndex); + PChar->pushPacket(PItem, static_cast(this->MyroomPlantCategory), this->MyroomPlantItemIndex); PChar->pushPacket(PChar); } } diff --git a/src/map/packets/c2s/0x100_myroom_job.cpp b/src/map/packets/c2s/0x100_myroom_job.cpp index ab828886170..d6540c4fbc2 100644 --- a/src/map/packets/c2s/0x100_myroom_job.cpp +++ b/src/map/packets/c2s/0x100_myroom_job.cpp @@ -43,19 +43,20 @@ auto GP_CLI_COMMAND_MYROOM_JOB::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - auto pv = PacketValidator() + auto pv = PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }) .mustEqual(PChar->loc.zone->CanUseMisc(MISC_MOGMENU) || PChar->m_moghouseID == PChar->id, true, "Player not in MH or zone with Moogle."); - if (MainJobIndex) + if (this->MainJobIndex) { - pv.range("MainJobIndex", MainJobIndex, 0x01, MAX_JOBTYPE - 1) - .mustEqual((PChar->jobs.unlocked & (1 << MainJobIndex)) != 0, true, "Main job not unlocked"); + pv.range("MainJobIndex", this->MainJobIndex, 0x01, MAX_JOBTYPE - 1) + .mustEqual((PChar->jobs.unlocked & (1 << this->MainJobIndex)) != 0, true, "Main job not unlocked"); } - if (SupportJobIndex) + if (this->SupportJobIndex) { - pv.range("SupportJobIndex", SupportJobIndex, 0x00, MAX_JOBTYPE - 1) - .mustEqual((PChar->jobs.unlocked & (1 << SupportJobIndex)) != 0, true, "Support job not unlocked"); + pv.range("SupportJobIndex", this->SupportJobIndex, 0x00, MAX_JOBTYPE - 1) + .mustEqual((PChar->jobs.unlocked & (1 << this->SupportJobIndex)) != 0, true, "Support job not unlocked"); } return pv; @@ -63,21 +64,21 @@ auto GP_CLI_COMMAND_MYROOM_JOB::validate(MapSession* PSession, const CCharEntity void GP_CLI_COMMAND_MYROOM_JOB::process(MapSession* PSession, CCharEntity* PChar) const { - if ((MainJobIndex > 0x00) && (MainJobIndex < MAX_JOBTYPE) && (PChar->jobs.unlocked & (1 << MainJobIndex))) + if ((this->MainJobIndex > 0x00) && (this->MainJobIndex < MAX_JOBTYPE) && (PChar->jobs.unlocked & (1 << this->MainJobIndex))) { const JOBTYPE prevjob = PChar->GetMJob(); PChar->resetPetZoningInfo(); charutils::SaveJobChangeGear(PChar); charutils::RemoveAllEquipment(PChar); - PChar->SetMJob(MainJobIndex); + PChar->SetMJob(this->MainJobIndex); PChar->SetMLevel(PChar->jobs.job[PChar->GetMJob()]); PChar->SetSLevel(PChar->jobs.job[PChar->GetSJob()]); // If removing RemoveAllEquipment, please add a charutils::CheckUnarmedItem(PChar) if main hand is empty. puppetutils::LoadAutomaton(PChar); - if (MainJobIndex == JOB_BLU) + if (this->MainJobIndex == JOB_BLU) { blueutils::LoadSetSpells(PChar); } @@ -96,18 +97,18 @@ void GP_CLI_COMMAND_MYROOM_JOB::process(MapSession* PSession, CCharEntity* PChar } } - if ((SupportJobIndex > 0x00) && (SupportJobIndex < MAX_JOBTYPE) && (PChar->jobs.unlocked & (1 << SupportJobIndex))) + if ((this->SupportJobIndex > 0x00) && (this->SupportJobIndex < MAX_JOBTYPE) && (PChar->jobs.unlocked & (1 << this->SupportJobIndex))) { JOBTYPE prevsjob = PChar->GetSJob(); PChar->resetPetZoningInfo(); - PChar->SetSJob(SupportJobIndex); + PChar->SetSJob(this->SupportJobIndex); PChar->SetSLevel(PChar->jobs.job[PChar->GetSJob()]); charutils::CheckEquipLogic(PChar, SCRIPT_CHANGESJOB, prevsjob); puppetutils::LoadAutomaton(PChar); - if (SupportJobIndex == JOB_BLU) + if (this->SupportJobIndex == JOB_BLU) { blueutils::LoadSetSpells(PChar); } diff --git a/src/map/packets/c2s/0x100_myroom_job.h b/src/map/packets/c2s/0x100_myroom_job.h index b89a22bd88e..07edb5f7cf0 100644 --- a/src/map/packets/c2s/0x100_myroom_job.h +++ b/src/map/packets/c2s/0x100_myroom_job.h @@ -25,6 +25,7 @@ // https://github.com/atom0s/XiPackets/tree/main/world/client/0x0100 // This packet is sent by the client when requesting to change jobs. GP_CLI_PACKET(GP_CLI_COMMAND_MYROOM_JOB, - uint8_t MainJobIndex; // PS2: MainJobIndex - uint8_t SupportJobIndex; // PS2: SupportJobIndex + uint8_t MainJobIndex; // PS2: MainJobIndex + uint8_t SupportJobIndex; // PS2: SupportJobIndex + uint16_t padding00; // Padding; unused. ); diff --git a/src/map/packets/c2s/0x102_extended_job.cpp b/src/map/packets/c2s/0x102_extended_job.cpp index fe93f96c5b1..e11b40d9b5b 100644 --- a/src/map/packets/c2s/0x102_extended_job.cpp +++ b/src/map/packets/c2s/0x102_extended_job.cpp @@ -33,15 +33,16 @@ auto GP_CLI_COMMAND_EXTENDED_JOB::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - auto pv = PacketValidator(); + auto pv = PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }); // Packet is used for 3 different systems. Validation differs based on the job. - if ((PChar->GetMJob() == JOB_BLU || PChar->GetSJob() == JOB_BLU) && Data.bluData.JobIndex == JOB_BLU) + if ((PChar->GetMJob() == JOB_BLU || PChar->GetSJob() == JOB_BLU) && this->Data.bluData.JobIndex == JOB_BLU) { // Case 1: Blue Mage spells // TODO: Check if they own the spell they are trying to equip. } - else if (((PChar->GetMJob() == JOB_PUP || PChar->GetSJob() == JOB_PUP) && Data.pupData.JobIndex == JOB_PUP)) + else if (((PChar->GetMJob() == JOB_PUP || PChar->GetSJob() == JOB_PUP) && this->Data.pupData.JobIndex == JOB_PUP)) { // Case 2: Puppetmaster attachments pv.mustEqual(dynamic_cast(PChar->PPet), nullptr, "Player has a deployed automaton."); @@ -50,37 +51,37 @@ auto GP_CLI_COMMAND_EXTENDED_JOB::validate(MapSession* PSession, const CCharEnti else if (PChar->loc.zone->GetID() == ZONE_FERETORY && PChar->m_PMonstrosity != nullptr) { // Case 3: Monstrosity equipment change - if (Data.monData.Flags0.SpeciesFlag) + if (this->Data.monData.Flags0.SpeciesFlag) { // Player requesting a species change // TODO: Capture actual accepted IDs in a vector in a namespace - pv.range("SpeciesIndex", Data.monData.SpeciesIndex, 1, 511); + pv.range("SpeciesIndex", this->Data.monData.SpeciesIndex, 1, 511); } - if (Data.monData.Flags0.InstinctFlag) + if (this->Data.monData.Flags0.InstinctFlag) { // Player requesting an instinct change for (std::size_t idx = 0; idx < 12; ++idx) { // Ignore instincts being unequipped or unset - if (Data.monData.Slots[idx] != 0xFFFF && Data.monData.Slots[idx] != 0x0) + if (this->Data.monData.Slots[idx] != 0xFFFF && this->Data.monData.Slots[idx] != 0x0) { // TODO: Capture actual range in a vector in a namespace - pv.range("Slots", Data.monData.Slots[idx], 3, 799); + pv.range("Slots", this->Data.monData.Slots[idx], 3, 799); } } } - if (Data.monData.Flags0.Descriptor1Flag) + if (this->Data.monData.Flags0.Descriptor1Flag) { // 0 to unset. Last entry has ID 248. - pv.range("Descriptor1Index", Data.monData.Descriptor1Index, 0, 248); + pv.range("Descriptor1Index", this->Data.monData.Descriptor1Index, 0, 248); } - if (Data.monData.Flags0.Descriptor2Flag) + if (this->Data.monData.Flags0.Descriptor2Flag) { // 0 to unset. Last entry has ID 248. - pv.range("Descriptor2Index", Data.monData.Descriptor2Index, 0, 248); + pv.range("Descriptor2Index", this->Data.monData.Descriptor2Index, 0, 248); } } else @@ -93,9 +94,9 @@ auto GP_CLI_COMMAND_EXTENDED_JOB::validate(MapSession* PSession, const CCharEnti void GP_CLI_COMMAND_EXTENDED_JOB::process(MapSession* PSession, CCharEntity* PChar) const { - if ((PChar->GetMJob() == JOB_BLU || PChar->GetSJob() == JOB_BLU) && Data.bluData.JobIndex == JOB_BLU) + if ((PChar->GetMJob() == JOB_BLU || PChar->GetSJob() == JOB_BLU) && this->Data.bluData.JobIndex == JOB_BLU) { - const auto bluData = Data.bluData; + const auto bluData = this->Data.bluData; // This may be a request to add or remove set spells, so lets check. @@ -201,9 +202,9 @@ void GP_CLI_COMMAND_EXTENDED_JOB::process(MapSession* PSession, CCharEntity* PCh } } } - else if ((PChar->GetMJob() == JOB_PUP || PChar->GetSJob() == JOB_PUP) && Data.pupData.JobIndex == JOB_PUP) + else if ((PChar->GetMJob() == JOB_PUP || PChar->GetSJob() == JOB_PUP) && this->Data.pupData.JobIndex == JOB_PUP) { - const auto pupData = Data.pupData; + const auto pupData = this->Data.pupData; if (pupData.ItemId == 0x00) { @@ -247,6 +248,6 @@ void GP_CLI_COMMAND_EXTENDED_JOB::process(MapSession* PSession, CCharEntity* PCh } else if (PChar->loc.zone->GetID() == ZONE_FERETORY && PChar->m_PMonstrosity != nullptr) { - monstrosity::HandleEquipChangePacket(PChar, Data.monData); + monstrosity::HandleEquipChangePacket(PChar, this->Data.monData); } } diff --git a/src/map/packets/c2s/0x104_bazaar_exit.cpp b/src/map/packets/c2s/0x104_bazaar_exit.cpp index 4566a9bd88d..0d8056bad53 100644 --- a/src/map/packets/c2s/0x104_bazaar_exit.cpp +++ b/src/map/packets/c2s/0x104_bazaar_exit.cpp @@ -27,7 +27,8 @@ auto GP_CLI_COMMAND_BAZAAR_EXIT::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { // No parameters to validate. - return PacketValidator(); + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }); } void GP_CLI_COMMAND_BAZAAR_EXIT::process(MapSession* PSession, CCharEntity* PChar) const diff --git a/src/map/packets/c2s/0x105_bazaar_list.cpp b/src/map/packets/c2s/0x105_bazaar_list.cpp index 410222c0f80..e286b8b01f9 100644 --- a/src/map/packets/c2s/0x105_bazaar_list.cpp +++ b/src/map/packets/c2s/0x105_bazaar_list.cpp @@ -27,16 +27,17 @@ auto GP_CLI_COMMAND_BAZAAR_LIST::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }) .mustEqual(PChar->BazaarID.id, 0, "Character already has a Bazaar ID") .mustEqual(PChar->BazaarID.targid, 0, "Character already has a Bazaar Target ID"); } void GP_CLI_COMMAND_BAZAAR_LIST::process(MapSession* PSession, CCharEntity* PChar) const { - CCharEntity* PTarget = UniqueNo != 0 ? PChar->loc.zone->GetCharByID(UniqueNo) : static_cast(PChar->GetEntity(PChar->m_TargID, TYPE_PC)); + CCharEntity* PTarget = this->UniqueNo != 0 ? PChar->loc.zone->GetCharByID(this->UniqueNo) : static_cast(PChar->GetEntity(PChar->m_TargID, TYPE_PC)); - if (PTarget != nullptr && PTarget->id == UniqueNo && PTarget->hasBazaar()) + if (PTarget != nullptr && PTarget->id == this->UniqueNo && PTarget->hasBazaar()) { PChar->BazaarID.id = PTarget->id; PChar->BazaarID.targid = PTarget->targid; diff --git a/src/map/packets/c2s/0x106_bazaar_buy.cpp b/src/map/packets/c2s/0x106_bazaar_buy.cpp index 6f1ebeff571..201395698c3 100644 --- a/src/map/packets/c2s/0x106_bazaar_buy.cpp +++ b/src/map/packets/c2s/0x106_bazaar_buy.cpp @@ -37,7 +37,8 @@ auto GP_CLI_COMMAND_BAZAAR_BUY::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { // TODO: Short-circuit PV so we can bring all the other checks into this function - return PacketValidator() + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }) .range("BuyNum", this->BuyNum, 1, 99); } diff --git a/src/map/packets/c2s/0x109_bazaar_open.cpp b/src/map/packets/c2s/0x109_bazaar_open.cpp index 0ffb1e787ff..900c01a6a15 100644 --- a/src/map/packets/c2s/0x109_bazaar_open.cpp +++ b/src/map/packets/c2s/0x109_bazaar_open.cpp @@ -25,7 +25,8 @@ auto GP_CLI_COMMAND_BAZAAR_OPEN::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }) .mustEqual(PChar->isSettingBazaarPrices, true, "isSettingBazaarPrices not true"); } diff --git a/src/map/packets/c2s/0x10a_bazaar_itemset.cpp b/src/map/packets/c2s/0x10a_bazaar_itemset.cpp index 55fe962e20a..b58eb4bd4f5 100644 --- a/src/map/packets/c2s/0x10a_bazaar_itemset.cpp +++ b/src/map/packets/c2s/0x10a_bazaar_itemset.cpp @@ -28,8 +28,9 @@ auto GP_CLI_COMMAND_BAZAAR_ITEMSET::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { // TODO: Need PV to support short-circuiting so we can nest null checks and move the PStorage/PItem checks here - return PacketValidator() - .range("Price", Price, 0, 99999999); // Bazaar max sell price is 99,999,999 gil + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }) + .range("Price", this->Price, 0, 99999999); // Bazaar max sell price is 99,999,999 gil } void GP_CLI_COMMAND_BAZAAR_ITEMSET::process(MapSession* PSession, CCharEntity* PChar) const @@ -40,7 +41,7 @@ void GP_CLI_COMMAND_BAZAAR_ITEMSET::process(MapSession* PSession, CCharEntity* P return; } - CItem* PItem = PStorage->GetItem(ItemIndex); + CItem* PItem = PStorage->GetItem(this->ItemIndex); if (PItem == nullptr) { return; @@ -48,20 +49,20 @@ void GP_CLI_COMMAND_BAZAAR_ITEMSET::process(MapSession* PSession, CCharEntity* P if (PItem->getReserve() > 0) { - ShowError("Player %s trying to bazaar a RESERVED item! [Item: %i | Slot ID: %i] ", PChar->getName(), PItem->getID(), ItemIndex); + ShowError("Player %s trying to bazaar a RESERVED item! [Item: %i | Slot ID: %i] ", PChar->getName(), PItem->getID(), this->ItemIndex); return; } if (!PItem->hasFlag(ItemFlag::Exclusive) && (!PItem->isSubType(ITEM_LOCKED) || PItem->getCharPrice() != 0)) { - db::preparedStmt("UPDATE char_inventory SET bazaar = ? WHERE charid = ? AND location = 0 AND slot = ?", Price, PChar->id, ItemIndex); + db::preparedStmt("UPDATE char_inventory SET bazaar = ? WHERE charid = ? AND location = 0 AND slot = ?", this->Price, PChar->id, this->ItemIndex); - PItem->setCharPrice(Price); - PItem->setSubType((Price == 0 ? ITEM_UNLOCKED : ITEM_LOCKED)); + PItem->setCharPrice(this->Price); + PItem->setSubType((this->Price == 0 ? ITEM_UNLOCKED : ITEM_LOCKED)); - PChar->pushPacket(PItem, LOC_INVENTORY, ItemIndex); + PChar->pushPacket(PItem, LOC_INVENTORY, this->ItemIndex); PChar->pushPacket(PChar); - DebugBazaarsFmt("Bazaar Interaction [Price Set] - Character: {}, Item: {}, Price: {}", PChar->name, PItem->getName(), Price); + DebugBazaarsFmt("Bazaar Interaction [Price Set] - Character: {}, Item: {}, Price: {}", PChar->name, PItem->getName(), this->Price); } } diff --git a/src/map/packets/c2s/0x10b_bazaar_close.cpp b/src/map/packets/c2s/0x10b_bazaar_close.cpp index 2066d44de61..5d77b822139 100644 --- a/src/map/packets/c2s/0x10b_bazaar_close.cpp +++ b/src/map/packets/c2s/0x10b_bazaar_close.cpp @@ -26,8 +26,9 @@ auto GP_CLI_COMMAND_BAZAAR_CLOSE::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() - .mustEqual(AllListClearFlg, 0, "AllListClearFlg not 0"); // Always 0 + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }) + .mustEqual(this->AllListClearFlg, 0, "AllListClearFlg not 0"); // Always 0 } void GP_CLI_COMMAND_BAZAAR_CLOSE::process(MapSession* PSession, CCharEntity* PChar) const diff --git a/src/map/packets/c2s/0x10c_roe_start.cpp b/src/map/packets/c2s/0x10c_roe_start.cpp index b3d1a333c47..30ec2d6837e 100644 --- a/src/map/packets/c2s/0x10c_roe_start.cpp +++ b/src/map/packets/c2s/0x10c_roe_start.cpp @@ -28,7 +28,8 @@ auto GP_CLI_COMMAND_ROE_START::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }) .mustEqual(settings::get("main.ENABLE_ROE"), true, "RoE is disabled") .range("ObjectiveId", this->ObjectiveId, 0, 4096) .mustEqual(roeutils::RoeSystem.TimedRecords.test(this->ObjectiveId), false, "Cannot start a timed record") diff --git a/src/map/packets/c2s/0x10d_roe_remove.cpp b/src/map/packets/c2s/0x10d_roe_remove.cpp index 7a594452cbf..bd2421b545d 100644 --- a/src/map/packets/c2s/0x10d_roe_remove.cpp +++ b/src/map/packets/c2s/0x10d_roe_remove.cpp @@ -27,13 +27,14 @@ auto GP_CLI_COMMAND_ROE_REMOVE::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }) .mustEqual(settings::get("main.ENABLE_ROE"), true, "RoE is disabled") - .range("ObjectiveId", ObjectiveId, 0, 4096); + .range("ObjectiveId", this->ObjectiveId, 0, 4096); } void GP_CLI_COMMAND_ROE_REMOVE::process(MapSession* PSession, CCharEntity* PChar) const { - roeutils::DelEminenceRecord(PChar, ObjectiveId); + roeutils::DelEminenceRecord(PChar, this->ObjectiveId); PChar->pushPacket(PChar); } diff --git a/src/map/packets/c2s/0x10e_roe_claim.cpp b/src/map/packets/c2s/0x10e_roe_claim.cpp index 2b1793796a1..571256d3223 100644 --- a/src/map/packets/c2s/0x10e_roe_claim.cpp +++ b/src/map/packets/c2s/0x10e_roe_claim.cpp @@ -27,13 +27,14 @@ auto GP_CLI_COMMAND_ROE_CLAIM::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }) .mustEqual(settings::get("main.ENABLE_ROE"), true, "RoE is disabled") - .range("ObjectiveId", ObjectiveId, 0, 4096); + .range("ObjectiveId", this->ObjectiveId, 0, 4096); } void GP_CLI_COMMAND_ROE_CLAIM::process(MapSession* PSession, CCharEntity* PChar) const { - roeutils::onRecordClaim(PChar, ObjectiveId); + roeutils::onRecordClaim(PChar, this->ObjectiveId); PChar->pushPacket(PChar); } diff --git a/src/map/packets/c2s/0x10f_currencies_1.cpp b/src/map/packets/c2s/0x10f_currencies_1.cpp index 24cd56acaae..7c27d6b7d1d 100644 --- a/src/map/packets/c2s/0x10f_currencies_1.cpp +++ b/src/map/packets/c2s/0x10f_currencies_1.cpp @@ -27,7 +27,8 @@ auto GP_CLI_COMMAND_CURRENCIES_1::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { // No parameters to validate for this packet. - return PacketValidator(); + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }); } void GP_CLI_COMMAND_CURRENCIES_1::process(MapSession* PSession, CCharEntity* PChar) const diff --git a/src/map/packets/c2s/0x110_fishing_2.cpp b/src/map/packets/c2s/0x110_fishing_2.cpp index 64643fabaab..72ef3a322ee 100644 --- a/src/map/packets/c2s/0x110_fishing_2.cpp +++ b/src/map/packets/c2s/0x110_fishing_2.cpp @@ -25,21 +25,22 @@ auto GP_CLI_COMMAND_FISHING_2::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }) .mustEqual(settings::get("map.FISHING_ENABLE"), true, "Fishing is disabled") .mustEqual(PChar->GetMLevel() >= settings::get("map.FISHING_MIN_LEVEL"), true, "Character below fishing minimum level") - .mustEqual(UniqueNo, PChar->id, "Character id mismatch") - .mustEqual(ActIndex, PChar->targid, "Character targid mismatch") - .oneOf(mode) + .mustEqual(this->UniqueNo, PChar->id, "Character id mismatch") + .mustEqual(this->ActIndex, PChar->targid, "Character targid mismatch") + .oneOf(this->mode) .custom([&](PacketValidator& v) { // clang-format off - switch (static_cast(mode)) + switch (static_cast(this->mode)) { case GP_CLI_COMMAND_FISHING_2_MODE::RequestCheckHook: // para and para2 are both 0 for RequestCheckHook - v.mustEqual(para, 0, "para must be 0") - .mustEqual(para2, 0, "para2 must be 0"); + v.mustEqual(this->para, 0, "para must be 0") + .mustEqual(this->para2, 0, "para2 must be 0"); break; case GP_CLI_COMMAND_FISHING_2_MODE::RequestEndMiniGame: // para has various values depending on the reason @@ -47,27 +48,27 @@ auto GP_CLI_COMMAND_FISHING_2::validate(MapSession* PSession, const CCharEntity* // - Equals to 200 when client force exits the mini game // - Equals to 0 when client successfully catches a fish // - Else it is equal to the fish remaining stamina - v.range("para", para, 0, 300); + v.range("para", this->para, 0, 300); // if para2 is non-zero, it must equal current hooked fish special - if (para2 != 0) + if (this->para2 != 0) { if (PChar->hookedFish) { - v.mustEqual(para2, PChar->hookedFish->special, "para2 not equal to current hooked fish special"); + v.mustEqual(this->para2, PChar->hookedFish->special, "para2 not equal to current hooked fish special"); } } break; case GP_CLI_COMMAND_FISHING_2_MODE::RequestRelease: // para and para2 are both 0 for RequestRelease - v.mustEqual(para, 0, "para must be 0") - .mustEqual(para2, 0, "para2 must be 0"); + v.mustEqual(this->para, 0, "para must be 0") + .mustEqual(this->para2, 0, "para2 must be 0"); break; case GP_CLI_COMMAND_FISHING_2_MODE::RequestPotentialTimeout: // para is set to time remaining, para2 is always 0 // todo: unknown actual range, this parameter is currently unused - v.range("para", para, 0, 10) - .mustEqual(para2, 0, "para2 must be 0"); + v.range("para", this->para, 0, 10) + .mustEqual(this->para2, 0, "para2 must be 0"); break; } // clang-format on @@ -76,5 +77,5 @@ auto GP_CLI_COMMAND_FISHING_2::validate(MapSession* PSession, const CCharEntity* void GP_CLI_COMMAND_FISHING_2::process(MapSession* PSession, CCharEntity* PChar) const { - fishingutils::FishingAction(PChar, static_cast(mode), para, para2); + fishingutils::FishingAction(PChar, static_cast(this->mode), this->para, this->para2); } diff --git a/src/map/packets/c2s/0x112_battlefield_req.cpp b/src/map/packets/c2s/0x112_battlefield_req.cpp index 849a707b379..417e6edef10 100644 --- a/src/map/packets/c2s/0x112_battlefield_req.cpp +++ b/src/map/packets/c2s/0x112_battlefield_req.cpp @@ -25,11 +25,11 @@ auto GP_CLI_COMMAND_BATTLEFIELD_REQ::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() - .oneOf(Kind); + return PacketValidator(PChar) + .oneOf(this->Kind); } void GP_CLI_COMMAND_BATTLEFIELD_REQ::process(MapSession* PSession, CCharEntity* PChar) const { - ShowDebugFmt("GP_CLI_COMMAND_BATTLEFIELD_REQ: Not implemented. Kind: {}", Kind); + ShowDebugFmt("GP_CLI_COMMAND_BATTLEFIELD_REQ: Not implemented. Kind: {}", this->Kind); } diff --git a/src/map/packets/c2s/0x112_battlefield_req.h b/src/map/packets/c2s/0x112_battlefield_req.h index f7f87c8083e..710d00f26bf 100644 --- a/src/map/packets/c2s/0x112_battlefield_req.h +++ b/src/map/packets/c2s/0x112_battlefield_req.h @@ -33,6 +33,6 @@ enum class GP_CLI_COMMAND_BATTLEFIELD_REQ_KIND : uint8_t // https://github.com/atom0s/XiPackets/tree/main/world/client/0x0112 // This packet is sent by the client when requesting extra data about certain battlefield content. GP_CLI_PACKET(GP_CLI_COMMAND_BATTLEFIELD_REQ, - uint8_t Kind; // The packet kind. - uint8_t padding00; // Padding; unused. + uint8_t Kind; // The packet kind. + uint8_t padding00[3]; // Padding; unused. ); diff --git a/src/map/packets/c2s/0x113_sitchair.cpp b/src/map/packets/c2s/0x113_sitchair.cpp index 497b7f8ffb8..b8572c24f5d 100644 --- a/src/map/packets/c2s/0x113_sitchair.cpp +++ b/src/map/packets/c2s/0x113_sitchair.cpp @@ -28,12 +28,10 @@ auto GP_CLI_COMMAND_SITCHAIR::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() - .isNotCrafting(PChar) - .isNormalStatus(PChar) - .isNotPreventedAction(PChar) - .oneOf(Mode) - .range("ChairId", ChairId, 0, 20); // 10 chairs + 10 reserved slots for future use + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent, BlockedState::AbnormalStatus, BlockedState::Crafting, BlockedState::PreventAction }) + .oneOf(this->Mode) + .range("ChairId", this->ChairId, 0, 20); // 10 chairs + 10 reserved slots for future use } void GP_CLI_COMMAND_SITCHAIR::process(MapSession* PSession, CCharEntity* PChar) const @@ -41,14 +39,14 @@ void GP_CLI_COMMAND_SITCHAIR::process(MapSession* PSession, CCharEntity* PChar) // Retail accurate: Can inject /sitchair while healing/logging out, but it cancels the effect. PChar->StatusEffectContainer->DelStatusEffectSilent(EFFECT_HEALING); - if (Mode == static_cast(GP_CLI_COMMAND_SITCHAIR_MODE::Off)) + if (this->Mode == static_cast(GP_CLI_COMMAND_SITCHAIR_MODE::Off)) { PChar->animation = ANIMATION_NONE; PChar->updatemask |= UPDATE_HP; return; } - uint8 chairId = ChairId + ANIMATION_SITCHAIR_0; + uint8 chairId = this->ChairId + ANIMATION_SITCHAIR_0; // Validate key item ownership for 64 through 83 if (chairId != ANIMATION_SITCHAIR_0 && !charutils::hasKeyItem(PChar, static_cast(chairId + 0xACA))) diff --git a/src/map/packets/c2s/0x114_map_markers.cpp b/src/map/packets/c2s/0x114_map_markers.cpp index 152e9f87bbf..5241bd788f4 100644 --- a/src/map/packets/c2s/0x114_map_markers.cpp +++ b/src/map/packets/c2s/0x114_map_markers.cpp @@ -27,7 +27,7 @@ auto GP_CLI_COMMAND_MAP_MARKERS::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { // No parameters to validate for this packet. - return PacketValidator(); + return PacketValidator(PChar); } void GP_CLI_COMMAND_MAP_MARKERS::process(MapSession* PSession, CCharEntity* PChar) const diff --git a/src/map/packets/c2s/0x115_currencies_2.cpp b/src/map/packets/c2s/0x115_currencies_2.cpp index 7af3b9919df..db2f77bddb7 100644 --- a/src/map/packets/c2s/0x115_currencies_2.cpp +++ b/src/map/packets/c2s/0x115_currencies_2.cpp @@ -27,7 +27,8 @@ auto GP_CLI_COMMAND_CURRENCIES_2::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { // No parameters to validate for this packet. - return PacketValidator(); + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }); } void GP_CLI_COMMAND_CURRENCIES_2::process(MapSession* PSession, CCharEntity* PChar) const diff --git a/src/map/packets/c2s/0x116_unity_menu.cpp b/src/map/packets/c2s/0x116_unity_menu.cpp index 7d60a9d6505..48947377874 100644 --- a/src/map/packets/c2s/0x116_unity_menu.cpp +++ b/src/map/packets/c2s/0x116_unity_menu.cpp @@ -27,8 +27,9 @@ auto GP_CLI_COMMAND_UNITY_MENU::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() - .range("Kind", Kind, 0x0, 0x1); // Kind 0 = First set of 32 packets, Kind 1 = Second set of 32 packets + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }) + .range("Kind", this->Kind, 0x0, 0x1); // Kind 0 = First set of 32 packets, Kind 1 = Second set of 32 packets } void GP_CLI_COMMAND_UNITY_MENU::process(MapSession* PSession, CCharEntity* PChar) const diff --git a/src/map/packets/c2s/0x117_unity_quest.cpp b/src/map/packets/c2s/0x117_unity_quest.cpp index 3e671fe1cd9..64fff5bbfec 100644 --- a/src/map/packets/c2s/0x117_unity_quest.cpp +++ b/src/map/packets/c2s/0x117_unity_quest.cpp @@ -27,8 +27,9 @@ auto GP_CLI_COMMAND_UNITY_QUEST::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() - .mustEqual(Kind, 0x0, "Kind not 0x0"); // Client always sends 0x0 despite possibly supporting 0x1, 0x2 + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }) + .mustEqual(this->Kind, 0x0, "Kind not 0x0"); // Client always sends 0x0 despite possibly supporting 0x1, 0x2 } void GP_CLI_COMMAND_UNITY_QUEST::process(MapSession* PSession, CCharEntity* PChar) const diff --git a/src/map/packets/c2s/0x118_unity_toggle.cpp b/src/map/packets/c2s/0x118_unity_toggle.cpp index 779a08d5556..8f7c68f04d9 100644 --- a/src/map/packets/c2s/0x118_unity_toggle.cpp +++ b/src/map/packets/c2s/0x118_unity_toggle.cpp @@ -27,8 +27,8 @@ auto GP_CLI_COMMAND_UNITY_TOGGLE::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() - .oneOf(Mode); + return PacketValidator(PChar) + .oneOf(this->Mode); } void GP_CLI_COMMAND_UNITY_TOGGLE::process(MapSession* PSession, CCharEntity* PChar) const @@ -38,7 +38,7 @@ void GP_CLI_COMMAND_UNITY_TOGGLE::process(MapSession* PSession, CCharEntity* PCh unitychat::DelOnlineMember(PChar, PChar->PUnityChat->getLeader()); } - if (Mode == static_cast(GP_CLI_COMMAND_UNITY_TOGGLE_MODE::Active)) + if (this->Mode == static_cast(GP_CLI_COMMAND_UNITY_TOGGLE_MODE::Active)) { unitychat::AddOnlineMember(PChar, PChar->profile.unity_leader); } diff --git a/src/map/packets/c2s/0x119_emote_list.cpp b/src/map/packets/c2s/0x119_emote_list.cpp index 5740398a48f..708dd1fae82 100644 --- a/src/map/packets/c2s/0x119_emote_list.cpp +++ b/src/map/packets/c2s/0x119_emote_list.cpp @@ -27,7 +27,8 @@ auto GP_CLI_COMMAND_EMOTE_LIST::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { // No input validation is needed for this packet. - return PacketValidator(); + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }); } void GP_CLI_COMMAND_EMOTE_LIST::process(MapSession* PSession, CCharEntity* PChar) const diff --git a/src/map/packets/c2s/0x11b_mastery_display.cpp b/src/map/packets/c2s/0x11b_mastery_display.cpp index a520e13c2a1..90ce467e81e 100644 --- a/src/map/packets/c2s/0x11b_mastery_display.cpp +++ b/src/map/packets/c2s/0x11b_mastery_display.cpp @@ -28,15 +28,15 @@ auto GP_CLI_COMMAND_MASTERY_DISPLAY::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() - .oneOf(Mode); + return PacketValidator(PChar) + .oneOf(this->Mode); } void GP_CLI_COMMAND_MASTERY_DISPLAY::process(MapSession* PSession, CCharEntity* PChar) const { - if (PChar->m_jobMasterDisplay != static_cast(Mode)) + if (PChar->m_jobMasterDisplay != static_cast(this->Mode)) { - PChar->m_jobMasterDisplay = Mode; + PChar->m_jobMasterDisplay = this->Mode; charutils::SaveJobMasterDisplay(PChar); PChar->pushPacket(PChar); diff --git a/src/map/packets/c2s/0x11c_party_request.cpp b/src/map/packets/c2s/0x11c_party_request.cpp index c0ce786449e..53fae2fc362 100644 --- a/src/map/packets/c2s/0x11c_party_request.cpp +++ b/src/map/packets/c2s/0x11c_party_request.cpp @@ -26,14 +26,15 @@ auto GP_CLI_COMMAND_PARTY_REQUEST::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { // Not implemented. - return PacketValidator() - .oneOf(Kind); + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }) + .oneOf(this->Kind); } void GP_CLI_COMMAND_PARTY_REQUEST::process(MapSession* PSession, CCharEntity* PChar) const { ShowDebugFmt("GP_CLI_COMMAND_PARTY_REQUEST: Not implemented. UniqueNo: {}, ActIndex: {}, Kind: {}", - UniqueNo, - ActIndex, - Kind); + this->UniqueNo, + this->ActIndex, + this->Kind); } diff --git a/src/map/packets/c2s/0x11c_party_request.h b/src/map/packets/c2s/0x11c_party_request.h index 6267fb8b5cd..3b9ffe2d9ae 100644 --- a/src/map/packets/c2s/0x11c_party_request.h +++ b/src/map/packets/c2s/0x11c_party_request.h @@ -36,4 +36,5 @@ GP_CLI_PACKET(GP_CLI_COMMAND_PARTY_REQUEST, uint16_t ActIndex; // The target index of the player whos party the client is requesting to join. uint8_t Kind; // The packet kind. uint8_t padding00; // Padding; unused. + uint32_t padding01; // Padding; unused. ); diff --git a/src/map/packets/c2s/0x11d_jump.cpp b/src/map/packets/c2s/0x11d_jump.cpp index 5af8c4bb3d5..c0577fff729 100644 --- a/src/map/packets/c2s/0x11d_jump.cpp +++ b/src/map/packets/c2s/0x11d_jump.cpp @@ -28,9 +28,10 @@ auto GP_CLI_COMMAND_JUMP::validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult { - return PacketValidator() - .mustEqual(UniqueNo, PChar->id, "Character ID mismatch") - .mustEqual(ActIndex, PChar->targid, "Target ID mismatch"); + return PacketValidator(PChar) + .blockedBy({ BlockedState::InEvent }) + .mustEqual(this->UniqueNo, PChar->id, "Character ID mismatch") + .mustEqual(this->ActIndex, PChar->targid, "Target ID mismatch"); } void GP_CLI_COMMAND_JUMP::process(MapSession* PSession, CCharEntity* PChar) const @@ -41,5 +42,5 @@ void GP_CLI_COMMAND_JUMP::process(MapSession* PSession, CCharEntity* PChar) cons return; } - PChar->loc.zone->PushPacket(PChar, CHAR_INRANGE_SELF, std::make_unique(PChar, ActIndex)); + PChar->loc.zone->PushPacket(PChar, CHAR_INRANGE_SELF, std::make_unique(PChar, this->ActIndex)); } diff --git a/src/map/packets/c2s/0x11d_jump.h b/src/map/packets/c2s/0x11d_jump.h index a435e60a5ce..e3a8deda560 100644 --- a/src/map/packets/c2s/0x11d_jump.h +++ b/src/map/packets/c2s/0x11d_jump.h @@ -25,7 +25,7 @@ // https://github.com/atom0s/XiPackets/tree/main/world/client/0x011D // This packet is sent by the client when using the jump command. GP_CLI_PACKET(GP_CLI_COMMAND_JUMP, - uint32_t UniqueNo; - uint16_t ActIndex; - uint16_t padding00[2]; // Unused + uint32_t UniqueNo; // PS2: UniqueNo + uint16_t ActIndex; // PS2: ActIndex + uint16_t padding00; // Padding; unused. ); diff --git a/src/map/packets/c2s/CMakeLists.txt b/src/map/packets/c2s/CMakeLists.txt index 87c433ce0df..bedc05d16d9 100644 --- a/src/map/packets/c2s/CMakeLists.txt +++ b/src/map/packets/c2s/CMakeLists.txt @@ -1,5 +1,7 @@ set(PACKET_C2S_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/base.h + ${CMAKE_CURRENT_SOURCE_DIR}/rate_limiter.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/rate_limiter.h ${CMAKE_CURRENT_SOURCE_DIR}/validation.cpp ${CMAKE_CURRENT_SOURCE_DIR}/validation.h ${CMAKE_CURRENT_SOURCE_DIR}/0x00a_login.cpp diff --git a/src/map/packets/c2s/base.h b/src/map/packets/c2s/base.h index 921b796a948..b5a366e1a51 100644 --- a/src/map/packets/c2s/base.h +++ b/src/map/packets/c2s/base.h @@ -22,6 +22,7 @@ #pragma once #include "common/cbasetypes.h" +#include "enums/packet_c2s.h" #include "validation.h" // https://github.com/atom0s/XiPackets/blob/main/world/Header.md @@ -32,18 +33,36 @@ struct GP_CLI_HEADER uint16_t sync; }; -#define GP_CLI_PACKET(PacketName, ...) \ - struct MapSession; \ - class CCharEntity; \ - struct PacketName \ - { \ - GP_CLI_HEADER header; \ - __VA_ARGS__ \ - \ - auto validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult; \ - void process(MapSession* PSession, CCharEntity* PChar) const; \ - inline auto getName() const -> std::string_view \ - { \ - return #PacketName; \ - } \ +#define GP_CLI_PACKET(PacketName, ...) \ + struct MapSession; \ + class CCharEntity; \ + struct PacketName \ + { \ + GP_CLI_HEADER header; \ + __VA_ARGS__ \ + \ + static constexpr std::string_view name = #PacketName; \ + static constexpr PacketC2S packetId = PacketC2S::PacketName; \ + \ + auto validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult; \ + void process(MapSession* PSession, CCharEntity* PChar) const; \ + } + +#define GP_CLI_PACKET_VLA(PacketName, VLAField, ...) \ + struct MapSession; \ + class CCharEntity; \ + struct PacketName \ + { \ + GP_CLI_HEADER header; \ + __VA_ARGS__ \ + \ + static constexpr std::string_view name = #PacketName; \ + static constexpr PacketC2S packetId = PacketC2S::PacketName; \ + static constexpr size_t getMinSize() \ + { \ + return offsetof(PacketName, VLAField); \ + } \ + \ + auto validate(MapSession* PSession, const CCharEntity* PChar) const -> PacketValidationResult; \ + void process(MapSession* PSession, CCharEntity* PChar) const; \ } diff --git a/src/map/packets/c2s/rate_limiter.cpp b/src/map/packets/c2s/rate_limiter.cpp new file mode 100644 index 00000000000..6f7cc6ef107 --- /dev/null +++ b/src/map/packets/c2s/rate_limiter.cpp @@ -0,0 +1,66 @@ +/* +=========================================================================== + + Copyright (c) 2026 LandSandBoat Dev Teams + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see http://www.gnu.org/licenses/ + +=========================================================================== +*/ + +#include "rate_limiter.h" + +#include "entities/charentity.h" + +using namespace std::chrono_literals; + +// TODO: Move these to settings once the settings system supports nested tables. +PacketRateLimiter::PacketRateLimiter() +{ + rateLimits_[0x017] = 1s; // Invalid NPC Information Response + rateLimits_[0x03B] = 1s; // Mannequin Equip + rateLimits_[0x05D] = 2s; // Emotes + rateLimits_[0x083] = 250ms; // Vendor Shop Purchase + rateLimits_[0x0AA] = 250ms; // Guild Shop Purchase + rateLimits_[0x0B7] = 1s; // Assist Channel + rateLimits_[0x0F4] = 1s; // Wide Scan + rateLimits_[0x0F5] = 1s; // Wide Scan Track + rateLimits_[0x11B] = 2s; // Set Job Master Display + rateLimits_[0x11D] = 2s; // Jump +} + +auto PacketRateLimiter::isLimited(CCharEntity* PChar, uint16 packetId) -> bool +{ + const auto rateLimitIt = rateLimits_.find(packetId); + if (rateLimitIt == rateLimits_.end()) + { + return false; + } + + auto timeNow = timer::now(); + const auto [it, wasInserted] = PChar->m_PacketRecievedTimestamps.emplace(packetId, timeNow); + if (wasInserted) + { + return false; + } + + const auto lastPacketReceivedTime = it->second; + const bool limited = timeNow < lastPacketReceivedTime + rateLimitIt->second; + if (!limited) + { + it->second = timeNow; + } + + return limited; +} diff --git a/src/map/packet_guard.h b/src/map/packets/c2s/rate_limiter.h similarity index 62% rename from src/map/packet_guard.h rename to src/map/packets/c2s/rate_limiter.h index 0bbe6c9c838..10e916298db 100644 --- a/src/map/packet_guard.h +++ b/src/map/packets/c2s/rate_limiter.h @@ -1,7 +1,7 @@ -/* +/* =========================================================================== - Copyright (c) 2025 LandSandBoat Dev Teams + Copyright (c) 2026 LandSandBoat Dev Teams This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -22,20 +22,18 @@ #pragma once #include "common/cbasetypes.h" -#include "packet_system.h" -#include "packets/basic.h" +#include "common/timer.h" + +#include class CCharEntity; -namespace PacketGuard +class PacketRateLimiter { +public: + PacketRateLimiter(); + auto isLimited(CCharEntity* PChar, uint16 packetId) -> bool; -void Init(); -bool PacketIsValidForPlayerState(CCharEntity* PChar, uint16 SmallPD_Type); -bool IsRateLimitedPacket(CCharEntity* PChar, uint16 SmallPD_Type); -bool PacketsArrivingInCorrectOrder(CCharEntity* PChar, uint16 SmallPD_Type); -void PrintPacketList(CCharEntity* PChar); - -auto GetPacketAllowList() -> std::unordered_map>&; - -} // namespace PacketGuard +private: + std::unordered_map rateLimits_; +}; diff --git a/src/map/packets/c2s/validation.cpp b/src/map/packets/c2s/validation.cpp index 08ac43e03b7..a6653618e06 100644 --- a/src/map/packets/c2s/validation.cpp +++ b/src/map/packets/c2s/validation.cpp @@ -25,64 +25,44 @@ #include "entities/charentity.h" #include "items/item_linkshell.h" #include "status_effect_container.h" -#include "trade_container.h" #include "utils/charutils.h" #include "utils/jailutils.h" -auto PacketValidator::isNotResting(const CCharEntity* PChar) -> PacketValidator& +auto PacketValidator::blockedBy(const magic_enum::containers::bitset states) -> PacketValidator& { - if (PChar->StatusEffectContainer->HasStatusEffect(EFFECT_HEALING) || - PChar->animation == ANIMATION_HEALING) + if (!result_.valid()) { - result_.addError("Character is resting."); - } - - return *this; -} - -auto PacketValidator::isNotCrafting(const CCharEntity* PChar) -> PacketValidator& -{ - if (PChar->isCrafting()) - { - result_.addError("Character is crafting."); - } - - return *this; -} - -auto PacketValidator::isNormalStatus(const CCharEntity* PChar) -> PacketValidator& -{ - if (PChar->status != STATUS_TYPE::NORMAL) - { - result_.addError("Character has abnormal status."); + return *this; } - return *this; -} - -auto PacketValidator::isNotPreventedAction(const CCharEntity* PChar) -> PacketValidator& -{ - if (PChar->StatusEffectContainer->HasPreventActionEffect()) - { - result_.addError("Character has prevent action effect."); - } + // Checks do short-circuit, keep more expensive ones at the tail end + // clang-format off + CHECK_BLOCKED(BlockedState::Jailed, jailutils::InPrison(PChar_)) + CHECK_BLOCKED(BlockedState::Dead, PChar_->isDead()) + CHECK_BLOCKED(BlockedState::Crafting, PChar_->isCrafting()) + CHECK_BLOCKED(BlockedState::Fishing, PChar_->isFishing()) + CHECK_BLOCKED(BlockedState::Sitting, PChar_->animation == ANIMATION_SIT || (PChar_->animation >= ANIMATION_SITCHAIR_0 && PChar_->animation <= ANIMATION_SITCHAIR_10)) + CHECK_BLOCKED(BlockedState::Mounted, PChar_->isMounted()) + CHECK_BLOCKED(BlockedState::InEvent, PChar_->isInEvent()) + CHECK_BLOCKED(BlockedState::Engaged, PChar_->PAI->IsEngaged()) + CHECK_BLOCKED(BlockedState::AbnormalStatus, PChar_->status != STATUS_TYPE::NORMAL) + CHECK_BLOCKED(BlockedState::Monstrosity, PChar_->m_PMonstrosity != nullptr) + CHECK_BLOCKED(BlockedState::Healing, PChar_->StatusEffectContainer->HasStatusEffect(EFFECT_HEALING) || PChar_->animation == ANIMATION_HEALING) + CHECK_BLOCKED(BlockedState::Charmed, PChar_->StatusEffectContainer->HasStatusEffect({ EFFECT_CHARM, EFFECT_CHARM_II })) + CHECK_BLOCKED(BlockedState::PreventAction, PChar_->StatusEffectContainer->HasPreventActionEffect()) + // clang-format on return *this; } -auto PacketValidator::isNotMonstrosity(const CCharEntity* PChar) -> PacketValidator& +auto PacketValidator::isInEvent(Maybe eventId) -> PacketValidator& { - if (PChar->m_PMonstrosity) + if (!result_.valid()) { - result_.addError("Character is a Monstrosity."); + return *this; } - return *this; -} - -auto PacketValidator::isInEvent(const CCharEntity* PChar, Maybe eventId) -> PacketValidator& -{ - if (!PChar->isInEvent()) + if (!PChar_->isInEvent()) { result_.addError("Not in an event."); } @@ -90,9 +70,9 @@ auto PacketValidator::isInEvent(const CCharEntity* PChar, Maybe eventI { if (eventId.has_value()) { - if (PChar->currentEvent->eventId != eventId.value()) + if (PChar_->currentEvent->eventId != eventId.value()) { - result_.addError(fmt::format("Event ID mismatch {} != {}.", PChar->currentEvent->eventId, eventId.value())); + result_.addError(std::format("Event ID mismatch {} != {}.", PChar_->currentEvent->eventId, eventId.value())); } } } @@ -100,17 +80,22 @@ auto PacketValidator::isInEvent(const CCharEntity* PChar, Maybe eventI return *this; } -auto PacketValidator::hasLinkshellRank(const CCharEntity* PChar, const uint8_t slot, const LSTYPE rank) -> PacketValidator& +auto PacketValidator::hasLinkshellRank(const uint8_t slot, const LSTYPE rank) -> PacketValidator& { + if (!result_.valid()) + { + return *this; + } + CItemLinkshell* PItemLinkshell = nullptr; switch (slot) { case 1: - PItemLinkshell = reinterpret_cast(PChar->getEquip(SLOT_LINK1)); + PItemLinkshell = reinterpret_cast(PChar_->getEquip(SLOT_LINK1)); break; case 2: - PItemLinkshell = reinterpret_cast(PChar->getEquip(SLOT_LINK2)); + PItemLinkshell = reinterpret_cast(PChar_->getEquip(SLOT_LINK2)); break; default: result_.addError("Invalid linkshell slot."); @@ -153,23 +138,33 @@ auto PacketValidator::hasLinkshellRank(const CCharEntity* PChar, const uint8_t s return *this; } -auto PacketValidator::hasZoneMiscFlag(const CCharEntity* PChar, const ZONEMISC flag) -> PacketValidator& +auto PacketValidator::hasZoneMiscFlag(const ZONEMISC flag) -> PacketValidator& { - if (PChar->m_GMlevel == 0 && !PChar->loc.zone->CanUseMisc(flag)) + if (!result_.valid()) + { + return *this; + } + + if (PChar_->m_GMlevel == 0 && !PChar_->loc.zone->CanUseMisc(flag)) { - result_.addError(std::format("Zone {} does not allow misc flag {}.", PChar->loc.zone->getName(), static_cast(flag))); + result_.addError(std::format("Zone {} does not allow misc flag {}.", PChar_->loc.zone->getName(), static_cast(flag))); } return *this; } -auto PacketValidator::isPartyLeader(const CCharEntity* PChar) -> PacketValidator& +auto PacketValidator::isPartyLeader() -> PacketValidator& { - if (!PChar->PParty) + if (!result_.valid()) + { + return *this; + } + + if (!PChar_->PParty) { result_.addError("Not in a party."); } - else if (PChar->PParty->GetLeader() != PChar) + else if (PChar_->PParty->GetLeader() != PChar_) { result_.addError("Not the party leader."); } @@ -177,21 +172,26 @@ auto PacketValidator::isPartyLeader(const CCharEntity* PChar) -> PacketValidator return *this; } -auto PacketValidator::isAllianceLeader(const CCharEntity* PChar) -> PacketValidator& +auto PacketValidator::isAllianceLeader() -> PacketValidator& { - if (!PChar->PParty) + if (!result_.valid()) + { + return *this; + } + + if (!PChar_->PParty) { result_.addError("Not in a party."); } - else if (!PChar->PParty->m_PAlliance) + else if (!PChar_->PParty->m_PAlliance) { result_.addError("Not in an alliance."); } - else if (PChar->PParty->m_PAlliance->getMainParty() == nullptr) + else if (PChar_->PParty->m_PAlliance->getMainParty() == nullptr) { result_.addError("No alliance main party."); } - else if (PChar->PParty->m_PAlliance->getMainParty()->GetLeader() != PChar) + else if (PChar_->PParty->m_PAlliance->getMainParty()->GetLeader() != PChar_) { result_.addError("Not the alliance leader."); } @@ -199,102 +199,61 @@ auto PacketValidator::isAllianceLeader(const CCharEntity* PChar) -> PacketValida return *this; } -auto PacketValidator::isNotFishing(const CCharEntity* PChar) -> PacketValidator& +auto PacketValidator::isEngaged() -> PacketValidator& { - if (PChar->isFishing()) + if (!result_.valid()) { - result_.addError("Character is fishing."); - } - - return *this; -} - -auto PacketValidator::isNotSitting(const CCharEntity* PChar) -> PacketValidator& -{ - if (PChar->animation == ANIMATION_SIT || - (PChar->animation >= ANIMATION_SITCHAIR_0 && PChar->animation <= ANIMATION_SITCHAIR_10)) - { - result_.addError("Character is sitting."); - } - - return *this; -} - -auto PacketValidator::isNotCharmed(const CCharEntity* PChar) -> PacketValidator& -{ - if (PChar->StatusEffectContainer->HasStatusEffect({ EFFECT_CHARM, EFFECT_CHARM_II })) - { - result_.addError("Character is charmed."); + return *this; } - return *this; -} - -auto PacketValidator::isNotMounted(const CCharEntity* PChar) -> PacketValidator& -{ - if (PChar->isMounted()) + if (!PChar_->PAI->IsEngaged()) { - result_.addError("Character is mounted."); + result_.addError("Character is not engaged."); } return *this; } -auto PacketValidator::isEngaged(const CCharEntity* PChar) -> PacketValidator& +auto PacketValidator::isInMogHouse() -> PacketValidator& { - if (!PChar->PAI->IsEngaged()) + if (!result_.valid()) { - result_.addError("Character is not engaged."); + return *this; } - return *this; -} - -auto PacketValidator::isNotEngaged(const CCharEntity* PChar) -> PacketValidator& -{ - if (PChar->PAI->IsEngaged()) + if (!PChar_->inMogHouse()) { - result_.addError("Character is engaged."); + result_.addError("Character is not in Mog House."); } return *this; } -auto PacketValidator::isNotInEvent(const CCharEntity* PChar) -> PacketValidator& +auto PacketValidator::hasKeyItem(const KeyItem keyItemId) -> PacketValidator& { - if (PChar->isInEvent()) + if (!result_.valid()) { - result_.addError("Character is in an event."); + return *this; } - return *this; -} - -auto PacketValidator::isNotJailed(const CCharEntity* PChar) -> PacketValidator& -{ - if (jailutils::InPrison(PChar)) + if (!charutils::hasKeyItem(PChar_, keyItemId)) { - result_.addError("Character is jailed."); + result_.addError(std::format("Missing Key Item {}.", static_cast(keyItemId))); } return *this; } -auto PacketValidator::isInMogHouse(const CCharEntity* PChar) -> PacketValidator& +auto PacketValidator::requiresPriorPacket(PacketC2S expectedPacketId) -> PacketValidator& { - if (!PChar->inMogHouse()) + if (!result_.valid()) { - result_.addError("Character is not in Mog House."); + return *this; } - return *this; -} - -auto PacketValidator::hasKeyItem(const CCharEntity* PChar, const KeyItem keyItemId) -> PacketValidator& -{ - if (!charutils::hasKeyItem(PChar, keyItemId)) + if (PChar_->m_LastPacketType != static_cast(expectedPacketId)) { - result_.addError(std::format("Missing Key Item {}.", static_cast(keyItemId))); + result_.addError(std::format("Expected prior packet {:#05x}, got {:#05x}.", static_cast(expectedPacketId), PChar_->m_LastPacketType)); } return *this; diff --git a/src/map/packets/c2s/validation.h b/src/map/packets/c2s/validation.h index cf24505e860..4bf03abfc68 100644 --- a/src/map/packets/c2s/validation.h +++ b/src/map/packets/c2s/validation.h @@ -21,72 +21,68 @@ #pragma once +#include "common/cbasetypes.h" +#include "enums/blocked_state.h" +#include "enums/packet_c2s.h" #include "magic_enum/magic_enum.hpp" #include "zone.h" +#include #include #include enum LSTYPE : std::uint8_t; enum class KeyItem : uint16_t; class CCharEntity; + class PacketValidationResult { public: PacketValidationResult() - : m_Valid(true) + : valid_(true) { } - auto addError(const std::string& error) -> PacketValidationResult& + auto addError(std::string error) -> PacketValidationResult& { - m_Errors.push_back(error); - setValid(false); + errors_.push_back(std::move(error)); + valid_ = false; return *this; } auto valid() const -> bool { - return m_Valid; - } - - void setValid(const bool valid) - { - m_Valid = valid; + return valid_; } auto errorString() const -> std::string { - std::string errorMessages; - for (const auto& error : m_Errors) - { - if (!errorMessages.empty()) - { - errorMessages += ", "; - } - - errorMessages += error; - } - - return errorMessages; + return fmt::format("{}", fmt::join(errors_, ", ")); } private: - bool m_Valid; - std::vector m_Errors; + bool valid_; + std::vector errors_; }; class PacketValidator { public: - PacketValidator() = default; + explicit PacketValidator(const CCharEntity* PChar) + : PChar_(PChar) + { + } // Left value must equal right value template auto mustEqual(T1 left, T2 right, const std::string& errMsg) -> PacketValidator& { - const auto rightVal = static_cast(right); - if (left != rightVal) + if (!result_.valid()) + { + return *this; + } + + if (left != static_cast(right)) { result_.addError(errMsg); } @@ -98,8 +94,12 @@ class PacketValidator template auto mustNotEqual(T1 left, T2 right, const std::string& errMsg) -> PacketValidator& { - const auto rightVal = static_cast(right); - if (left == rightVal) + if (!result_.valid()) + { + return *this; + } + + if (left == static_cast(right)) { result_.addError(errMsg); } @@ -111,6 +111,10 @@ class PacketValidator template auto range(const std::string& fieldName, T value, MinT min, MaxT max) -> PacketValidator& { + if (!result_.valid()) + { + return *this; + } const auto val = value; const auto minVal = static_cast(min); const auto maxVal = static_cast(max); @@ -131,6 +135,10 @@ class PacketValidator template auto multipleOf(const std::string& fieldName, T value, DivT divisor) -> PacketValidator& { + if (!result_.valid()) + { + return *this; + } const auto divVal = static_cast(divisor); if (value % divVal != 0) { @@ -144,6 +152,11 @@ class PacketValidator template auto oneOf(const std::string& fieldName, T value, const std::set& container) -> PacketValidator& { + if (!result_.valid()) + { + return *this; + } + if (!container.contains(value)) { if constexpr (std::is_enum_v) @@ -164,6 +177,10 @@ class PacketValidator template auto oneOf(const std::underlying_type_t value) -> PacketValidator& { + if (!result_.valid()) + { + return *this; + } static_assert(std::is_enum_v, "Template parameter E must be an enum"); if (!magic_enum::enum_contains(value)) @@ -180,6 +197,10 @@ class PacketValidator template auto oneOf(const E value) -> PacketValidator& { + if (!result_.valid()) + { + return *this; + } static_assert(std::is_enum_v, "Template parameter E must be an enum"); if (!magic_enum::enum_contains(value)) @@ -192,51 +213,36 @@ class PacketValidator return *this; } - // Character must not be resting - auto isNotResting(const CCharEntity* PChar) -> PacketValidator&; - // Character must not be crafting - auto isNotCrafting(const CCharEntity* PChar) -> PacketValidator&; - // Character current status must be NORMAL - auto isNormalStatus(const CCharEntity* PChar) -> PacketValidator&; - // Character must not have any status effect preventing action (Sleep, Stun, Terror etc..) - auto isNotPreventedAction(const CCharEntity* PChar) -> PacketValidator&; - // Character is not assuming a Monstrosity form - auto isNotMonstrosity(const CCharEntity* PChar) -> PacketValidator&; + // Reject if the player is in any of the specified states + auto blockedBy(magic_enum::containers::bitset states) -> PacketValidator&; // Character must be in a valid event state, with optional eventId check. - auto isInEvent(const CCharEntity* PChar, Maybe eventId = std::nullopt) -> PacketValidator&; + auto isInEvent(Maybe eventId = std::nullopt) -> PacketValidator&; // Character must have necessary rank in the linkshell in the given slot - auto hasLinkshellRank(const CCharEntity* PChar, uint8_t slot, LSTYPE rank) -> PacketValidator&; + auto hasLinkshellRank(uint8_t slot, LSTYPE rank) -> PacketValidator&; // Character zone must allow specified flag. GMs can bypass this check. - auto hasZoneMiscFlag(const CCharEntity* PChar, ZONEMISC flag) -> PacketValidator&; + auto hasZoneMiscFlag(ZONEMISC flag) -> PacketValidator&; // Character must be the party leader - auto isPartyLeader(const CCharEntity* PChar) -> PacketValidator&; + auto isPartyLeader() -> PacketValidator&; // Character must be the alliance leader - auto isAllianceLeader(const CCharEntity* PChar) -> PacketValidator&; - // Character must not be fishing - auto isNotFishing(const CCharEntity* PChar) -> PacketValidator&; - // Character must not be sitting - auto isNotSitting(const CCharEntity* PChar) -> PacketValidator&; - // Character must not be charmed - auto isNotCharmed(const CCharEntity* PChar) -> PacketValidator&; - // Character must not be mounted - auto isNotMounted(const CCharEntity* PChar) -> PacketValidator&; + auto isAllianceLeader() -> PacketValidator&; // Character must be engaged in combat - auto isEngaged(const CCharEntity* PChar) -> PacketValidator&; - // Character must not be engaged in combat - auto isNotEngaged(const CCharEntity* PChar) -> PacketValidator&; - // Character must not be in an event - auto isNotInEvent(const CCharEntity* PChar) -> PacketValidator&; - // Character must not be jailed - auto isNotJailed(const CCharEntity* PChar) -> PacketValidator&; + auto isEngaged() -> PacketValidator&; // Character must be in Mog House - auto isInMogHouse(const CCharEntity* PChar) -> PacketValidator&; + auto isInMogHouse() -> PacketValidator&; // Character must have a specific key item - auto hasKeyItem(const CCharEntity* PChar, KeyItem keyItemId) -> PacketValidator&; + auto hasKeyItem(KeyItem keyItemId) -> PacketValidator&; + // The previous packet received from this character must match the expected packet ID + auto requiresPriorPacket(PacketC2S expectedPacketId) -> PacketValidator&; // Custom validation function template auto custom(Func customValidation) -> PacketValidator& { + if (!result_.valid()) + { + return *this; + } + customValidation(*this); return *this; } @@ -252,5 +258,13 @@ class PacketValidator } private: + const CCharEntity* PChar_; PacketValidationResult result_; }; + +#define CHECK_BLOCKED(flag, condition) \ + if (states.test(flag) && (condition)) \ + { \ + result_.addError(std::format("Invalid state: {}", magic_enum::enum_name(flag))); \ + return *this; \ + } diff --git a/src/test/lua/helpers/lua_client_entity_pair_actions.cpp b/src/test/lua/helpers/lua_client_entity_pair_actions.cpp index 1cc5f6f6365..69a44464639 100644 --- a/src/test/lua/helpers/lua_client_entity_pair_actions.cpp +++ b/src/test/lua/helpers/lua_client_entity_pair_actions.cpp @@ -25,7 +25,6 @@ #include "common/logging.h" #include "common/timer.h" #include "common/utils.h" -#include "enums/packet_c2s.h" #include "lua/helpers/lua_client_entity_pair_entities.h" #include "lua/helpers/lua_client_entity_pair_events.h" #include "lua/helpers/lua_client_entity_pair_packets.h" @@ -61,7 +60,7 @@ CLuaClientEntityPairActions::CLuaClientEntityPairActions(CLuaClientEntityPair* p void CLuaClientEntityPairActions::move(const float x, const float y, const float z, sol::optional rot) const { - const auto packet = parent_->packets().createPacket(PacketC2S::GP_CLI_COMMAND_POS); + const auto packet = parent_->packets().createPacket(); auto* posPacket = packet->as(); posPacket->x = x; posPacket->z = y; @@ -86,7 +85,7 @@ void CLuaClientEntityPairActions::useSpell(CLuaBaseEntity* target, const SpellID return; } - const auto packet = parent_->packets().createPacket(PacketC2S::GP_CLI_COMMAND_ACTION); + const auto packet = parent_->packets().createPacket(); auto* actionPacket = packet->as(); actionPacket->UniqueNo = target->getID(); actionPacket->ActIndex = target->getTargID(); @@ -111,7 +110,7 @@ void CLuaClientEntityPairActions::useWeaponskill(CLuaBaseEntity* target, const u return; } - const auto packet = parent_->packets().createPacket(PacketC2S::GP_CLI_COMMAND_ACTION); + const auto packet = parent_->packets().createPacket(); auto* actionPacket = packet->as(); actionPacket->UniqueNo = target->getID(); actionPacket->ActIndex = target->getTargID(); @@ -136,7 +135,7 @@ void CLuaClientEntityPairActions::useAbility(CLuaBaseEntity* target, const ABILI return; } - const auto packet = parent_->packets().createPacket(PacketC2S::GP_CLI_COMMAND_ACTION); + const auto packet = parent_->packets().createPacket(); auto* actionPacket = packet->as(); actionPacket->UniqueNo = target->getID(); actionPacket->ActIndex = target->getTargID(); @@ -161,7 +160,7 @@ void CLuaClientEntityPairActions::changeTarget(CLuaBaseEntity* target) const return; } - const auto packet = parent_->packets().createPacket(PacketC2S::GP_CLI_COMMAND_ACTION); + const auto packet = parent_->packets().createPacket(); auto* actionPacket = packet->as(); actionPacket->UniqueNo = target->getID(); actionPacket->ActIndex = target->getTargID(); @@ -185,7 +184,7 @@ void CLuaClientEntityPairActions::rangedAttack(CLuaBaseEntity* target) const return; } - const auto packet = parent_->packets().createPacket(PacketC2S::GP_CLI_COMMAND_ACTION); + const auto packet = parent_->packets().createPacket(); auto* actionPacket = packet->as(); actionPacket->UniqueNo = target->getID(); actionPacket->ActIndex = target->getTargID(); @@ -209,7 +208,7 @@ void CLuaClientEntityPairActions::useItem(CLuaBaseEntity* target, const uint8 sl return; } - const auto packet = parent_->packets().createPacket(PacketC2S::GP_CLI_COMMAND_ITEM_USE); + const auto packet = parent_->packets().createPacket(); auto* itemPacket = packet->as(); itemPacket->UniqueNo = target->getID(); itemPacket->ItemNum = 0; @@ -235,7 +234,7 @@ void CLuaClientEntityPairActions::trigger(CLuaBaseEntity* target, sol::optional< return; } - const auto packet = parent_->packets().createPacket(PacketC2S::GP_CLI_COMMAND_ACTION); + const auto packet = parent_->packets().createPacket(); auto* actionPacket = packet->as(); actionPacket->UniqueNo = target->getID(); actionPacket->ActIndex = target->getTargID(); @@ -263,7 +262,7 @@ void CLuaClientEntityPairActions::inviteToParty(CLuaBaseEntity* player) const return; } - const auto packet = parent_->packets().createPacket(PacketC2S::GP_CLI_COMMAND_GROUP_SOLICIT_REQ); + const auto packet = parent_->packets().createPacket(); auto* invitePacket = packet->as(); invitePacket->UniqueNo = player->getID(); invitePacket->ActIndex = player->getTargID(); @@ -287,7 +286,7 @@ void CLuaClientEntityPairActions::formAlliance(CLuaBaseEntity* player) const return; } - const auto packet = parent_->packets().createPacket(PacketC2S::GP_CLI_COMMAND_GROUP_SOLICIT_REQ); + const auto packet = parent_->packets().createPacket(); auto* invitePacket = packet->as(); invitePacket->UniqueNo = player->getID(); invitePacket->ActIndex = player->getTargID(); @@ -305,7 +304,7 @@ void CLuaClientEntityPairActions::formAlliance(CLuaBaseEntity* player) const void CLuaClientEntityPairActions::acceptPartyInvite() const { - const auto packet = parent_->packets().createPacket(PacketC2S::GP_CLI_COMMAND_GROUP_SOLICIT_RES); + const auto packet = parent_->packets().createPacket(); auto* responsePacket = packet->as(); responsePacket->Res = static_cast(GP_CLI_COMMAND_GROUP_SOLICIT_RES_RES::Accept); @@ -343,7 +342,7 @@ void CLuaClientEntityPairActions::tradeNpc(const sol::object& npcQuery, const so return; } - const auto packet = parent_->packets().createPacket(PacketC2S::GP_CLI_COMMAND_ITEM_TRANSFER); + const auto packet = parent_->packets().createPacket(); auto* tradePacket = packet->as(); tradePacket->UniqueNo = npc.value().getID(); @@ -401,7 +400,7 @@ void CLuaClientEntityPairActions::tradeNpc(const sol::object& npcQuery, const so void CLuaClientEntityPairActions::acceptRaise() const { - const auto packet = parent_->packets().createPacket(PacketC2S::GP_CLI_COMMAND_ACTION); + const auto packet = parent_->packets().createPacket(); auto* responsePacket = packet->as(); responsePacket->ActionID = GP_CLI_COMMAND_ACTION_ACTIONID::RaiseMenu; responsePacket->HomepointMenu.StatusId = GP_CLI_COMMAND_ACTION_HOMEPOINTMENU::Accept; @@ -433,7 +432,7 @@ void CLuaClientEntityPairActions::engage(CLuaBaseEntity* mob) const controller->setLastAttackTime(timer::now() - 30s); // 4. Send packet to engage - const auto packet = parent_->packets().createPacket(PacketC2S::GP_CLI_COMMAND_ACTION); + const auto packet = parent_->packets().createPacket(); auto* attackPacket = packet->as(); attackPacket->UniqueNo = mob->getID(); attackPacket->ActIndex = mob->getTargID(); diff --git a/src/test/lua/helpers/lua_client_entity_pair_events.cpp b/src/test/lua/helpers/lua_client_entity_pair_events.cpp index 98f39f5a97b..7798686439e 100644 --- a/src/test/lua/helpers/lua_client_entity_pair_events.cpp +++ b/src/test/lua/helpers/lua_client_entity_pair_events.cpp @@ -23,7 +23,6 @@ #include "common/logging.h" #include "common/lua.h" -#include "enums/packet_c2s.h" #include "lua/helpers/lua_client_entity_pair_packets.h" #include "lua/lua_client_entity_pair.h" #include "lua/lua_simulation.h" @@ -66,7 +65,7 @@ void CLuaClientEntityPairEvents::sendEventPacket(sol::optional eventId, return; } - const auto packet = parent_->packets().createPacket(PacketC2S::GP_CLI_COMMAND_EVENTEND); + const auto packet = parent_->packets().createPacket(); auto* eventPacket = packet->as(); eventPacket->EndPara = option.value_or(0); diff --git a/src/test/lua/helpers/lua_client_entity_pair_packets.cpp b/src/test/lua/helpers/lua_client_entity_pair_packets.cpp index 00a4f301fc7..dfd3edc501b 100644 --- a/src/test/lua/helpers/lua_client_entity_pair_packets.cpp +++ b/src/test/lua/helpers/lua_client_entity_pair_packets.cpp @@ -30,7 +30,7 @@ #include "lua/lua_simulation.h" #include "lua/sol_bindings.h" #include "map/map_engine.h" -#include "map/packet_system.h" +#include "map/map_networking.h" #include "map/packets/c2s/0x00a_login.h" #include "map/packets/s2c/0x028_battle2.h" #include "packets/c2s/0x011_zone_transition.h" @@ -48,7 +48,6 @@ auto CLuaClientEntityPairPackets::createPacket(PacketC2S packetType) -> std::uni { auto packet = std::make_unique(); packet->setType(static_cast(packetType)); - packet->setSize(PacketSize[static_cast(packetType)]); packet->setSequence(sequenceNum_++); return packet; @@ -58,7 +57,7 @@ void CLuaClientEntityPairPackets::sendBasicPacket(CBasicPacket& packet) const { const auto testChar = parent_->testChar(); DebugTestFmt("C2S 0x{:03X} {}", packet.getType(), magic_enum::enum_name(static_cast(packet.getType()))); - PacketParser[packet.getType()](testChar->session(), testChar->entity(), packet); + parent_->engine()->networking().packetSystem().dispatch(packet.getType(), testChar->session(), testChar->entity(), packet); } /************************************************************************ @@ -120,13 +119,13 @@ void CLuaClientEntityPairPackets::sendZonePackets() parent_->setEntity(testChar->entity()); // Send LOGIN packet to begin zone-in sequence - const auto loginPacket = createPacket(PacketC2S::GP_CLI_COMMAND_LOGIN); + const auto loginPacket = createPacket(); auto* login = loginPacket->as(); login->UniqueNo = testChar->charId(); sendBasicPacket(*loginPacket); // Send ZONE_TRANSITION packet to complete zone-in sequence - const auto transitionPacket = createPacket(PacketC2S::GP_CLI_COMMAND_ZONE_TRANSITION); + const auto transitionPacket = createPacket(); auto* transition = transitionPacket->as(); transition->unknown00 = 2; transition->unknown01 = 0; diff --git a/src/test/lua/helpers/lua_client_entity_pair_packets.h b/src/test/lua/helpers/lua_client_entity_pair_packets.h index 2321a27bbc6..ab478e97886 100644 --- a/src/test/lua/helpers/lua_client_entity_pair_packets.h +++ b/src/test/lua/helpers/lua_client_entity_pair_packets.h @@ -22,11 +22,12 @@ #pragma once #include "common/cbasetypes.h" +#include "packets/basic.h" + #include #include enum class PacketC2S : uint16_t; -class CBasicPacket; class CLuaClientEntityPair; class CLuaClientEntityPairPackets { @@ -34,6 +35,9 @@ class CLuaClientEntityPairPackets CLuaClientEntityPairPackets(CLuaClientEntityPair* parent); ~CLuaClientEntityPairPackets() = default; + template + auto createPacket() -> std::unique_ptr; + auto createPacket(PacketC2S packetType) -> std::unique_ptr; void sendBasicPacket(CBasicPacket& packet) const; void send(PacketC2S packetId, const sol::object& ffiData, size_t ffiSize); @@ -50,3 +54,11 @@ class CLuaClientEntityPairPackets CLuaClientEntityPair* parent_; uint8 sequenceNum_{ 0 }; }; + +template +auto CLuaClientEntityPairPackets::createPacket() -> std::unique_ptr +{ + auto packet = createPacket(T::packetId); + packet->setSize(sizeof(T)); + return packet; +} diff --git a/tools/ci/sanity_checks/cpp.sh b/tools/ci/sanity_checks/cpp.sh index e44f8470b62..5171e15eec2 100755 --- a/tools/ci/sanity_checks/cpp.sh +++ b/tools/ci/sanity_checks/cpp.sh @@ -34,6 +34,7 @@ for file in "${targets[@]}"; do cppcheck_output=$(cppcheck -v -j 4 --force --quiet --inconclusive --std=c++23 \ --suppress=passedByValue:src/map/packet_system.cpp \ + --suppress=templateRecursion:src/map/packet_system.cpp \ --suppress=unmatchedSuppression \ --suppress=missingIncludeSystem \ --suppress=missingInclude \