refactor: Database abstraction and organization of files (#1274)

* Database: Convert to proper namespace

* Database: Use base class and getter

* Database: Move files around

* Database: Add property Management query

Database: Move over user queries

Tested at gm 0 that pre-approved names are pre-approved, unapproved need moderator approval
deleting characters deletes the selcted one
refreshing the character page shows the last character you logged in as
tested all my characters show up when i login
tested that you can delete all 4 characters and the correct character is selected each time
tested renaming, approving names as gm0

Database: Add ugc model getter

Hey it works, look I got around the mariadb issue.

Database: Add queries

Database: consolidate name query

Database: Add friends list query

Update name of approved names query

Documentation

Database: Add name check

Database: Add BFF Query

Database: Move BFF Setter

Database: Move new friend query

Database: Add remove friend queries

Database: Add activity log

Database: Add ugc & prop content removal

Database: Add model update

Database: Add migration queries

Database: Add character and xml queries

Database: Add user queries

Untested, but compiling code

Need to test that new character names are properly assigned in the following scenarios
gm 0 and pre-approved name
gm 0 and unapproved name
gm 9 and pre-approved name
gm 9 and unapproved name

Database: constify function arguments

Database: Add pet queries

* Database: Move property model queries

Untested.  Need to test
placing a new model
moving existing one
removing ugc model
placing ugc model
moving ugc model(?)
changing privacy option variously
change description and name
approve property
can properly travel to property

* Property: Move stale reference deletion

* Database: Move performance update query

* Database: Add bug report query

* Database: Add cheat detection query

* Database: Add mail send query

* Untested code

need to test mailing from slash command, from all users of SendMail, getting bbb of a property and sending messages to bffs

* Update CDComponentsRegistryTable.h

Database: Rename and add further comments

Datavbase: Add comments

Add some comments

Build: Fix PCH directories

Database: Fix time

thanks apple

Database: Fix compiler warnings

Overload destructor
Define specialty for time_t
Use string instead of string_view for temp empty string

Update CDTable.h

Property: Update queries to use mapId

Database: Reorganize

Reorganize into CDClient folder and GameDatabase folder for clearer meanings and file structure

Folders: Rename to GameDatabase

MySQL: Remove MySQL Specifier from table

Database: Move Tables to Interfaces

Database: Reorder functions in header

Database: Simplify property queries

Database: Remove unused queries

Remove extra query definitions as well

Database: Consolidate User getters

Database: Comment logs

Update MySQLDatabase.cpp

Database: Use generic code

Playkey: Fix bad optional access

Database: Move stuff around

WorldServer: Update queries

Ugc reduced by many scopes
use new queries
very fast
tested that ugc still loads

Database: Add auth queries

I tested that only the correct password can sign into an account.
Tested that disabled playkeys do not allow the user to play the game

Database: Add donation query

Database: add objectId queries

Database: Add master queries

Database: Fix mis-named function

Database: Add slash command queries

Mail: Fix itemId type

CharFilter: Use new query

ObjectID: Remove duplicate code

SlashCommand: Update query with function

Database: Add mail queries

Ugc: Fix issues with saving models

Resolve large scope blocks as well

* Database: Add debug try catch rethrow macro

* General fixes

* fix play key not working

* Further fixes

---------

Co-authored-by: Aaron Kimbre <aronwk.aaron@gmail.com>
This commit is contained in:
David Markowitz
2023-11-17 16:47:18 -08:00
committed by GitHub
parent b68823b4cb
commit 7f623d358c
161 changed files with 2114 additions and 1516 deletions

View File

@@ -700,7 +700,7 @@ std::string CharacterComponent::StatisticsToString() const {
}
uint64_t CharacterComponent::GetStatisticFromSplit(std::vector<std::string> split, uint32_t index) {
return split.size() > index ? std::stoul(split.at(index)) : 0;
return split.size() > index ? std::stoull(split.at(index)) : 0;
}
ZoneStatistics& CharacterComponent::GetZoneStatisticsForMap(LWOMAPID mapID) {

View File

@@ -22,10 +22,8 @@ DonationVendorComponent::DonationVendorComponent(Entity* parent) : VendorCompone
return;
}
std::unique_ptr<sql::PreparedStatement> query(Database::CreatePreppedStmt("SELECT SUM(primaryScore) as donation_total FROM leaderboard WHERE game_id = ?;"));
query->setInt(1, m_ActivityId);
std::unique_ptr<sql::ResultSet> donation_total(query->executeQuery());
if (donation_total->next()) m_TotalDonated = donation_total->getInt("donation_total");
auto donationTotal = Database::Get()->GetDonationTotal(m_ActivityId);
if (donationTotal) m_TotalDonated = donationTotal.value();
m_TotalRemaining = m_Goal - m_TotalDonated;
m_PercentComplete = m_TotalDonated/static_cast<float>(m_Goal);
}

View File

@@ -1097,37 +1097,18 @@ void PetComponent::SetPetNameForModeration(const std::string& petName) {
approved = 2; //approved
}
auto deleteStmt = Database::CreatePreppedStmt("DELETE FROM pet_names WHERE id = ? LIMIT 1;");
deleteStmt->setUInt64(1, m_DatabaseId);
deleteStmt->execute();
delete deleteStmt;
//Save to db:
auto stmt = Database::CreatePreppedStmt("INSERT INTO `pet_names` (`id`, `pet_name`, `approved`) VALUES (?, ?, ?);");
stmt->setUInt64(1, m_DatabaseId);
stmt->setString(2, petName);
stmt->setInt(3, approved);
stmt->execute();
delete stmt;
Database::Get()->SetPetNameModerationStatus(m_DatabaseId, IPetNames::Info{petName, approved});
}
void PetComponent::LoadPetNameFromModeration() {
auto stmt = Database::CreatePreppedStmt("SELECT pet_name, approved FROM pet_names WHERE id = ? LIMIT 1;");
stmt->setUInt64(1, m_DatabaseId);
auto res = stmt->executeQuery();
while (res->next()) {
m_ModerationStatus = res->getInt(2);
auto petNameInfo = Database::Get()->GetPetNameInfo(m_DatabaseId);
if (petNameInfo) {
m_ModerationStatus = petNameInfo->approvalStatus;
if (m_ModerationStatus == 2) {
m_Name = res->getString(1);
m_Name = petNameInfo->petName;
}
}
delete res;
delete stmt;
}
void PetComponent::SetPreconditions(std::string& preconditions) {

View File

@@ -103,7 +103,7 @@ std::string PropertyEntranceComponent::BuildQuery(Entity* entity, int32_t sortMe
if (sortMethod == SORT_TYPE_FEATURED || sortMethod == SORT_TYPE_FRIENDS) {
std::string friendsList = " AND p.owner_id IN (";
auto friendsListQuery = Database::CreatePreppedStmt("SELECT * FROM (SELECT CASE WHEN player_id = ? THEN friend_id WHEN friend_id = ? THEN player_id END AS requested_player FROM friends ) AS fr WHERE requested_player IS NOT NULL ORDER BY requested_player DESC;");
auto friendsListQuery = Database::Get()->CreatePreppedStmt("SELECT * FROM (SELECT CASE WHEN player_id = ? THEN friend_id WHEN friend_id = ? THEN player_id END AS requested_player FROM friends ) AS fr WHERE requested_player IS NOT NULL ORDER BY requested_player DESC;");
friendsListQuery->setUInt(1, character->GetID());
friendsListQuery->setUInt(2, character->GetID());
@@ -147,7 +147,7 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl
if (!character) return;
// Player property goes in index 1 of the vector. This is how the client expects it.
auto playerPropertyLookup = Database::CreatePreppedStmt("SELECT * FROM properties WHERE owner_id = ? AND zone_id = ?");
auto playerPropertyLookup = Database::Get()->CreatePreppedStmt("SELECT * FROM properties WHERE owner_id = ? AND zone_id = ?");
playerPropertyLookup->setInt(1, character->GetID());
playerPropertyLookup->setInt(2, this->m_MapID);
@@ -180,7 +180,7 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl
const auto query = BuildQuery(entity, sortMethod, character);
auto propertyLookup = Database::CreatePreppedStmt(query);
auto propertyLookup = Database::Get()->CreatePreppedStmt(query);
const auto searchString = "%" + filterText + "%";
propertyLookup->setUInt(1, this->m_MapID);
@@ -209,7 +209,7 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl
std::string ownerName = "";
bool isOwned = true;
auto nameLookup = Database::CreatePreppedStmt("SELECT name FROM charinfo WHERE prop_clone_id = ?;");
auto nameLookup = Database::Get()->CreatePreppedStmt("SELECT name FROM charinfo WHERE prop_clone_id = ?;");
nameLookup->setUInt64(1, cloneId);
@@ -245,7 +245,7 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl
GeneralUtils::SetBit(ownerObjId, eObjectBits::PERSISTENT);
// Query to get friend and best friend fields
auto friendCheck = Database::CreatePreppedStmt("SELECT best_friend FROM friends WHERE (player_id = ? AND friend_id = ?) OR (player_id = ? AND friend_id = ?)");
auto friendCheck = Database::Get()->CreatePreppedStmt("SELECT best_friend FROM friends WHERE (player_id = ? AND friend_id = ?) OR (player_id = ? AND friend_id = ?)");
friendCheck->setUInt(1, character->GetID());
friendCheck->setUInt(2, ownerObjId);
@@ -278,7 +278,7 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl
bool isAlt = false;
// Query to determine whether this property is an alt character of the entity.
auto isAltQuery = Database::CreatePreppedStmt("SELECT id FROM charinfo where account_id in (SELECT account_id from charinfo WHERE id = ?) AND id = ?;");
auto isAltQuery = Database::Get()->CreatePreppedStmt("SELECT id FROM charinfo where account_id in (SELECT account_id from charinfo WHERE id = ?) AND id = ?;");
isAltQuery->setInt(1, character->GetID());
isAltQuery->setInt(2, owner);
@@ -312,7 +312,7 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl
int32_t numberOfProperties = 0;
auto buttonQuery = BuildQuery(entity, sortMethod, character, "SELECT COUNT(*) FROM properties as p JOIN charinfo as ci ON ci.prop_clone_id = p.clone_id where p.zone_id = ? AND (p.description LIKE ? OR p.name LIKE ? OR ci.name LIKE ?) AND p.privacy_option >= ? ", false);
auto propertiesLeft = Database::CreatePreppedStmt(buttonQuery);
auto propertiesLeft = Database::Get()->CreatePreppedStmt(buttonQuery);
propertiesLeft->setUInt(1, this->m_MapID);
propertiesLeft->setString(2, searchString.c_str());

View File

@@ -39,13 +39,12 @@ PropertyManagementComponent::PropertyManagementComponent(Entity* parent) : Compo
instance = this;
const auto& worldId = Game::zoneManager->GetZone()->GetZoneID();
const auto zoneId = worldId.GetMapID();
const auto cloneId = worldId.GetCloneID();
auto query = CDClientDatabase::CreatePreppedStmt(
"SELECT id FROM PropertyTemplate WHERE mapID = ?;");
query.bind(1, (int)zoneId);
auto query = CDClientDatabase::CreatePreppedStmt("SELECT id FROM PropertyTemplate WHERE mapID = ?;");
query.bind(1, static_cast<int32_t>(zoneId));
auto result = query.execQuery();
@@ -55,34 +54,25 @@ PropertyManagementComponent::PropertyManagementComponent(Entity* parent) : Compo
templateId = result.getIntField(0);
result.finalize();
auto propertyInfo = Database::Get()->GetPropertyInfo(zoneId, cloneId);
auto* propertyLookup = Database::CreatePreppedStmt("SELECT * FROM properties WHERE template_id = ? AND clone_id = ?;");
propertyLookup->setInt(1, templateId);
propertyLookup->setInt64(2, cloneId);
auto* propertyEntry = propertyLookup->executeQuery();
if (propertyEntry->next()) {
this->propertyId = propertyEntry->getUInt64(1);
this->owner = propertyEntry->getUInt64(2);
if (propertyInfo) {
this->propertyId = propertyInfo->id;
this->owner = propertyInfo->ownerId;
GeneralUtils::SetBit(this->owner, eObjectBits::CHARACTER);
GeneralUtils::SetBit(this->owner, eObjectBits::PERSISTENT);
this->clone_Id = propertyEntry->getInt(2);
this->propertyName = propertyEntry->getString(5).c_str();
this->propertyDescription = propertyEntry->getString(6).c_str();
this->privacyOption = static_cast<PropertyPrivacyOption>(propertyEntry->getUInt(9));
this->moderatorRequested = propertyEntry->getInt(10) == 0 && rejectionReason == "" && privacyOption == PropertyPrivacyOption::Public;
this->LastUpdatedTime = propertyEntry->getUInt64(11);
this->claimedTime = propertyEntry->getUInt64(12);
this->rejectionReason = std::string(propertyEntry->getString(13).c_str());
this->reputation = propertyEntry->getUInt(14);
this->clone_Id = propertyInfo->cloneId;
this->propertyName = propertyInfo->name;
this->propertyDescription = propertyInfo->description;
this->privacyOption = static_cast<PropertyPrivacyOption>(propertyInfo->privacyOption);
this->rejectionReason = propertyInfo->rejectionReason;
this->moderatorRequested = propertyInfo->modApproved == 0 && rejectionReason == "" && privacyOption == PropertyPrivacyOption::Public;
this->LastUpdatedTime = propertyInfo->lastUpdatedTime;
this->claimedTime = propertyInfo->claimedTime;
this->reputation = propertyInfo->reputation;
Load();
}
delete propertyLookup;
}
LWOOBJID PropertyManagementComponent::GetOwnerId() const {
@@ -152,14 +142,13 @@ void PropertyManagementComponent::SetPrivacyOption(PropertyPrivacyOption value)
}
privacyOption = value;
auto* propertyUpdate = Database::CreatePreppedStmt("UPDATE properties SET privacy_option = ?, rejection_reason = ?, mod_approved = ? WHERE id = ?;");
IProperty::Info info;
info.id = propertyId;
info.privacyOption = static_cast<uint32_t>(privacyOption);
info.rejectionReason = rejectionReason;
info.modApproved = 0;
propertyUpdate->setInt(1, static_cast<int32_t>(value));
propertyUpdate->setString(2, "");
propertyUpdate->setInt(3, 0);
propertyUpdate->setInt64(4, propertyId);
propertyUpdate->executeUpdate();
Database::Get()->UpdatePropertyModerationInfo(info);
}
void PropertyManagementComponent::UpdatePropertyDetails(std::string name, std::string description) {
@@ -169,13 +158,12 @@ void PropertyManagementComponent::UpdatePropertyDetails(std::string name, std::s
propertyDescription = description;
auto* propertyUpdate = Database::CreatePreppedStmt("UPDATE properties SET name = ?, description = ? WHERE id = ?;");
IProperty::Info info;
info.id = propertyId;
info.name = propertyName;
info.description = propertyDescription;
propertyUpdate->setString(1, name.c_str());
propertyUpdate->setString(2, description.c_str());
propertyUpdate->setInt64(3, propertyId);
propertyUpdate->executeUpdate();
Database::Get()->UpdatePropertyDetails(info);
OnQueryPropertyData(GetOwner(), UNASSIGNED_SYSTEM_ADDRESS);
}
@@ -217,28 +205,14 @@ bool PropertyManagementComponent::Claim(const LWOOBJID playerId) {
propertyId = ObjectIDManager::GenerateRandomObjectID();
auto* insertion = Database::CreatePreppedStmt(
"INSERT INTO properties"
"(id, owner_id, template_id, clone_id, name, description, rent_amount, rent_due, privacy_option, last_updated, time_claimed, rejection_reason, reputation, zone_id, performance_cost)"
"VALUES (?, ?, ?, ?, ?, ?, 0, 0, 0, UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), '', 0, ?, 0.0)"
);
insertion->setUInt64(1, propertyId);
insertion->setUInt64(2, (uint32_t)playerId);
insertion->setUInt(3, templateId);
insertion->setUInt64(4, playerCloneId);
insertion->setString(5, name.c_str());
insertion->setString(6, description.c_str());
insertion->setInt(7, propertyZoneId);
IProperty::Info info;
info.id = propertyId;
info.ownerId = character->GetID();
info.cloneId = playerCloneId;
info.name = name;
info.description = description;
// Try and execute the query, print an error if it fails.
try {
insertion->execute();
} catch (sql::SQLException& exception) {
LOG("Failed to execute query: (%s)!", exception.what());
throw exception;
return false;
}
Database::Get()->InsertNewProperty(info, templateId, worldId);
auto* zoneControlObject = Game::zoneManager->GetZoneControlObject();
for (CppScripts::Script* script : CppScripts::GetEntityScripts(zoneControlObject)) {
@@ -545,7 +519,7 @@ void PropertyManagementComponent::DeleteModel(const LWOOBJID id, const int delet
{
item->SetCount(item->GetCount() - 1);
LOG("YES IT GOES HERE");
LOG("BODGE TIME, YES IT GOES HERE");
break;
}
@@ -569,14 +543,13 @@ void PropertyManagementComponent::DeleteModel(const LWOOBJID id, const int delet
void PropertyManagementComponent::UpdateApprovedStatus(const bool value) {
if (owner == LWOOBJID_EMPTY) return;
auto* update = Database::CreatePreppedStmt("UPDATE properties SET mod_approved = ? WHERE id = ?;");
IProperty::Info info;
info.id = propertyId;
info.modApproved = value;
info.privacyOption = static_cast<uint32_t>(privacyOption);
info.rejectionReason = "";
update->setBoolean(1, value);
update->setInt64(2, propertyId);
update->executeUpdate();
delete update;
Database::Get()->UpdatePropertyModerationInfo(info);
}
void PropertyManagementComponent::Load() {
@@ -584,39 +557,17 @@ void PropertyManagementComponent::Load() {
return;
}
auto* lookup = Database::CreatePreppedStmt("SELECT id, lot, x, y, z, rx, ry, rz, rw, ugc_id FROM properties_contents WHERE property_id = ?;");
lookup->setUInt64(1, propertyId);
auto* lookupResult = lookup->executeQuery();
while (lookupResult->next()) {
const LWOOBJID id = lookupResult->getUInt64(1);
const LOT lot = lookupResult->getInt(2);
const NiPoint3 position =
{
static_cast<float>(lookupResult->getDouble(3)),
static_cast<float>(lookupResult->getDouble(4)),
static_cast<float>(lookupResult->getDouble(5))
};
const NiQuaternion rotation =
{
static_cast<float>(lookupResult->getDouble(9)),
static_cast<float>(lookupResult->getDouble(6)),
static_cast<float>(lookupResult->getDouble(7)),
static_cast<float>(lookupResult->getDouble(8))
};
auto propertyModels = Database::Get()->GetPropertyModels(propertyId);
for (const auto& databaseModel : propertyModels) {
auto* node = new SpawnerNode();
node->position = position;
node->rotation = rotation;
node->position = databaseModel.position;
node->rotation = databaseModel.rotation;
SpawnerInfo info{};
info.templateID = lot;
info.templateID = databaseModel.lot;
info.nodes = { node };
info.templateScale = 1.0f;
info.activeOnLoad = true;
@@ -626,13 +577,13 @@ void PropertyManagementComponent::Load() {
//info.emulated = true;
//info.emulator = Game::entityManager->GetZoneControlEntity()->GetObjectID();
info.spawnerID = id;
info.spawnerID = databaseModel.id;
std::vector<LDFBaseData*> settings;
//BBB property models need to have extra stuff set for them:
if (lot == 14) {
LWOOBJID blueprintID = lookupResult->getUInt(10);
if (databaseModel.lot == 14) {
LWOOBJID blueprintID = databaseModel.ugcId;
GeneralUtils::SetBit(blueprintID, eObjectBits::CHARACTER);
GeneralUtils::SetBit(blueprintID, eObjectBits::PERSISTENT);
@@ -640,7 +591,7 @@ void PropertyManagementComponent::Load() {
LDFBaseData* componentWhitelist = new LDFData<int>(u"componentWhitelist", 1);
LDFBaseData* modelType = new LDFData<int>(u"modelType", 2);
LDFBaseData* propertyObjectID = new LDFData<bool>(u"propertyObjectID", true);
LDFBaseData* userModelID = new LDFData<LWOOBJID>(u"userModelID", id);
LDFBaseData* userModelID = new LDFData<LWOOBJID>(u"userModelID", databaseModel.id);
settings.push_back(ldfBlueprintID);
settings.push_back(componentWhitelist);
@@ -649,7 +600,7 @@ void PropertyManagementComponent::Load() {
settings.push_back(userModelID);
} else {
auto modelType = new LDFData<int>(u"modelType", 2);
auto userModelID = new LDFData<LWOOBJID>(u"userModelID", id);
auto userModelID = new LDFData<LWOOBJID>(u"userModelID", databaseModel.id);
auto ldfModelBehavior = new LDFData<LWOOBJID>(u"modelBehaviors", 0);
auto propertyObjectID = new LDFData<bool>(u"propertyObjectID", true);
auto componentWhitelist = new LDFData<int>(u"componentWhitelist", 1);
@@ -671,8 +622,6 @@ void PropertyManagementComponent::Load() {
models.insert_or_assign(model->GetObjectID(), spawnerId);
}
delete lookup;
}
void PropertyManagementComponent::Save() {
@@ -680,27 +629,7 @@ void PropertyManagementComponent::Save() {
return;
}
auto* insertion = Database::CreatePreppedStmt("INSERT INTO properties_contents VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);");
auto* update = Database::CreatePreppedStmt("UPDATE properties_contents SET x = ?, y = ?, z = ?, rx = ?, ry = ?, rz = ?, rw = ? WHERE id = ?;");
auto* lookup = Database::CreatePreppedStmt("SELECT id FROM properties_contents WHERE property_id = ?;");
auto* remove = Database::CreatePreppedStmt("DELETE FROM properties_contents WHERE id = ?;");
lookup->setUInt64(1, propertyId);
sql::ResultSet* lookupResult = nullptr;
try {
lookupResult = lookup->executeQuery();
} catch (sql::SQLException& ex) {
LOG("lookup error %s", ex.what());
}
std::vector<LWOOBJID> present;
while (lookupResult->next()) {
const auto dbId = lookupResult->getUInt64(1);
present.push_back(dbId);
}
delete lookupResult;
auto present = Database::Get()->GetPropertyModels(propertyId);
std::vector<LWOOBJID> modelIds;
@@ -719,69 +648,26 @@ void PropertyManagementComponent::Save() {
const auto rotation = entity->GetRotation();
if (std::find(present.begin(), present.end(), id) == present.end()) {
insertion->setInt64(1, id);
insertion->setUInt64(2, propertyId);
insertion->setNull(3, 0);
insertion->setInt(4, entity->GetLOT());
insertion->setDouble(5, position.x);
insertion->setDouble(6, position.y);
insertion->setDouble(7, position.z);
insertion->setDouble(8, rotation.x);
insertion->setDouble(9, rotation.y);
insertion->setDouble(10, rotation.z);
insertion->setDouble(11, rotation.w);
insertion->setString(12, ("Objects_" + std::to_string(entity->GetLOT()) + "_name").c_str()); // Model name. TODO make this customizable
insertion->setString(13, ""); // Model description. TODO implement this.
insertion->setDouble(14, 0); // behavior 1. TODO implement this.
insertion->setDouble(15, 0); // behavior 2. TODO implement this.
insertion->setDouble(16, 0); // behavior 3. TODO implement this.
insertion->setDouble(17, 0); // behavior 4. TODO implement this.
insertion->setDouble(18, 0); // behavior 5. TODO implement this.
try {
insertion->execute();
} catch (sql::SQLException& ex) {
LOG("Error inserting into properties_contents. Error %s", ex.what());
}
} else {
update->setDouble(1, position.x);
update->setDouble(2, position.y);
update->setDouble(3, position.z);
update->setDouble(4, rotation.x);
update->setDouble(5, rotation.y);
update->setDouble(6, rotation.z);
update->setDouble(7, rotation.w);
IPropertyContents::Model model;
model.id = id;
model.lot = entity->GetLOT();
model.position = position;
model.rotation = rotation;
model.ugcId = 0;
update->setInt64(8, id);
try {
update->executeUpdate();
} catch (sql::SQLException& ex) {
LOG("Error updating properties_contents. Error: %s", ex.what());
}
Database::Get()->InsertNewPropertyModel(propertyId, model, "Objects_" + std::to_string(model.lot) + "_name");
} else {
Database::Get()->UpdateModelPositionRotation(id, position, rotation);
}
}
for (auto id : present) {
if (std::find(modelIds.begin(), modelIds.end(), id) != modelIds.end()) {
for (auto model : present) {
if (std::find(modelIds.begin(), modelIds.end(), model.id) != modelIds.end()) {
continue;
}
remove->setInt64(1, id);
try {
remove->execute();
} catch (sql::SQLException& ex) {
LOG("Error removing from properties_contents. Error %s", ex.what());
}
Database::Get()->RemoveModel(model.id);
}
auto* removeUGC = Database::CreatePreppedStmt("DELETE FROM ugc WHERE id NOT IN (SELECT ugc_id FROM properties_contents);");
removeUGC->execute();
delete removeUGC;
delete insertion;
delete update;
delete lookup;
delete remove;
}
void PropertyManagementComponent::AddModel(LWOOBJID modelId, LWOOBJID spawnerId) {
@@ -799,6 +685,7 @@ void PropertyManagementComponent::OnQueryPropertyData(Entity* originator, const
const auto& worldId = Game::zoneManager->GetZone()->GetZoneID();
const auto zoneId = worldId.GetMapID();
const auto cloneId = worldId.GetCloneID();
LOG("Getting property info for %d", zoneId);
GameMessages::PropertyDataMessage message = GameMessages::PropertyDataMessage(zoneId);
@@ -806,45 +693,25 @@ void PropertyManagementComponent::OnQueryPropertyData(Entity* originator, const
const auto isClaimed = GetOwnerId() != LWOOBJID_EMPTY;
LWOOBJID ownerId = GetOwnerId();
std::string ownerName = "";
std::string ownerName;
auto charInfo = Database::Get()->GetCharacterInfo(ownerId);
if (charInfo) ownerName = charInfo->name;
std::string name = "";
std::string description = "";
uint64_t claimed = 0;
char privacy = 0;
if (isClaimed) {
const auto cloneId = worldId.GetCloneID();
auto* nameLookup = Database::CreatePreppedStmt("SELECT name FROM charinfo WHERE prop_clone_id = ?;");
nameLookup->setUInt64(1, cloneId);
auto* nameResult = nameLookup->executeQuery();
if (nameResult->next()) {
ownerName = nameResult->getString(1).c_str();
}
delete nameResult;
delete nameLookup;
name = propertyName;
description = propertyDescription;
claimed = claimedTime;
privacy = static_cast<char>(this->privacyOption);
if (moderatorRequested) {
auto checkStatus = Database::CreatePreppedStmt("SELECT rejection_reason, mod_approved FROM properties WHERE id = ?;");
checkStatus->setInt64(1, propertyId);
auto result = checkStatus->executeQuery();
result->next();
const auto reason = std::string(result->getString(1).c_str());
const auto modApproved = result->getInt(2);
if (reason != "") {
auto moderationInfo = Database::Get()->GetPropertyInfo(zoneId, cloneId);
if (moderationInfo->rejectionReason != "") {
moderatorRequested = false;
rejectionReason = reason;
} else if (reason == "" && modApproved == 1) {
rejectionReason = moderationInfo->rejectionReason;
} else if (moderationInfo->rejectionReason == "" && moderationInfo->modApproved == 1) {
moderatorRequested = false;
rejectionReason = "";
} else {