From 3b45a66498144b065d56c5725c74f8690deeb356 Mon Sep 17 00:00:00 2001 From: Trevius Date: Wed, 18 Feb 2015 21:32:18 -0600 Subject: [PATCH] Fix for potential recursive loops if using RemoveFromHateList() within EVENT_HATE_LIST. Some work on Bazaar searching, but not functional yet. --- changelog.txt | 3 ++ common/eq_packet_structs.h | 5 +- common/patches/rof2.cpp | 38 ++++++++++++++- common/patches/rof2_structs.h | 10 ++-- zone/client_packet.cpp | 87 +++++++++++++++++++++-------------- zone/hate_list.cpp | 6 +-- zone/trading.cpp | 28 +++++------ 7 files changed, 119 insertions(+), 58 deletions(-) diff --git a/changelog.txt b/changelog.txt index 393a954c8..60af1336d 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 02/18/2015 == +Trevius: Fix for potential recursive loops if using RemoveFromHateList() within EVENT_HATE_LIST. + == 02/17/2015 == Uleat: Implemented per-client character creation limiting. Caps are unknown atm..so, don't get over-zealous! Notes: diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index 188214dad..3f14e1cc9 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -2776,7 +2776,8 @@ struct BazaarWelcome_Struct { BazaarWindowStart_Struct Beginning; uint32 Traders; uint32 Items; - uint8 Unknown012[8]; + uint32 Unknown012; + uint32 Unknown016; }; struct BazaarSearch_Struct { @@ -3207,7 +3208,7 @@ struct TraderDelItem_Struct{ struct TraderClick_Struct{ /*000*/ uint32 TraderID; -/*004*/ uint32 Unknown004; +/*004*/ uint32 Code; /*008*/ uint32 Unknown008; /*012*/ uint32 Approval; /*016*/ diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 0ad31517e..e1f3b071a 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -3667,6 +3667,23 @@ namespace RoF2 FINISH_ENCODE(); } + else if (psize == sizeof(BazaarWelcome_Struct)) + { + ENCODE_LENGTH_EXACT(BazaarWelcome_Struct); + SETUP_DIRECT_ENCODE(BazaarWelcome_Struct, structs::BazaarWelcome_Struct); + + eq->Code = emu->Beginning.Action; + eq->EntityID = emu->Unknown012; + OUT(Traders); + OUT(Items); + eq->Traders2 = emu->Traders; + eq->Items2 = emu->Items; + + Log.Out(Logs::Detail, Logs::Trading, "ENCODE(OP_TraderShop): BazaarWelcome_Struct Code %d, Traders %d, Items %d", + eq->Code, eq->Traders, eq->Items); + + FINISH_ENCODE(); + } else if (psize == sizeof(TraderBuy_Struct)) { ENCODE_LENGTH_EXACT(TraderBuy_Struct); @@ -5009,8 +5026,25 @@ namespace RoF2 DECODE_LENGTH_EXACT(structs::TraderClick_Struct); SETUP_DIRECT_DECODE(TraderClick_Struct, structs::TraderClick_Struct); + IN(Code); IN(TraderID); IN(Approval); + Log.Out(Logs::Detail, Logs::Trading, "DECODE(OP_TraderShop): TraderClick_Struct Code %d, TraderID %d, Approval %d", + eq->Code, eq->TraderID, eq->Approval); + + FINISH_DIRECT_DECODE(); + } + else if (psize == sizeof(structs::BazaarWelcome_Struct)) + { + // Don't think this size gets used in RoF+ - Leaving for now... + DECODE_LENGTH_EXACT(structs::BazaarWelcome_Struct); + SETUP_DIRECT_DECODE(BazaarWelcome_Struct, structs::BazaarWelcome_Struct); + + emu->Beginning.Action = eq->Code; + IN(Traders); + IN(Items); + Log.Out(Logs::Detail, Logs::Trading, "DECODE(OP_TraderShop): BazaarWelcome_Struct Code %d, Traders %d, Items %d", + eq->Code, eq->Traders, eq->Items); FINISH_DIRECT_DECODE(); } @@ -5026,9 +5060,9 @@ namespace RoF2 memcpy(emu->ItemName, eq->ItemName, sizeof(emu->ItemName)); IN(ItemID); IN(Quantity); - Log.Out(Logs::Detail, Logs::Trading, "DECODE(OP_TraderShop): (Unknowns) Unknown004 %d, Unknown008 %d, Unknown012 %d, Unknown076 %d, Unknown276 %d", + Log.Out(Logs::Detail, Logs::Trading, "DECODE(OP_TraderShop): TraderBuy_Struct (Unknowns) Unknown004 %d, Unknown008 %d, Unknown012 %d, Unknown076 %d, Unknown276 %d", eq->Unknown004, eq->Unknown008, eq->Unknown012, eq->Unknown076, eq->Unknown276); - Log.Out(Logs::Detail, Logs::Trading, "DECODE(OP_TraderShop): Buy Action %d, Price %d, Trader %d, ItemID %d, Quantity %d, ItemName, %s", + Log.Out(Logs::Detail, Logs::Trading, "DECODE(OP_TraderShop): TraderBuy_Struct Buy Action %d, Price %d, Trader %d, ItemID %d, Quantity %d, ItemName, %s", eq->Action, eq->Price, eq->TraderID, eq->ItemID, eq->Quantity, eq->ItemName); FINISH_DIRECT_DECODE(); diff --git a/common/patches/rof2_structs.h b/common/patches/rof2_structs.h index fd6f0b2ea..520e9066e 100644 --- a/common/patches/rof2_structs.h +++ b/common/patches/rof2_structs.h @@ -2940,10 +2940,12 @@ struct BazaarWindowStart_Struct { struct BazaarWelcome_Struct { - BazaarWindowStart_Struct Beginning; - uint32 Traders; - uint32 Items; - uint8 Unknown012[8]; + uint32 Code; + uint32 EntityID; + uint32 Traders; + uint32 Items; + uint32 Traders2; + uint32 Items2; }; struct BazaarSearch_Struct { diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 789071848..5205942b2 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -13516,49 +13516,68 @@ void Client::Handle_OP_TraderShop(const EQApplicationPacket *app) if (app->size == sizeof(TraderClick_Struct)) { - // This is when a potential purchaser right clicks on this client who is in Trader mode to - // browse their goods. + TraderClick_Struct* tcs = (TraderClick_Struct*)app->pBuffer; - EQApplicationPacket* outapp = new EQApplicationPacket(OP_TraderShop, sizeof(TraderClick_Struct)); + Log.Out(Logs::Detail, Logs::Trading, "Handle_OP_TraderShop: TraderClick_Struct TraderID %d, Code %d, Unknown008 %d, Approval %d", + tcs->TraderID, tcs->Code, tcs->Unknown008, tcs->Approval); - TraderClick_Struct* outtcs = (TraderClick_Struct*)outapp->pBuffer; - - Client* Trader = entity_list.GetClientByID(tcs->TraderID); - - if (Trader) + if (tcs->Code == BazaarWelcome) { - outtcs->Approval = Trader->WithCustomer(GetID()); - Log.Out(Logs::Detail, Logs::Trading, "Client::Handle_OP_TraderShop: Shop Request (%s) to (%s) with Approval: %d", GetCleanName(), Trader->GetCleanName(), outtcs->Approval); - } - else { - Log.Out(Logs::Detail, Logs::Trading, "Client::Handle_OP_TraderShop: entity_list.GetClientByID(tcs->traderid)" - " returned a nullptr pointer"); - return; - } - - outtcs->TraderID = tcs->TraderID; - - outtcs->Unknown008 = 0x3f800000; - - QueuePacket(outapp); - - - if (outtcs->Approval) { - this->BulkSendTraderInventory(Trader->CharacterID()); - Trader->Trader_CustomerBrowsing(this); - TraderID = tcs->TraderID; - Log.Out(Logs::Detail, Logs::Trading, "Client::Handle_OP_TraderShop: Trader Inventory Sent"); + Log.Out(Logs::Detail, Logs::Trading, "Client::Handle_OP_TraderShop: Sent Bazaar Welcome Info"); + SendBazaarWelcome(); } else { - Message_StringID(clientMessageYellow, TRADER_BUSY); - Log.Out(Logs::Detail, Logs::Trading, "Client::Handle_OP_TraderShop: Trader Busy"); + // This is when a potential purchaser right clicks on this client who is in Trader mode to + // browse their goods. + EQApplicationPacket* outapp = new EQApplicationPacket(OP_TraderShop, sizeof(TraderClick_Struct)); + + TraderClick_Struct* outtcs = (TraderClick_Struct*)outapp->pBuffer; + + Client* Trader = entity_list.GetClientByID(tcs->TraderID); + + if (Trader) + { + outtcs->Approval = Trader->WithCustomer(GetID()); + Log.Out(Logs::Detail, Logs::Trading, "Client::Handle_OP_TraderShop: Shop Request (%s) to (%s) with Approval: %d", GetCleanName(), Trader->GetCleanName(), outtcs->Approval); + } + else { + Log.Out(Logs::Detail, Logs::Trading, "Client::Handle_OP_TraderShop: entity_list.GetClientByID(tcs->traderid)" + " returned a nullptr pointer"); + return; + } + + outtcs->TraderID = tcs->TraderID; + + outtcs->Unknown008 = 0x3f800000; + + QueuePacket(outapp); + + + if (outtcs->Approval) { + this->BulkSendTraderInventory(Trader->CharacterID()); + Trader->Trader_CustomerBrowsing(this); + TraderID = tcs->TraderID; + Log.Out(Logs::Detail, Logs::Trading, "Client::Handle_OP_TraderShop: Trader Inventory Sent"); + } + else + { + Message_StringID(clientMessageYellow, TRADER_BUSY); + Log.Out(Logs::Detail, Logs::Trading, "Client::Handle_OP_TraderShop: Trader Busy"); + } + + safe_delete(outapp); + return; } - safe_delete(outapp); - - return; + } + else if (app->size == sizeof(BazaarWelcome_Struct)) + { + // RoF+ + // Client requested Bazaar Welcome Info (Trader and Item Total Counts) + SendBazaarWelcome(); + Log.Out(Logs::Detail, Logs::Trading, "Client::Handle_OP_TraderShop: Sent Bazaar Welcome Info"); } else if (app->size == sizeof(TraderBuy_Struct)) { diff --git a/zone/hate_list.cpp b/zone/hate_list.cpp index df76216ae..e68924844 100644 --- a/zone/hate_list.cpp +++ b/zone/hate_list.cpp @@ -219,17 +219,17 @@ bool HateList::RemoveEntFromHateList(Mob *in_entity) { if ((*iterator)->entity_on_hatelist == in_entity) { - if (in_entity) - parse->EventNPC(EVENT_HATE_LIST, hate_owner->CastToNPC(), in_entity, "0", 0); is_found = true; - if (in_entity && in_entity->IsClient()) in_entity->CastToClient()->DecrementAggroCount(); delete (*iterator); iterator = list.erase(iterator); + if (in_entity) + parse->EventNPC(EVENT_HATE_LIST, hate_owner->CastToNPC(), in_entity, "0", 0); + } else ++iterator; diff --git a/zone/trading.cpp b/zone/trading.cpp index 047aa3a6a..91d9c8a8a 100644 --- a/zone/trading.cpp +++ b/zone/trading.cpp @@ -1558,18 +1558,7 @@ void Client::BuyTraderItem(TraderBuy_Struct* tbs, Client* Trader, const EQApplic return; } - EQApplicationPacket* outapp = nullptr; - - if (Trader->GetClientVersion() >= ClientVersion::RoF) - { - //outapp = new EQApplicationPacket(OP_TraderShop, sizeof(TraderBuy_Struct)); - } - else - { - //outapp = new EQApplicationPacket(OP_Trader, sizeof(TraderBuy_Struct)); - } - - outapp = new EQApplicationPacket(OP_Trader, sizeof(TraderBuy_Struct)); + EQApplicationPacket* outapp = new EQApplicationPacket(OP_Trader, sizeof(TraderBuy_Struct)); TraderBuy_Struct* outtbs = (TraderBuy_Struct*)outapp->pBuffer; @@ -1701,7 +1690,15 @@ void Client::SendBazaarWelcome() if (results.Success() && results.RowCount() == 1){ auto row = results.begin(); - EQApplicationPacket* outapp = new EQApplicationPacket(OP_BazaarSearch, sizeof(BazaarWelcome_Struct)); + EQApplicationPacket* outapp = nullptr; + if (GetClientVersion() >= ClientVersion::RoF) + { + outapp = new EQApplicationPacket(OP_TraderShop, sizeof(BazaarWelcome_Struct)); + } + else + { + outapp = new EQApplicationPacket(OP_BazaarSearch, sizeof(BazaarWelcome_Struct)); + } memset(outapp->pBuffer,0,outapp->size); @@ -1712,6 +1709,11 @@ void Client::SendBazaarWelcome() bws->Traders = atoi(row[0]); bws->Items = atoi(row[1]); + if (GetClientVersion() >= ClientVersion::RoF) + { + bws->Unknown012 = GetID(); + } + QueuePacket(outapp); safe_delete(outapp);