Make sure a vendor is actually selling the item a player wants to buy

This commit is contained in:
gsemaj 2021-06-20 10:15:02 -04:00
parent bb12a60e04
commit 0accd1f345
2 changed files with 26 additions and 4 deletions

View File

@ -13,8 +13,25 @@ static void vendorBuy(CNSocket* sock, CNPacketData* data) {
INITSTRUCT(sP_FE2CL_REP_PC_VENDOR_ITEM_BUY_FAIL, failResp); INITSTRUCT(sP_FE2CL_REP_PC_VENDOR_ITEM_BUY_FAIL, failResp);
failResp.iErrorCode = 0; failResp.iErrorCode = 0;
Items::Item* itemDat = Items::getItemData(req->Item.iID, req->Item.iType); if (req->iVendorID != req->iNPC_ID || Vendors::VendorTables.find(req->iVendorID) == Vendors::VendorTables.end()) {
std::cout << "[WARN] Vendor with ID " << req->iVendorID << " mismatched or not found (buy)" << std::endl;
sock->sendPacket(failResp, P_FE2CL_REP_PC_VENDOR_ITEM_BUY_FAIL);
return;
}
std::vector<VendorListing>* listings = &Vendors::VendorTables[req->iVendorID];
VendorListing reqItem;
reqItem.id = req->Item.iID;
reqItem.type = req->Item.iType;
reqItem.sort = 0; // just to be safe
if (std::find(listings->begin(), listings->end(), reqItem) == listings->end()) { // item not found in listing
std::cout << "[WARN] Player " << PlayerManager::getPlayerName(plr) << " tried to buy an item that wasn't on sale" << std::endl;
sock->sendPacket(failResp, P_FE2CL_REP_PC_VENDOR_ITEM_BUY_FAIL);
return;
}
Items::Item* itemDat = Items::getItemData(req->Item.iID, req->Item.iType);
if (itemDat == nullptr) { if (itemDat == nullptr) {
std::cout << "[WARN] Item id " << req->Item.iID << " with type " << req->Item.iType << " not found (buy)" << std::endl; std::cout << "[WARN] Item id " << req->Item.iID << " with type " << req->Item.iType << " not found (buy)" << std::endl;
sock->sendPacket(failResp, P_FE2CL_REP_PC_VENDOR_ITEM_BUY_FAIL); sock->sendPacket(failResp, P_FE2CL_REP_PC_VENDOR_ITEM_BUY_FAIL);
@ -202,13 +219,13 @@ static void vendorTable(CNSocket* sock, CNPacketData* data) {
if (req->iVendorID != req->iNPC_ID || Vendors::VendorTables.find(req->iVendorID) == Vendors::VendorTables.end()) if (req->iVendorID != req->iNPC_ID || Vendors::VendorTables.find(req->iVendorID) == Vendors::VendorTables.end())
return; return;
std::vector<VendorListing> listings = Vendors::VendorTables[req->iVendorID]; std::vector<VendorListing>& listings = Vendors::VendorTables[req->iVendorID];
INITSTRUCT(sP_FE2CL_REP_PC_VENDOR_TABLE_UPDATE_SUCC, resp); INITSTRUCT(sP_FE2CL_REP_PC_VENDOR_TABLE_UPDATE_SUCC, resp);
for (int i = 0; i < (int)listings.size() && i < 20; i++) { // 20 is the max for (int i = 0; i < (int)listings.size() && i < 20; i++) { // 20 is the max
sItemBase base; sItemBase base;
base.iID = listings[i].iID; base.iID = listings[i].id;
base.iOpt = 0; base.iOpt = 0;
base.iTimeLimit = 0; base.iTimeLimit = 0;
base.iType = listings[i].type; base.iType = listings[i].type;

View File

@ -7,7 +7,12 @@
#include "PlayerManager.hpp" #include "PlayerManager.hpp"
struct VendorListing { struct VendorListing {
int sort, type, iID; int sort, type, id;
// when validating a listing, we don't really care about the sorting index
bool operator==(const VendorListing& other) const {
return type == other.type && id == other.id;
}
}; };
namespace Vendors { namespace Vendors {