[Corpses] Add corpse entity variables to DB (#4911)

* [Corpses] Add corpse entity variables to DB

- When corpses have entity variables add/remove/modified it will update the database accordingly.
- Corpse loading will pull the database values if they exist.

* Updates per review

* Update version.h

---------

Co-authored-by: Chris Miles <akkadius1@gmail.com>
This commit is contained in:
Fryguy 2025-06-25 16:21:52 -04:00 committed by GitHub
parent dc261bb203
commit 50ae0f8351
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 87 additions and 1 deletions

View File

@ -7121,6 +7121,18 @@ ADD COLUMN `first_login` int(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `xtargets`;
.sql = R"( .sql = R"(
ALTER TABLE player_event_logs ROW_FORMAT=COMPRESSED; ALTER TABLE player_event_logs ROW_FORMAT=COMPRESSED;
CREATE INDEX idx_event_type_char_id ON player_event_logs (event_type_id, character_id); CREATE INDEX idx_event_type_char_id ON player_event_logs (event_type_id, character_id);
)",
.content_schema_update = false
},
ManifestEntry{
.version = 9325,
.description = "2025_06_10_character_corpses_entity_variables.sql",
.check = "SHOW COLUMNS FROM `character_corpses` LIKE 'entity_variables'",
.condition = "empty",
.match = "",
.sql = R"(
ALTER TABLE `character_corpses`
ADD COLUMN `entity_variables` TEXT DEFAULT NULL AFTER `rezzable`;
)", )",
.content_schema_update = false .content_schema_update = false
}, },

View File

@ -70,6 +70,7 @@ public:
uint32_t gm_exp; uint32_t gm_exp;
uint32_t killed_by; uint32_t killed_by;
uint8_t rezzable; uint8_t rezzable;
std::string entity_variables;
}; };
static std::string PrimaryKey() static std::string PrimaryKey()
@ -131,6 +132,7 @@ public:
"gm_exp", "gm_exp",
"killed_by", "killed_by",
"rezzable", "rezzable",
"entity_variables",
}; };
} }
@ -188,6 +190,7 @@ public:
"gm_exp", "gm_exp",
"killed_by", "killed_by",
"rezzable", "rezzable",
"entity_variables",
}; };
} }
@ -279,6 +282,7 @@ public:
e.gm_exp = 0; e.gm_exp = 0;
e.killed_by = 0; e.killed_by = 0;
e.rezzable = 0; e.rezzable = 0;
e.entity_variables = "";
return e; return e;
} }
@ -366,6 +370,7 @@ public:
e.gm_exp = row[48] ? static_cast<uint32_t>(strtoul(row[48], nullptr, 10)) : 0; e.gm_exp = row[48] ? static_cast<uint32_t>(strtoul(row[48], nullptr, 10)) : 0;
e.killed_by = row[49] ? static_cast<uint32_t>(strtoul(row[49], nullptr, 10)) : 0; e.killed_by = row[49] ? static_cast<uint32_t>(strtoul(row[49], nullptr, 10)) : 0;
e.rezzable = row[50] ? static_cast<uint8_t>(strtoul(row[50], nullptr, 10)) : 0; e.rezzable = row[50] ? static_cast<uint8_t>(strtoul(row[50], nullptr, 10)) : 0;
e.entity_variables = row[51] ? row[51] : "";
return e; return e;
} }
@ -449,6 +454,7 @@ public:
v.push_back(columns[48] + " = " + std::to_string(e.gm_exp)); v.push_back(columns[48] + " = " + std::to_string(e.gm_exp));
v.push_back(columns[49] + " = " + std::to_string(e.killed_by)); v.push_back(columns[49] + " = " + std::to_string(e.killed_by));
v.push_back(columns[50] + " = " + std::to_string(e.rezzable)); v.push_back(columns[50] + " = " + std::to_string(e.rezzable));
v.push_back(columns[51] + " = '" + Strings::Escape(e.entity_variables) + "'");
auto results = db.QueryDatabase( auto results = db.QueryDatabase(
fmt::format( fmt::format(
@ -521,6 +527,7 @@ public:
v.push_back(std::to_string(e.gm_exp)); v.push_back(std::to_string(e.gm_exp));
v.push_back(std::to_string(e.killed_by)); v.push_back(std::to_string(e.killed_by));
v.push_back(std::to_string(e.rezzable)); v.push_back(std::to_string(e.rezzable));
v.push_back("'" + Strings::Escape(e.entity_variables) + "'");
auto results = db.QueryDatabase( auto results = db.QueryDatabase(
fmt::format( fmt::format(
@ -601,6 +608,7 @@ public:
v.push_back(std::to_string(e.gm_exp)); v.push_back(std::to_string(e.gm_exp));
v.push_back(std::to_string(e.killed_by)); v.push_back(std::to_string(e.killed_by));
v.push_back(std::to_string(e.rezzable)); v.push_back(std::to_string(e.rezzable));
v.push_back("'" + Strings::Escape(e.entity_variables) + "'");
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
} }
@ -685,6 +693,7 @@ public:
e.gm_exp = row[48] ? static_cast<uint32_t>(strtoul(row[48], nullptr, 10)) : 0; e.gm_exp = row[48] ? static_cast<uint32_t>(strtoul(row[48], nullptr, 10)) : 0;
e.killed_by = row[49] ? static_cast<uint32_t>(strtoul(row[49], nullptr, 10)) : 0; e.killed_by = row[49] ? static_cast<uint32_t>(strtoul(row[49], nullptr, 10)) : 0;
e.rezzable = row[50] ? static_cast<uint8_t>(strtoul(row[50], nullptr, 10)) : 0; e.rezzable = row[50] ? static_cast<uint8_t>(strtoul(row[50], nullptr, 10)) : 0;
e.entity_variables = row[51] ? row[51] : "";
all_entries.push_back(e); all_entries.push_back(e);
} }
@ -760,6 +769,7 @@ public:
e.gm_exp = row[48] ? static_cast<uint32_t>(strtoul(row[48], nullptr, 10)) : 0; e.gm_exp = row[48] ? static_cast<uint32_t>(strtoul(row[48], nullptr, 10)) : 0;
e.killed_by = row[49] ? static_cast<uint32_t>(strtoul(row[49], nullptr, 10)) : 0; e.killed_by = row[49] ? static_cast<uint32_t>(strtoul(row[49], nullptr, 10)) : 0;
e.rezzable = row[50] ? static_cast<uint8_t>(strtoul(row[50], nullptr, 10)) : 0; e.rezzable = row[50] ? static_cast<uint8_t>(strtoul(row[50], nullptr, 10)) : 0;
e.entity_variables = row[51] ? row[51] : "";
all_entries.push_back(e); all_entries.push_back(e);
} }
@ -885,6 +895,7 @@ public:
v.push_back(std::to_string(e.gm_exp)); v.push_back(std::to_string(e.gm_exp));
v.push_back(std::to_string(e.killed_by)); v.push_back(std::to_string(e.killed_by));
v.push_back(std::to_string(e.rezzable)); v.push_back(std::to_string(e.rezzable));
v.push_back("'" + Strings::Escape(e.entity_variables) + "'");
auto results = db.QueryDatabase( auto results = db.QueryDatabase(
fmt::format( fmt::format(
@ -958,6 +969,7 @@ public:
v.push_back(std::to_string(e.gm_exp)); v.push_back(std::to_string(e.gm_exp));
v.push_back(std::to_string(e.killed_by)); v.push_back(std::to_string(e.killed_by));
v.push_back(std::to_string(e.rezzable)); v.push_back(std::to_string(e.rezzable));
v.push_back("'" + Strings::Escape(e.entity_variables) + "'");
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
} }

View File

@ -231,6 +231,21 @@ public:
return UpdateOne(db, corpse); return UpdateOne(db, corpse);
} }
static int UpdateEntityVariables(Database& db, uint32 corpse_id, const std::string& json_string)
{
auto results = db.QueryDatabase(
fmt::format(
"UPDATE `{}` SET `entity_variables` = '{}' WHERE `{}` = {}",
TableName(),
Strings::Escape(json_string),
PrimaryKey(),
corpse_id
)
);
return results.Success() ? results.RowsAffected() : 0;
}
}; };
#endif //EQEMU_CHARACTER_CORPSES_REPOSITORY_H #endif //EQEMU_CHARACTER_CORPSES_REPOSITORY_H

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 9324 #define CURRENT_BINARY_DATABASE_VERSION 9325
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9054 #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9054
#define CUSTOM_BINARY_DATABASE_VERSION 0 #define CUSTOM_BINARY_DATABASE_VERSION 0

View File

@ -32,7 +32,9 @@
#include "../common/repositories/character_corpse_items_repository.h" #include "../common/repositories/character_corpse_items_repository.h"
#include <iostream> #include <iostream>
#include "queryserv.h" #include "queryserv.h"
#include "../common/json/json.hpp"
using json = nlohmann::json;
extern EntityList entity_list; extern EntityList entity_list;
extern Zone *zone; extern Zone *zone;
@ -674,6 +676,21 @@ bool Corpse::Save()
ce.drakkin_tattoo = drakkin_tattoo; ce.drakkin_tattoo = drakkin_tattoo;
ce.drakkin_details = drakkin_details; ce.drakkin_details = drakkin_details;
{
json j;
for (const auto& kv : m_EntityVariables) {
j[kv.first] = kv.second;
}
if (!j.empty()) {
ce.entity_variables = j.dump();
} else {
ce.entity_variables = "{}";
}
LogCorpses("Corpse entity_variables: %s", ce.entity_variables.c_str());
}
for (auto &item: m_item_list) { for (auto &item: m_item_list) {
CharacterCorpseItemEntry e; CharacterCorpseItemEntry e;
@ -2428,9 +2445,36 @@ Corpse *Corpse::LoadCharacterCorpse(
c->m_become_npc = false; c->m_become_npc = false;
c->m_consented_guild_id = cc.guild_consent_id; c->m_consented_guild_id = cc.guild_consent_id;
try {
if (Strings::IsValidJson(cc.entity_variables)) {
json j = json::parse(cc.entity_variables);
for (auto& el : j.items()) {
c->SetEntityVariable(el.key(), el.value().get<std::string>());
}
}
} catch (const std::exception& ex) {
LogError("Failed to parse entity_variables JSON for corpse ID %u: %s", cc.id, ex.what());
}
c->IsRezzed(cc.is_rezzed); c->IsRezzed(cc.is_rezzed);
c->UpdateEquipmentLight(); c->UpdateEquipmentLight();
return c; return c;
} }
void Corpse::SyncEntityVariablesToCorpseDB()
{
if (!m_is_player_corpse || m_corpse_db_id == 0) {
return;
}
json j;
for (const auto& [key, value] : m_EntityVariables) {
j[key] = value;
}
std::string serialized = j.dump();
CharacterCorpsesRepository::UpdateEntityVariables(database, m_corpse_db_id, serialized);
}

View File

@ -244,6 +244,8 @@ public:
const glm::vec4 &position const glm::vec4 &position
); );
void SyncEntityVariablesToCorpseDB();
protected: protected:
void MoveItemToCorpse(Client *client, EQ::ItemInstance *inst, int16 equipSlot, std::list<uint32> &removedList); void MoveItemToCorpse(Client *client, EQ::ItemInstance *inst, int16 equipSlot, std::list<uint32> &removedList);

View File

@ -336,6 +336,7 @@ struct CharacterCorpseEntry
uint32 drakkin_tattoo; uint32 drakkin_tattoo;
uint32 drakkin_details; uint32 drakkin_details;
std::vector<CharacterCorpseItemEntry> items; std::vector<CharacterCorpseItemEntry> items;
std::string entity_variables;
}; };
namespace BeastlordPetData { namespace BeastlordPetData {