mirror of
https://github.com/EQEmu/Server.git
synced 2026-07-09 20:17:16 +00:00
Integrate client-based say links for TOB+ clients (#5105)
This commit is contained in:
+67
-28
@@ -17,18 +17,20 @@
|
||||
*/
|
||||
#include "say_link.h"
|
||||
|
||||
#include "common/features.h"
|
||||
#include "common/emu_constants.h"
|
||||
#include "common/strings.h"
|
||||
#include "common/item_instance.h"
|
||||
#include "common/item_data.h"
|
||||
#include "zone/zonedb.h"
|
||||
#include "common/shareddb.h"
|
||||
|
||||
#include <algorithm>
|
||||
// static database pointer (must be SharedDatabase since this module is in common)
|
||||
static SharedDatabase* s_database = nullptr;
|
||||
|
||||
// static bucket global
|
||||
std::vector<SaylinkRepository::Saylink> g_cached_saylinks = {};
|
||||
|
||||
bool EQ::saylink::DegenerateLinkBody(SayLinkBody_Struct &say_link_body_struct, const std::string &say_link_body)
|
||||
bool EQ::saylink::DeserializeLinkBody(SayLinkBody_Struct &say_link_body_struct, const std::string &say_link_body)
|
||||
{
|
||||
memset(&say_link_body_struct, 0, sizeof(say_link_body_struct));
|
||||
if (say_link_body.length() != EQ::constants::SAY_LINK_BODY_SIZE) {
|
||||
@@ -52,8 +54,9 @@ bool EQ::saylink::DegenerateLinkBody(SayLinkBody_Struct &say_link_body_struct, c
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EQ::saylink::GenerateLinkBody(std::string &say_link_body, const SayLinkBody_Struct &say_link_body_struct)
|
||||
bool EQ::saylink::SerializeLinkBody(std::string &say_link_body, const SayLinkBody_Struct &say_link_body_struct)
|
||||
{
|
||||
// This is specifically the server struct for link bodies
|
||||
say_link_body = StringFormat(
|
||||
"%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%02X" "%05X" "%08X",
|
||||
(0x0F & say_link_body_struct.action_id),
|
||||
@@ -85,10 +88,16 @@ EQ::SayLinkEngine::SayLinkEngine()
|
||||
|
||||
const std::string &EQ::SayLinkEngine::GenerateLink()
|
||||
{
|
||||
// At this point, we can assume that we are generated an item link. Any client before TOB can only do item links
|
||||
// so even dialog links will end up here. Other types of links aren't supported by the server yet, but they
|
||||
// would require TOB+ without some other hacks like dialog links use now
|
||||
|
||||
m_Link.clear();
|
||||
m_LinkBody.clear();
|
||||
m_LinkText.clear();
|
||||
|
||||
// These two functions translate multiple server-internal objects into the saylink-internal struct for rendering
|
||||
// to the packet. Detect the client version after this
|
||||
generate_body();
|
||||
generate_text();
|
||||
|
||||
@@ -162,8 +171,8 @@ void EQ::SayLinkEngine::generate_body()
|
||||
// TODO: add hash call
|
||||
break;
|
||||
case saylink::SayLinkLootItem:
|
||||
if (m_LootData == nullptr) { break; }
|
||||
item_data = database.GetItem(m_LootData->item_id);
|
||||
if (m_LootData == nullptr || !s_database) { break; }
|
||||
item_data = s_database->GetItem(m_LootData->item_id);
|
||||
if (item_data == nullptr) { break; }
|
||||
m_LinkBodyStruct.item_id = item_data->ID;
|
||||
m_LinkBodyStruct.augment_1 = m_LootData->aug_1;
|
||||
@@ -276,8 +285,8 @@ void EQ::SayLinkEngine::generate_text()
|
||||
m_LinkText = m_ItemData->Name;
|
||||
return;
|
||||
case saylink::SayLinkLootItem:
|
||||
if (m_LootData == nullptr) { break; }
|
||||
item_data = database.GetItem(m_LootData->item_id);
|
||||
if (m_LootData == nullptr || !s_database) { break; }
|
||||
item_data = s_database->GetItem(m_LootData->item_id);
|
||||
if (item_data == nullptr) { break; }
|
||||
m_LinkText = item_data->Name;
|
||||
return;
|
||||
@@ -373,11 +382,39 @@ std::string EQ::SayLinkEngine::InjectSaylinksIfNotExist(const char *message)
|
||||
return new_message;
|
||||
}
|
||||
|
||||
std::string EQ::SayLinkEngine::GetSaylinkPhrase(uint32_t saylink_id)
|
||||
{
|
||||
auto cached_link = std::find_if(g_cached_saylinks.begin(), g_cached_saylinks.end(),
|
||||
[&saylink_id](const SaylinkRepository::Saylink& saylink) {
|
||||
return saylink.id == saylink_id;
|
||||
});
|
||||
|
||||
if (cached_link != g_cached_saylinks.end()) {
|
||||
return cached_link->phrase;
|
||||
}
|
||||
|
||||
if (s_database != nullptr) {
|
||||
auto saylink = SaylinkRepository::FindOne(*s_database, saylink_id);
|
||||
return saylink.phrase; // this will just be empty if it's not found, same as the default return case
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
void EQ::SayLinkEngine::SetDatabase(SharedDatabase* db)
|
||||
{
|
||||
s_database = db;
|
||||
}
|
||||
|
||||
void EQ::SayLinkEngine::LoadCachedSaylinks()
|
||||
{
|
||||
auto saylinks = SaylinkRepository::GetWhere(database, "phrase not REGEXP '[A-Z]' and phrase not REGEXP '[0-9]'");
|
||||
LogSaylink("Loaded [{}] saylinks into cache", saylinks.size());
|
||||
g_cached_saylinks = saylinks;
|
||||
if (s_database != nullptr) {
|
||||
auto saylinks = SaylinkRepository::GetWhere(*s_database, "phrase not REGEXP '[A-Z]' and phrase not REGEXP '[0-9]'");
|
||||
LogSaylink("Loaded [{}] saylinks into cache", saylinks.size());
|
||||
g_cached_saylinks = saylinks;
|
||||
} else {
|
||||
LogSaylink("Failed to load saylinks into cache: no database");
|
||||
}
|
||||
}
|
||||
|
||||
SaylinkRepository::Saylink EQ::SayLinkEngine::GetOrSaveSaylink(std::string saylink_text)
|
||||
@@ -391,26 +428,28 @@ SaylinkRepository::Saylink EQ::SayLinkEngine::GetOrSaveSaylink(std::string sayli
|
||||
}
|
||||
}
|
||||
|
||||
auto saylinks = SaylinkRepository::GetWhere(
|
||||
database,
|
||||
fmt::format("phrase = '{}'", Strings::Escape(saylink_text))
|
||||
);
|
||||
if (s_database != nullptr) {
|
||||
auto saylinks = SaylinkRepository::GetWhere(
|
||||
*s_database,
|
||||
fmt::format("phrase = '{}'", Strings::Escape(saylink_text))
|
||||
);
|
||||
|
||||
// return if found from the database
|
||||
if (!saylinks.empty()) {
|
||||
g_cached_saylinks.emplace_back(saylinks[0]);
|
||||
return saylinks[0];
|
||||
}
|
||||
// return if found from the database
|
||||
if (!saylinks.empty()) {
|
||||
g_cached_saylinks.emplace_back(saylinks[0]);
|
||||
return saylinks[0];
|
||||
}
|
||||
|
||||
// if not found in database - save
|
||||
auto new_saylink = SaylinkRepository::NewEntity();
|
||||
new_saylink.phrase = saylink_text;
|
||||
// if not found in database - save
|
||||
auto new_saylink = SaylinkRepository::NewEntity();
|
||||
new_saylink.phrase = saylink_text;
|
||||
|
||||
// persist to database
|
||||
auto link = SaylinkRepository::InsertOne(database, new_saylink);
|
||||
if (link.id > 0) {
|
||||
g_cached_saylinks.emplace_back(link);
|
||||
return link;
|
||||
// persist to database
|
||||
auto link = SaylinkRepository::InsertOne(*s_database, new_saylink);
|
||||
if (link.id > 0) {
|
||||
g_cached_saylinks.emplace_back(link);
|
||||
return link;
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
|
||||
Reference in New Issue
Block a user