Compare commits

..

5 Commits

65 changed files with 1706 additions and 842 deletions
+20 -28
View File
@@ -8,14 +8,13 @@ std::vector<BazaarSearchResultsFromDB_Struct>
Bazaar::GetSearchResults( Bazaar::GetSearchResults(
SharedDatabase &db, SharedDatabase &db,
BazaarSearchCriteria_Struct search, BazaarSearchCriteria_Struct search,
uint32 char_zone_id, uint32 char_zone_id
int32 char_zone_instance_id
) )
{ {
LogTrading( LogTrading(
"Searching for items with search criteria - item_name [{}] min_cost [{}] max_cost [{}] min_level [{}] " "Searching for items with search criteria - item_name [{}] min_cost [{}] max_cost [{}] min_level [{}] "
"max_level [{}] max_results [{}] prestige [{}] augment [{}] trader_entity_id [{}] trader_id [{}] " "max_level [{}] max_results [{}] prestige [{}] augment [{}] trader_entity_id [{}] trader_id [{}] "
"search_scope [{}] char_zone_id [{}], char_zone_instance_id [{}]", "search_scope [{}] char_zone_id [{}]",
search.item_name, search.item_name,
search.min_cost, search.min_cost,
search.max_cost, search.max_cost,
@@ -27,8 +26,7 @@ Bazaar::GetSearchResults(
search.trader_entity_id, search.trader_entity_id,
search.trader_id, search.trader_id,
search.search_scope, search.search_scope,
char_zone_id, char_zone_id
char_zone_instance_id
); );
std::string search_criteria_trader("TRUE "); std::string search_criteria_trader("TRUE ");
@@ -36,19 +34,14 @@ Bazaar::GetSearchResults(
if (search.search_scope == NonRoFBazaarSearchScope) { if (search.search_scope == NonRoFBazaarSearchScope) {
search_criteria_trader.append( search_criteria_trader.append(
fmt::format( fmt::format(
" AND trader.char_entity_id = {} AND trader.char_zone_id = {} AND trader.char_zone_instance_id = {}", " AND trader.char_entity_id = {} AND trader.char_zone_id = {}",
search.trader_entity_id, search.trader_entity_id,
Zones::BAZAAR, Zones::BAZAAR
char_zone_instance_id
) )
); );
} }
else if (search.search_scope == Local_Scope) { else if (search.search_scope == Local_Scope) {
search_criteria_trader.append(fmt::format( search_criteria_trader.append(fmt::format(" AND trader.char_zone_id = {}", char_zone_id));
" AND trader.char_zone_id = {} AND trader.char_zone_instance_id = {}",
char_zone_id,
char_zone_instance_id)
);
} }
else if (search.trader_id > 0) { else if (search.trader_id > 0) {
search_criteria_trader.append(fmt::format(" AND trader.char_id = {}", search.trader_id)); search_criteria_trader.append(fmt::format(" AND trader.char_id = {}", search.trader_id));
@@ -69,7 +62,7 @@ Bazaar::GetSearchResults(
std::string query = fmt::format( std::string query = fmt::format(
"SELECT COUNT(item_id), trader.char_id, trader.item_id, trader.item_sn, trader.item_charges, trader.item_cost, " "SELECT COUNT(item_id), trader.char_id, trader.item_id, trader.item_sn, trader.item_charges, trader.item_cost, "
"trader.slot_id, SUM(trader.item_charges), trader.char_zone_id, trader.char_entity_id, character_data.name, " "trader.slot_id, SUM(trader.item_charges), trader.char_zone_id, trader.char_entity_id, character_data.name, "
"aug_slot_1, aug_slot_2, aug_slot_3, aug_slot_4, aug_slot_5, aug_slot_6, trader.char_zone_instance_id " "aug_slot_1, aug_slot_2, aug_slot_3, aug_slot_4, aug_slot_5, aug_slot_6 "
"FROM trader, character_data " "FROM trader, character_data "
"WHERE {} AND trader.char_id = character_data.id " "WHERE {} AND trader.char_id = character_data.id "
"GROUP BY trader.item_sn, trader.item_charges, trader.char_id", "GROUP BY trader.item_sn, trader.item_charges, trader.char_id",
@@ -129,20 +122,19 @@ Bazaar::GetSearchResults(
continue; continue;
} }
r.count = Strings::ToInt(row[0]); r.count = Strings::ToInt(row[0]);
r.trader_id = Strings::ToInt(row[1]); r.trader_id = Strings::ToInt(row[1]);
r.serial_number = Strings::ToInt(row[3]); r.serial_number = Strings::ToInt(row[3]);
r.cost = Strings::ToInt(row[5]); r.cost = Strings::ToInt(row[5]);
r.slot_id = Strings::ToInt(row[6]); r.slot_id = Strings::ToInt(row[6]);
r.sum_charges = Strings::ToInt(row[7]); r.sum_charges = Strings::ToInt(row[7]);
r.stackable = item->Stackable; r.stackable = item->Stackable;
r.icon_id = item->Icon; r.icon_id = item->Icon;
r.trader_zone_id = Strings::ToInt(row[8]); r.trader_zone_id = Strings::ToInt(row[8]);
r.trader_zone_instance_id = Strings::ToInt(row[17]); r.trader_entity_id = Strings::ToInt(row[9]);
r.trader_entity_id = Strings::ToInt(row[9]); r.serial_number_RoF = fmt::format("{:016}\0", Strings::ToInt(row[3]));
r.serial_number_RoF = fmt::format("{:016}\0", Strings::ToInt(row[3])); r.item_name = fmt::format("{:.63}\0", item->Name);
r.item_name = fmt::format("{:.63}\0", item->Name); r.trader_name = fmt::format("{:.63}\0", std::string(row[10]).c_str());
r.trader_name = fmt::format("{:.63}\0", std::string(row[10]).c_str());
LogTradingDetail( LogTradingDetail(
"Searching against item [{}] ({}) for trader [{}]", "Searching against item [{}] ({}) for trader [{}]",
+1 -1
View File
@@ -7,7 +7,7 @@
class Bazaar { class Bazaar {
public: public:
static std::vector<BazaarSearchResultsFromDB_Struct> static std::vector<BazaarSearchResultsFromDB_Struct>
GetSearchResults(SharedDatabase &db, BazaarSearchCriteria_Struct search, unsigned int char_zone_id, int char_zone_instance_id); GetSearchResults(SharedDatabase &db, BazaarSearchCriteria_Struct search, unsigned int char_zone_id);
}; };
@@ -5770,17 +5770,6 @@ MODIFY COLUMN `exp_modifier` float NOT NULL DEFAULT 1.0 AFTER `aa_modifier`;
CREATE INDEX idx_character_expires ON data_buckets (character_id, expires); CREATE INDEX idx_character_expires ON data_buckets (character_id, expires);
CREATE INDEX idx_npc_expires ON data_buckets (npc_id, expires); CREATE INDEX idx_npc_expires ON data_buckets (npc_id, expires);
CREATE INDEX idx_bot_expires ON data_buckets (bot_id, expires); CREATE INDEX idx_bot_expires ON data_buckets (bot_id, expires);
)"
},
ManifestEntry{
.version = 9286,
.description = "2024_11_26_bazaar_find_trader.sql",
.check = "SHOW COLUMNS FROM `trader` LIKE 'char_zone_instance_id'",
.condition = "empty",
.match = "",
.sql = R"(
ALTER TABLE `trader`
ADD COLUMN `char_zone_instance_id` INT NULL DEFAULT '0' AFTER `char_zone_id`;
)" )"
} }
// -- template; copy/paste this when you need to create a new entry // -- template; copy/paste this when you need to create a new entry
+23 -15
View File
@@ -140,6 +140,29 @@ std::string EQ::constants::GetLanguageName(uint8 language_id)
return EQ::constants::GetLanguageMap().find(language_id)->second; return EQ::constants::GetLanguageMap().find(language_id)->second;
} }
const std::map<uint32, std::string>& EQ::constants::GetLDoNThemeMap()
{
static const std::map<uint32, std::string> ldon_theme_map = {
{ LDoNThemes::Unused, "Unused" },
{ LDoNThemes::GUK, "Deepest Guk" },
{ LDoNThemes::MIR, "Miragul's Menagerie" },
{ LDoNThemes::MMC, "Mistmoore Catacombs" },
{ LDoNThemes::RUJ, "Rujarkian Hills" },
{ LDoNThemes::TAK, "Takish-Hiz" },
};
return ldon_theme_map;
}
std::string EQ::constants::GetLDoNThemeName(uint32 theme_id)
{
if (!EQ::ValueWithin(theme_id, LDoNThemes::Unused, LDoNThemes::TAK)) {
return std::string();
}
return EQ::constants::GetLDoNThemeMap().find(theme_id)->second;
}
const std::map<int8, std::string>& EQ::constants::GetFlyModeMap() const std::map<int8, std::string>& EQ::constants::GetFlyModeMap()
{ {
static const std::map<int8, std::string> flymode_map = { static const std::map<int8, std::string> flymode_map = {
@@ -436,18 +459,3 @@ bool ComparisonType::IsValid(uint8 type)
{ {
return comparison_types.find(type) != comparison_types.end(); return comparison_types.find(type) != comparison_types.end();
} }
uint32 LDoNTheme::GetBitmask(uint32 theme_id)
{
return IsValid(theme_id) ? ldon_theme_names[theme_id].second : LDoNTheme::UnusedBit;
}
std::string LDoNTheme::GetName(uint32 theme_id)
{
return IsValid(theme_id) ? ldon_theme_names[theme_id].first : "UNKNOWN LDON THEME";
}
bool LDoNTheme::IsValid(uint32 theme_id)
{
return ldon_theme_names.find(theme_id) != ldon_theme_names.end();
}
+3 -29
View File
@@ -352,6 +352,9 @@ namespace EQ
extern const std::map<uint8, std::string>& GetLanguageMap(); extern const std::map<uint8, std::string>& GetLanguageMap();
std::string GetLanguageName(uint8 language_id); std::string GetLanguageName(uint8 language_id);
extern const std::map<uint32, std::string>& GetLDoNThemeMap();
std::string GetLDoNThemeName(uint32 theme_id);
extern const std::map<int8, std::string>& GetFlyModeMap(); extern const std::map<int8, std::string>& GetFlyModeMap();
std::string GetFlyModeName(int8 flymode_id); std::string GetFlyModeName(int8 flymode_id);
@@ -748,35 +751,6 @@ static std::map<uint32, std::string> stance_names = {
{ Stance::AEBurn, "AE Burn" } { Stance::AEBurn, "AE Burn" }
}; };
namespace LDoNTheme {
constexpr uint32 Unused = 0;
constexpr uint32 GUK = 1;
constexpr uint32 MIR = 2;
constexpr uint32 MMC = 3;
constexpr uint32 RUJ = 4;
constexpr uint32 TAK = 5;
constexpr uint32 UnusedBit = 0;
constexpr uint32 GUKBit = 1;
constexpr uint32 MIRBit = 2;
constexpr uint32 MMCBit = 4;
constexpr uint32 RUJBit = 8;
constexpr uint32 TAKBit = 16;
uint32 GetBitmask(uint32 theme_id);
std::string GetName(uint32 theme_id);
bool IsValid(uint32 theme_id);
}
static std::map<uint32, std::pair<std::string, uint32>> ldon_theme_names = {
{ LDoNTheme::Unused, { "Unused", LDoNTheme::UnusedBit }, },
{ LDoNTheme::GUK, { "Deepest Guk", LDoNTheme::GUKBit }, },
{ LDoNTheme::MIR, { "Miragul's Menagerie", LDoNTheme::MIRBit }, },
{ LDoNTheme::MMC, { "Mistmoore Catacombs", LDoNTheme::MMCBit }, },
{ LDoNTheme::RUJ, { "Rujarkian Hills", LDoNTheme::RUJBit }, },
{ LDoNTheme::TAK, { "Takish-Hiz", LDoNTheme::TAKBit }, },
};
namespace PCNPCOnlyFlagType { namespace PCNPCOnlyFlagType {
constexpr int PC = 1; constexpr int PC = 1;
constexpr int NPC = 2; constexpr int NPC = 2;
+1
View File
@@ -465,6 +465,7 @@ N(OP_SendAAStats),
N(OP_SendAATable), N(OP_SendAATable),
N(OP_SendCharInfo), N(OP_SendCharInfo),
N(OP_SendExpZonein), N(OP_SendExpZonein),
N(OP_SendFindableLocations),
N(OP_SendFindableNPCs), N(OP_SendFindableNPCs),
N(OP_SendGuildTributes), N(OP_SendGuildTributes),
N(OP_SendLoginInfo), N(OP_SendLoginInfo),
+18
View File
@@ -993,6 +993,24 @@ enum class DynamicZoneMemberStatus : uint8_t
LinkDead LinkDead
}; };
enum LDoNThemes {
Unused = 0,
GUK,
MIR,
MMC,
RUJ,
TAK
};
enum LDoNThemeBits {
UnusedBit = 0,
GUKBit = 1,
MIRBit = 2,
MMCBit = 4,
RUJBit = 8,
TAKBit = 16
};
enum StartZoneIndex { enum StartZoneIndex {
Odus = 0, Odus = 0,
Qeynos, Qeynos,
+33 -10
View File
@@ -3742,8 +3742,7 @@ struct GetItems_Struct{
struct BecomeTrader_Struct { struct BecomeTrader_Struct {
uint32 action; uint32 action;
uint16 zone_id; uint32 zone_id;
uint16 zone_instance_id;
uint32 trader_id; uint32 trader_id;
uint32 entity_id; uint32 entity_id;
char trader_name[64]; char trader_name[64];
@@ -4401,11 +4400,6 @@ struct FindPerson_Point {
float z; float z;
}; };
struct FindPersonRequest_Struct {
uint32 npc_id;
FindPerson_Point client_pos;
};
//variable length packet of points //variable length packet of points
struct FindPersonResult_Struct { struct FindPersonResult_Struct {
FindPerson_Point dest; FindPerson_Point dest;
@@ -6348,7 +6342,6 @@ enum BazaarTraderBarterActions {
TraderAck2 = 22, TraderAck2 = 22,
AddTraderToBazaarWindow = 24, AddTraderToBazaarWindow = 24,
RemoveTraderFromBazaarWindow = 25, RemoveTraderFromBazaarWindow = 25,
FirstOpenSearch = 26,
ClickTrader = 28, ClickTrader = 28,
DeliveryCostUpdate = 29 DeliveryCostUpdate = 29
}; };
@@ -6388,7 +6381,6 @@ struct BazaarSearchResultsFromDB_Struct {
uint32 icon_id; uint32 icon_id;
uint32 sum_charges; uint32 sum_charges;
uint32 trader_zone_id; uint32 trader_zone_id;
int32 trader_zone_instance_id;
uint32 trader_entity_id; uint32 trader_entity_id;
uint32 item_stat; uint32 item_stat;
bool stackable; bool stackable;
@@ -6410,7 +6402,6 @@ struct BazaarSearchResultsFromDB_Struct {
CEREAL_NVP(icon_id), CEREAL_NVP(icon_id),
CEREAL_NVP(sum_charges), CEREAL_NVP(sum_charges),
CEREAL_NVP(trader_zone_id), CEREAL_NVP(trader_zone_id),
CEREAL_NVP(trader_zone_instance_id),
CEREAL_NVP(trader_entity_id), CEREAL_NVP(trader_entity_id),
CEREAL_NVP(item_stat), CEREAL_NVP(item_stat),
CEREAL_NVP(stackable), CEREAL_NVP(stackable),
@@ -6440,6 +6431,38 @@ struct BuylineItemDetails_Struct {
uint32 item_quantity; uint32 item_quantity;
}; };
/* Taken from libeq */
enum FindLocationType : uint32 {
LocationUnknown,
LocationPlayer,
LocationPOI,
LocationRealEstateItem,
LocationRealEstatePlot,
LocationMapPoint,
LocationSwitch,
LocationLocation
};
//For reference
struct FindableLocation_Struct {
/*00*/ FindLocationType type;
/*04*/ int32 id;
/*08*/ int32 sub_id;
/*12*/ int32 zone_id;
/*16*/ int32 zone_point_identifier;
/*20*/ float y;
/*24*/ float x;
/*28*/ float z;
/*32*/
};
struct FindPersonRequest_Struct {
FindLocationType type;
int32 id;
FindPerson_Point client_pos;
FindPerson_Point target_pos;
};
// Restore structure packing to default // Restore structure packing to default
#pragma pack() #pragma pack()
+3 -10
View File
@@ -4,7 +4,6 @@
#include "../eqemu_logsys.h" #include "../eqemu_logsys.h"
#include "../servertalk.h" #include "../servertalk.h"
#include "../rulesys.h" #include "../rulesys.h"
#include "../event/timer.h"
#include <fmt/format.h> #include <fmt/format.h>
EQ::Net::ConsoleServerConnection::ConsoleServerConnection(ConsoleServer *parent, std::shared_ptr<TCPConnection> connection) EQ::Net::ConsoleServerConnection::ConsoleServerConnection(ConsoleServer *parent, std::shared_ptr<TCPConnection> connection)
@@ -22,11 +21,7 @@ EQ::Net::ConsoleServerConnection::ConsoleServerConnection(ConsoleServer *parent,
m_connection->OnDisconnect(std::bind(&ConsoleServerConnection::OnDisconnect, this, std::placeholders::_1)); m_connection->OnDisconnect(std::bind(&ConsoleServerConnection::OnDisconnect, this, std::placeholders::_1));
m_connection->Start(); m_connection->Start();
ClearBuffer(); ClearBuffer();
m_keepalive = std::make_unique<EQ::Timer>(1000, true, [this](EQ::Timer *t) {
m_connection->Write("", 0);
});
auto addr = m_connection->RemoteIP(); auto addr = m_connection->RemoteIP();
SendLine(fmt::format("Establishing connection from: {0}:{1}", addr, m_connection->RemotePort())); SendLine(fmt::format("Establishing connection from: {0}:{1}", addr, m_connection->RemotePort()));
@@ -90,12 +85,12 @@ void EQ::Net::ConsoleServerConnection::QueueMessage(const std::string &msg)
} }
else { else {
std::string cmd(m_line, m_line + m_cursor); std::string cmd(m_line, m_line + m_cursor);
size_t len = m_user.length() + 2 + cmd.length(); size_t len = m_user.length() + 2 + cmd.length();
for (size_t i = 0; i < len; ++i) { for (size_t i = 0; i < len; ++i) {
Send("\x08"); Send("\x08");
} }
if (msg.length() < cmd.length()) { if (msg.length() < cmd.length()) {
Send(msg); Send(msg);
size_t blank_spaces = 2 + cmd.length() - msg.length(); size_t blank_spaces = 2 + cmd.length() - msg.length();
@@ -232,8 +227,6 @@ void EQ::Net::ConsoleServerConnection::OnRead(TCPConnection *c, const unsigned c
void EQ::Net::ConsoleServerConnection::OnDisconnect(TCPConnection *c) void EQ::Net::ConsoleServerConnection::OnDisconnect(TCPConnection *c)
{ {
LogInfo("Console connection disconnected");
m_parent->ConnectionDisconnected(this); m_parent->ConnectionDisconnected(this);
} }
-2
View File
@@ -1,7 +1,6 @@
#pragma once #pragma once
#include "tcp_server.h" #include "tcp_server.h"
#include "../event/timer.h"
#include <memory> #include <memory>
#include <map> #include <map>
@@ -59,7 +58,6 @@ namespace EQ
int m_user_id; int m_user_id;
int m_admin; int m_admin;
bool m_accept_messages; bool m_accept_messages;
std::unique_ptr<EQ::Timer> m_keepalive;
size_t m_cursor; size_t m_cursor;
char m_line[MaxConsoleLineLength]; char m_line[MaxConsoleLineLength];
+5 -1
View File
@@ -4538,10 +4538,14 @@ namespace RoF
DECODE_LENGTH_EXACT(structs::FindPersonRequest_Struct); DECODE_LENGTH_EXACT(structs::FindPersonRequest_Struct);
SETUP_DIRECT_DECODE(FindPersonRequest_Struct, structs::FindPersonRequest_Struct); SETUP_DIRECT_DECODE(FindPersonRequest_Struct, structs::FindPersonRequest_Struct);
IN(npc_id); IN(type)
IN(id);
IN(client_pos.x); IN(client_pos.x);
IN(client_pos.y); IN(client_pos.y);
IN(client_pos.z); IN(client_pos.z);
IN(target_pos.x);
IN(target_pos.y);
IN(target_pos.z);
FINISH_DIRECT_DECODE(); FINISH_DIRECT_DECODE();
} }
+15 -27
View File
@@ -583,21 +583,19 @@ namespace RoF2
auto outapp = new EQApplicationPacket(OP_TraderShop, sizeof(BecomeTrader_Struct)); auto outapp = new EQApplicationPacket(OP_TraderShop, sizeof(BecomeTrader_Struct));
auto eq = (BecomeTrader_Struct *) outapp->pBuffer; auto eq = (BecomeTrader_Struct *) outapp->pBuffer;
eq->action = emu->action; eq->action = emu->action;
eq->entity_id = emu->entity_id; eq->entity_id = emu->entity_id;
eq->trader_id = emu->trader_id; eq->trader_id = emu->trader_id;
eq->zone_id = emu->zone_id; eq->zone_id = emu->zone_id;
eq->zone_instance_id = emu->zone_instance_id;
strn0cpy(eq->trader_name, emu->trader_name, sizeof(eq->trader_name)); strn0cpy(eq->trader_name, emu->trader_name, sizeof(eq->trader_name));
LogTrading( LogTrading(
"(RoF2) AddTraderToBazaarWindow action <green>[{}] trader_id <green>[{}] entity_id <green>[{}] " "(RoF2) AddTraderToBazaarWindow action <green>[{}] trader_id <green>[{}] entity_id <green>[{}] zone_id <green>[{}]",
"zone_id <green>[{}] zone_instance_id <green>[{}]",
eq->action, eq->action,
eq->trader_id, eq->trader_id,
eq->entity_id, eq->entity_id,
eq->zone_id, eq->zone_id
eq->zone_instance_id); );
dest->FastQueuePacket(&outapp); dest->FastQueuePacket(&outapp);
break; break;
} }
@@ -5519,10 +5517,14 @@ namespace RoF2
DECODE_LENGTH_EXACT(structs::FindPersonRequest_Struct); DECODE_LENGTH_EXACT(structs::FindPersonRequest_Struct);
SETUP_DIRECT_DECODE(FindPersonRequest_Struct, structs::FindPersonRequest_Struct); SETUP_DIRECT_DECODE(FindPersonRequest_Struct, structs::FindPersonRequest_Struct);
IN(npc_id); IN(type)
IN(id);
IN(client_pos.x); IN(client_pos.x);
IN(client_pos.y); IN(client_pos.y);
IN(client_pos.z); IN(client_pos.z);
IN(target_pos.x);
IN(target_pos.y);
IN(target_pos.z);
FINISH_DIRECT_DECODE(); FINISH_DIRECT_DECODE();
} }
@@ -6220,11 +6222,6 @@ namespace RoF2
FINISH_DIRECT_DECODE(); FINISH_DIRECT_DECODE();
break; break;
} }
case structs::RoF2BazaarTraderBuyerActions::FirstOpenSearch: {
__packet->SetOpcode(OP_BazaarSearch);
LogTrading("(RoF2) First time opening Bazaar Search since zoning. Action <green>[{}]", action);
break;
}
case structs::RoF2BazaarTraderBuyerActions::WelcomeMessage: { case structs::RoF2BazaarTraderBuyerActions::WelcomeMessage: {
__packet->SetOpcode(OP_BazaarSearch); __packet->SetOpcode(OP_BazaarSearch);
LogTrading("(RoF2) WelcomeMessage action <green>[{}]", action); LogTrading("(RoF2) WelcomeMessage action <green>[{}]", action);
@@ -6365,18 +6362,9 @@ namespace RoF2
//sprintf(hdr.unknown000, "06e0002Y1W00"); //sprintf(hdr.unknown000, "06e0002Y1W00");
strn0cpy(hdr.unknown000, fmt::format("{:016}\0", inst->GetSerialNumber()).c_str(),sizeof(hdr.unknown000)); strn0cpy(hdr.unknown000, fmt::format("{:016}\0", inst->GetSerialNumber()).c_str(),sizeof(hdr.unknown000));
hdr.stacksize = 1; hdr.stacksize =
item->ID == PARCEL_MONEY_ITEM_ID ? inst->GetPrice() : (inst->IsStackable() ? ((inst->GetCharges() > 1000)
if (item->ID == PARCEL_MONEY_ITEM_ID) { ? 0xFFFFFFFF : inst->GetCharges()) : 1);
hdr.stacksize = inst->GetPrice();
} else if (inst->IsStackable()) {
if (inst->GetCharges() > std::numeric_limits<int16>::max()) {
hdr.stacksize = std::numeric_limits<uint32>::max();
} else {
hdr.stacksize = inst->GetCharges();
}
}
hdr.unknown004 = 0; hdr.unknown004 = 0;
structs::InventorySlot_Struct slot_id{}; structs::InventorySlot_Struct slot_id{};
+7 -9
View File
@@ -3119,8 +3119,7 @@ enum RoF2BazaarTraderBuyerActions {
BazaarInspect = 18, BazaarInspect = 18,
ClickTrader = 28, ClickTrader = 28,
ItemMove = 19, ItemMove = 19,
ReconcileItems = 20, ReconcileItems = 20
FirstOpenSearch = 26
}; };
enum RoF2BuyerActions { enum RoF2BuyerActions {
@@ -4017,14 +4016,13 @@ struct FindPerson_Point {
}; };
struct FindPersonRequest_Struct { struct FindPersonRequest_Struct {
/*00*/ uint32 unknown00; /*00*/ FindLocationType type;
/*04*/ uint32 npc_id; /*04*/ int32 id;
/*08*/ uint32 unknown08; /*08*/ int32 unknown08;
/*12*/ uint32 unknown12; /*12*/ int32 unknown12;
/*16*/ FindPerson_Point client_pos; /*16*/ FindPerson_Point client_pos;
/*28*/ uint32 unknown28; /*28*/ FindPerson_Point target_pos;
/*32*/ uint32 unknown32; /*40*/
/*36*/ uint32 unknown36;
}; };
//variable length packet of points //variable length packet of points
+7 -8
View File
@@ -3779,14 +3779,13 @@ struct FindPerson_Point {
}; };
struct FindPersonRequest_Struct { struct FindPersonRequest_Struct {
/*00*/ uint32 unknown00; /*00*/ FindLocationType type;
/*04*/ uint32 npc_id; /*04*/ int32 id;
/*08*/ uint32 unknown08; /*08*/ int32 unknown08;
/*12*/ uint32 unknown12; /*12*/ int32 unknown12;
/*16*/ FindPerson_Point client_pos; /*16*/ FindPerson_Point client_pos;
/*28*/ uint32 unknown28; /*28*/ FindPerson_Point target_pos;
/*32*/ uint32 unknown32; /*40*/
/*36*/ uint32 unknown36;
}; };
//variable length packet of points //variable length packet of points
+2 -1
View File
@@ -3150,7 +3150,8 @@ namespace SoD
DECODE_LENGTH_EXACT(structs::FindPersonRequest_Struct); DECODE_LENGTH_EXACT(structs::FindPersonRequest_Struct);
SETUP_DIRECT_DECODE(FindPersonRequest_Struct, structs::FindPersonRequest_Struct); SETUP_DIRECT_DECODE(FindPersonRequest_Struct, structs::FindPersonRequest_Struct);
IN(npc_id); emu->type = FindLocationType::LocationPlayer;
emu->id = eq->npc_id;
IN(client_pos.x); IN(client_pos.x);
IN(client_pos.y); IN(client_pos.y);
IN(client_pos.z); IN(client_pos.z);
+2 -1
View File
@@ -2605,7 +2605,8 @@ namespace SoF
DECODE_LENGTH_EXACT(structs::FindPersonRequest_Struct); DECODE_LENGTH_EXACT(structs::FindPersonRequest_Struct);
SETUP_DIRECT_DECODE(FindPersonRequest_Struct, structs::FindPersonRequest_Struct); SETUP_DIRECT_DECODE(FindPersonRequest_Struct, structs::FindPersonRequest_Struct);
IN(npc_id); emu->type = FindLocationType::LocationPlayer;
emu->id = eq->npc_id;
IN(client_pos.x); IN(client_pos.x);
IN(client_pos.y); IN(client_pos.y);
IN(client_pos.z); IN(client_pos.z);
+14
View File
@@ -3327,6 +3327,20 @@ namespace Titanium
FINISH_DIRECT_DECODE(); FINISH_DIRECT_DECODE();
} }
DECODE(OP_FindPersonRequest)
{
DECODE_LENGTH_EXACT(structs::FindPersonRequest_Struct);
SETUP_DIRECT_DECODE(FindPersonRequest_Struct, structs::FindPersonRequest_Struct);
emu->type = FindLocationType::LocationPlayer;
emu->id = eq->npc_id;
IN(client_pos.x);
IN(client_pos.y);
IN(client_pos.z);
FINISH_DIRECT_DECODE();
}
// file scope helper methods // file scope helper methods
void SerializeItem(EQ::OutBuffer& ob, const EQ::ItemInstance *inst, int16 slot_id_in, uint8 depth) { void SerializeItem(EQ::OutBuffer& ob, const EQ::ItemInstance *inst, int16 slot_id_in, uint8 depth) {
const char *protection = "\\\\\\\\\\"; const char *protection = "\\\\\\\\\\";
+1
View File
@@ -132,6 +132,7 @@ D(OP_TradeSkillCombine)
D(OP_TributeItem) D(OP_TributeItem)
D(OP_WearChange) D(OP_WearChange)
D(OP_WhoAllRequest) D(OP_WhoAllRequest)
D(OP_FindPersonRequest)
#undef E #undef E
#undef D #undef D
+2 -1
View File
@@ -3982,7 +3982,8 @@ namespace UF
DECODE_LENGTH_EXACT(structs::FindPersonRequest_Struct); DECODE_LENGTH_EXACT(structs::FindPersonRequest_Struct);
SETUP_DIRECT_DECODE(FindPersonRequest_Struct, structs::FindPersonRequest_Struct); SETUP_DIRECT_DECODE(FindPersonRequest_Struct, structs::FindPersonRequest_Struct);
IN(npc_id); emu->type = FindLocationType::LocationPlayer;
emu->id = eq->npc_id;
IN(client_pos.x); IN(client_pos.x);
IN(client_pos.y); IN(client_pos.y);
IN(client_pos.z); IN(client_pos.z);
@@ -49,23 +49,23 @@ public:
std::string field; std::string field;
switch (theme_id) { switch (theme_id) {
case LDoNTheme::GUK: { case LDoNThemes::GUK: {
field = "guk_"; field = "guk_";
break; break;
} }
case LDoNTheme::MIR: { case LDoNThemes::MIR: {
field = "mir_"; field = "mir_";
break; break;
} }
case LDoNTheme::MMC: { case LDoNThemes::MMC: {
field = "mmc_"; field = "mmc_";
break; break;
} }
case LDoNTheme::RUJ: { case LDoNThemes::RUJ: {
field = "ruj_"; field = "ruj_";
break; break;
} }
case LDoNTheme::TAK: { case LDoNThemes::TAK: {
field = "tak_"; field = "tak_";
break; break;
} }
@@ -0,0 +1,547 @@
/**
* DO NOT MODIFY THIS FILE
*
* This repository was automatically generated and is NOT to be modified directly.
* Any repository modifications are meant to be made to the repository extending the base.
* Any modifications to base repositories are to be made by the generator only
*
* @generator ./utils/scripts/generators/repository-generator.pl
* @docs https://docs.eqemu.io/developer/repositories
*/
#ifndef EQEMU_BASE_FINDABLE_LOCATION_REPOSITORY_H
#define EQEMU_BASE_FINDABLE_LOCATION_REPOSITORY_H
#include "../../database.h"
#include "../../strings.h"
#include <ctime>
class BaseFindableLocationRepository {
public:
struct FindableLocation {
uint32_t id;
std::string zone;
int32_t version;
int32_t findable_id;
int32_t findable_sub_id;
int32_t type;
int32_t zone_id;
int32_t zone_id_index;
float x;
float y;
float z;
int8_t min_expansion;
int8_t max_expansion;
std::string content_flags;
std::string content_flags_disabled;
};
static std::string PrimaryKey()
{
return std::string("id");
}
static std::vector<std::string> Columns()
{
return {
"id",
"zone",
"version",
"findable_id",
"findable_sub_id",
"type",
"zone_id",
"zone_id_index",
"x",
"y",
"z",
"min_expansion",
"max_expansion",
"content_flags",
"content_flags_disabled",
};
}
static std::vector<std::string> SelectColumns()
{
return {
"id",
"zone",
"version",
"findable_id",
"findable_sub_id",
"type",
"zone_id",
"zone_id_index",
"x",
"y",
"z",
"min_expansion",
"max_expansion",
"content_flags",
"content_flags_disabled",
};
}
static std::string ColumnsRaw()
{
return std::string(Strings::Implode(", ", Columns()));
}
static std::string SelectColumnsRaw()
{
return std::string(Strings::Implode(", ", SelectColumns()));
}
static std::string TableName()
{
return std::string("findable_location");
}
static std::string BaseSelect()
{
return fmt::format(
"SELECT {} FROM {}",
SelectColumnsRaw(),
TableName()
);
}
static std::string BaseInsert()
{
return fmt::format(
"INSERT INTO {} ({}) ",
TableName(),
ColumnsRaw()
);
}
static FindableLocation NewEntity()
{
FindableLocation e{};
e.id = 0;
e.zone = "";
e.version = 0;
e.findable_id = 0;
e.findable_sub_id = 0;
e.type = 0;
e.zone_id = 0;
e.zone_id_index = 0;
e.x = 0;
e.y = 0;
e.z = 0;
e.min_expansion = -1;
e.max_expansion = -1;
e.content_flags = "";
e.content_flags_disabled = "";
return e;
}
static FindableLocation GetFindableLocation(
const std::vector<FindableLocation> &findable_locations,
int findable_location_id
)
{
for (auto &findable_location : findable_locations) {
if (findable_location.id == findable_location_id) {
return findable_location;
}
}
return NewEntity();
}
static FindableLocation FindOne(
Database& db,
int findable_location_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"{} WHERE {} = {} LIMIT 1",
BaseSelect(),
PrimaryKey(),
findable_location_id
)
);
auto row = results.begin();
if (results.RowCount() == 1) {
FindableLocation e{};
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.zone = row[1] ? row[1] : "";
e.version = row[2] ? static_cast<int32_t>(atoi(row[2])) : 0;
e.findable_id = row[3] ? static_cast<int32_t>(atoi(row[3])) : 0;
e.findable_sub_id = row[4] ? static_cast<int32_t>(atoi(row[4])) : 0;
e.type = row[5] ? static_cast<int32_t>(atoi(row[5])) : 0;
e.zone_id = row[6] ? static_cast<int32_t>(atoi(row[6])) : 0;
e.zone_id_index = row[7] ? static_cast<int32_t>(atoi(row[7])) : 0;
e.x = row[8] ? strtof(row[8], nullptr) : 0;
e.y = row[9] ? strtof(row[9], nullptr) : 0;
e.z = row[10] ? strtof(row[10], nullptr) : 0;
e.min_expansion = row[11] ? static_cast<int8_t>(atoi(row[11])) : -1;
e.max_expansion = row[12] ? static_cast<int8_t>(atoi(row[12])) : -1;
e.content_flags = row[13] ? row[13] : "";
e.content_flags_disabled = row[14] ? row[14] : "";
return e;
}
return NewEntity();
}
static int DeleteOne(
Database& db,
int findable_location_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {} = {}",
TableName(),
PrimaryKey(),
findable_location_id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int UpdateOne(
Database& db,
const FindableLocation &e
)
{
std::vector<std::string> v;
auto columns = Columns();
v.push_back(columns[1] + " = '" + Strings::Escape(e.zone) + "'");
v.push_back(columns[2] + " = " + std::to_string(e.version));
v.push_back(columns[3] + " = " + std::to_string(e.findable_id));
v.push_back(columns[4] + " = " + std::to_string(e.findable_sub_id));
v.push_back(columns[5] + " = " + std::to_string(e.type));
v.push_back(columns[6] + " = " + std::to_string(e.zone_id));
v.push_back(columns[7] + " = " + std::to_string(e.zone_id_index));
v.push_back(columns[8] + " = " + std::to_string(e.x));
v.push_back(columns[9] + " = " + std::to_string(e.y));
v.push_back(columns[10] + " = " + std::to_string(e.z));
v.push_back(columns[11] + " = " + std::to_string(e.min_expansion));
v.push_back(columns[12] + " = " + std::to_string(e.max_expansion));
v.push_back(columns[13] + " = '" + Strings::Escape(e.content_flags) + "'");
v.push_back(columns[14] + " = '" + Strings::Escape(e.content_flags_disabled) + "'");
auto results = db.QueryDatabase(
fmt::format(
"UPDATE {} SET {} WHERE {} = {}",
TableName(),
Strings::Implode(", ", v),
PrimaryKey(),
e.id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static FindableLocation InsertOne(
Database& db,
FindableLocation e
)
{
std::vector<std::string> v;
v.push_back(std::to_string(e.id));
v.push_back("'" + Strings::Escape(e.zone) + "'");
v.push_back(std::to_string(e.version));
v.push_back(std::to_string(e.findable_id));
v.push_back(std::to_string(e.findable_sub_id));
v.push_back(std::to_string(e.type));
v.push_back(std::to_string(e.zone_id));
v.push_back(std::to_string(e.zone_id_index));
v.push_back(std::to_string(e.x));
v.push_back(std::to_string(e.y));
v.push_back(std::to_string(e.z));
v.push_back(std::to_string(e.min_expansion));
v.push_back(std::to_string(e.max_expansion));
v.push_back("'" + Strings::Escape(e.content_flags) + "'");
v.push_back("'" + Strings::Escape(e.content_flags_disabled) + "'");
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES ({})",
BaseInsert(),
Strings::Implode(",", v)
)
);
if (results.Success()) {
e.id = results.LastInsertedID();
return e;
}
e = NewEntity();
return e;
}
static int InsertMany(
Database& db,
const std::vector<FindableLocation> &entries
)
{
std::vector<std::string> insert_chunks;
for (auto &e: entries) {
std::vector<std::string> v;
v.push_back(std::to_string(e.id));
v.push_back("'" + Strings::Escape(e.zone) + "'");
v.push_back(std::to_string(e.version));
v.push_back(std::to_string(e.findable_id));
v.push_back(std::to_string(e.findable_sub_id));
v.push_back(std::to_string(e.type));
v.push_back(std::to_string(e.zone_id));
v.push_back(std::to_string(e.zone_id_index));
v.push_back(std::to_string(e.x));
v.push_back(std::to_string(e.y));
v.push_back(std::to_string(e.z));
v.push_back(std::to_string(e.min_expansion));
v.push_back(std::to_string(e.max_expansion));
v.push_back("'" + Strings::Escape(e.content_flags) + "'");
v.push_back("'" + Strings::Escape(e.content_flags_disabled) + "'");
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
}
std::vector<std::string> v;
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES {}",
BaseInsert(),
Strings::Implode(",", insert_chunks)
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static std::vector<FindableLocation> All(Database& db)
{
std::vector<FindableLocation> all_entries;
auto results = db.QueryDatabase(
fmt::format(
"{}",
BaseSelect()
)
);
all_entries.reserve(results.RowCount());
for (auto row = results.begin(); row != results.end(); ++row) {
FindableLocation e{};
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.zone = row[1] ? row[1] : "";
e.version = row[2] ? static_cast<int32_t>(atoi(row[2])) : 0;
e.findable_id = row[3] ? static_cast<int32_t>(atoi(row[3])) : 0;
e.findable_sub_id = row[4] ? static_cast<int32_t>(atoi(row[4])) : 0;
e.type = row[5] ? static_cast<int32_t>(atoi(row[5])) : 0;
e.zone_id = row[6] ? static_cast<int32_t>(atoi(row[6])) : 0;
e.zone_id_index = row[7] ? static_cast<int32_t>(atoi(row[7])) : 0;
e.x = row[8] ? strtof(row[8], nullptr) : 0;
e.y = row[9] ? strtof(row[9], nullptr) : 0;
e.z = row[10] ? strtof(row[10], nullptr) : 0;
e.min_expansion = row[11] ? static_cast<int8_t>(atoi(row[11])) : -1;
e.max_expansion = row[12] ? static_cast<int8_t>(atoi(row[12])) : -1;
e.content_flags = row[13] ? row[13] : "";
e.content_flags_disabled = row[14] ? row[14] : "";
all_entries.push_back(e);
}
return all_entries;
}
static std::vector<FindableLocation> GetWhere(Database& db, const std::string &where_filter)
{
std::vector<FindableLocation> all_entries;
auto results = db.QueryDatabase(
fmt::format(
"{} WHERE {}",
BaseSelect(),
where_filter
)
);
all_entries.reserve(results.RowCount());
for (auto row = results.begin(); row != results.end(); ++row) {
FindableLocation e{};
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.zone = row[1] ? row[1] : "";
e.version = row[2] ? static_cast<int32_t>(atoi(row[2])) : 0;
e.findable_id = row[3] ? static_cast<int32_t>(atoi(row[3])) : 0;
e.findable_sub_id = row[4] ? static_cast<int32_t>(atoi(row[4])) : 0;
e.type = row[5] ? static_cast<int32_t>(atoi(row[5])) : 0;
e.zone_id = row[6] ? static_cast<int32_t>(atoi(row[6])) : 0;
e.zone_id_index = row[7] ? static_cast<int32_t>(atoi(row[7])) : 0;
e.x = row[8] ? strtof(row[8], nullptr) : 0;
e.y = row[9] ? strtof(row[9], nullptr) : 0;
e.z = row[10] ? strtof(row[10], nullptr) : 0;
e.min_expansion = row[11] ? static_cast<int8_t>(atoi(row[11])) : -1;
e.max_expansion = row[12] ? static_cast<int8_t>(atoi(row[12])) : -1;
e.content_flags = row[13] ? row[13] : "";
e.content_flags_disabled = row[14] ? row[14] : "";
all_entries.push_back(e);
}
return all_entries;
}
static int DeleteWhere(Database& db, const std::string &where_filter)
{
auto results = db.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {}",
TableName(),
where_filter
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int Truncate(Database& db)
{
auto results = db.QueryDatabase(
fmt::format(
"TRUNCATE TABLE {}",
TableName()
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int64 GetMaxId(Database& db)
{
auto results = db.QueryDatabase(
fmt::format(
"SELECT COALESCE(MAX({}), 0) FROM {}",
PrimaryKey(),
TableName()
)
);
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
}
static int64 Count(Database& db, const std::string &where_filter = "")
{
auto results = db.QueryDatabase(
fmt::format(
"SELECT COUNT(*) FROM {} {}",
TableName(),
(where_filter.empty() ? "" : "WHERE " + where_filter)
)
);
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
}
static std::string BaseReplace()
{
return fmt::format(
"REPLACE INTO {} ({}) ",
TableName(),
ColumnsRaw()
);
}
static int ReplaceOne(
Database& db,
const FindableLocation &e
)
{
std::vector<std::string> v;
v.push_back(std::to_string(e.id));
v.push_back("'" + Strings::Escape(e.zone) + "'");
v.push_back(std::to_string(e.version));
v.push_back(std::to_string(e.findable_id));
v.push_back(std::to_string(e.findable_sub_id));
v.push_back(std::to_string(e.type));
v.push_back(std::to_string(e.zone_id));
v.push_back(std::to_string(e.zone_id_index));
v.push_back(std::to_string(e.x));
v.push_back(std::to_string(e.y));
v.push_back(std::to_string(e.z));
v.push_back(std::to_string(e.min_expansion));
v.push_back(std::to_string(e.max_expansion));
v.push_back("'" + Strings::Escape(e.content_flags) + "'");
v.push_back("'" + Strings::Escape(e.content_flags_disabled) + "'");
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES ({})",
BaseReplace(),
Strings::Implode(",", v)
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int ReplaceMany(
Database& db,
const std::vector<FindableLocation> &entries
)
{
std::vector<std::string> insert_chunks;
for (auto &e: entries) {
std::vector<std::string> v;
v.push_back(std::to_string(e.id));
v.push_back("'" + Strings::Escape(e.zone) + "'");
v.push_back(std::to_string(e.version));
v.push_back(std::to_string(e.findable_id));
v.push_back(std::to_string(e.findable_sub_id));
v.push_back(std::to_string(e.type));
v.push_back(std::to_string(e.zone_id));
v.push_back(std::to_string(e.zone_id_index));
v.push_back(std::to_string(e.x));
v.push_back(std::to_string(e.y));
v.push_back(std::to_string(e.z));
v.push_back(std::to_string(e.min_expansion));
v.push_back(std::to_string(e.max_expansion));
v.push_back("'" + Strings::Escape(e.content_flags) + "'");
v.push_back("'" + Strings::Escape(e.content_flags_disabled) + "'");
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
}
std::vector<std::string> v;
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES {}",
BaseReplace(),
Strings::Implode(",", insert_chunks)
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
};
#endif //EQEMU_BASE_FINDABLE_LOCATION_REPOSITORY_H
@@ -28,14 +28,13 @@ public:
uint32_t aug_slot_4; uint32_t aug_slot_4;
uint32_t aug_slot_5; uint32_t aug_slot_5;
uint32_t aug_slot_6; uint32_t aug_slot_6;
uint32_t item_sn; int32_t item_sn;
int32_t item_charges; int32_t item_charges;
uint32_t item_cost; uint64_t item_cost;
uint8_t slot_id; uint8_t slot_id;
uint32_t char_entity_id; uint32_t char_entity_id;
uint32_t char_zone_id; uint32_t char_zone_id;
int32_t char_zone_instance_id; int8_t active_transaction;
uint8_t active_transaction;
}; };
static std::string PrimaryKey() static std::string PrimaryKey()
@@ -61,7 +60,6 @@ public:
"slot_id", "slot_id",
"char_entity_id", "char_entity_id",
"char_zone_id", "char_zone_id",
"char_zone_instance_id",
"active_transaction", "active_transaction",
}; };
} }
@@ -84,7 +82,6 @@ public:
"slot_id", "slot_id",
"char_entity_id", "char_entity_id",
"char_zone_id", "char_zone_id",
"char_zone_instance_id",
"active_transaction", "active_transaction",
}; };
} }
@@ -126,23 +123,22 @@ public:
{ {
Trader e{}; Trader e{};
e.id = 0; e.id = 0;
e.char_id = 0; e.char_id = 0;
e.item_id = 0; e.item_id = 0;
e.aug_slot_1 = 0; e.aug_slot_1 = 0;
e.aug_slot_2 = 0; e.aug_slot_2 = 0;
e.aug_slot_3 = 0; e.aug_slot_3 = 0;
e.aug_slot_4 = 0; e.aug_slot_4 = 0;
e.aug_slot_5 = 0; e.aug_slot_5 = 0;
e.aug_slot_6 = 0; e.aug_slot_6 = 0;
e.item_sn = 0; e.item_sn = 0;
e.item_charges = 0; e.item_charges = 0;
e.item_cost = 0; e.item_cost = 0;
e.slot_id = 0; e.slot_id = 0;
e.char_entity_id = 0; e.char_entity_id = 0;
e.char_zone_id = 0; e.char_zone_id = 0;
e.char_zone_instance_id = 0; e.active_transaction = 0;
e.active_transaction = 0;
return e; return e;
} }
@@ -179,23 +175,22 @@ public:
if (results.RowCount() == 1) { if (results.RowCount() == 1) {
Trader e{}; Trader e{};
e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0;
e.char_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0; e.char_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
e.item_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0; e.item_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
e.aug_slot_1 = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0; e.aug_slot_1 = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
e.aug_slot_2 = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0; e.aug_slot_2 = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
e.aug_slot_3 = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0; e.aug_slot_3 = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
e.aug_slot_4 = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0; e.aug_slot_4 = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
e.aug_slot_5 = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0; e.aug_slot_5 = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
e.aug_slot_6 = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0; e.aug_slot_6 = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
e.item_sn = row[9] ? static_cast<uint32_t>(strtoul(row[9], nullptr, 10)) : 0; e.item_sn = row[9] ? static_cast<int32_t>(atoi(row[9])) : 0;
e.item_charges = row[10] ? static_cast<int32_t>(atoi(row[10])) : 0; e.item_charges = row[10] ? static_cast<int32_t>(atoi(row[10])) : 0;
e.item_cost = row[11] ? static_cast<uint32_t>(strtoul(row[11], nullptr, 10)) : 0; e.item_cost = row[11] ? strtoull(row[11], nullptr, 10) : 0;
e.slot_id = row[12] ? static_cast<uint8_t>(strtoul(row[12], nullptr, 10)) : 0; e.slot_id = row[12] ? static_cast<uint8_t>(strtoul(row[12], nullptr, 10)) : 0;
e.char_entity_id = row[13] ? static_cast<uint32_t>(strtoul(row[13], nullptr, 10)) : 0; e.char_entity_id = row[13] ? static_cast<uint32_t>(strtoul(row[13], nullptr, 10)) : 0;
e.char_zone_id = row[14] ? static_cast<uint32_t>(strtoul(row[14], nullptr, 10)) : 0; e.char_zone_id = row[14] ? static_cast<uint32_t>(strtoul(row[14], nullptr, 10)) : 0;
e.char_zone_instance_id = row[15] ? static_cast<int32_t>(atoi(row[15])) : 0; e.active_transaction = row[15] ? static_cast<int8_t>(atoi(row[15])) : 0;
e.active_transaction = row[16] ? static_cast<uint8_t>(strtoul(row[16], nullptr, 10)) : 0;
return e; return e;
} }
@@ -243,8 +238,7 @@ public:
v.push_back(columns[12] + " = " + std::to_string(e.slot_id)); v.push_back(columns[12] + " = " + std::to_string(e.slot_id));
v.push_back(columns[13] + " = " + std::to_string(e.char_entity_id)); v.push_back(columns[13] + " = " + std::to_string(e.char_entity_id));
v.push_back(columns[14] + " = " + std::to_string(e.char_zone_id)); v.push_back(columns[14] + " = " + std::to_string(e.char_zone_id));
v.push_back(columns[15] + " = " + std::to_string(e.char_zone_instance_id)); v.push_back(columns[15] + " = " + std::to_string(e.active_transaction));
v.push_back(columns[16] + " = " + std::to_string(e.active_transaction));
auto results = db.QueryDatabase( auto results = db.QueryDatabase(
fmt::format( fmt::format(
@@ -281,7 +275,6 @@ public:
v.push_back(std::to_string(e.slot_id)); v.push_back(std::to_string(e.slot_id));
v.push_back(std::to_string(e.char_entity_id)); v.push_back(std::to_string(e.char_entity_id));
v.push_back(std::to_string(e.char_zone_id)); v.push_back(std::to_string(e.char_zone_id));
v.push_back(std::to_string(e.char_zone_instance_id));
v.push_back(std::to_string(e.active_transaction)); v.push_back(std::to_string(e.active_transaction));
auto results = db.QueryDatabase( auto results = db.QueryDatabase(
@@ -327,7 +320,6 @@ public:
v.push_back(std::to_string(e.slot_id)); v.push_back(std::to_string(e.slot_id));
v.push_back(std::to_string(e.char_entity_id)); v.push_back(std::to_string(e.char_entity_id));
v.push_back(std::to_string(e.char_zone_id)); v.push_back(std::to_string(e.char_zone_id));
v.push_back(std::to_string(e.char_zone_instance_id));
v.push_back(std::to_string(e.active_transaction)); v.push_back(std::to_string(e.active_transaction));
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
@@ -362,23 +354,22 @@ public:
for (auto row = results.begin(); row != results.end(); ++row) { for (auto row = results.begin(); row != results.end(); ++row) {
Trader e{}; Trader e{};
e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0;
e.char_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0; e.char_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
e.item_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0; e.item_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
e.aug_slot_1 = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0; e.aug_slot_1 = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
e.aug_slot_2 = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0; e.aug_slot_2 = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
e.aug_slot_3 = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0; e.aug_slot_3 = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
e.aug_slot_4 = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0; e.aug_slot_4 = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
e.aug_slot_5 = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0; e.aug_slot_5 = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
e.aug_slot_6 = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0; e.aug_slot_6 = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
e.item_sn = row[9] ? static_cast<uint32_t>(strtoul(row[9], nullptr, 10)) : 0; e.item_sn = row[9] ? static_cast<int32_t>(atoi(row[9])) : 0;
e.item_charges = row[10] ? static_cast<int32_t>(atoi(row[10])) : 0; e.item_charges = row[10] ? static_cast<int32_t>(atoi(row[10])) : 0;
e.item_cost = row[11] ? static_cast<uint32_t>(strtoul(row[11], nullptr, 10)) : 0; e.item_cost = row[11] ? strtoull(row[11], nullptr, 10) : 0;
e.slot_id = row[12] ? static_cast<uint8_t>(strtoul(row[12], nullptr, 10)) : 0; e.slot_id = row[12] ? static_cast<uint8_t>(strtoul(row[12], nullptr, 10)) : 0;
e.char_entity_id = row[13] ? static_cast<uint32_t>(strtoul(row[13], nullptr, 10)) : 0; e.char_entity_id = row[13] ? static_cast<uint32_t>(strtoul(row[13], nullptr, 10)) : 0;
e.char_zone_id = row[14] ? static_cast<uint32_t>(strtoul(row[14], nullptr, 10)) : 0; e.char_zone_id = row[14] ? static_cast<uint32_t>(strtoul(row[14], nullptr, 10)) : 0;
e.char_zone_instance_id = row[15] ? static_cast<int32_t>(atoi(row[15])) : 0; e.active_transaction = row[15] ? static_cast<int8_t>(atoi(row[15])) : 0;
e.active_transaction = row[16] ? static_cast<uint8_t>(strtoul(row[16], nullptr, 10)) : 0;
all_entries.push_back(e); all_entries.push_back(e);
} }
@@ -403,23 +394,22 @@ public:
for (auto row = results.begin(); row != results.end(); ++row) { for (auto row = results.begin(); row != results.end(); ++row) {
Trader e{}; Trader e{};
e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0;
e.char_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0; e.char_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
e.item_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0; e.item_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
e.aug_slot_1 = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0; e.aug_slot_1 = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
e.aug_slot_2 = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0; e.aug_slot_2 = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
e.aug_slot_3 = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0; e.aug_slot_3 = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
e.aug_slot_4 = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0; e.aug_slot_4 = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
e.aug_slot_5 = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0; e.aug_slot_5 = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
e.aug_slot_6 = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0; e.aug_slot_6 = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
e.item_sn = row[9] ? static_cast<uint32_t>(strtoul(row[9], nullptr, 10)) : 0; e.item_sn = row[9] ? static_cast<int32_t>(atoi(row[9])) : 0;
e.item_charges = row[10] ? static_cast<int32_t>(atoi(row[10])) : 0; e.item_charges = row[10] ? static_cast<int32_t>(atoi(row[10])) : 0;
e.item_cost = row[11] ? static_cast<uint32_t>(strtoul(row[11], nullptr, 10)) : 0; e.item_cost = row[11] ? strtoull(row[11], nullptr, 10) : 0;
e.slot_id = row[12] ? static_cast<uint8_t>(strtoul(row[12], nullptr, 10)) : 0; e.slot_id = row[12] ? static_cast<uint8_t>(strtoul(row[12], nullptr, 10)) : 0;
e.char_entity_id = row[13] ? static_cast<uint32_t>(strtoul(row[13], nullptr, 10)) : 0; e.char_entity_id = row[13] ? static_cast<uint32_t>(strtoul(row[13], nullptr, 10)) : 0;
e.char_zone_id = row[14] ? static_cast<uint32_t>(strtoul(row[14], nullptr, 10)) : 0; e.char_zone_id = row[14] ? static_cast<uint32_t>(strtoul(row[14], nullptr, 10)) : 0;
e.char_zone_instance_id = row[15] ? static_cast<int32_t>(atoi(row[15])) : 0; e.active_transaction = row[15] ? static_cast<int8_t>(atoi(row[15])) : 0;
e.active_transaction = row[16] ? static_cast<uint8_t>(strtoul(row[16], nullptr, 10)) : 0;
all_entries.push_back(e); all_entries.push_back(e);
} }
@@ -509,7 +499,6 @@ public:
v.push_back(std::to_string(e.slot_id)); v.push_back(std::to_string(e.slot_id));
v.push_back(std::to_string(e.char_entity_id)); v.push_back(std::to_string(e.char_entity_id));
v.push_back(std::to_string(e.char_zone_id)); v.push_back(std::to_string(e.char_zone_id));
v.push_back(std::to_string(e.char_zone_instance_id));
v.push_back(std::to_string(e.active_transaction)); v.push_back(std::to_string(e.active_transaction));
auto results = db.QueryDatabase( auto results = db.QueryDatabase(
@@ -548,7 +537,6 @@ public:
v.push_back(std::to_string(e.slot_id)); v.push_back(std::to_string(e.slot_id));
v.push_back(std::to_string(e.char_entity_id)); v.push_back(std::to_string(e.char_entity_id));
v.push_back(std::to_string(e.char_zone_id)); v.push_back(std::to_string(e.char_zone_id));
v.push_back(std::to_string(e.char_zone_instance_id));
v.push_back(std::to_string(e.active_transaction)); v.push_back(std::to_string(e.active_transaction));
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
@@ -0,0 +1,50 @@
#ifndef EQEMU_FINDABLE_LOCATION_REPOSITORY_H
#define EQEMU_FINDABLE_LOCATION_REPOSITORY_H
#include "../database.h"
#include "../strings.h"
#include "base/base_findable_location_repository.h"
class FindableLocationRepository: public BaseFindableLocationRepository {
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
*
* FindableLocationRepository::GetByZoneAndVersion(int zone_id, int zone_version)
* FindableLocationRepository::GetWhereNeverExpires()
* FindableLocationRepository::GetWhereXAndY()
* FindableLocationRepository::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
};
#endif //EQEMU_FINDABLE_LOCATION_REPOSITORY_H
+6 -9
View File
@@ -16,7 +16,6 @@ public:
struct DistinctTraders_Struct { struct DistinctTraders_Struct {
uint32 trader_id; uint32 trader_id;
uint32 zone_id; uint32 zone_id;
uint32 zone_instance_id;
uint32 entity_id; uint32 entity_id;
std::string trader_name; std::string trader_name;
}; };
@@ -36,8 +35,7 @@ public:
GetBazaarSearchResults( GetBazaarSearchResults(
SharedDatabase &db, SharedDatabase &db,
BazaarSearchCriteria_Struct search, BazaarSearchCriteria_Struct search,
uint32 char_zone_id, uint32 char_zone_id
int32 char_zone_instance_id
); );
static BulkTraders_Struct GetDistinctTraders(Database &db) static BulkTraders_Struct GetDistinctTraders(Database &db)
@@ -46,7 +44,7 @@ public:
std::vector<DistinctTraders_Struct> distinct_traders; std::vector<DistinctTraders_Struct> distinct_traders;
auto results = db.QueryDatabase( auto results = db.QueryDatabase(
"SELECT DISTINCT(t.char_id), t.char_zone_id, t.char_zone_instance_id, t.char_entity_id, c.name " "SELECT DISTINCT(t.char_id), t.char_zone_id, t.char_entity_id, c.name "
"FROM trader AS t " "FROM trader AS t "
"JOIN character_data AS c ON t.char_id = c.id;" "JOIN character_data AS c ON t.char_id = c.id;"
); );
@@ -56,11 +54,10 @@ public:
for (auto row: results) { for (auto row: results) {
DistinctTraders_Struct e{}; DistinctTraders_Struct e{};
e.trader_id = Strings::ToInt(row[0]); e.trader_id = Strings::ToInt(row[0]);
e.zone_id = Strings::ToInt(row[1]); e.zone_id = Strings::ToInt(row[1]);
e.zone_instance_id = Strings::ToInt(row[2]); e.entity_id = Strings::ToInt(row[2]);
e.entity_id = Strings::ToInt(row[3]); e.trader_name = row[3] ? row[3] : "";
e.trader_name = row[4] ? row[4] : "";
all_entries.name_length += e.trader_name.length() + 1; all_entries.name_length += e.trader_name.length() + 1;
all_entries.traders.push_back(e); all_entries.traders.push_back(e);
-3
View File
@@ -340,9 +340,6 @@ RULE_STRING(World, Rules, "", "Server Rules, change from empty to have this be u
RULE_BOOL(World, EnableAutoLogin, false, "Enables or disables auto login of characters, allowing people to log characters in directly from loginserver to ingame") RULE_BOOL(World, EnableAutoLogin, false, "Enables or disables auto login of characters, allowing people to log characters in directly from loginserver to ingame")
RULE_BOOL(World, EnablePVPRegions, true, "Enables or disables PVP Regions automatically setting your PVP flag") RULE_BOOL(World, EnablePVPRegions, true, "Enables or disables PVP Regions automatically setting your PVP flag")
RULE_STRING(World, SupportedClients, "", "Comma-delimited list of clients to restrict to. Supported values are Titanium | SoF | SoD | UF | RoF | RoF2. Example: Titanium,RoF2") RULE_STRING(World, SupportedClients, "", "Comma-delimited list of clients to restrict to. Supported values are Titanium | SoF | SoD | UF | RoF | RoF2. Example: Titanium,RoF2")
RULE_STRING(World, CustomFilesKey, "", "Enable if the server requires custom files and sends a key to validate. Empty string to disable. Example: eqcustom_v1")
RULE_STRING(World, CustomFilesUrl, "github.com/knervous/eqnexus/releases", "URL to display at character select if client is missing custom files")
RULE_INT(World, CustomFilesAdminLevel, 20, "Admin level at which custom file key is not required when CustomFilesKey is specified")
RULE_CATEGORY_END() RULE_CATEGORY_END()
RULE_CATEGORY(Zone) RULE_CATEGORY(Zone)
+3
View File
@@ -282,6 +282,7 @@
#define ServerOP_ReloadBaseData 0x4128 #define ServerOP_ReloadBaseData 0x4128
#define ServerOP_ReloadSkillCaps 0x4129 #define ServerOP_ReloadSkillCaps 0x4129
#define ServerOP_ReloadNPCSpells 0x4130 #define ServerOP_ReloadNPCSpells 0x4130
#define ServerOP_ReloadFindableLocations 0x4131
#define ServerOP_CZDialogueWindow 0x4500 #define ServerOP_CZDialogueWindow 0x4500
#define ServerOP_CZLDoNUpdate 0x4501 #define ServerOP_CZLDoNUpdate 0x4501
@@ -319,6 +320,8 @@
// player events // player events
#define ServerOP_PlayerEvent 0x5100 #define ServerOP_PlayerEvent 0x5100
#define ServerOP_DataBucketCacheUpdate 0x5200
enum { enum {
CZUpdateType_Character, CZUpdateType_Character,
CZUpdateType_Group, CZUpdateType_Group,
+1 -1
View File
@@ -42,7 +42,7 @@
* Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt * Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
*/ */
#define CURRENT_BINARY_DATABASE_VERSION 9286 #define CURRENT_BINARY_DATABASE_VERSION 9285
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9045 #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9045
#endif #endif
+1
View File
@@ -311,6 +311,7 @@ OP_SetGroupTarget=0x2814
OP_Charm=0x5d92 OP_Charm=0x5d92
OP_Stun=0x36a4 OP_Stun=0x36a4
OP_SendFindableNPCs=0x4613 OP_SendFindableNPCs=0x4613
OP_SendFindableLocations=0x6a68
OP_FindPersonRequest=0x5cea OP_FindPersonRequest=0x5cea
OP_FindPersonReply=0x7e58 OP_FindPersonReply=0x7e58
OP_Sound=0x1a30 OP_Sound=0x1a30
+1 -1
View File
@@ -10,7 +10,7 @@ require (
require ( require (
github.com/golang/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.3.2 // indirect
github.com/google/go-querystring v1.1.0 // indirect github.com/google/go-querystring v1.1.0 // indirect
golang.org/x/crypto v0.31.0 // indirect golang.org/x/crypto v0.21.0 // indirect
golang.org/x/net v0.23.0 // indirect golang.org/x/net v0.23.0 // indirect
google.golang.org/appengine v1.6.7 // indirect google.golang.org/appengine v1.6.7 // indirect
) )
+2 -2
View File
@@ -10,8 +10,8 @@ github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs=
+33
View File
@@ -0,0 +1,33 @@
CREATE TABLE `findable_location` (
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`zone` VARCHAR(32) NOT NULL COLLATE 'utf8mb4_general_ci',
`version` INT(11) NOT NULL DEFAULT '0',
`findable_id` INT(11) NOT NULL DEFAULT '0',
`findable_sub_id` INT(11) NOT NULL DEFAULT '0',
`type` INT(11) NOT NULL DEFAULT '0',
`zone_id` INT(11) NOT NULL DEFAULT '0',
`zone_id_index` INT(11) NOT NULL DEFAULT '0',
`x` FLOAT NOT NULL DEFAULT '0',
`y` FLOAT NOT NULL DEFAULT '0',
`z` FLOAT NOT NULL DEFAULT '0',
`min_expansion` TINYINT(4) NOT NULL DEFAULT '-1',
`max_expansion` TINYINT(4) NOT NULL DEFAULT '-1',
`content_flags` VARCHAR(100) NULL DEFAULT NULL COLLATE 'utf8mb4_general_ci',
`content_flags_disabled` VARCHAR(100) NULL DEFAULT NULL COLLATE 'utf8mb4_general_ci',
PRIMARY KEY (`id`) USING BTREE,
INDEX `zone_version` (`zone`, `version`) USING BTREE
);
INSERT INTO `findable_location` (zone, version, findable_id, findable_sub_id, type, zone_id, zone_id_index, x, y, z) VALUES ('qeynos2', 0, 77, -1, 6, 202, 0, 484.484130859375, 183.69752502441406, 0.0020000000949949026);
INSERT INTO `findable_location` (zone, version, findable_id, findable_sub_id, type, zone_id, zone_id_index, x, y, z) VALUES ('qeynos2', 0, 16, 0, 7, 45, 1, 342.86285400390625, 188.9244384765625, -181.92721557617188);
INSERT INTO `findable_location` (zone, version, findable_id, findable_sub_id, type, zone_id, zone_id_index, x, y, z) VALUES ('qeynos2', 0, 17, 0, 7, 1, 1, -6.997137069702148, -174.92999267578125, 15.993850708007812);
INSERT INTO `findable_location` (zone, version, findable_id, findable_sub_id, type, zone_id, zone_id_index, x, y, z) VALUES ('qeynos2', 0, 18, 0, 7, 1, 2, 356.8572692871094, -48.98040771484375, 15.993560791015625);
INSERT INTO `findable_location` (zone, version, findable_id, findable_sub_id, type, zone_id, zone_id_index, x, y, z) VALUES ('qeynos2', 0, 19, 0, 7, 4, 1, 566.7733154296875, 1699.3203125, 54.97816467285156);
INSERT INTO `findable_location` (zone, version, findable_id, findable_sub_id, type, zone_id, zone_id_index, x, y, z) VALUES ('qeynos2', 0, 19, 2, 7, 4, 2, 230.90762329101562, 1699.3203125, 59.97674560546875);
INSERT INTO `findable_location` (zone, version, findable_id, findable_sub_id, type, zone_id, zone_id_index, x, y, z) VALUES ('qeynos2', 0, 20, 0, 7, 4, 3, 141.9432373046875, 1699.3203125, 20.986679077148438);
INSERT INTO `findable_location` (zone, version, findable_id, findable_sub_id, type, zone_id, zone_id_index, x, y, z) VALUES ('qeynos2', 0, 21, 0, 7, 4, 4, -3.9984021186828613, 1699.3203125, 20.986663818359375);
INSERT INTO `findable_location` (zone, version, findable_id, findable_sub_id, type, zone_id, zone_id_index, x, y, z) VALUES ('qeynos2', 0, 21, 3, 7, 4, 5, -333.866455078125, 1699.3203125, 59.97560119628906);
INSERT INTO `findable_location` (zone, version, findable_id, findable_sub_id, type, zone_id, zone_id_index, x, y, z) VALUES ('qeynos2', 0, 22, 0, 7, 4, 6, 899.6401977539062, 1699.3203125, 54.97816467285156);
INSERT INTO `findable_location` (zone, version, findable_id, findable_sub_id, type, zone_id, zone_id_index, x, y, z) VALUES ('qeynos2', 0, 23, 0, 7, 4, 7, -799.6800537109375, 1699.3203125, 54.97825622558594);
INSERT INTO `findable_location` (zone, version, findable_id, findable_sub_id, type, zone_id, zone_id_index, x, y, z) VALUES ('qeynos2', 0, 53, 0, 7, 45, 2, 76.9692153930664, 174.9300537109375, -34.986000061035156);
INSERT INTO `findable_location` (zone, version, findable_id, findable_sub_id, type, zone_id, zone_id_index, x, y, z) VALUES ('qeynos2', 0, 54, 0, 7, 45, 3, -160.9356231689453, 300.879638671875, -139.94403076171875);
-11
View File
@@ -541,17 +541,6 @@ bool Client::HandleSendLoginInfoPacket(const EQApplicationPacket *app)
skip_char_info = true; skip_char_info = true;
} }
} }
const auto& custom_files_key = RuleS(World, CustomFilesKey);
if (!skip_char_info && !custom_files_key.empty() && cle->Admin() < RuleI(World, CustomFilesAdminLevel)) {
// Modified clients can utilize this unused block in login_info to send custom payloads on login
// which indicates they are using custom client files with the correct version, based on key payload.
const auto client_key = std::string(reinterpret_cast<char*>(login_info->unknown064));
if (custom_files_key != client_key) {
std::string message = fmt::format("Missing Files [{}]", RuleS(World, CustomFilesUrl) );
SendUnsupportedClientPacket(message);
skip_char_info = true;
}
}
if (!skip_char_info) { if (!skip_char_info) {
SendExpansionInfo(); SendExpansionInfo();
+1
View File
@@ -140,6 +140,7 @@ std::vector<Reload> reload_types = {
Reload{.command = "aa", .opcode = ServerOP_ReloadAAData, .desc = "Alternate Advancement"}, Reload{.command = "aa", .opcode = ServerOP_ReloadAAData, .desc = "Alternate Advancement"},
Reload{.command = "alternate_currencies", .opcode = ServerOP_ReloadAlternateCurrencies, .desc = "Alternate Currencies"}, Reload{.command = "alternate_currencies", .opcode = ServerOP_ReloadAlternateCurrencies, .desc = "Alternate Currencies"},
Reload{.command = "base_data", .opcode = ServerOP_ReloadBaseData, .desc = "Base Data"}, Reload{.command = "base_data", .opcode = ServerOP_ReloadBaseData, .desc = "Base Data"},
Reload{.command = "finable_locations", .opcode = ServerOP_ReloadFindableLocations, .desc = "Findable Locations"},
Reload{.command = "blocked_spells", .opcode = ServerOP_ReloadBlockedSpells, .desc = "Blocked Spells"}, Reload{.command = "blocked_spells", .opcode = ServerOP_ReloadBlockedSpells, .desc = "Blocked Spells"},
Reload{.command = "commands", .opcode = ServerOP_ReloadCommands, .desc = "Commands"}, Reload{.command = "commands", .opcode = ServerOP_ReloadCommands, .desc = "Commands"},
Reload{.command = "content_flags", .opcode = ServerOP_ReloadContentFlags, .desc = "Content Flags"}, Reload{.command = "content_flags", .opcode = ServerOP_ReloadContentFlags, .desc = "Content Flags"},
+6
View File
@@ -1401,6 +1401,7 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
case ServerOP_ReloadAAData: case ServerOP_ReloadAAData:
case ServerOP_ReloadAlternateCurrencies: case ServerOP_ReloadAlternateCurrencies:
case ServerOP_ReloadBaseData: case ServerOP_ReloadBaseData:
case ServerOP_ReloadFindableLocations:
case ServerOP_ReloadBlockedSpells: case ServerOP_ReloadBlockedSpells:
case ServerOP_ReloadCommands: case ServerOP_ReloadCommands:
case ServerOP_ReloadDoors: case ServerOP_ReloadDoors:
@@ -1564,6 +1565,11 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
DynamicZone::HandleZoneMessage(pack); DynamicZone::HandleZoneMessage(pack);
break; break;
} }
case ServerOP_DataBucketCacheUpdate: {
zoneserver_list.SendPacket(pack);
break;
}
case ServerOP_GuildTributeUpdate: { case ServerOP_GuildTributeUpdate: {
auto data = (GuildTributeUpdate *)pack->pBuffer; auto data = (GuildTributeUpdate *)pack->pBuffer;
auto guild = guild_mgr.GetGuildByGuildID(data->guild_id); auto guild = guild_mgr.GetGuildByGuildID(data->guild_id);
+1
View File
@@ -170,6 +170,7 @@ SET(zone_sources
zonedb.cpp zonedb.cpp
zone_base_data.cpp zone_base_data.cpp
zone_event_scheduler.cpp zone_event_scheduler.cpp
zone_finable_locations.cpp
zone_npc_factions.cpp zone_npc_factions.cpp
zone_reload.cpp zone_reload.cpp
zoning.cpp zoning.cpp
+22 -7
View File
@@ -1550,7 +1550,10 @@ void Mob::DoAttack(Mob *other, DamageHitInfo &hit, ExtraAttackOptions *opts, boo
hit.damage_done = 0; hit.damage_done = 0;
} }
parse->EventBotMerc(EVENT_USE_SKILL, this, nullptr, parse->EventBotMerc(
EVENT_USE_SKILL,
this,
nullptr,
[&]() { [&]() {
return fmt::format( return fmt::format(
"{} {}", "{} {}",
@@ -3075,7 +3078,10 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy
std::vector<std::any> args = { corpse }; std::vector<std::any> args = { corpse };
parse->EventMercNPC(EVENT_DEATH_COMPLETE, this, owner_or_self, parse->EventMercNPC(
EVENT_DEATH_COMPLETE,
this,
owner_or_self,
[&]() { [&]() {
return fmt::format( return fmt::format(
"{} {} {} {} {} {} {} {} {}", "{} {} {} {} {} {} {} {} {}",
@@ -3090,7 +3096,8 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy
m_combat_record.GetHealingReceived() m_combat_record.GetHealingReceived()
); );
}, },
0, &args 0,
&args
); );
// Zone controller process EVENT_DEATH_ZONE (Death events) // Zone controller process EVENT_DEATH_ZONE (Death events)
@@ -4259,7 +4266,10 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons
if (attacker) { if (attacker) {
args = { this }; args = { this };
parse->EventMob(EVENT_DAMAGE_GIVEN, attacker, this, parse->EventMob(
EVENT_DAMAGE_GIVEN,
attacker,
this,
[&]() { [&]() {
return fmt::format( return fmt::format(
"{} {} {} {} {} {} {} {} {}", "{} {} {} {} {} {} {} {} {}",
@@ -4274,13 +4284,17 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons
static_cast<int>(special) static_cast<int>(special)
); );
}, },
0, &args 0,
&args
); );
} }
args = { attacker }; args = { attacker };
damage_override = parse->EventMob(EVENT_DAMAGE_TAKEN, this, attacker, damage_override = parse->EventMob(
EVENT_DAMAGE_TAKEN,
this,
attacker,
[&]() { [&]() {
return fmt::format( return fmt::format(
"{} {} {} {} {} {} {} {} {}", "{} {} {} {} {} {} {} {} {}",
@@ -4295,7 +4309,8 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons
static_cast<int>(special) static_cast<int>(special)
); );
}, },
0, &args 0,
&args
); );
if (damage_override > 0) { if (damage_override > 0) {
+17 -4
View File
@@ -1265,7 +1265,7 @@ void Bot::LoadAAs() {
} }
while(current) { while(current) {
if (current->level_req > GetLevel() || !CanUseAlternateAdvancementRank(current)) { if (!CanUseAlternateAdvancementRank(current)) {
current = nullptr; current = nullptr;
} else { } else {
current = current->next; current = current->next;
@@ -3089,7 +3089,6 @@ bool Bot::Spawn(Client* botCharacterOwner) {
m_targetable = true; m_targetable = true;
entity_list.AddBot(this, true, true); entity_list.AddBot(this, true, true);
ClearDataBucketCache();
DataBucket::GetDataBuckets(this); DataBucket::GetDataBuckets(this);
LoadBotSpellSettings(); LoadBotSpellSettings();
if (!AI_AddBotSpells(GetBotSpellID())) { if (!AI_AddBotSpells(GetBotSpellID())) {
@@ -4193,7 +4192,14 @@ void Bot::PerformTradeWithClient(int16 begin_slot_id, int16 end_slot_id, Client*
std::vector<std::any> args = { return_iterator.return_item_instance }; std::vector<std::any> args = { return_iterator.return_item_instance };
parse->EventBot(EVENT_UNEQUIP_ITEM_BOT, this, nullptr, export_string, return_iterator.return_item_instance->GetID(), &args); parse->EventBot(
EVENT_UNEQUIP_ITEM_BOT,
this,
nullptr,
export_string,
return_iterator.return_item_instance->GetID(),
&args
);
} }
if (return_instance) { if (return_instance) {
@@ -4258,7 +4264,14 @@ void Bot::PerformTradeWithClient(int16 begin_slot_id, int16 end_slot_id, Client*
std::vector<std::any> args = { trade_iterator.trade_item_instance }; std::vector<std::any> args = { trade_iterator.trade_item_instance };
parse->EventBot(EVENT_EQUIP_ITEM_BOT, this, nullptr, export_string, trade_iterator.trade_item_instance->GetID(), &args); parse->EventBot(
EVENT_EQUIP_ITEM_BOT,
this,
nullptr,
export_string,
trade_iterator.trade_item_instance->GetID(),
&args
);
} }
trade_iterator.trade_item_instance = nullptr; // actual deletion occurs in client delete below trade_iterator.trade_item_instance = nullptr; // actual deletion occurs in client delete below
+53 -64
View File
@@ -329,7 +329,7 @@ Client::Client(EQStreamInterface *ieqs) : Mob(
adventure_stats_timer = nullptr; adventure_stats_timer = nullptr;
adventure_leaderboard_timer = nullptr; adventure_leaderboard_timer = nullptr;
adv_data = nullptr; adv_data = nullptr;
adv_requested_theme = LDoNTheme::Unused; adv_requested_theme = LDoNThemes::Unused;
adv_requested_id = 0; adv_requested_id = 0;
adv_requested_member_count = 0; adv_requested_member_count = 0;
@@ -1469,7 +1469,7 @@ bool Client::UpdateLDoNPoints(uint32 theme_id, int points)
bool is_loss = false; bool is_loss = false;
switch (theme_id) { switch (theme_id) {
case LDoNTheme::Unused: { // No theme, so distribute evenly across all case LDoNThemes::Unused: { // No theme, so distribute evenly across all
int split_points = (points / 5); int split_points = (points / 5);
int guk_points = (split_points + (points % 5)); int guk_points = (split_points + (points % 5));
@@ -1522,12 +1522,12 @@ bool Client::UpdateLDoNPoints(uint32 theme_id, int points)
points -= split_points; points -= split_points;
if (split_points != 0) { // if anything left, recursively loop thru again if (split_points != 0) { // if anything left, recursively loop thru again
UpdateLDoNPoints(LDoNTheme::Unused, split_points); UpdateLDoNPoints(LDoNThemes::Unused, split_points);
} }
break; break;
} }
case LDoNTheme::GUK: { case LDoNThemes::GUK: {
if (points < 0) { if (points < 0) {
if (m_pp.ldon_points_guk < (0 - points)) { if (m_pp.ldon_points_guk < (0 - points)) {
return false; return false;
@@ -1539,7 +1539,7 @@ bool Client::UpdateLDoNPoints(uint32 theme_id, int points)
m_pp.ldon_points_guk += points; m_pp.ldon_points_guk += points;
break; break;
} }
case LDoNTheme::MIR: { case LDoNThemes::MIR: {
if (points < 0) { if (points < 0) {
if (m_pp.ldon_points_mir < (0 - points)) { if (m_pp.ldon_points_mir < (0 - points)) {
return false; return false;
@@ -1551,7 +1551,7 @@ bool Client::UpdateLDoNPoints(uint32 theme_id, int points)
m_pp.ldon_points_mir += points; m_pp.ldon_points_mir += points;
break; break;
} }
case LDoNTheme::MMC: { case LDoNThemes::MMC: {
if (points < 0) { if (points < 0) {
if (m_pp.ldon_points_mmc < (0 - points)) { if (m_pp.ldon_points_mmc < (0 - points)) {
return false; return false;
@@ -1563,7 +1563,7 @@ bool Client::UpdateLDoNPoints(uint32 theme_id, int points)
m_pp.ldon_points_mmc += points; m_pp.ldon_points_mmc += points;
break; break;
} }
case LDoNTheme::RUJ: { case LDoNThemes::RUJ: {
if (points < 0) { if (points < 0) {
if (m_pp.ldon_points_ruj < (0 - points)) { if (m_pp.ldon_points_ruj < (0 - points)) {
return false; return false;
@@ -1575,7 +1575,7 @@ bool Client::UpdateLDoNPoints(uint32 theme_id, int points)
m_pp.ldon_points_ruj += points; m_pp.ldon_points_ruj += points;
break; break;
} }
case LDoNTheme::TAK: { case LDoNThemes::TAK: {
if (points < 0) { if (points < 0) {
if (m_pp.ldon_points_tak < (0 - points)) { if (m_pp.ldon_points_tak < (0 - points)) {
return false; return false;
@@ -1623,23 +1623,23 @@ bool Client::UpdateLDoNPoints(uint32 theme_id, int points)
void Client::SetLDoNPoints(uint32 theme_id, uint32 points) void Client::SetLDoNPoints(uint32 theme_id, uint32 points)
{ {
switch (theme_id) { switch (theme_id) {
case LDoNTheme::GUK: { case LDoNThemes::GUK: {
m_pp.ldon_points_guk = points; m_pp.ldon_points_guk = points;
break; break;
} }
case LDoNTheme::MIR: { case LDoNThemes::MIR: {
m_pp.ldon_points_mir = points; m_pp.ldon_points_mir = points;
break; break;
} }
case LDoNTheme::MMC: { case LDoNThemes::MMC: {
m_pp.ldon_points_mmc = points; m_pp.ldon_points_mmc = points;
break; break;
} }
case LDoNTheme::RUJ: { case LDoNThemes::RUJ: {
m_pp.ldon_points_ruj = points; m_pp.ldon_points_ruj = points;
break; break;
} }
case LDoNTheme::TAK: { case LDoNThemes::TAK: {
m_pp.ldon_points_tak = points; m_pp.ldon_points_tak = points;
break; break;
} }
@@ -5676,15 +5676,15 @@ uint32 Client::GetLDoNPointsTheme(uint32 t)
{ {
switch(t) switch(t)
{ {
case LDoNTheme::GUK: case LDoNThemes::GUK:
return m_pp.ldon_points_guk; return m_pp.ldon_points_guk;
case LDoNTheme::MIR: case LDoNThemes::MIR:
return m_pp.ldon_points_mir; return m_pp.ldon_points_mir;
case LDoNTheme::MMC: case LDoNThemes::MMC:
return m_pp.ldon_points_mmc; return m_pp.ldon_points_mmc;
case LDoNTheme::RUJ: case LDoNThemes::RUJ:
return m_pp.ldon_points_ruj; return m_pp.ldon_points_ruj;
case LDoNTheme::TAK: case LDoNThemes::TAK:
return m_pp.ldon_points_tak; return m_pp.ldon_points_tak;
default: default:
return 0; return 0;
@@ -5695,15 +5695,15 @@ uint32 Client::GetLDoNWinsTheme(uint32 t)
{ {
switch(t) switch(t)
{ {
case LDoNTheme::GUK: case LDoNThemes::GUK:
return m_pp.ldon_wins_guk; return m_pp.ldon_wins_guk;
case LDoNTheme::MIR: case LDoNThemes::MIR:
return m_pp.ldon_wins_mir; return m_pp.ldon_wins_mir;
case LDoNTheme::MMC: case LDoNThemes::MMC:
return m_pp.ldon_wins_mmc; return m_pp.ldon_wins_mmc;
case LDoNTheme::RUJ: case LDoNThemes::RUJ:
return m_pp.ldon_wins_ruj; return m_pp.ldon_wins_ruj;
case LDoNTheme::TAK: case LDoNThemes::TAK:
return m_pp.ldon_wins_tak; return m_pp.ldon_wins_tak;
default: default:
return 0; return 0;
@@ -5714,15 +5714,15 @@ uint32 Client::GetLDoNLossesTheme(uint32 t)
{ {
switch(t) switch(t)
{ {
case LDoNTheme::GUK: case LDoNThemes::GUK:
return m_pp.ldon_losses_guk; return m_pp.ldon_losses_guk;
case LDoNTheme::MIR: case LDoNThemes::MIR:
return m_pp.ldon_losses_mir; return m_pp.ldon_losses_mir;
case LDoNTheme::MMC: case LDoNThemes::MMC:
return m_pp.ldon_losses_mmc; return m_pp.ldon_losses_mmc;
case LDoNTheme::RUJ: case LDoNThemes::RUJ:
return m_pp.ldon_losses_ruj; return m_pp.ldon_losses_ruj;
case LDoNTheme::TAK: case LDoNThemes::TAK:
return m_pp.ldon_losses_tak; return m_pp.ldon_losses_tak;
default: default:
return 0; return 0;
@@ -5731,35 +5731,35 @@ uint32 Client::GetLDoNLossesTheme(uint32 t)
void Client::UpdateLDoNWinLoss(uint32 theme_id, bool win, bool remove) { void Client::UpdateLDoNWinLoss(uint32 theme_id, bool win, bool remove) {
switch (theme_id) { switch (theme_id) {
case LDoNTheme::GUK: case LDoNThemes::GUK:
if (win) { if (win) {
m_pp.ldon_wins_guk += (remove ? -1 : 1); m_pp.ldon_wins_guk += (remove ? -1 : 1);
} else { } else {
m_pp.ldon_losses_guk += (remove ? -1 : 1); m_pp.ldon_losses_guk += (remove ? -1 : 1);
} }
break; break;
case LDoNTheme::MIR: case LDoNThemes::MIR:
if (win) { if (win) {
m_pp.ldon_wins_mir += (remove ? -1 : 1); m_pp.ldon_wins_mir += (remove ? -1 : 1);
} else { } else {
m_pp.ldon_losses_mir += (remove ? -1 : 1); m_pp.ldon_losses_mir += (remove ? -1 : 1);
} }
break; break;
case LDoNTheme::MMC: case LDoNThemes::MMC:
if (win) { if (win) {
m_pp.ldon_wins_mmc += (remove ? -1 : 1); m_pp.ldon_wins_mmc += (remove ? -1 : 1);
} else { } else {
m_pp.ldon_losses_mmc += (remove ? -1 : 1); m_pp.ldon_losses_mmc += (remove ? -1 : 1);
} }
break; break;
case LDoNTheme::RUJ: case LDoNThemes::RUJ:
if (win) { if (win) {
m_pp.ldon_wins_ruj += (remove ? -1 : 1); m_pp.ldon_wins_ruj += (remove ? -1 : 1);
} else { } else {
m_pp.ldon_losses_ruj += (remove ? -1 : 1); m_pp.ldon_losses_ruj += (remove ? -1 : 1);
} }
break; break;
case LDoNTheme::TAK: case LDoNThemes::TAK:
if (win) { if (win) {
m_pp.ldon_wins_tak += (remove ? -1 : 1); m_pp.ldon_wins_tak += (remove ? -1 : 1);
} else { } else {
@@ -6227,7 +6227,7 @@ void Client::NewAdventure(int id, int theme, const char *text, int member_count,
void Client::ClearPendingAdventureData() void Client::ClearPendingAdventureData()
{ {
adv_requested_id = 0; adv_requested_id = 0;
adv_requested_theme = LDoNTheme::Unused; adv_requested_theme = LDoNThemes::Unused;
safe_delete_array(adv_requested_data); safe_delete_array(adv_requested_data);
adv_requested_member_count = 0; adv_requested_member_count = 0;
} }
@@ -11995,15 +11995,13 @@ void Client::MaxSkills()
} }
} }
void Client::SendPath(Mob* target) void Client::SendPath(Mob* target) {
{
if (!target) { if (!target) {
EQApplicationPacket outapp(OP_FindPersonReply, 0); EQApplicationPacket outapp(OP_FindPersonReply, 0);
QueuePacket(&outapp); QueuePacket(&outapp);
return; return;
} }
if ( if (
!RuleB(Pathing, Find) && !RuleB(Pathing, Find) &&
RuleB(Bazaar, EnableWarpToTrader) && RuleB(Bazaar, EnableWarpToTrader) &&
@@ -12011,7 +12009,7 @@ void Client::SendPath(Mob* target)
( (
target->CastToClient()->IsTrader() || target->CastToClient()->IsTrader() ||
target->CastToClient()->IsBuyer() target->CastToClient()->IsBuyer()
) )
) { ) {
Message( Message(
Chat::Yellow, Chat::Yellow,
@@ -12031,6 +12029,17 @@ void Client::SendPath(Mob* target)
return; return;
} }
glm::vec3 target_loc(
target->GetX(),
target->GetY(),
target->GetZ() + (target->GetSize() < 6.0 ? 6 : target->GetSize()) * HEAD_POSITION
);
SendPath(target_loc);
}
void Client::SendPath(const glm::vec3& loc)
{
std::vector<FindPerson_Point> points; std::vector<FindPerson_Point> points;
if (!RuleB(Pathing, Find) || !zone->pathing) { if (!RuleB(Pathing, Find) || !zone->pathing) {
@@ -12041,9 +12050,9 @@ void Client::SendPath(Mob* target)
a.x = GetX(); a.x = GetX();
a.y = GetY(); a.y = GetY();
a.z = GetZ(); a.z = GetZ();
b.x = target->GetX(); b.x = loc.x;
b.y = target->GetY(); b.y = loc.y;
b.z = target->GetZ(); b.z = loc.z;
points.push_back(a); points.push_back(a);
points.push_back(b); points.push_back(b);
@@ -12056,9 +12065,9 @@ void Client::SendPath(Mob* target)
); );
glm::vec3 path_end( glm::vec3 path_end(
target->GetX(), loc.x,
target->GetY(), loc.y,
target->GetZ() + (target->GetSize() < 6.0 ? 6 : target->GetSize()) * HEAD_POSITION loc.z
); );
bool partial = false; bool partial = false;
@@ -12081,18 +12090,6 @@ void Client::SendPath(Mob* target)
bool leads_to_teleporter = false; bool leads_to_teleporter = false;
auto v = path_list.back();
p.x = v.pos.x;
p.y = v.pos.y;
p.z = v.pos.z;
points.push_back(p);
p.x = GetX();
p.y = GetY();
p.z = GetZ();
points.push_back(p);
for (const auto &n: path_list) { for (const auto &n: path_list) {
if (n.teleport) { if (n.teleport) {
leads_to_teleporter = true; leads_to_teleporter = true;
@@ -12108,14 +12105,6 @@ void Client::SendPath(Mob* target)
++point_number; ++point_number;
} }
if (!leads_to_teleporter) {
p.x = target->GetX();
p.y = target->GetY();
p.z = target->GetZ();
points.push_back(p);
}
} }
SendPathPacket(points); SendPathPacket(points);
+1
View File
@@ -869,6 +869,7 @@ public:
int GetAccountAge(); int GetAccountAge();
void SendPath(Mob* target); void SendPath(Mob* target);
void SendPath(const glm::vec3 &loc);
bool IsDiscovered(uint32 itemid); bool IsDiscovered(uint32 itemid);
void DiscoverItem(uint32 itemid); void DiscoverItem(uint32 itemid);
+170 -44
View File
@@ -524,6 +524,7 @@ int Client::HandlePacket(const EQApplicationPacket *app)
// Finish client connecting state // Finish client connecting state
void Client::CompleteConnect() void Client::CompleteConnect()
{ {
UpdateWho(); UpdateWho();
client_state = CLIENT_CONNECTED; client_state = CLIENT_CONNECTED;
SendAllPackets(); SendAllPackets();
@@ -857,6 +858,9 @@ void Client::CompleteConnect()
if (ClientVersion() >= EQ::versions::ClientVersion::SoD) if (ClientVersion() >= EQ::versions::ClientVersion::SoD)
entity_list.SendFindableNPCList(this); entity_list.SendFindableNPCList(this);
if (ClientVersion() >= EQ::versions::ClientVersion::RoF2)
zone->SendFindableLocations(this);
if (IsInAGuild()) { if (IsInAGuild()) {
if (firstlogon == 1) { if (firstlogon == 1) {
guild_mgr.UpdateDbMemberOnline(CharacterID(), true); guild_mgr.UpdateDbMemberOnline(CharacterID(), true);
@@ -912,6 +916,10 @@ void Client::CompleteConnect()
CastToClient()->FastQueuePacket(&outapp); CastToClient()->FastQueuePacket(&outapp);
} }
if (ClientVersion() >= EQ::versions::ClientVersion::RoF) {
SendBulkBazaarTraders();
}
// TODO: load these states // TODO: load these states
// We at least will set them to the correct state for now // We at least will set them to the correct state for now
if (m_ClientVersionBit & EQ::versions::maskUFAndLater && GetPet()) { if (m_ClientVersionBit & EQ::versions::maskUFAndLater && GetPet()) {
@@ -1408,7 +1416,6 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
drakkin_details = m_pp.drakkin_details; drakkin_details = m_pp.drakkin_details;
// Load Data Buckets // Load Data Buckets
ClearDataBucketCache();
DataBucket::GetDataBuckets(this); DataBucket::GetDataBuckets(this);
// Max Level for Character:PerCharacterQglobalMaxLevel and Character:PerCharacterBucketMaxLevel // Max Level for Character:PerCharacterQglobalMaxLevel and Character:PerCharacterBucketMaxLevel
@@ -2019,38 +2026,38 @@ void Client::Handle_OP_AdventureMerchantPurchase(const EQApplicationPacket *app)
return; return;
} }
if (item->LDoNTheme <= LDoNTheme::TAKBit) { if (item->LDoNTheme <= LDoNThemeBits::TAKBit) {
uint32 ldon_theme; uint32 ldon_theme;
if (item->LDoNTheme & LDoNTheme::TAKBit) { if (item->LDoNTheme & LDoNThemeBits::TAKBit) {
if (m_pp.ldon_points_tak < item_cost) { if (m_pp.ldon_points_tak < item_cost) {
cannot_afford = true; cannot_afford = true;
ldon_theme = LDoNTheme::TAK; ldon_theme = LDoNThemes::TAK;
} }
} else if (item->LDoNTheme & LDoNTheme::RUJBit) { } else if (item->LDoNTheme & LDoNThemeBits::RUJBit) {
if (m_pp.ldon_points_ruj < item_cost) { if (m_pp.ldon_points_ruj < item_cost) {
cannot_afford = true; cannot_afford = true;
ldon_theme = LDoNTheme::RUJ; ldon_theme = LDoNThemes::RUJ;
} }
} else if (item->LDoNTheme & LDoNTheme::MMCBit) { } else if (item->LDoNTheme & LDoNThemeBits::MMCBit) {
if (m_pp.ldon_points_mmc < item_cost) { if (m_pp.ldon_points_mmc < item_cost) {
cannot_afford = true; cannot_afford = true;
ldon_theme = LDoNTheme::MMC; ldon_theme = LDoNThemes::MMC;
} }
} else if (item->LDoNTheme & LDoNTheme::MIRBit) { } else if (item->LDoNTheme & LDoNThemeBits::MIRBit) {
if (m_pp.ldon_points_mir < item_cost) { if (m_pp.ldon_points_mir < item_cost) {
cannot_afford = true; cannot_afford = true;
ldon_theme = LDoNTheme::MIR; ldon_theme = LDoNThemes::MIR;
} }
} else if (item->LDoNTheme & LDoNTheme::GUKBit) { } else if (item->LDoNTheme & LDoNThemeBits::GUKBit) {
if (m_pp.ldon_points_guk < item_cost) { if (m_pp.ldon_points_guk < item_cost) {
cannot_afford = true; cannot_afford = true;
ldon_theme = LDoNTheme::GUK; ldon_theme = LDoNThemes::GUK;
} }
} }
merchant_type = fmt::format( merchant_type = fmt::format(
"{} Point{}", "{} Point{}",
LDoNTheme::GetName(ldon_theme), EQ::constants::GetLDoNThemeName(ldon_theme),
item_cost != 1 ? "s" : "" item_cost != 1 ? "s" : ""
); );
} }
@@ -2194,19 +2201,19 @@ void Client::Handle_OP_AdventureMerchantRequest(const EQApplicationPacket *app)
item = database.GetItem(ml.item); item = database.GetItem(ml.item);
if (item) { if (item) {
uint32 theme = LDoNTheme::Unused; uint32 theme = LDoNThemes::Unused;
if (item->LDoNTheme > LDoNTheme::TAKBit) { if (item->LDoNTheme > LDoNThemeBits::TAKBit) {
theme = LDoNTheme::Unused; theme = LDoNThemes::Unused;
} else if (item->LDoNTheme & LDoNTheme::TAKBit) { } else if (item->LDoNTheme & LDoNThemeBits::TAKBit) {
theme = LDoNTheme::TAK; theme = LDoNThemes::TAK;
} else if (item->LDoNTheme & LDoNTheme::RUJBit) { } else if (item->LDoNTheme & LDoNThemeBits::RUJBit) {
theme = LDoNTheme::RUJ; theme = LDoNThemes::RUJ;
} else if (item->LDoNTheme & LDoNTheme::MMCBit) { } else if (item->LDoNTheme & LDoNThemeBits::MMCBit) {
theme = LDoNTheme::MMC; theme = LDoNThemes::MMC;
} else if (item->LDoNTheme & LDoNTheme::MIRBit) { } else if (item->LDoNTheme & LDoNThemeBits::MIRBit) {
theme = LDoNTheme::MIR; theme = LDoNThemes::MIR;
} else if (item->LDoNTheme & LDoNTheme::GUKBit) { } else if (item->LDoNTheme & LDoNThemeBits::GUKBit) {
theme = LDoNTheme::GUK; theme = LDoNThemes::GUK;
} }
ss << "^" << item->Name << "|"; ss << "^" << item->Name << "|";
ss << item->ID << "|"; ss << item->ID << "|";
@@ -3247,14 +3254,30 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app)
args.push_back(old_aug); args.push_back(old_aug);
if (parse->ItemHasQuestSub(tobe_auged, EVENT_UNAUGMENT_ITEM)) { if (parse->ItemHasQuestSub(tobe_auged, EVENT_UNAUGMENT_ITEM)) {
parse->EventItem(EVENT_UNAUGMENT_ITEM, this, tobe_auged, nullptr, "", in_augment->augment_index, &args); parse->EventItem(
EVENT_UNAUGMENT_ITEM,
this,
tobe_auged,
nullptr,
"",
in_augment->augment_index,
&args
);
} }
args.assign(1, tobe_auged); args.assign(1, tobe_auged);
args.push_back(false); args.push_back(false);
if (parse->ItemHasQuestSub(old_aug, EVENT_AUGMENT_REMOVE)) { if (parse->ItemHasQuestSub(old_aug, EVENT_AUGMENT_REMOVE)) {
parse->EventItem(EVENT_AUGMENT_REMOVE, this, old_aug, nullptr, "", in_augment->augment_index, &args); parse->EventItem(
EVENT_AUGMENT_REMOVE,
this,
old_aug,
nullptr,
"",
in_augment->augment_index,
&args
);
} }
if (parse->PlayerHasQuestSub(EVENT_AUGMENT_REMOVE_CLIENT)) { if (parse->PlayerHasQuestSub(EVENT_AUGMENT_REMOVE_CLIENT)) {
@@ -3286,13 +3309,29 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app)
args.push_back(aug); args.push_back(aug);
if (parse->ItemHasQuestSub(tobe_auged, EVENT_AUGMENT_ITEM)) { if (parse->ItemHasQuestSub(tobe_auged, EVENT_AUGMENT_ITEM)) {
parse->EventItem(EVENT_AUGMENT_ITEM, this, tobe_auged, nullptr, "", in_augment->augment_index, &args); parse->EventItem(
EVENT_AUGMENT_ITEM,
this,
tobe_auged,
nullptr,
"",
in_augment->augment_index,
&args
);
} }
args.assign(1, tobe_auged); args.assign(1, tobe_auged);
if (parse->ItemHasQuestSub(aug, EVENT_AUGMENT_INSERT)) { if (parse->ItemHasQuestSub(aug, EVENT_AUGMENT_INSERT)) {
parse->EventItem(EVENT_AUGMENT_INSERT, this, aug, nullptr, "", in_augment->augment_index, &args); parse->EventItem(
EVENT_AUGMENT_INSERT,
this,
aug,
nullptr,
"",
in_augment->augment_index,
&args
);
} }
args.push_back(aug); args.push_back(aug);
@@ -3362,14 +3401,30 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app)
args.push_back(aug); args.push_back(aug);
if (parse->ItemHasQuestSub(tobe_auged, EVENT_UNAUGMENT_ITEM)) { if (parse->ItemHasQuestSub(tobe_auged, EVENT_UNAUGMENT_ITEM)) {
parse->EventItem(EVENT_UNAUGMENT_ITEM, this, tobe_auged, nullptr, "", in_augment->augment_index, &args); parse->EventItem(
EVENT_UNAUGMENT_ITEM,
this,
tobe_auged,
nullptr,
"",
in_augment->augment_index,
&args
);
} }
args.assign(1, tobe_auged); args.assign(1, tobe_auged);
args.push_back(false); args.push_back(false);
if (parse->ItemHasQuestSub(aug, EVENT_AUGMENT_REMOVE)) { if (parse->ItemHasQuestSub(aug, EVENT_AUGMENT_REMOVE)) {
parse->EventItem(EVENT_AUGMENT_REMOVE, this, aug, nullptr, "", in_augment->augment_index, &args); parse->EventItem(
EVENT_AUGMENT_REMOVE,
this,
aug,
nullptr,
"",
in_augment->augment_index,
&args
);
} }
args.push_back(aug); args.push_back(aug);
@@ -3434,14 +3489,30 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app)
args.push_back(aug); args.push_back(aug);
if (parse->ItemHasQuestSub(tobe_auged, EVENT_UNAUGMENT_ITEM)) { if (parse->ItemHasQuestSub(tobe_auged, EVENT_UNAUGMENT_ITEM)) {
parse->EventItem(EVENT_UNAUGMENT_ITEM, this, tobe_auged, nullptr, "", in_augment->augment_index, &args); parse->EventItem(
EVENT_UNAUGMENT_ITEM,
this,
tobe_auged,
nullptr,
"",
in_augment->augment_index,
&args
);
} }
args.assign(1, tobe_auged); args.assign(1, tobe_auged);
args.push_back(true); args.push_back(true);
if (parse->ItemHasQuestSub(aug, EVENT_AUGMENT_REMOVE)) { if (parse->ItemHasQuestSub(aug, EVENT_AUGMENT_REMOVE)) {
parse->EventItem(EVENT_AUGMENT_REMOVE, this, aug, nullptr, "", in_augment->augment_index, &args); parse->EventItem(
EVENT_AUGMENT_REMOVE,
this,
aug,
nullptr,
"",
in_augment->augment_index,
&args
);
} }
args.push_back(aug); args.push_back(aug);
@@ -3917,10 +3988,6 @@ void Client::Handle_OP_BazaarSearch(const EQApplicationPacket *app)
SendBazaarWelcome(); SendBazaarWelcome();
break; break;
} }
case FirstOpenSearch: {
SendBulkBazaarTraders();
break;
}
default: { default: {
LogError("Malformed BazaarSearch_Struct packet received, ignoring\n"); LogError("Malformed BazaarSearch_Struct packet received, ignoring\n");
} }
@@ -4415,7 +4482,14 @@ void Client::Handle_OP_CastSpell(const EQApplicationPacket *app)
int i = 0; int i = 0;
if (parse->ItemHasQuestSub(p_inst, EVENT_ITEM_CLICK_CAST)) { if (parse->ItemHasQuestSub(p_inst, EVENT_ITEM_CLICK_CAST)) {
i = parse->EventItem(EVENT_ITEM_CLICK_CAST, this, p_inst, nullptr, "", castspell->inventoryslot); i = parse->EventItem(
EVENT_ITEM_CLICK_CAST,
this,
p_inst,
nullptr,
"",
castspell->inventoryslot
);
} }
if (parse->PlayerHasQuestSub(EVENT_ITEM_CLICK_CAST_CLIENT)) { if (parse->PlayerHasQuestSub(EVENT_ITEM_CLICK_CAST_CLIENT)) {
@@ -4447,7 +4521,14 @@ void Client::Handle_OP_CastSpell(const EQApplicationPacket *app)
int i = 0; int i = 0;
if (parse->ItemHasQuestSub(p_inst, EVENT_ITEM_CLICK_CAST)) { if (parse->ItemHasQuestSub(p_inst, EVENT_ITEM_CLICK_CAST)) {
i = parse->EventItem(EVENT_ITEM_CLICK_CAST, this, p_inst, nullptr, "", castspell->inventoryslot); i = parse->EventItem(
EVENT_ITEM_CLICK_CAST,
this,
p_inst,
nullptr,
"",
castspell->inventoryslot
);
} }
if (parse->PlayerHasQuestSub(EVENT_ITEM_CLICK_CAST_CLIENT)) { if (parse->PlayerHasQuestSub(EVENT_ITEM_CLICK_CAST_CLIENT)) {
@@ -6396,9 +6477,40 @@ void Client::Handle_OP_FindPersonRequest(const EQApplicationPacket *app)
else { else {
auto* t = (FindPersonRequest_Struct*)app->pBuffer; auto* t = (FindPersonRequest_Struct*)app->pBuffer;
auto* m = entity_list.GetMob(t->npc_id); switch (t->type) {
case FindLocationType::LocationPlayer: {
auto* m = entity_list.GetMob(t->id);
SendPath(m);
break;
}
case FindLocationType::LocationSwitch:
{
auto *d = entity_list.GetDoorsByDoorID(t->id);
if (d == nullptr) {
Message(Chat::Red, "Switch for find not found.");
return;
}
SendPath(m); glm::vec3 door_loc;
door_loc.x = d->GetX();
door_loc.y = d->GetY();
door_loc.z = d->GetZ();
SendPath(door_loc);
break;
}
case FindLocationType::LocationLocation:
{
glm::vec3 target_pos;
target_pos.x = t->target_pos.x;
target_pos.y = t->target_pos.y;
target_pos.z = t->target_pos.z;
SendPath(target_pos);
break;
}
default:
break;
}
} }
} }
@@ -9513,7 +9625,14 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app)
int i = 0; int i = 0;
if (parse->ItemHasQuestSub(p_inst, EVENT_ITEM_CLICK_CAST)) { if (parse->ItemHasQuestSub(p_inst, EVENT_ITEM_CLICK_CAST)) {
i = parse->EventItem(EVENT_ITEM_CLICK_CAST, this, p_inst, nullptr, "", slot_id); i = parse->EventItem(
EVENT_ITEM_CLICK_CAST,
this,
p_inst,
nullptr,
"",
slot_id
);
} }
if (parse->PlayerHasQuestSub(EVENT_ITEM_CLICK_CAST_CLIENT)) { if (parse->PlayerHasQuestSub(EVENT_ITEM_CLICK_CAST_CLIENT)) {
@@ -9577,7 +9696,14 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app)
int i = 0; int i = 0;
if (parse->ItemHasQuestSub(p_inst, EVENT_ITEM_CLICK_CAST)) { if (parse->ItemHasQuestSub(p_inst, EVENT_ITEM_CLICK_CAST)) {
i = parse->EventItem(EVENT_ITEM_CLICK_CAST, this, clickaug, nullptr, "", slot_id); i = parse->EventItem(
EVENT_ITEM_CLICK_CAST,
this,
clickaug,
nullptr,
"",
slot_id
);
} }
if (parse->PlayerHasQuestSub(EVENT_ITEM_CLICK_CAST_CLIENT)) { if (parse->PlayerHasQuestSub(EVENT_ITEM_CLICK_CAST_CLIENT)) {
+275 -153
View File
@@ -8,7 +8,7 @@
extern WorldServer worldserver; extern WorldServer worldserver;
std::vector<DataBucketsRepository::DataBuckets> g_data_bucket_cache = {}; std::vector<DataBucketCacheEntry> g_data_bucket_cache = {};
void DataBucket::SetData(const std::string &bucket_key, const std::string &bucket_value, std::string expires_time) void DataBucket::SetData(const std::string &bucket_key, const std::string &bucket_value, std::string expires_time)
{ {
@@ -58,14 +58,14 @@ void DataBucket::SetData(const DataBucketKey &k)
b.value = k.value; b.value = k.value;
if (bucket_id) { if (bucket_id) {
// loop cache and update cache value and timestamp
// update the cache if it exists for (auto &ce: g_data_bucket_cache) {
if (CanCache(k)) { if (CheckBucketMatch(ce.e, k)) {
for (auto &e: g_data_bucket_cache) { ce.e = b;
if (CheckBucketMatch(e, k)) { ce.updated_time = GetCurrentTimeUNIX();
e = b; ce.update_action = DataBucketCacheUpdateAction::Upsert;
break; SendDataBucketCacheUpdate(ce);
} break;
} }
} }
@@ -74,18 +74,28 @@ void DataBucket::SetData(const DataBucketKey &k)
else { else {
b.key_ = k.key; b.key_ = k.key;
b = DataBucketsRepository::InsertOne(database, b); b = DataBucketsRepository::InsertOne(database, b);
if (!ExistsInCache(b)) {
// add data bucket and timestamp to cache
auto ce = DataBucketCacheEntry{
.e = b,
.updated_time = DataBucket::GetCurrentTimeUNIX(),
.update_action = DataBucketCacheUpdateAction::Upsert
};
g_data_bucket_cache.emplace_back(ce);
SendDataBucketCacheUpdate(ce);
// add to cache if it doesn't exist
if (CanCache(k) && !ExistsInCache(b)) {
DeleteFromMissesCache(b); DeleteFromMissesCache(b);
g_data_bucket_cache.emplace_back(b);
} }
} }
} }
std::string DataBucket::GetData(const std::string &bucket_key) std::string DataBucket::GetData(const std::string &bucket_key)
{ {
return GetData(DataBucketKey{.key = bucket_key}).value; DataBucketKey k = {};
k.key = bucket_key;
return GetData(k).value;
} }
// GetData fetches bucket data from the database or cache if it exists // GetData fetches bucket data from the database or cache if it exists
@@ -102,27 +112,22 @@ DataBucketsRepository::DataBuckets DataBucket::GetData(const DataBucketKey &k, b
k.npc_id k.npc_id
); );
bool can_cache = CanCache(k); for (const auto &ce: g_data_bucket_cache) {
if (CheckBucketMatch(ce.e, k)) {
// check the cache first if we can cache if (ce.e.expires > 0 && ce.e.expires < std::time(nullptr)) {
if (can_cache) { LogDataBuckets("Attempted to read expired key [{}] removing from cache", ce.e.key_);
for (const auto &e: g_data_bucket_cache) { DeleteData(k);
if (CheckBucketMatch(e, k)) { return DataBucketsRepository::NewEntity();
if (e.expires > 0 && e.expires < std::time(nullptr)) {
LogDataBuckets("Attempted to read expired key [{}] removing from cache", e.key_);
DeleteData(k);
return DataBucketsRepository::NewEntity();
}
// this is a bucket miss, return empty entity
// we still cache bucket misses, so we don't have to hit the database
if (e.id == 0) {
return DataBucketsRepository::NewEntity();
}
LogDataBuckets("Returning key [{}] value [{}] from cache", e.key_, e.value);
return e;
} }
// this is a bucket miss, return empty entity
// we still cache bucket misses, so we don't have to hit the database
if (ce.e.id == 0) {
return DataBucketsRepository::NewEntity();
}
LogDataBuckets("Returning key [{}] value [{}] from cache", ce.e.key_, ce.e.value);
return ce.e;
} }
} }
@@ -139,21 +144,23 @@ DataBucketsRepository::DataBuckets DataBucket::GetData(const DataBucketKey &k, b
// if we're ignoring the misses cache, don't add to the cache // if we're ignoring the misses cache, don't add to the cache
// the only place this is ignored is during the initial read of SetData // the only place this is ignored is during the initial read of SetData
bool add_to_misses_cache = !ignore_misses_cache && can_cache; if (!ignore_misses_cache) {
if (add_to_misses_cache) {
size_t size_before = g_data_bucket_cache.size(); size_t size_before = g_data_bucket_cache.size();
// cache bucket misses, so we don't have to hit the database // cache bucket misses, so we don't have to hit the database
// when scripts try to read a bucket that doesn't exist // when scripts try to read a bucket that doesn't exist
g_data_bucket_cache.emplace_back( g_data_bucket_cache.emplace_back(
DataBucketsRepository::DataBuckets{ DataBucketCacheEntry{
.id = 0, .e = DataBucketsRepository::DataBuckets{
.key_ = k.key, .id = 0,
.value = "", .key_ = k.key,
.expires = 0, .value = "",
.character_id = k.character_id, .expires = 0,
.npc_id = k.npc_id, .character_id = k.character_id,
.bot_id = k.bot_id .npc_id = k.npc_id,
.bot_id = k.bot_id
},
.updated_time = DataBucket::GetCurrentTimeUNIX()
} }
); );
@@ -171,54 +178,60 @@ DataBucketsRepository::DataBuckets DataBucket::GetData(const DataBucketKey &k, b
return {}; return {};
} }
auto bucket = r.front();
// if the entry has expired, delete it // if the entry has expired, delete it
if (bucket.expires > 0 && bucket.expires < (long long) std::time(nullptr)) { if (r[0].expires > 0 && r[0].expires < (long long) std::time(nullptr)) {
DeleteData(k); DeleteData(k);
return {}; return {};
} }
// add to cache if it doesn't exist bool has_cache = false;
if (can_cache) { for (auto &ce: g_data_bucket_cache) {
bool has_cache = false; if (ce.e.id == r[0].id) {
has_cache = true;
for (auto &e: g_data_bucket_cache) { break;
if (e.id == bucket.id) {
has_cache = true;
break;
}
}
if (!has_cache) {
g_data_bucket_cache.emplace_back(bucket);
} }
} }
return bucket; if (!has_cache) {
// add data bucket and timestamp to cache
g_data_bucket_cache.emplace_back(
DataBucketCacheEntry{
.e = r[0],
.updated_time = DataBucket::GetCurrentTimeUNIX()
}
);
}
return r[0];
} }
std::string DataBucket::GetDataExpires(const std::string &bucket_key) std::string DataBucket::GetDataExpires(const std::string &bucket_key)
{ {
return GetDataExpires(DataBucketKey{.key = bucket_key}); DataBucketKey k = {};
k.key = bucket_key;
return GetDataExpires(k);
} }
std::string DataBucket::GetDataRemaining(const std::string &bucket_key) std::string DataBucket::GetDataRemaining(const std::string &bucket_key)
{ {
return GetDataRemaining(DataBucketKey{.key = bucket_key}); DataBucketKey k = {};
k.key = bucket_key;
return GetDataRemaining(k);
} }
bool DataBucket::DeleteData(const std::string &bucket_key) bool DataBucket::DeleteData(const std::string &bucket_key)
{ {
return DeleteData(DataBucketKey{.key = bucket_key}); DataBucketKey k = {};
k.key = bucket_key;
return DeleteData(k);
} }
// GetDataBuckets bulk loads all data buckets for a mob // GetDataBuckets bulk loads all data buckets for a mob
bool DataBucket::GetDataBuckets(Mob *mob) bool DataBucket::GetDataBuckets(Mob *mob)
{ {
DataBucketLoadType::Type t{}; DataBucketLoadType::Type t;
const uint32 id = mob->GetMobTypeIdentifier();
const uint32 id = mob->GetMobTypeIdentifier();
if (!id) { if (!id) {
return false; return false;
@@ -230,39 +243,46 @@ bool DataBucket::GetDataBuckets(Mob *mob)
else if (mob->IsClient()) { else if (mob->IsClient()) {
t = DataBucketLoadType::Client; t = DataBucketLoadType::Client;
} }
else if (mob->IsNPC()) {
t = DataBucketLoadType::NPC;
}
BulkLoadEntitiesToCache(t, {id}); BulkLoadEntities(t, {id});
return true; return true;
} }
bool DataBucket::DeleteData(const DataBucketKey &k) bool DataBucket::DeleteData(const DataBucketKey &k)
{ {
if (CanCache(k)) { size_t size_before = g_data_bucket_cache.size();
size_t size_before = g_data_bucket_cache.size();
// delete from cache where contents match // delete from cache where contents match
g_data_bucket_cache.erase( g_data_bucket_cache.erase(
std::remove_if( std::remove_if(
g_data_bucket_cache.begin(), g_data_bucket_cache.begin(),
g_data_bucket_cache.end(), g_data_bucket_cache.end(),
[&](DataBucketsRepository::DataBuckets &e) { [&](DataBucketCacheEntry &ce) {
return CheckBucketMatch(e, k); bool match = CheckBucketMatch(ce.e, k);
if (match) {
ce.update_action = DataBucketCacheUpdateAction::Delete;
SendDataBucketCacheUpdate(ce);
} }
),
g_data_bucket_cache.end()
);
LogDataBuckets( return match;
"Deleting bucket key [{}] bot_id [{}] character_id [{}] npc_id [{}] cache size before [{}] after [{}]", }
k.key, ),
k.bot_id, g_data_bucket_cache.end()
k.character_id, );
k.npc_id,
size_before, LogDataBuckets(
g_data_bucket_cache.size() "Deleting bucket key [{}] bot_id [{}] character_id [{}] npc_id [{}] cache size before [{}] after [{}]",
); k.key,
} k.bot_id,
k.character_id,
k.npc_id,
size_before,
g_data_bucket_cache.size()
);
return DataBucketsRepository::DeleteWhere( return DataBucketsRepository::DeleteWhere(
database, database,
@@ -351,21 +371,23 @@ bool DataBucket::CheckBucketMatch(const DataBucketsRepository::DataBuckets &dbe,
); );
} }
void DataBucket::BulkLoadEntitiesToCache(DataBucketLoadType::Type t, std::vector<uint32> ids) void DataBucket::BulkLoadEntities(DataBucketLoadType::Type t, std::vector<uint32> ids)
{ {
if (ids.empty()) { if (ids.empty()) {
return; return;
} }
if (ids.size() == 1) { if (ids.size() == 1) {
bool has_cache = false; bool has_cache = false;
for (const auto &ce: g_data_bucket_cache) {
for (const auto &e: g_data_bucket_cache) {
if (t == DataBucketLoadType::Bot) { if (t == DataBucketLoadType::Bot) {
has_cache = e.bot_id == ids[0]; has_cache = ce.e.bot_id == ids[0];
} }
else if (t == DataBucketLoadType::Client) { else if (t == DataBucketLoadType::Client) {
has_cache = e.character_id == ids[0]; has_cache = ce.e.character_id == ids[0];
}
else if (t == DataBucketLoadType::NPC) {
has_cache = ce.e.npc_id == ids[0];
} }
} }
@@ -384,6 +406,9 @@ void DataBucket::BulkLoadEntitiesToCache(DataBucketLoadType::Type t, std::vector
case DataBucketLoadType::Client: case DataBucketLoadType::Client:
column = "character_id"; column = "character_id";
break; break;
case DataBucketLoadType::NPC:
column = "npc_id";
break;
default: default:
LogError("Incorrect LoadType [{}]", static_cast<int>(t)); LogError("Incorrect LoadType [{}]", static_cast<int>(t));
break; break;
@@ -417,7 +442,12 @@ void DataBucket::BulkLoadEntitiesToCache(DataBucketLoadType::Type t, std::vector
if (!ExistsInCache(e)) { if (!ExistsInCache(e)) {
LogDataBucketsDetail("bucket id [{}] bucket key [{}] bucket value [{}]", e.id, e.key_, e.value); LogDataBucketsDetail("bucket id [{}] bucket key [{}] bucket value [{}]", e.id, e.key_, e.value);
g_data_bucket_cache.emplace_back(e); g_data_bucket_cache.emplace_back(
DataBucketCacheEntry{
.e = e,
.updated_time = GetCurrentTimeUNIX()
}
);
} }
} }
@@ -431,7 +461,7 @@ void DataBucket::BulkLoadEntitiesToCache(DataBucketLoadType::Type t, std::vector
); );
} }
void DataBucket::DeleteCachedBuckets(DataBucketLoadType::Type type, uint32 id) void DataBucket::DeleteCachedBuckets(DataBucketLoadType::Type t, uint32 id)
{ {
size_t size_before = g_data_bucket_cache.size(); size_t size_before = g_data_bucket_cache.size();
@@ -439,10 +469,11 @@ void DataBucket::DeleteCachedBuckets(DataBucketLoadType::Type type, uint32 id)
std::remove_if( std::remove_if(
g_data_bucket_cache.begin(), g_data_bucket_cache.begin(),
g_data_bucket_cache.end(), g_data_bucket_cache.end(),
[&](DataBucketsRepository::DataBuckets &e) { [&](DataBucketCacheEntry &ce) {
return ( return (
(type == DataBucketLoadType::Bot && e.bot_id == id) || (t == DataBucketLoadType::Bot && ce.e.bot_id == id) ||
(type == DataBucketLoadType::Client && e.character_id == id) (t == DataBucketLoadType::Client && ce.e.character_id == id) ||
(t == DataBucketLoadType::NPC && ce.e.npc_id == id)
); );
} }
), ),
@@ -451,17 +482,24 @@ void DataBucket::DeleteCachedBuckets(DataBucketLoadType::Type type, uint32 id)
LogDataBuckets( LogDataBuckets(
"LoadType [{}] id [{}] cache size before [{}] after [{}]", "LoadType [{}] id [{}] cache size before [{}] after [{}]",
DataBucketLoadType::Name[type], DataBucketLoadType::Name[t],
id, id,
size_before, size_before,
g_data_bucket_cache.size() g_data_bucket_cache.size()
); );
} }
bool DataBucket::ExistsInCache(const DataBucketsRepository::DataBuckets &entry) int64_t DataBucket::GetCurrentTimeUNIX()
{ {
for (const auto &e: g_data_bucket_cache) { return std::chrono::duration_cast<std::chrono::nanoseconds>(
if (e.id == entry.id) { std::chrono::system_clock::now().time_since_epoch()
).count();
}
bool DataBucket::ExistsInCache(const DataBucketsRepository::DataBuckets &e)
{
for (const auto &ce: g_data_bucket_cache) {
if (ce.e.id == e.id) {
return true; return true;
} }
} }
@@ -469,6 +507,134 @@ bool DataBucket::ExistsInCache(const DataBucketsRepository::DataBuckets &entry)
return false; return false;
} }
bool DataBucket::SendDataBucketCacheUpdate(const DataBucketCacheEntry &e)
{
if (!e.e.id) {
return false;
}
EQ::Net::DynamicPacket p;
p.PutSerialize(0, e);
auto pack_size = sizeof(ServerDataBucketCacheUpdate_Struct) + p.Length();
auto pack = new ServerPacket(ServerOP_DataBucketCacheUpdate, static_cast<uint32_t>(pack_size));
auto buf = reinterpret_cast<ServerDataBucketCacheUpdate_Struct *>(pack->pBuffer);
buf->cereal_size = static_cast<uint32_t>(p.Length());
memcpy(buf->cereal_data, p.Data(), p.Length());
worldserver.SendPacket(pack);
return true;
}
void DataBucket::HandleWorldMessage(ServerPacket *p)
{
DataBucketCacheEntry n;
auto s = (ServerDataBucketCacheUpdate_Struct *) p->pBuffer;
EQ::Util::MemoryStreamReader ss(s->cereal_data, s->cereal_size);
cereal::BinaryInputArchive archive(ss);
archive(n);
LogDataBucketsDetail(
"Received cache packet for id [{}] key [{}] value [{}] action [{}]",
n.e.id,
n.e.key_,
n.e.value,
static_cast<int>(n.update_action)
);
// delete
if (n.update_action == DataBucketCacheUpdateAction::Delete) {
DeleteFromMissesCache(n.e);
g_data_bucket_cache.erase(
std::remove_if(
g_data_bucket_cache.begin(),
g_data_bucket_cache.end(),
[&](DataBucketCacheEntry &ce) {
bool match = n.e.id > 0 && ce.e.id == n.e.id;
if (match) {
LogDataBuckets(
"[delete] cache key [{}] id [{}] cache_size before [{}] after [{}]",
ce.e.key_,
ce.e.id,
g_data_bucket_cache.size(),
g_data_bucket_cache.size() - 1
);
}
return match;
}
),
g_data_bucket_cache.end()
);
return;
}
// update
bool has_key = false;
for (auto &ce: g_data_bucket_cache) {
// update cache
if (ce.e.id == n.e.id) {
// reject old updates
int64 time_delta = ce.updated_time - n.updated_time;
if (ce.updated_time >= n.updated_time) {
LogDataBuckets(
"Attempted to update older cache key [{}] rejecting old time [{}] new time [{}] delta [{}] cache_size [{}]",
ce.e.key_,
ce.updated_time,
n.updated_time,
time_delta,
g_data_bucket_cache.size()
);
return;
}
DeleteFromMissesCache(n.e);
LogDataBuckets(
"[update] cache id [{}] key [{}] value [{}] old time [{}] new time [{}] delta [{}] cache_size [{}]",
ce.e.id,
ce.e.key_,
n.e.value,
ce.updated_time,
n.updated_time,
time_delta,
g_data_bucket_cache.size()
);
ce.e = n.e;
ce.updated_time = n.updated_time;
has_key = true;
break;
}
}
// create
if (!has_key) {
DeleteFromMissesCache(n.e);
size_t size_before = g_data_bucket_cache.size();
g_data_bucket_cache.emplace_back(
DataBucketCacheEntry{
.e = n.e,
.updated_time = GetCurrentTimeUNIX()
}
);
LogDataBuckets(
"[create] Adding new cache id [{}] key [{}] value [{}] cache size before [{}] after [{}]",
n.e.id,
n.e.key_,
n.e.value,
size_before,
g_data_bucket_cache.size()
);
}
}
void DataBucket::DeleteFromMissesCache(DataBucketsRepository::DataBuckets e) void DataBucket::DeleteFromMissesCache(DataBucketsRepository::DataBuckets e)
{ {
// delete from cache where there might have been a written bucket miss to the cache // delete from cache where there might have been a written bucket miss to the cache
@@ -479,11 +645,11 @@ void DataBucket::DeleteFromMissesCache(DataBucketsRepository::DataBuckets e)
std::remove_if( std::remove_if(
g_data_bucket_cache.begin(), g_data_bucket_cache.begin(),
g_data_bucket_cache.end(), g_data_bucket_cache.end(),
[&](DataBucketsRepository::DataBuckets &ce) { [&](DataBucketCacheEntry &ce) {
return ce.id == 0 && ce.key_ == e.key_ && return ce.e.id == 0 && ce.e.key_ == e.key_ &&
ce.character_id == e.character_id && ce.e.character_id == e.character_id &&
ce.npc_id == e.npc_id && ce.e.npc_id == e.npc_id &&
ce.bot_id == e.bot_id; ce.e.bot_id == e.bot_id;
} }
), ),
g_data_bucket_cache.end() g_data_bucket_cache.end()
@@ -501,47 +667,3 @@ void DataBucket::ClearCache()
g_data_bucket_cache.clear(); g_data_bucket_cache.clear();
LogInfo("Cleared data buckets cache"); LogInfo("Cleared data buckets cache");
} }
void DataBucket::DeleteFromCache(uint64 id, DataBucketLoadType::Type type)
{
size_t size_before = g_data_bucket_cache.size();
g_data_bucket_cache.erase(
std::remove_if(
g_data_bucket_cache.begin(),
g_data_bucket_cache.end(),
[&](DataBucketsRepository::DataBuckets &e) {
switch (type) {
case DataBucketLoadType::Bot:
return e.bot_id == id;
case DataBucketLoadType::Client:
return e.character_id == id;
default:
return false;
}
}
),
g_data_bucket_cache.end()
);
LogDataBuckets(
"Deleted [{}] id [{}] from cache size before [{}] after [{}]",
DataBucketLoadType::Name[type],
id,
size_before,
g_data_bucket_cache.size()
);
}
// CanCache returns whether a bucket can be cached or not
// characters are only in one zone at a time so we can cache locally to the zone
// bots (not implemented) are only in one zone at a time so we can cache locally to the zone
// npcs (ids) can be in multiple zones so we can't cache locally to the zone
bool DataBucket::CanCache(const DataBucketKey &key)
{
if (key.character_id > 0 || key.bot_id > 0) {
return true;
}
return false;
}
+34 -5
View File
@@ -1,3 +1,7 @@
//
// Created by Akkadius on 7/7/18.
//
#ifndef EQEMU_DATABUCKET_H #ifndef EQEMU_DATABUCKET_H
#define EQEMU_DATABUCKET_H #define EQEMU_DATABUCKET_H
@@ -8,6 +12,27 @@
#include "../common/json/json_archive_single_line.h" #include "../common/json/json_archive_single_line.h"
#include "../common/servertalk.h" #include "../common/servertalk.h"
enum DataBucketCacheUpdateAction : uint8 {
Upsert,
Delete
};
struct DataBucketCacheEntry {
DataBucketsRepository::DataBuckets e;
int64_t updated_time{};
DataBucketCacheUpdateAction update_action{};
template<class Archive>
void serialize(Archive &ar)
{
ar(
CEREAL_NVP(e),
CEREAL_NVP(updated_time),
CEREAL_NVP(update_action)
);
}
};
struct DataBucketKey { struct DataBucketKey {
std::string key; std::string key;
std::string value; std::string value;
@@ -21,12 +46,14 @@ namespace DataBucketLoadType {
enum Type : uint8 { enum Type : uint8 {
Bot, Bot,
Client, Client,
NPC,
MaxType MaxType
}; };
static const std::string Name[Type::MaxType] = { static const std::string Name[Type::MaxType] = {
"Bot", "Bot",
"Client", "Client",
"NPC",
}; };
} }
@@ -41,6 +68,8 @@ public:
static bool GetDataBuckets(Mob *mob); static bool GetDataBuckets(Mob *mob);
static int64_t GetCurrentTimeUNIX();
// scoped bucket methods // scoped bucket methods
static void SetData(const DataBucketKey &k); static void SetData(const DataBucketKey &k);
static bool DeleteData(const DataBucketKey &k); static bool DeleteData(const DataBucketKey &k);
@@ -51,15 +80,15 @@ public:
// bucket repository versus key matching // bucket repository versus key matching
static bool CheckBucketMatch(const DataBucketsRepository::DataBuckets &dbe, const DataBucketKey &k); static bool CheckBucketMatch(const DataBucketsRepository::DataBuckets &dbe, const DataBucketKey &k);
static bool ExistsInCache(const DataBucketsRepository::DataBuckets &entry); static bool ExistsInCache(const DataBucketsRepository::DataBuckets &e);
static void BulkLoadEntitiesToCache(DataBucketLoadType::Type t, std::vector<uint32> ids); static void BulkLoadEntities(DataBucketLoadType::Type t, std::vector<uint32> ids);
static void DeleteCachedBuckets(DataBucketLoadType::Type type, uint32 id); static void DeleteCachedBuckets(DataBucketLoadType::Type t, uint32 id);
static bool SendDataBucketCacheUpdate(const DataBucketCacheEntry &e);
static void HandleWorldMessage(ServerPacket *p);
static void DeleteFromMissesCache(DataBucketsRepository::DataBuckets e); static void DeleteFromMissesCache(DataBucketsRepository::DataBuckets e);
static void ClearCache(); static void ClearCache();
static void DeleteFromCache(uint64 id, DataBucketLoadType::Type type);
static bool CanCache(const DataBucketKey &key);
}; };
#endif //EQEMU_DATABUCKET_H #endif //EQEMU_DATABUCKET_H
+14 -2
View File
@@ -1817,13 +1817,25 @@ void EntityList::DuelMessage(Mob *winner, Mob *loser, bool flee)
if (parse->PlayerHasQuestSub(EVENT_DUEL_WIN)) { if (parse->PlayerHasQuestSub(EVENT_DUEL_WIN)) {
std::vector<std::any> args = { winner, loser }; std::vector<std::any> args = { winner, loser };
parse->EventPlayer(EVENT_DUEL_WIN, winner->CastToClient(), loser->GetName(), loser->CastToClient()->CharacterID(), &args); parse->EventPlayer(
EVENT_DUEL_WIN,
winner->CastToClient(),
loser->GetName(),
loser->CastToClient()->CharacterID(),
&args
);
} }
if (parse->PlayerHasQuestSub(EVENT_DUEL_LOSE)) { if (parse->PlayerHasQuestSub(EVENT_DUEL_LOSE)) {
std::vector<std::any> args = { winner, loser }; std::vector<std::any> args = { winner, loser };
parse->EventPlayer(EVENT_DUEL_LOSE, loser->CastToClient(), winner->GetName(), winner->CastToClient()->CharacterID(), &args); parse->EventPlayer(
EVENT_DUEL_LOSE,
loser->CastToClient(),
winner->GetName(),
winner->CastToClient()->CharacterID(),
&args
);
} }
} }
-13
View File
@@ -1,7 +1,6 @@
#include "../client.h" #include "../client.h"
#include "find/aa.cpp" #include "find/aa.cpp"
#include "find/body_type.cpp" #include "find/body_type.cpp"
#include "find/bot.cpp"
#include "find/bug_category.cpp" #include "find/bug_category.cpp"
#include "find/character.cpp" #include "find/character.cpp"
#include "find/class.cpp" #include "find/class.cpp"
@@ -12,7 +11,6 @@
#include "find/faction.cpp" #include "find/faction.cpp"
#include "find/item.cpp" #include "find/item.cpp"
#include "find/language.cpp" #include "find/language.cpp"
#include "find/ldon_theme.cpp"
#include "find/npctype.cpp" #include "find/npctype.cpp"
#include "find/object_type.cpp" #include "find/object_type.cpp"
#include "find/race.cpp" #include "find/race.cpp"
@@ -49,7 +47,6 @@ void command_find(Client *c, const Seperator *sep)
Cmd{.cmd = "faction", .u = "faction [Search Criteria]", .fn = FindFaction, .a = {"#findfaction"}}, Cmd{.cmd = "faction", .u = "faction [Search Criteria]", .fn = FindFaction, .a = {"#findfaction"}},
Cmd{.cmd = "item", .u = "item [Search Criteria]", .fn = FindItem, .a = {"#fi", "#finditem"}}, Cmd{.cmd = "item", .u = "item [Search Criteria]", .fn = FindItem, .a = {"#fi", "#finditem"}},
Cmd{.cmd = "language", .u = "language [Search Criteria]", .fn = FindLanguage, .a = {"#findlanguage"}}, Cmd{.cmd = "language", .u = "language [Search Criteria]", .fn = FindLanguage, .a = {"#findlanguage"}},
Cmd{.cmd = "ldon_theme", .u = "ldon_theme [Search Criteria]", .fn = FindLDoNTheme, .a = {"#findldontheme"}},
Cmd{ Cmd{
.cmd = "npctype", .u = "npctype [Search Criteria]", .fn = FindNPCType, .a = { .cmd = "npctype", .u = "npctype [Search Criteria]", .fn = FindNPCType, .a = {
"#fn", "#fn",
@@ -68,16 +65,6 @@ void command_find(Client *c, const Seperator *sep)
Cmd{.cmd = "zone", .u = "zone [Search Criteria]", .fn = FindZone, .a = {"#fz", "#findzone"}}, Cmd{.cmd = "zone", .u = "zone [Search Criteria]", .fn = FindZone, .a = {"#fz", "#findzone"}},
}; };
if (RuleB(Bots, Enabled)) {
commands.emplace_back(
Cmd{.cmd = "bot", .u = "bot [Search Criteria]", .fn = FindBot, .a = {"#findbot"}}
);
std::sort(commands.begin(), commands.end(), [](const Cmd& a, const Cmd& b) {
return a.cmd < b.cmd;
});
}
// Check for arguments // Check for arguments
const auto arguments = sep->argnum; const auto arguments = sep->argnum;
if (!arguments) { if (!arguments) {
-95
View File
@@ -1,95 +0,0 @@
#include "../../client.h"
#include "../../common/repositories/bot_data_repository.h"
void FindBot(Client *c, const Seperator *sep)
{
if (sep->IsNumber(2)) {
const auto bot_id = Strings::ToUnsignedInt(sep->arg[2]);
const auto& e = BotDataRepository::FindOne(content_db, bot_id);
if (!e.bot_id) {
c->Message(
Chat::White,
fmt::format(
"Bot ID {} does not exist or is invalid.",
bot_id
).c_str()
);
return;
}
c->Message(
Chat::White,
fmt::format(
"Bot ID {} | {}",
bot_id,
e.name
).c_str()
);
return;
}
const auto search_criteria = Strings::ToLower(sep->argplus[2]);
const auto& l = BotDataRepository::GetWhere(
content_db,
fmt::format(
"LOWER(`name`) LIKE '%%{}%%' AND `name` NOT LIKE '%-deleted-%' ORDER BY `bot_id` ASC LIMIT 50",
search_criteria
)
);
if (l.empty()) {
c->Message(
Chat::White,
fmt::format(
"No bots found matching '{}'.",
sep->argplus[2]
).c_str()
);
}
auto found_count = 0;
for (const auto& e : l) {
c->Message(
Chat::White,
fmt::format(
"Bot ID {} | {}",
Strings::Commify(e.bot_id),
e.name
).c_str()
);
found_count++;
if (found_count == 50) {
break;
}
}
if (found_count == 50) {
c->Message(
Chat::White,
fmt::format(
"50 Bots found matching '{}', max reached.",
sep->argplus[2]
).c_str()
);
return;
}
c->Message(
Chat::White,
fmt::format(
"{} Bot{} found matching '{}'.",
found_count,
found_count != 1 ? "s" : "",
sep->argplus[2]
).c_str()
);
}
+1 -1
View File
@@ -36,7 +36,7 @@ void FindCharacter(Client *c, const Seperator *sep)
const auto& l = CharacterDataRepository::GetWhere( const auto& l = CharacterDataRepository::GetWhere(
content_db, content_db,
fmt::format( fmt::format(
"LOWER(`name`) LIKE '%%{}%%' AND `name` NOT LIKE '%-deleted-%' ORDER BY `id` ASC LIMIT 50", "LOWER(`name`) LIKE '%%{}%%' ORDER BY `id` ASC LIMIT 50",
search_criteria search_criteria
) )
); );
+1 -1
View File
@@ -57,7 +57,7 @@ void FindClass(Client *c, const Seperator *sep)
( (
IsPlayerClass(class_id) ? IsPlayerClass(class_id) ?
fmt::format( fmt::format(
" ({})", " | ({})",
Strings::Commify(GetPlayerClassBit(class_id)) Strings::Commify(GetPlayerClassBit(class_id))
) : ) :
"" ""
-65
View File
@@ -1,65 +0,0 @@
#include "../../client.h"
void FindLDoNTheme(Client *c, const Seperator *sep)
{
if (sep->IsNumber(2)) {
const uint32 theme_id = Strings::ToUnsignedInt(sep->arg[2]);
if (LDoNTheme::IsValid(theme_id)) {
c->Message(
Chat::White,
fmt::format(
"Theme {} | {} ({})",
theme_id,
LDoNTheme::GetName(theme_id),
LDoNTheme::GetBitmask(theme_id)
).c_str()
);
return;
}
c->Message(
Chat::White,
fmt::format(
"Theme ID {} was not found.",
theme_id
).c_str()
);
return;
}
const std::string& search_criteria = Strings::ToLower(sep->argplus[2]);
uint32 found_count = 0;
for (const auto& l : ldon_theme_names) {
const std::string& ldon_theme_name_lower = Strings::ToLower(l.second.first);
if (!Strings::Contains(ldon_theme_name_lower, search_criteria)) {
continue;
}
c->Message(
Chat::White,
fmt::format(
"Theme {} | {} ({})",
l.first,
l.second.first,
l.second.second
).c_str()
);
found_count++;
}
c->Message(
Chat::White,
fmt::format(
"{} Theme{} found matching '{}'.",
found_count,
found_count != 1 ? "s" : "",
sep->argplus[2]
).c_str()
);
}
+13 -15
View File
@@ -3,21 +3,20 @@
void SetAdventurePoints(Client *c, const Seperator *sep) void SetAdventurePoints(Client *c, const Seperator *sep)
{ {
const uint16 arguments = sep->argnum; const auto arguments = sep->argnum;
if (arguments < 3 || !sep->IsNumber(2) || !sep->IsNumber(3)) { if (arguments < 3 || !sep->IsNumber(2) || !sep->IsNumber(3)) {
c->Message(Chat::White, "Usage: #set adventure_points [Theme] [Points]"); c->Message(Chat::White, "Usage: #set adventure_points [Theme] [Points]");
c->Message(Chat::White, "Valid themes are as follows:"); c->Message(Chat::White, "Valid themes are as follows:");
for (const auto& e : ldon_theme_names) { for (const auto& e : EQ::constants::GetLDoNThemeMap()) {
if (e.first != LDoNTheme::Unused) { if (e.first != LDoNThemes::Unused) {
c->Message( c->Message(
Chat::White, Chat::White,
fmt::format( fmt::format(
"Theme {} | {} ({})", "Theme {} | {}",
e.first, e.first,
e.second.first, e.second
e.second.second
).c_str() ).c_str()
); );
} }
@@ -26,26 +25,25 @@ void SetAdventurePoints(Client *c, const Seperator *sep)
return; return;
} }
Client* t = c; auto t = c;
if (c->GetTarget() && c->GetTarget()->IsClient()) { if (c->GetTarget() && c->GetTarget()->IsClient()) {
t = c->GetTarget()->CastToClient(); t = c->GetTarget()->CastToClient();
} }
const uint32 theme_id = Strings::ToUnsignedInt(sep->arg[2]); const uint32 theme_id = Strings::ToUnsignedInt(sep->arg[2]);
const uint32 points = Strings::ToUnsignedInt(sep->arg[3]); const uint32 points = Strings::ToUnsignedInt(sep->arg[3]);
if (!LDoNTheme::IsValid(theme_id)) { if (!EQ::ValueWithin(theme_id, LDoNThemes::GUK, LDoNThemes::TAK)) {
c->Message(Chat::White, "Valid themes are as follows:"); c->Message(Chat::White, "Valid themes are as follows:");
for (const auto& e : ldon_theme_names) { for (const auto& e : EQ::constants::GetLDoNThemeMap()) {
if (e.first != LDoNTheme::Unused) { if (e.first != LDoNThemes::Unused) {
c->Message( c->Message(
Chat::White, Chat::White,
fmt::format( fmt::format(
"Theme {} | {} ({})", "Theme {} | {}",
e.first, e.first,
e.second.first, e.second
e.second.second
).c_str() ).c_str()
); );
} }
@@ -58,7 +56,7 @@ void SetAdventurePoints(Client *c, const Seperator *sep)
Chat::White, Chat::White,
fmt::format( fmt::format(
"Set {} Points to {} for {}.", "Set {} Points to {} for {}.",
LDoNTheme::GetName(theme_id), EQ::constants::GetLDoNThemeName(theme_id),
Strings::Commify(points), Strings::Commify(points),
c->GetTargetDescription(t) c->GetTargetDescription(t)
).c_str() ).c_str()
+2 -2
View File
@@ -89,11 +89,11 @@ void ShowCurrencies(Client *c, const Seperator *sep)
} }
} }
for (const auto& l : ldon_theme_names) { for (const auto& l : EQ::constants::GetLDoNThemeMap()) {
const uint32 ldon_currency_value = t->GetLDoNPointsTheme(l.first); const uint32 ldon_currency_value = t->GetLDoNPointsTheme(l.first);
if (ldon_currency_value) { if (ldon_currency_value) {
currency_table += DialogueWindow::TableRow( currency_table += DialogueWindow::TableRow(
DialogueWindow::TableCell(l.second.first) + DialogueWindow::TableCell(l.second) +
DialogueWindow::TableCell(Strings::Commify(ldon_currency_value)) DialogueWindow::TableCell(Strings::Commify(ldon_currency_value))
); );
+1 -1
View File
@@ -2419,7 +2419,7 @@ bool Group::AmIMainAssist(const char *mob_name)
if (!mob_name) if (!mob_name)
return false; return false;
return !((bool)MainAssistName.compare(mob_name)); return !((bool)MainTankName.compare(mob_name));
} }
bool Group::AmIPuller(const char *mob_name) bool Group::AmIPuller(const char *mob_name)
+2
View File
@@ -63,6 +63,7 @@ public:
void AddMember(const std::string& new_member_name); void AddMember(const std::string& new_member_name);
void SendUpdate(uint32 type,Mob* member); void SendUpdate(uint32 type,Mob* member);
void SendLeadershipAAUpdate(); void SendLeadershipAAUpdate();
void SendWorldGroup(uint32 zone_id,Mob* zoningmember);
bool DelMemberOOZ(const char *Name); bool DelMemberOOZ(const char *Name);
bool DelMember(Mob* oldmember,bool ignoresender = false); bool DelMember(Mob* oldmember,bool ignoresender = false);
void DisbandGroup(bool joinraid = false); void DisbandGroup(bool joinraid = false);
@@ -72,6 +73,7 @@ public:
bool IsGroupMember(Mob* c); bool IsGroupMember(Mob* c);
bool IsGroupMember(const char* name); bool IsGroupMember(const char* name);
bool Process(); bool Process();
bool IsGroup() { return true; }
void SendGroupJoinOOZ(Mob* NewMember); void SendGroupJoinOOZ(Mob* NewMember);
void CastGroupSpell(Mob* caster,uint16 spellid); void CastGroupSpell(Mob* caster,uint16 spellid);
void SplitExp(ExpSource exp_source, const uint64 exp, Mob* other); void SplitExp(ExpSource exp_source, const uint64 exp, Mob* other);
+1
View File
@@ -839,6 +839,7 @@ luabind::scope lua_register_packet_opcodes() {
luabind::value("GroupLeaderChange", static_cast<int>(OP_GroupLeaderChange)), luabind::value("GroupLeaderChange", static_cast<int>(OP_GroupLeaderChange)),
luabind::value("GroupLeadershipAAUpdate", static_cast<int>(OP_GroupLeadershipAAUpdate)), luabind::value("GroupLeadershipAAUpdate", static_cast<int>(OP_GroupLeadershipAAUpdate)),
luabind::value("GroupRoles", static_cast<int>(OP_GroupRoles)), luabind::value("GroupRoles", static_cast<int>(OP_GroupRoles)),
luabind::value("OP_SendFindableLocations", static_cast<int>(OP_SendFindableLocations)),
luabind::value("SendFindableNPCs", static_cast<int>(OP_SendFindableNPCs)), luabind::value("SendFindableNPCs", static_cast<int>(OP_SendFindableNPCs)),
luabind::value("HideCorpse", static_cast<int>(OP_HideCorpse)), luabind::value("HideCorpse", static_cast<int>(OP_HideCorpse)),
luabind::value("TargetBuffs", static_cast<int>(OP_TargetBuffs)), luabind::value("TargetBuffs", static_cast<int>(OP_TargetBuffs)),
+8 -21
View File
@@ -572,8 +572,6 @@ Mob::~Mob()
m_close_mobs.clear(); m_close_mobs.clear();
ClearDataBucketCache();
LeaveHealRotationTargetPool(); LeaveHealRotationTargetPool();
} }
@@ -5327,7 +5325,14 @@ void Mob::ExecWeaponProc(const EQ::ItemInstance* inst, uint16 spell_id, Mob* on,
//It should be safe as we don't have any truly const EQ::ItemInstance floating around anywhere. //It should be safe as we don't have any truly const EQ::ItemInstance floating around anywhere.
//So we'll live with it for now //So we'll live with it for now
if (parse->ItemHasQuestSub(const_cast<EQ::ItemInstance*>(inst), EVENT_WEAPON_PROC)) { if (parse->ItemHasQuestSub(const_cast<EQ::ItemInstance*>(inst), EVENT_WEAPON_PROC)) {
int i = parse->EventItem(EVENT_WEAPON_PROC, CastToClient(), const_cast<EQ::ItemInstance*>(inst), on, "", spell_id); int i = parse->EventItem(
EVENT_WEAPON_PROC,
CastToClient(),
const_cast<EQ::ItemInstance*>(inst),
on,
"",
spell_id
);
if (i != 0) { if (i != 0) {
return; return;
@@ -8608,21 +8613,3 @@ std::unordered_map<uint16, Mob *> &Mob::GetCloseMobList(float distance)
{ {
return entity_list.GetCloseMobList(this, distance); return entity_list.GetCloseMobList(this, distance);
} }
void Mob::ClearDataBucketCache()
{
if (IsOfClientBot()) {
uint64 id = 0;
DataBucketLoadType::Type t{};
if (IsBot()) {
id = CastToBot()->GetBotID();
t = DataBucketLoadType::Bot;
}
else if (IsClient()) {
id = CastToClient()->CharacterID();
t = DataBucketLoadType::Client;
}
DataBucket::DeleteFromCache(id, t);
}
}
-2
View File
@@ -1491,8 +1491,6 @@ public:
std::unordered_map<uint16, Mob *> &GetCloseMobList(float distance = 0.0f); std::unordered_map<uint16, Mob *> &GetCloseMobList(float distance = 0.0f);
void CheckScanCloseMobsMovingTimer(); void CheckScanCloseMobsMovingTimer();
void ClearDataBucketCache();
protected: protected:
void CommonDamage(Mob* other, int64 &damage, const uint16 spell_id, const EQ::skills::SkillType attack_skill, bool &avoidable, const int8 buffslot, const bool iBuffTic, eSpecialAttacks specal = eSpecialAttacks::None); void CommonDamage(Mob* other, int64 &damage, const uint16 spell_id, const EQ::skills::SkillType attack_skill, bool &avoidable, const int8 buffslot, const bool iBuffTic, eSpecialAttacks specal = eSpecialAttacks::None);
static uint16 GetProcID(uint16 spell_id, uint8 effect_index); static uint16 GetProcID(uint16 spell_id, uint8 effect_index);
+10 -13
View File
@@ -72,22 +72,19 @@ void Client::SendPathPacket(const std::vector<FindPerson_Point> &points) {
Message(Chat::System, "Total points %u", points.size()); Message(Chat::System, "Total points %u", points.size());
} }
int len = sizeof(FindPersonResult_Struct) + (points.size() + 1) * sizeof(FindPerson_Point); int len = (points.size() + 1) * sizeof(FindPerson_Point);
auto outapp = new EQApplicationPacket(OP_FindPersonReply, len); auto outapp = new EQApplicationPacket(OP_FindPersonReply, len);
FindPersonResult_Struct* fpr = (FindPersonResult_Struct*)outapp->pBuffer;
std::vector<FindPerson_Point>::iterator cur, end;
cur = points.begin();
end = points.end();
unsigned int r;
for (r = 0; cur != end; ++cur, r++) {
fpr->path[r] = *cur;
auto& last = points.back();
outapp->WriteFloat(last.y);
outapp->WriteFloat(last.x);
outapp->WriteFloat(last.z);
for (auto& p : points) {
outapp->WriteFloat(p.y);
outapp->WriteFloat(p.x);
outapp->WriteFloat(p.z);
} }
//put the last element into the destination field
--cur;
fpr->path[r] = *cur;
fpr->dest = *cur;
FastQueuePacket(&outapp); FastQueuePacket(&outapp);
}) })
+52 -13
View File
@@ -91,7 +91,13 @@ void QuestManager::Process() {
if (cur->Timer_.Enabled() && cur->Timer_.Check()) { if (cur->Timer_.Enabled() && cur->Timer_.Check()) {
if (cur->mob) { if (cur->mob) {
if (cur->mob->IsEncounter()) { if (cur->mob->IsEncounter()) {
parse->EventEncounter(EVENT_TIMER, cur->mob->CastToEncounter()->GetEncounterName(), cur->name, 0, nullptr); parse->EventEncounter(
EVENT_TIMER,
cur->mob->CastToEncounter()->GetEncounterName(),
cur->name,
0,
nullptr
);
} else { } else {
parse->EventMob(EVENT_TIMER, cur->mob, nullptr, [&]() { return cur->name; }, 0); parse->EventMob(EVENT_TIMER, cur->mob, nullptr, [&]() { return cur->name; }, 0);
} }
@@ -655,7 +661,14 @@ void QuestManager::stoptimer(const std::string& timer_name)
for (auto e = QTimerList.begin(); e != QTimerList.end(); ++e) { for (auto e = QTimerList.begin(); e != QTimerList.end(); ++e) {
if (e->mob && e->mob == owner && e->name == timer_name) { if (e->mob && e->mob == owner && e->name == timer_name) {
parse->EventMob(EVENT_TIMER_STOP, owner, nullptr, [&]() { return timer_name; }); parse->EventMob(
EVENT_TIMER_STOP,
owner,
nullptr,
[&]() {
return timer_name;
}
);
QTimerList.erase(e); QTimerList.erase(e);
break; break;
@@ -682,7 +695,14 @@ void QuestManager::stoptimer(const std::string& timer_name, Mob* m)
for (auto e = QTimerList.begin(); e != QTimerList.end();) { for (auto e = QTimerList.begin(); e != QTimerList.end();) {
if (e->mob && e->mob == m) { if (e->mob && e->mob == m) {
parse->EventMob(EVENT_TIMER_STOP, m, nullptr, [&]() { return timer_name; }); parse->EventMob(
EVENT_TIMER_STOP,
m,
nullptr,
[&]() {
return timer_name;
}
);
QTimerList.erase(e); QTimerList.erase(e);
break; break;
@@ -723,7 +743,14 @@ void QuestManager::stopalltimers()
for (auto e = QTimerList.begin(); e != QTimerList.end();) { for (auto e = QTimerList.begin(); e != QTimerList.end();) {
if (e->mob && e->mob == owner) { if (e->mob && e->mob == owner) {
parse->EventMob(EVENT_TIMER_STOP, owner, nullptr, [&]() { return e->name; }); parse->EventMob(
EVENT_TIMER_STOP,
owner,
nullptr,
[&]() {
return e->name;
}
);
e = QTimerList.erase(e); e = QTimerList.erase(e);
} else { } else {
@@ -765,7 +792,14 @@ void QuestManager::stopalltimers(Mob* m)
for (auto e = QTimerList.begin(); e != QTimerList.end();) { for (auto e = QTimerList.begin(); e != QTimerList.end();) {
if (e->mob && e->mob == m) { if (e->mob && e->mob == m) {
parse->EventMob(EVENT_TIMER_STOP, m, nullptr, [&]() { return e->name; }); parse->EventMob(
EVENT_TIMER_STOP,
m,
nullptr,
[&]() {
return e->name;
}
);
e = QTimerList.erase(e); e = QTimerList.erase(e);
} else { } else {
@@ -819,13 +853,18 @@ void QuestManager::pausetimer(const std::string& timer_name, Mob* m)
} }
); );
parse->EventMob(EVENT_TIMER_PAUSE, mob, nullptr, [&]() { parse->EventMob(
return fmt::format( EVENT_TIMER_PAUSE,
"{} {}", mob,
timer_name, nullptr,
milliseconds [&]() {
); return fmt::format(
}); "{} {}",
timer_name,
milliseconds
);
}
);
LogQuests("Pausing timer [{}] for [{}] with [{}] ms remaining", timer_name, owner->GetName(), milliseconds); LogQuests("Pausing timer [{}] for [{}] with [{}] ms remaining", timer_name, owner->GetName(), milliseconds);
} }
@@ -1287,7 +1326,7 @@ std::string QuestManager::getskillname(int skill_id) {
} }
std::string QuestManager::getldonthemename(uint32 theme_id) { std::string QuestManager::getldonthemename(uint32 theme_id) {
return LDoNTheme::GetName(theme_id); return EQ::constants::GetLDoNThemeName(theme_id);
} }
std::string QuestManager::getfactionname(int faction_id) { std::string QuestManager::getfactionname(int faction_id) {
+38 -20
View File
@@ -256,15 +256,22 @@ bool Mob::CastSpell(uint16 spell_id, uint16 target_id, CastingSlot slot,
Mob* spell_target = entity_list.GetMobID(target_id); Mob* spell_target = entity_list.GetMobID(target_id);
std::vector<std::any> args = { spell_target }; std::vector<std::any> args = { spell_target };
int return_value = parse->EventMob(EVENT_CAST_BEGIN, this, nullptr, [&]() { int return_value = parse->EventMob(
return fmt::format( EVENT_CAST_BEGIN,
"{} {} {} {}", this,
spell_id, nullptr,
GetID(), [&]() {
GetCasterLevel(spell_id), return fmt::format(
target_id "{} {} {} {}",
); spell_id,
}, 0, &args); GetID(),
GetCasterLevel(spell_id),
target_id
);
},
0,
&args
);
if (IsClient() && return_value != 0) { if (IsClient() && return_value != 0) {
if (IsDiscipline(spell_id)) { if (IsDiscipline(spell_id)) {
@@ -1797,15 +1804,22 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, CastingSlot slo
std::vector<std::any> args = { spell_target }; std::vector<std::any> args = { spell_target };
parse->EventMob(EVENT_CAST, this, nullptr, [&]() { parse->EventMob(
return fmt::format( EVENT_CAST,
"{} {} {} {}", this,
spell_id, nullptr,
GetID(), [&]() {
GetCasterLevel(spell_id), return fmt::format(
target_id "{} {} {} {}",
); spell_id,
}, 0, &args); GetID(),
GetCasterLevel(spell_id),
target_id
);
},
0,
&args
);
if(bard_song_mode) if(bard_song_mode)
{ {
@@ -3951,7 +3965,10 @@ bool Mob::SpellOnTarget(
std::vector<std::any> args = { spelltar }; std::vector<std::any> args = { spelltar };
parse->EventMob(EVENT_CAST_ON, spelltar, this, parse->EventMob(
EVENT_CAST_ON,
spelltar,
this,
[&]() { [&]() {
return fmt::format( return fmt::format(
"{} {} {} {}", "{} {} {} {}",
@@ -3961,7 +3978,8 @@ bool Mob::SpellOnTarget(
target_id target_id
); );
}, },
0, &args 0,
&args
); );
if (!DoCastingChecksOnTarget(false, spell_id, spelltar)) { if (!DoCastingChecksOnTarget(false, spell_id, spelltar)) {
+22 -27
View File
@@ -1093,16 +1093,15 @@ void Client::TraderStartTrader(const EQApplicationPacket *app)
inst->SetPrice(in->item_cost[i]); inst->SetPrice(in->item_cost[i]);
TraderRepository::Trader trader_item{}; TraderRepository::Trader trader_item{};
trader_item.id = 0; trader_item.id = 0;
trader_item.char_entity_id = GetID(); trader_item.char_entity_id = GetID();
trader_item.char_id = CharacterID(); trader_item.char_id = CharacterID();
trader_item.char_zone_id = GetZoneID(); trader_item.char_zone_id = GetZoneID();
trader_item.char_zone_instance_id = GetInstanceID(); trader_item.item_charges = inst->GetCharges() == 0 ? 1 : inst->GetCharges();
trader_item.item_charges = inst->GetCharges() == 0 ? 1 : inst->GetCharges(); trader_item.item_cost = inst->GetPrice();
trader_item.item_cost = inst->GetPrice(); trader_item.item_id = inst->GetID();
trader_item.item_id = inst->GetID(); trader_item.item_sn = in->serial_number[i];
trader_item.item_sn = in->serial_number[i]; trader_item.slot_id = i;
trader_item.slot_id = i;
if (inst->IsAugmented()) { if (inst->IsAugmented()) {
auto augs = inst->GetAugmentIDs(); auto augs = inst->GetAugmentIDs();
trader_item.aug_slot_1 = augs.at(0); trader_item.aug_slot_1 = augs.at(0);
@@ -1797,7 +1796,7 @@ void Client::SendBarterWelcome()
void Client::DoBazaarSearch(BazaarSearchCriteria_Struct search_criteria) void Client::DoBazaarSearch(BazaarSearchCriteria_Struct search_criteria)
{ {
auto results = Bazaar::GetSearchResults(database, search_criteria, GetZoneID(), GetInstanceID()); auto results = Bazaar::GetSearchResults(database, search_criteria, GetZoneID());
if (results.empty()) { if (results.empty()) {
SendBazaarDone(GetID()); SendBazaarDone(GetID());
return; return;
@@ -2941,11 +2940,9 @@ void Client::SendBecomeTrader(BazaarTraderBarterActions action, uint32 entity_id
auto outapp = new EQApplicationPacket(OP_BecomeTrader, sizeof(BecomeTrader_Struct)); auto outapp = new EQApplicationPacket(OP_BecomeTrader, sizeof(BecomeTrader_Struct));
auto data = (BecomeTrader_Struct *) outapp->pBuffer; auto data = (BecomeTrader_Struct *) outapp->pBuffer;
data->action = action; data->action = action;
data->entity_id = trader->GetID(); data->entity_id = trader->GetID();
data->trader_id = trader->CharacterID(); data->trader_id = trader->CharacterID();
data->zone_id = trader->GetZoneID();
data->zone_instance_id = trader->GetInstanceID();
strn0cpy(data->trader_name, trader->GetCleanName(), sizeof(data->trader_name)); strn0cpy(data->trader_name, trader->GetCleanName(), sizeof(data->trader_name));
QueuePacket(outapp); QueuePacket(outapp);
@@ -3091,15 +3088,14 @@ void Client::TraderPriceUpdate(const EQApplicationPacket *app)
auto item_detail = FindTraderItemBySerialNumber(newgis->serial_number[i]); auto item_detail = FindTraderItemBySerialNumber(newgis->serial_number[i]);
TraderRepository::Trader trader_item{}; TraderRepository::Trader trader_item{};
trader_item.id = 0; trader_item.id = 0;
trader_item.char_entity_id = GetID(); trader_item.char_entity_id = GetID();
trader_item.char_id = CharacterID(); trader_item.char_id = CharacterID();
trader_item.char_zone_id = GetZoneID(); trader_item.char_zone_id = GetZoneID();
trader_item.char_zone_instance_id = GetInstanceID(); trader_item.item_charges = newgis->charges[i];
trader_item.item_charges = newgis->charges[i]; trader_item.item_cost = tpus->NewPrice;
trader_item.item_cost = tpus->NewPrice; trader_item.item_id = newgis->items[i];
trader_item.item_id = newgis->items[i]; trader_item.item_sn = newgis->serial_number[i];
trader_item.item_sn = newgis->serial_number[i];
if (item_detail->IsAugmented()) { if (item_detail->IsAugmented()) {
auto augs = item_detail->GetAugmentIDs(); auto augs = item_detail->GetAugmentIDs();
trader_item.aug_slot_1 = augs.at(0); trader_item.aug_slot_1 = augs.at(0);
@@ -3228,8 +3224,7 @@ void Client::SendBulkBazaarTraders()
VARSTRUCT_ENCODE_TYPE(uint32, bufptr, results.count); VARSTRUCT_ENCODE_TYPE(uint32, bufptr, results.count);
for (auto t : results.traders) { for (auto t : results.traders) {
VARSTRUCT_ENCODE_TYPE(uint16, bufptr, t.zone_id); VARSTRUCT_ENCODE_TYPE(uint32, bufptr, t.zone_id);
VARSTRUCT_ENCODE_TYPE(uint16, bufptr, t.zone_instance_id);
VARSTRUCT_ENCODE_TYPE(uint32, bufptr, t.trader_id); VARSTRUCT_ENCODE_TYPE(uint32, bufptr, t.trader_id);
VARSTRUCT_ENCODE_TYPE(uint32, bufptr, t.entity_id); VARSTRUCT_ENCODE_TYPE(uint32, bufptr, t.entity_id);
VARSTRUCT_ENCODE_STRING(bufptr, t.trader_name.c_str()); VARSTRUCT_ENCODE_STRING(bufptr, t.trader_name.c_str());
+18 -6
View File
@@ -2005,6 +2005,15 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
break; break;
} }
case ServerOP_ReloadFindableLocations:
{
if (zone && zone->IsLoaded()) {
zone->SendReloadMessage("Findable Locations");
zone->ReloadFindableLocations();
}
break;
}
case ServerOP_ReloadBlockedSpells: case ServerOP_ReloadBlockedSpells:
{ {
if (zone && zone->IsLoaded()) { if (zone && zone->IsLoaded()) {
@@ -3644,6 +3653,11 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
SharedTaskZoneMessaging::HandleWorldMessage(pack); SharedTaskZoneMessaging::HandleWorldMessage(pack);
break; break;
} }
case ServerOP_DataBucketCacheUpdate:
{
DataBucket::HandleWorldMessage(pack);
break;
}
case ServerOP_GuildTributeUpdate: { case ServerOP_GuildTributeUpdate: {
GuildTributeUpdate* in = (GuildTributeUpdate*)pack->pBuffer; GuildTributeUpdate* in = (GuildTributeUpdate*)pack->pBuffer;
@@ -3929,14 +3943,12 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
out->action = 0; out->action = 0;
} }
} }
out->entity_id = in->entity_id;
out->entity_id = in->entity_id; out->zone_id = in->zone_id;
out->zone_id = in->zone_id; out->trader_id = in->trader_id;
out->zone_instance_id = in->instance_id;
out->trader_id = in->trader_id;
strn0cpy(out->trader_name, in->trader_name, sizeof(out->trader_name)); strn0cpy(out->trader_name, in->trader_name, sizeof(out->trader_name));
c.second->QueuePacket(outapp, true, Mob::CLIENT_CONNECTED); c.second->QueuePacket(outapp);
safe_delete(outapp); safe_delete(outapp);
} }
if (zone && zone->GetZoneID() == Zones::BAZAAR && in->instance_id == zone->GetInstanceID()) { if (zone && zone->GetZoneID() == Zones::BAZAAR && in->instance_id == zone->GetInstanceID()) {
+1
View File
@@ -1200,6 +1200,7 @@ bool Zone::Init(bool is_static) {
LoadNPCEmotes(&npc_emote_list); LoadNPCEmotes(&npc_emote_list);
LoadAlternateAdvancement(); LoadAlternateAdvancement();
LoadBaseData(); LoadBaseData();
LoadFindableLocations();
LoadMerchants(); LoadMerchants();
LoadTempMerchantData(); LoadTempMerchantData();
+10
View File
@@ -47,6 +47,7 @@
#include "../common/repositories/lootdrop_entries_repository.h" #include "../common/repositories/lootdrop_entries_repository.h"
#include "../common/repositories/base_data_repository.h" #include "../common/repositories/base_data_repository.h"
#include "../common/repositories/skill_caps_repository.h" #include "../common/repositories/skill_caps_repository.h"
#include "../common/repositories/findable_location_repository.h"
struct EXPModifier struct EXPModifier
{ {
@@ -454,6 +455,12 @@ public:
void LoadBaseData(); void LoadBaseData();
void ReloadBaseData(); void ReloadBaseData();
// Findable Locations
void LoadFindableLocations();
void ReloadFindableLocations();
void ClearFindableLocations();
void SendFindableLocations(Client* client = nullptr);
private: private:
bool allow_mercs; bool allow_mercs;
@@ -518,6 +525,9 @@ private:
// Base Data // Base Data
std::vector<BaseDataRepository::BaseData> m_base_data = { }; std::vector<BaseDataRepository::BaseData> m_base_data = { };
// Findable Locations
std::vector<FindableLocationRepository::FindableLocation> m_findable_locations = { };
}; };
#endif #endif
+42
View File
@@ -0,0 +1,42 @@
#include "zone.h"
void Zone::LoadFindableLocations() {
m_findable_locations = content_db.LoadFindableLocations(GetShortName(), GetInstanceVersion());
if (m_findable_locations.empty()) {
LogInfo("No findable loacations loaded");
return;
}
}
void Zone::ReloadFindableLocations() {
ClearFindableLocations();
LoadFindableLocations();
}
void Zone::ClearFindableLocations() {
m_findable_locations.clear();
}
void Zone::SendFindableLocations(Client* client) {
if (m_findable_locations.empty()) {
return;
}
size_t size = sizeof(uint32) + (m_findable_locations.size() * sizeof(FindableLocation_Struct));
auto outapp = new EQApplicationPacket(OP_SendFindableLocations, size);
outapp->WriteUInt32(m_findable_locations.size());
for (auto& location : m_findable_locations) {
outapp->WriteUInt32(location.type);
outapp->WriteSInt32(location.findable_id);
outapp->WriteSInt32(location.findable_sub_id);
outapp->WriteSInt32(location.zone_id);
outapp->WriteSInt32(location.zone_id_index);
outapp->WriteFloat(location.y);
outapp->WriteFloat(location.x);
outapp->WriteFloat(location.z);
}
client->FastQueuePacket(&outapp);
}
+12 -2
View File
@@ -50,9 +50,8 @@
#include "../common/repositories/character_corpses_repository.h" #include "../common/repositories/character_corpses_repository.h"
#include "../common/repositories/character_corpse_items_repository.h" #include "../common/repositories/character_corpse_items_repository.h"
#include "../common/repositories/zone_repository.h" #include "../common/repositories/zone_repository.h"
#include "../common/repositories/trader_repository.h" #include "../common/repositories/trader_repository.h"
#include "../common/repositories/findable_location_repository.h"
#include <ctime> #include <ctime>
#include <iostream> #include <iostream>
@@ -1923,6 +1922,8 @@ const NPCType *ZoneDatabase::LoadNPCTypesData(uint32 npc_type_id, bool bulk_load
} }
} }
DataBucket::BulkLoadEntities(DataBucketLoadType::NPC, npc_ids);
if (!npc_faction_ids.empty()) { if (!npc_faction_ids.empty()) {
zone->LoadNPCFactions(npc_faction_ids); zone->LoadNPCFactions(npc_faction_ids);
zone->LoadNPCFactionAssociations(npc_faction_ids); zone->LoadNPCFactionAssociations(npc_faction_ids);
@@ -2873,6 +2874,15 @@ void ZoneDatabase::UpdateAltCurrencyValue(uint32 char_id, uint32 currency_id, ui
CharacterAltCurrencyRepository::ReplaceOne(*this, e); CharacterAltCurrencyRepository::ReplaceOne(*this, e);
} }
std::vector<FindableLocationRepository::FindableLocation> ZoneDatabase::LoadFindableLocations(const std::string& zone_name, int16 version) {
auto findable_locations = FindableLocationRepository::GetWhere(
*this, fmt::format(
"zone = '{}' AND (version = {} OR version = -1) {} ORDER BY id ASC",
zone_name, version, ContentFilterCriteria::apply()));
return findable_locations;
}
void ZoneDatabase::SaveBuffs(Client *client) void ZoneDatabase::SaveBuffs(Client *client)
{ {
CharacterBuffsRepository::DeleteWhere( CharacterBuffsRepository::DeleteWhere(
+4
View File
@@ -13,6 +13,7 @@
#include "../common/repositories/doors_repository.h" #include "../common/repositories/doors_repository.h"
#include "../common/races.h" #include "../common/races.h"
#include "../common/repositories/npc_faction_entries_repository.h" #include "../common/repositories/npc_faction_entries_repository.h"
#include "../common/repositories/findable_location_repository.h"
#include "bot_database.h" #include "bot_database.h"
@@ -638,6 +639,9 @@ public:
void LoadAltCurrencyValues(uint32 char_id, std::map<uint32, uint32> &currency); void LoadAltCurrencyValues(uint32 char_id, std::map<uint32, uint32> &currency);
void UpdateAltCurrencyValue(uint32 char_id, uint32 currency_id, uint32 value); void UpdateAltCurrencyValue(uint32 char_id, uint32 currency_id, uint32 value);
/* Findable Locations */
std::vector<FindableLocationRepository::FindableLocation> LoadFindableLocations(const std::string& zone_name, int16 version);
/* /*
* Misc stuff. * Misc stuff.
* PLEASE DO NOT ADD TO THIS COLLECTION OF CRAP UNLESS YOUR METHOD * PLEASE DO NOT ADD TO THIS COLLECTION OF CRAP UNLESS YOUR METHOD