mirror of
https://github.com/EQEmu/Server.git
synced 2026-04-07 09:02:26 +00:00
* Add Barter/Buyer Features Adds barter and buyer features, for ROF2 only at this time including item compensation * Remove FKs from buyer tables Remove FKs from buyer tables * Bug fix for Find Buyer and mutli item selling Update for quantity purchases not correctly providing multi items. Update for Find Buyer functionality based on zone instancing. Update buyer messaging Update buyer LORE duplicate check * Revert zone instance comment * Revert zone_id packet size field * Add zone instancing to barter/buyer --------- Co-authored-by: Akkadius <akkadius1@gmail.com>
357 lines
9.9 KiB
C++
357 lines
9.9 KiB
C++
#ifndef EQEMU_BUYER_BUY_LINES_REPOSITORY_H
|
|
#define EQEMU_BUYER_BUY_LINES_REPOSITORY_H
|
|
|
|
#include "../database.h"
|
|
#include "../strings.h"
|
|
#include "base/base_buyer_buy_lines_repository.h"
|
|
#include "buyer_trade_items_repository.h"
|
|
#include "character_data_repository.h"
|
|
#include "buyer_repository.h"
|
|
|
|
#include "../eq_packet_structs.h"
|
|
|
|
class BuyerBuyLinesRepository: public BaseBuyerBuyLinesRepository {
|
|
public:
|
|
|
|
/**
|
|
* This file was auto generated and can be modified and extended upon
|
|
*
|
|
* Base repository methods are automatically
|
|
* generated in the "base" version of this repository. The base repository
|
|
* is immutable and to be left untouched, while methods in this class
|
|
* are used as extension methods for more specific persistence-layer
|
|
* accessors or mutators.
|
|
*
|
|
* Base Methods (Subject to be expanded upon in time)
|
|
*
|
|
* Note: Not all tables are designed appropriately to fit functionality with all base methods
|
|
*
|
|
* InsertOne
|
|
* UpdateOne
|
|
* DeleteOne
|
|
* FindOne
|
|
* GetWhere(std::string where_filter)
|
|
* DeleteWhere(std::string where_filter)
|
|
* InsertMany
|
|
* All
|
|
*
|
|
* Example custom methods in a repository
|
|
*
|
|
* BuyerBuyLinesRepository::GetByZoneAndVersion(int zone_id, int zone_version)
|
|
* BuyerBuyLinesRepository::GetWhereNeverExpires()
|
|
* BuyerBuyLinesRepository::GetWhereXAndY()
|
|
* BuyerBuyLinesRepository::DeleteWhereXAndY()
|
|
*
|
|
* Most of the above could be covered by base methods, but if you as a developer
|
|
* find yourself re-using logic for other parts of the code, its best to just make a
|
|
* method that can be re-used easily elsewhere especially if it can use a base repository
|
|
* method and encapsulate filters there
|
|
*/
|
|
|
|
// Custom extended repository methods here
|
|
|
|
struct WelcomeData_Struct {
|
|
uint32 count_of_buyers;
|
|
uint32 count_of_items;
|
|
};
|
|
|
|
static int CreateBuyLine(Database& db, const BuyerLineItems_Struct b, uint32 char_id)
|
|
{
|
|
auto buyer = BuyerRepository::GetWhere(db, fmt::format("`char_id` = '{}' LIMIT 1", char_id));
|
|
if (buyer.empty()){
|
|
return 0;
|
|
}
|
|
|
|
BuyerBuyLinesRepository::BuyerBuyLines buy_lines{};
|
|
buy_lines.id = 0;
|
|
buy_lines.buyer_id = buyer.front().id;
|
|
buy_lines.char_id = char_id;
|
|
buy_lines.buy_slot_id = b.slot;
|
|
buy_lines.item_id = b.item_id;
|
|
buy_lines.item_name = b.item_name;
|
|
buy_lines.item_icon = b.item_icon;
|
|
buy_lines.item_qty = b.item_quantity;
|
|
buy_lines.item_price = b.item_cost;
|
|
auto e = InsertOne(db, buy_lines);
|
|
|
|
std::vector<BuyerTradeItemsRepository::BuyerTradeItems> queue;
|
|
|
|
for (auto const &r: b.trade_items) {
|
|
BuyerTradeItemsRepository::BuyerTradeItems bti{};
|
|
bti.id = 0;
|
|
bti.buyer_buy_lines_id = e.id;
|
|
bti.item_id = r.item_id;
|
|
bti.item_qty = r.item_quantity;
|
|
bti.item_icon = r.item_icon;
|
|
bti.item_name = r.item_name;
|
|
|
|
if (bti.item_id) {
|
|
queue.push_back(bti);
|
|
}
|
|
}
|
|
|
|
if (!queue.empty()) {
|
|
BuyerTradeItemsRepository::InsertMany(db, queue);
|
|
}
|
|
|
|
return e.id;
|
|
}
|
|
|
|
static int ModifyBuyLine(Database& db, const BuyerLineItems_Struct b, uint32 char_id)
|
|
{
|
|
auto b_lines = GetWhere(db, fmt::format("`char_id` = '{}' AND `buy_slot_id` = '{}';", char_id, b.slot));
|
|
if (b_lines.empty() || b_lines.size() > 1){
|
|
return 0;
|
|
}
|
|
|
|
auto b_line = b_lines.front();
|
|
|
|
b_line.item_qty = b.item_quantity;
|
|
b_line.item_price = b.item_cost;
|
|
b_line.item_icon = b.item_icon;
|
|
auto e = UpdateOne(db, b_line);
|
|
|
|
std::vector<BuyerTradeItemsRepository::BuyerTradeItems> queue;
|
|
|
|
BuyerTradeItemsRepository::DeleteWhere(db, fmt::format("`buyer_buy_lines_id` = '{}';", b_line.id));
|
|
for (auto const &r: b.trade_items) {
|
|
BuyerTradeItemsRepository::BuyerTradeItems bti{};
|
|
bti.id = 0;
|
|
bti.buyer_buy_lines_id = b_line.id;
|
|
bti.item_id = r.item_id;
|
|
bti.item_qty = r.item_quantity;
|
|
bti.item_icon = r.item_icon;
|
|
bti.item_name = r.item_name;
|
|
|
|
if (bti.item_id) {
|
|
queue.push_back(bti);
|
|
}
|
|
}
|
|
|
|
if (!queue.empty()) {
|
|
BuyerTradeItemsRepository::InsertMany(db, queue);
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
static bool DeleteBuyLine(Database &db, uint32 char_id, int32 slot_id = 0xffffffff)
|
|
{
|
|
std::vector<BuyerBuyLines> buylines{};
|
|
if (slot_id == 0xffffffff) {
|
|
auto buylines = GetWhere(db, fmt::format("`char_id` = '{}'", char_id));
|
|
DeleteWhere(db, fmt::format("`char_id` = '{}'", char_id));
|
|
}
|
|
else {
|
|
auto buylines = GetWhere(db, fmt::format("`char_id` = '{}' AND `buy_slot_id` = '{}'", char_id, slot_id));
|
|
DeleteWhere(db, fmt::format("`char_id` = '{}' AND `buy_slot_id` = '{}'", char_id, slot_id));
|
|
}
|
|
|
|
if (buylines.empty()) {
|
|
return 0;
|
|
}
|
|
|
|
std::vector<std::string> buyline_ids{};
|
|
for (auto const &bl: buylines) {
|
|
buyline_ids.push_back((std::to_string(bl.id)));
|
|
}
|
|
|
|
if (!buyline_ids.empty()) {
|
|
BuyerTradeItemsRepository::DeleteWhere(
|
|
db,
|
|
fmt::format(
|
|
"`buyer_buy_lines_id` IN({})",
|
|
Strings::Implode(", ", buyline_ids)
|
|
)
|
|
);
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
static std::vector<BuyerLineItems_Struct> GetBuyLines(Database &db, uint32 char_id)
|
|
{
|
|
std::vector<BuyerLineItems_Struct> all_entries{};
|
|
|
|
auto buy_line = GetWhere(db, fmt::format("`char_id` = '{}';", char_id));
|
|
if (buy_line.empty()){
|
|
return all_entries;
|
|
}
|
|
|
|
auto buy_line_trade_items = BuyerTradeItemsRepository::GetWhere(
|
|
db,
|
|
fmt::format(
|
|
"`buyer_buy_lines_id` IN (SELECT b.id FROM buyer_buy_lines AS b WHERE b.char_id = '{}')",
|
|
char_id
|
|
)
|
|
);
|
|
|
|
all_entries.reserve(buy_line.size());
|
|
|
|
for (auto const &l: buy_line) {
|
|
BuyerLineItems_Struct bli{};
|
|
bli.item_id = l.item_id;
|
|
bli.item_cost = l.item_price;
|
|
bli.item_quantity = l.item_qty;
|
|
bli.slot = l.buy_slot_id;
|
|
bli.item_name = l.item_name;
|
|
|
|
for (auto const &i: GetSubIDs(buy_line_trade_items, l.id)) {
|
|
BuyerLineTradeItems_Struct blti{};
|
|
blti.item_id = i.item_id;
|
|
blti.item_icon = i.item_icon;
|
|
blti.item_quantity = i.item_qty;
|
|
blti.item_id = i.item_id;
|
|
blti.item_name = i.item_name;
|
|
bli.trade_items.push_back(blti);
|
|
}
|
|
all_entries.push_back(bli);
|
|
}
|
|
|
|
return all_entries;
|
|
}
|
|
|
|
static BuyerLineSearch_Struct SearchBuyLines(
|
|
Database &db,
|
|
std::string &search_string,
|
|
uint32 char_id = 0,
|
|
uint32 zone_id = 0,
|
|
uint32 zone_instance_id = 0
|
|
)
|
|
{
|
|
BuyerLineSearch_Struct all_entries{};
|
|
std::string where_clause(fmt::format("`item_name` LIKE \"%{}%\" ", search_string));
|
|
|
|
if (char_id) {
|
|
where_clause += fmt::format("AND `char_id` = '{}' ", char_id);
|
|
}
|
|
|
|
if (zone_id) {
|
|
auto buyers = BuyerRepository::GetWhere(
|
|
db,
|
|
fmt::format(
|
|
"`char_zone_id` = '{}' AND char_zone_instance_id = '{}'",
|
|
zone_id,
|
|
zone_instance_id
|
|
)
|
|
);
|
|
|
|
std::vector<std::string> char_ids{};
|
|
for (auto const &bl : buyers) {
|
|
char_ids.push_back((std::to_string(bl.char_id)));
|
|
}
|
|
|
|
where_clause += fmt::format("AND `char_id` IN ({}) ", Strings::Implode(", ", char_ids));
|
|
}
|
|
|
|
auto buy_line = GetWhere(db, where_clause);
|
|
if (buy_line.empty()){
|
|
return all_entries;
|
|
}
|
|
|
|
std::vector<std::string> ids{};
|
|
std::vector<std::string> char_ids{};
|
|
for (auto const &bl : buy_line) {
|
|
if (std::find(ids.begin(), ids.end(), std::to_string(bl.id)) == std::end(ids)) {
|
|
ids.push_back(std::to_string(bl.id));
|
|
}
|
|
if (std::find(char_ids.begin(), char_ids.end(), std::to_string(bl.char_id)) == std::end(char_ids)) {
|
|
char_ids.push_back((std::to_string(bl.char_id)));
|
|
}
|
|
}
|
|
|
|
auto buy_line_trade_items = BuyerTradeItemsRepository::GetWhere(
|
|
db,
|
|
fmt::format(
|
|
"`buyer_buy_lines_id` IN ({});",
|
|
Strings::Implode(", ", ids)
|
|
)
|
|
);
|
|
|
|
auto char_names = BuyerRepository::GetWhere(
|
|
db,
|
|
fmt::format(
|
|
"`char_id` IN ({});",
|
|
Strings::Implode(", ", char_ids)
|
|
)
|
|
);
|
|
|
|
all_entries.no_items = buy_line.size();
|
|
for (auto const &l: buy_line) {
|
|
BuyerLineItemsSearch_Struct blis{};
|
|
blis.slot = l.buy_slot_id;
|
|
blis.item_id = l.item_id;
|
|
blis.item_cost = l.item_price;
|
|
blis.item_icon = l.item_icon;
|
|
blis.item_quantity = l.item_qty;
|
|
blis.buyer_id = l.char_id;
|
|
auto it = std::find_if(
|
|
char_names.cbegin(),
|
|
char_names.cend(),
|
|
[&](BuyerRepository::Buyer e) { return e.char_id == l.char_id; }
|
|
);
|
|
blis.buyer_name = it != char_names.end() ? it->char_name : std::string("");
|
|
blis.buyer_entity_id = it != char_names.end() ? it->char_entity_id : 0;
|
|
blis.buyer_zone_id = it != char_names.end() ? it->char_zone_id : 0;
|
|
blis.buyer_zone_instance_id = it != char_names.end() ? it->char_zone_instance_id : 0;
|
|
strn0cpy(blis.item_name, l.item_name.c_str(), sizeof(blis.item_name));
|
|
|
|
for (auto const &i: GetSubIDs(buy_line_trade_items, l.id)) {
|
|
BuyerLineTradeItems_Struct e{};
|
|
e.item_id = i.item_id;
|
|
e.item_icon = i.item_icon;
|
|
e.item_quantity = i.item_qty;
|
|
e.item_id = i.item_id;
|
|
e.item_name = i.item_name;
|
|
|
|
blis.trade_items.push_back(e);
|
|
}
|
|
all_entries.buy_line.push_back(blis);
|
|
}
|
|
|
|
return all_entries;
|
|
}
|
|
|
|
static std::vector<BuyerTradeItemsRepository::BuyerTradeItems>
|
|
GetSubIDs(std::vector<BuyerTradeItemsRepository::BuyerTradeItems> &in, uint64 id)
|
|
{
|
|
std::vector<BuyerTradeItemsRepository::BuyerTradeItems> results{};
|
|
std::vector<uint64> indices{};
|
|
|
|
auto it = in.begin();
|
|
while ((it = std::find_if(
|
|
it,
|
|
in.end(),
|
|
[&](BuyerTradeItemsRepository::BuyerTradeItems const &e) {
|
|
return e.buyer_buy_lines_id == id;
|
|
}
|
|
))
|
|
!= in.end()
|
|
) {
|
|
indices.push_back(std::distance(in.begin(), it));
|
|
results.push_back(*it);
|
|
it++;
|
|
}
|
|
return results;
|
|
}
|
|
|
|
static WelcomeData_Struct GetWelcomeData(Database &db)
|
|
{
|
|
WelcomeData_Struct e{};
|
|
|
|
auto results = db.QueryDatabase("SELECT COUNT(DISTINCT char_id), COUNT(char_id) FROM buyer;");
|
|
|
|
if (!results.RowCount()) {
|
|
return e;
|
|
}
|
|
|
|
auto r = results.begin();
|
|
e.count_of_buyers = Strings::ToInt(r[0]);
|
|
e.count_of_items = Strings::ToInt(r[1]);
|
|
return e;
|
|
}
|
|
|
|
};
|
|
|
|
#endif //EQEMU_BUYER_BUY_LINES_REPOSITORY_H
|