remove complex queries and move logic to dDatabase

remove unused code

Use correct id

fix arrows

use correct parameter

fix queries

Update Property.cpp

remove unused header

remove extra include
This commit is contained in:
David Markowitz 2024-11-17 14:18:57 -08:00
parent de3fe93100
commit bf61ae8984
10 changed files with 251 additions and 253 deletions

View File

@ -73,4 +73,4 @@ cpp_space_around_assignment_operator=insert
cpp_space_pointer_reference_alignment=left cpp_space_pointer_reference_alignment=left
cpp_space_around_ternary_operator=insert cpp_space_around_ternary_operator=insert
cpp_wrap_preserve_blocks=one_liners cpp_wrap_preserve_blocks=one_liners
cpp_indent_comment=fasle cpp_indent_comment=false

View File

@ -0,0 +1,11 @@
#ifndef EPROPERTYSORTTYPE_H
#define EPROPERTYSORTTYPE_H
enum ePropertySortType : int32_t {
SORT_TYPE_FRIENDS = 0,
SORT_TYPE_REPUTATION = 1,
SORT_TYPE_RECENT = 3,
SORT_TYPE_FEATURED = 5
};
#endif //!EPROPERTYSORTTYPE_H

View File

@ -4,6 +4,8 @@
#include <cstdint> #include <cstdint>
#include <optional> #include <optional>
enum ePropertySortType : int32_t;
class IProperty { class IProperty {
public: public:
struct Info { struct Info {
@ -18,11 +20,33 @@ public:
uint32_t lastUpdatedTime{}; uint32_t lastUpdatedTime{};
uint32_t claimedTime{}; uint32_t claimedTime{};
uint32_t reputation{}; uint32_t reputation{};
float performanceCost{};
};
struct PropertyLookup {
uint32_t mapId{};
std::string searchString;
ePropertySortType sortChoice{};
uint32_t playerId{};
uint32_t numResults{};
uint32_t startIndex{};
uint32_t playerSort{};
};
struct PropertyEntranceResult {
int32_t totalEntriesMatchingQuery{};
// The entries that match the query. This should only contain up to 12 entries.
std::vector<IProperty::Info> entries;
}; };
// Get the property info for the given property id. // Get the property info for the given property id.
virtual std::optional<IProperty::Info> GetPropertyInfo(const LWOMAPID mapId, const LWOCLONEID cloneId) = 0; virtual std::optional<IProperty::Info> GetPropertyInfo(const LWOMAPID mapId, const LWOCLONEID cloneId) = 0;
// Get the properties for the given property lookup params.
// This is expected to return a result set of up to 12 properties
// so as not to transfer too much data at once.
virtual std::optional<IProperty::PropertyEntranceResult> GetProperties(const PropertyLookup& params) = 0;
// Update the property moderation info for the given property id. // Update the property moderation info for the given property id.
virtual void UpdatePropertyModerationInfo(const IProperty::Info& info) = 0; virtual void UpdatePropertyModerationInfo(const IProperty::Info& info) = 0;

View File

@ -112,6 +112,7 @@ public:
std::string GetBehavior(const int32_t behaviorId) override; std::string GetBehavior(const int32_t behaviorId) override;
void RemoveBehavior(const int32_t characterId) override; void RemoveBehavior(const int32_t characterId) override;
void UpdateAccountGmLevel(const uint32_t accountId, const eGameMasterLevel gmLevel) override; void UpdateAccountGmLevel(const uint32_t accountId, const eGameMasterLevel gmLevel) override;
std::optional<IProperty::PropertyEntranceResult> GetProperties(const IProperty::PropertyLookup& params) override;
private: private:
// Generic query functions that can be used for any query. // Generic query functions that can be used for any query.

View File

@ -1,8 +1,140 @@
#include "MySQLDatabase.h" #include "MySQLDatabase.h"
#include "ePropertySortType.h"
std::optional<IProperty::PropertyEntranceResult> MySQLDatabase::GetProperties(const IProperty::PropertyLookup& params) {
std::optional<IProperty::PropertyEntranceResult> result;
std::string query;
std::unique_ptr<sql::ResultSet> properties;
if (params.sortChoice == SORT_TYPE_FEATURED || params.sortChoice == SORT_TYPE_FRIENDS) {
query = R"QUERY(
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 >= ?
AND p.owner_id IN (
SELECT fr.requested_player AS player FROM (
SELECT CASE
WHEN player_id = ? THEN friend_id
WHEN friend_id = ? THEN player_id
END AS requested_player FROM friends
) AS fr
JOIN charinfo AS ci ON ci.id = fr.requested_player
WHERE fr.requested_player IS NOT NULL AND fr.requested_player != ?
) ORDER BY ci.name ASC
)QUERY";
const auto completeQuery = "SELECT p.* " + query + " LIMIT ? OFFSET ?;";
properties = ExecuteSelect(
completeQuery,
params.mapId,
"%" + params.searchString + "%",
"%" + params.searchString + "%",
"%" + params.searchString + "%",
params.playerSort,
params.playerId,
params.playerId,
params.playerId,
params.numResults,
params.startIndex
);
const auto countQuery = "SELECT COUNT(*) as count" + query + ";";
auto count = ExecuteSelect(
countQuery,
params.mapId,
"%" + params.searchString + "%",
"%" + params.searchString + "%",
"%" + params.searchString + "%",
params.playerSort,
params.playerId,
params.playerId,
params.playerId
);
if (count->next()) {
result->totalEntriesMatchingQuery = count->getUInt("count");
}
} else {
if (params.sortChoice == SORT_TYPE_REPUTATION) {
query = R"QUERY(
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 >= ?
ORDER BY p.reputation DESC, p.last_updated DESC
)QUERY";
} else {
query = R"QUERY(
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 >= ?
ORDER BY p.last_updated DESC
)QUERY";
}
const auto completeQuery = "SELECT p.* " + query + " LIMIT ? OFFSET ?;";
properties = ExecuteSelect(
completeQuery,
params.mapId,
"%" + params.searchString + "%",
"%" + params.searchString + "%",
"%" + params.searchString + "%",
params.playerSort,
params.numResults,
params.startIndex
);
const auto countQuery = "SELECT COUNT(*) as count" + query + ";";
auto count = ExecuteSelect(
countQuery,
params.mapId,
"%" + params.searchString + "%",
"%" + params.searchString + "%",
"%" + params.searchString + "%",
params.playerSort
);
if (count->next()) {
result->totalEntriesMatchingQuery = count->getUInt("count");
}
}
while (properties->next()) {
auto& entry = result->entries.emplace_back();
entry.id = properties->getUInt64("id");
entry.ownerId = properties->getUInt64("owner_id");
entry.cloneId = properties->getUInt64("clone_id");
entry.name = properties->getString("name").c_str();
entry.description = properties->getString("description").c_str();
entry.privacyOption = properties->getInt("privacy_option");
entry.rejectionReason = properties->getString("rejection_reason").c_str();
entry.lastUpdatedTime = properties->getUInt("last_updated");
entry.claimedTime = properties->getUInt("time_claimed");
entry.reputation = properties->getUInt("reputation");
entry.modApproved = properties->getUInt("mod_approved");
entry.performanceCost = properties->getFloat("performance_cost");
}
return result;
}
std::optional<IProperty::Info> MySQLDatabase::GetPropertyInfo(const LWOMAPID mapId, const LWOCLONEID cloneId) { std::optional<IProperty::Info> MySQLDatabase::GetPropertyInfo(const LWOMAPID mapId, const LWOCLONEID cloneId) {
auto propertyEntry = ExecuteSelect( auto propertyEntry = ExecuteSelect(
"SELECT id, owner_id, clone_id, name, description, privacy_option, rejection_reason, last_updated, time_claimed, reputation, mod_approved " "SELECT id, owner_id, clone_id, name, description, privacy_option, rejection_reason, last_updated, time_claimed, reputation, mod_approved, performance_cost "
"FROM properties WHERE zone_id = ? AND clone_id = ?;", mapId, cloneId); "FROM properties WHERE zone_id = ? AND clone_id = ?;", mapId, cloneId);
if (!propertyEntry->next()) { if (!propertyEntry->next()) {
@ -21,6 +153,7 @@ std::optional<IProperty::Info> MySQLDatabase::GetPropertyInfo(const LWOMAPID map
toReturn.claimedTime = propertyEntry->getUInt("time_claimed"); toReturn.claimedTime = propertyEntry->getUInt("time_claimed");
toReturn.reputation = propertyEntry->getUInt("reputation"); toReturn.reputation = propertyEntry->getUInt("reputation");
toReturn.modApproved = propertyEntry->getUInt("mod_approved"); toReturn.modApproved = propertyEntry->getUInt("mod_approved");
toReturn.performanceCost = propertyEntry->getFloat("performance_cost");
return toReturn; return toReturn;
} }

View File

@ -25,7 +25,7 @@ public:
User& operator=(const User& other); User& operator=(const User& other);
bool operator==(const User& other) const; bool operator==(const User& other) const;
uint32_t GetAccountID() { return m_AccountID; } uint32_t GetAccountID() const { return m_AccountID; }
std::string& GetUsername() { return m_Username; } std::string& GetUsername() { return m_Username; }
std::string& GetSessionKey() { return m_SessionKey; } std::string& GetSessionKey() { return m_SessionKey; }
SystemAddress& GetSystemAddress() { return m_SystemAddress; } SystemAddress& GetSystemAddress() { return m_SystemAddress; }

View File

@ -14,6 +14,8 @@
#include "Amf3.h" #include "Amf3.h"
#include "eObjectBits.h" #include "eObjectBits.h"
#include "eGameMasterLevel.h" #include "eGameMasterLevel.h"
#include "ePropertySortType.h"
#include "User.h"
PropertyEntranceComponent::PropertyEntranceComponent(Entity* parent, uint32_t componentID) : Component(parent) { PropertyEntranceComponent::PropertyEntranceComponent(Entity* parent, uint32_t componentID) : Component(parent) {
this->propertyQueries = {}; this->propertyQueries = {};
@ -74,261 +76,103 @@ void PropertyEntranceComponent::OnEnterProperty(Entity* entity, uint32_t index,
launcher->Launch(entity, launcher->GetTargetZone(), cloneId); launcher->Launch(entity, launcher->GetTargetZone(), cloneId);
} }
PropertySelectQueryProperty PropertyEntranceComponent::SetPropertyValues(PropertySelectQueryProperty property, LWOCLONEID cloneId, std::string ownerName, std::string propertyName, std::string propertyDescription, float reputation, bool isBFF, bool isFriend, bool isModeratorApproved, bool isAlt, bool isOwned, uint32_t privacyOption, uint32_t timeLastUpdated, float performanceCost) {
property.CloneId = cloneId;
property.OwnerName = ownerName;
property.Name = propertyName;
property.Description = propertyDescription;
property.Reputation = reputation;
property.IsBestFriend = isBFF;
property.IsFriend = isFriend;
property.IsModeratorApproved = isModeratorApproved;
property.IsAlt = isAlt;
property.IsOwned = isOwned;
property.AccessType = privacyOption;
property.DateLastPublished = timeLastUpdated;
property.PerformanceCost = performanceCost;
return property;
}
std::string PropertyEntranceComponent::BuildQuery(Entity* entity, int32_t sortMethod, Character* character, std::string customQuery, bool wantLimits) {
std::string base;
if (customQuery == "") {
base = baseQueryForProperties;
} else {
base = customQuery;
}
std::string orderBy = "";
if (sortMethod == SORT_TYPE_FEATURED || sortMethod == SORT_TYPE_FRIENDS) {
std::string friendsList = " AND p.owner_id IN (";
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());
auto friendsListQueryResult = friendsListQuery->executeQuery();
while (friendsListQueryResult->next()) {
auto playerIDToConvert = friendsListQueryResult->getInt(1);
friendsList = friendsList + std::to_string(playerIDToConvert) + ",";
}
// Replace trailing comma with the closing parenthesis.
if (friendsList.at(friendsList.size() - 1) == ',') friendsList.erase(friendsList.size() - 1, 1);
friendsList += ") ";
// If we have no friends then use a -1 for the query.
if (friendsList.find("()") != std::string::npos) friendsList = " AND p.owner_id IN (-1) ";
orderBy += friendsList + "ORDER BY ci.name ASC ";
delete friendsListQueryResult;
friendsListQueryResult = nullptr;
delete friendsListQuery;
friendsListQuery = nullptr;
} else if (sortMethod == SORT_TYPE_RECENT) {
orderBy = "ORDER BY p.last_updated DESC ";
} else if (sortMethod == SORT_TYPE_REPUTATION) {
orderBy = "ORDER BY p.reputation DESC, p.last_updated DESC ";
} else {
orderBy = "ORDER BY p.last_updated DESC ";
}
return base + orderBy + (wantLimits ? "LIMIT ? OFFSET ?;" : ";");
}
void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool includeNullAddress, bool includeNullDescription, bool playerOwn, bool updateUi, int32_t numResults, int32_t lReputationTime, int32_t sortMethod, int32_t startIndex, std::string filterText, const SystemAddress& sysAddr) { void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool includeNullAddress, bool includeNullDescription, bool playerOwn, bool updateUi, int32_t numResults, int32_t lReputationTime, int32_t sortMethod, int32_t startIndex, std::string filterText, const SystemAddress& sysAddr) {
const auto* const character = entity->GetCharacter();
std::vector<PropertySelectQueryProperty> entries{};
PropertySelectQueryProperty playerEntry{};
auto character = entity->GetCharacter();
if (!character) return; if (!character) return;
const auto* const user = character->GetParentUser();
if (!user) return;
auto& entries = propertyQueries[entity->GetObjectID()];
entries.clear();
// Player property goes in index 1 of the vector. This is how the client expects it. // Player property goes in index 1 of the vector. This is how the client expects it.
auto playerPropertyLookup = Database::Get()->CreatePreppedStmt("SELECT * FROM properties WHERE owner_id = ? AND zone_id = ?"); const auto playerProperty = Database::Get()->GetPropertyInfo(m_MapID, character->GetPropertyCloneID());
playerPropertyLookup->setInt(1, character->GetID());
playerPropertyLookup->setInt(2, this->m_MapID);
auto playerPropertyLookupResults = playerPropertyLookup->executeQuery();
// If the player has a property this query will have a single result. // If the player has a property this query will have a single result.
if (playerPropertyLookupResults->next()) { auto& playerEntry = entries.emplace_back();
const auto cloneId = playerPropertyLookupResults->getUInt64(4); if (playerProperty.has_value()) {
const auto propertyName = std::string(playerPropertyLookupResults->getString(5).c_str()); playerEntry.OwnerName = character->GetName();
const auto propertyDescription = std::string(playerPropertyLookupResults->getString(6).c_str()); playerEntry.IsBestFriend = true;
const auto privacyOption = playerPropertyLookupResults->getInt(9); playerEntry.IsFriend = true;
const auto modApproved = playerPropertyLookupResults->getBoolean(10); playerEntry.IsAlt = true;
const auto dateLastUpdated = playerPropertyLookupResults->getInt64(11); playerEntry.IsOwned = true;
const auto reputation = playerPropertyLookupResults->getUInt(14); playerEntry.CloneId = playerProperty->cloneId;
const auto performanceCost = playerPropertyLookupResults->getFloat(16); playerEntry.Name = playerProperty->name;
playerEntry.Description = playerProperty->description;
playerEntry = SetPropertyValues(playerEntry, cloneId, character->GetName(), propertyName, propertyDescription, reputation, true, true, modApproved, true, true, privacyOption, dateLastUpdated, performanceCost); playerEntry.AccessType = playerProperty->privacyOption;
playerEntry.IsModeratorApproved = playerProperty->modApproved;
playerEntry.DateLastPublished = playerProperty->lastUpdatedTime;
playerEntry.Reputation = playerProperty->reputation;
playerEntry.PerformanceCost = playerProperty->performanceCost;
auto& entry = playerEntry;
} else { } else {
playerEntry = SetPropertyValues(playerEntry, character->GetPropertyCloneID(), character->GetName(), "", "", 0, true, true); playerEntry.OwnerName = character->GetName();
playerEntry.IsBestFriend = true;
playerEntry.IsFriend = true;
playerEntry.IsAlt = false;
playerEntry.IsOwned = false;
playerEntry.CloneId = character->GetPropertyCloneID();
playerEntry.Name = "";
playerEntry.Description = "";
playerEntry.AccessType = 0;
playerEntry.IsModeratorApproved = false;
playerEntry.DateLastPublished = 0;
playerEntry.Reputation = 0;
playerEntry.PerformanceCost = 0.0f;
} }
delete playerPropertyLookupResults; IProperty::PropertyLookup propertyLookup;
playerPropertyLookupResults = nullptr; propertyLookup.mapId = m_MapID;
propertyLookup.searchString = filterText;
propertyLookup.sortChoice = static_cast<ePropertySortType>(sortMethod);
propertyLookup.playerSort = static_cast<uint32_t>(sortMethod == SORT_TYPE_FEATURED || sortMethod == SORT_TYPE_FRIENDS ? PropertyPrivacyOption::Friends : PropertyPrivacyOption::Public);
propertyLookup.playerId = character->GetID();
propertyLookup.numResults = numResults;
propertyLookup.startIndex = startIndex;
delete playerPropertyLookup; const auto lookupResult = Database::Get()->GetProperties(propertyLookup);
playerPropertyLookup = nullptr;
entries.push_back(playerEntry);
const auto query = BuildQuery(entity, sortMethod, character);
auto propertyLookup = Database::Get()->CreatePreppedStmt(query);
const auto searchString = "%" + filterText + "%";
propertyLookup->setUInt(1, this->m_MapID);
propertyLookup->setString(2, searchString.c_str());
propertyLookup->setString(3, searchString.c_str());
propertyLookup->setString(4, searchString.c_str());
propertyLookup->setInt(5, sortMethod == SORT_TYPE_FEATURED || sortMethod == SORT_TYPE_FRIENDS ? static_cast<uint32_t>(PropertyPrivacyOption::Friends) : static_cast<uint32_t>(PropertyPrivacyOption::Public));
propertyLookup->setInt(6, numResults);
propertyLookup->setInt(7, startIndex);
auto propertyEntry = propertyLookup->executeQuery();
while (propertyEntry->next()) {
const auto propertyId = propertyEntry->getUInt64(1);
const auto owner = propertyEntry->getInt(2);
const auto cloneId = propertyEntry->getUInt64(4);
const auto propertyNameFromDb = std::string(propertyEntry->getString(5).c_str());
const auto propertyDescriptionFromDb = std::string(propertyEntry->getString(6).c_str());
const auto privacyOption = propertyEntry->getInt(9);
const auto modApproved = propertyEntry->getBoolean(10);
const auto dateLastUpdated = propertyEntry->getInt(11);
const float reputation = propertyEntry->getInt(14);
const auto performanceCost = propertyEntry->getFloat(16);
PropertySelectQueryProperty entry{};
std::string ownerName = "";
bool isOwned = true;
auto nameLookup = Database::Get()->CreatePreppedStmt("SELECT name FROM charinfo WHERE prop_clone_id = ?;");
nameLookup->setUInt64(1, cloneId);
auto nameResult = nameLookup->executeQuery();
if (!nameResult->next()) {
delete nameLookup;
nameLookup = nullptr;
LOG("Failed to find property owner name for %llu!", cloneId);
for (const auto& propertyEntry : lookupResult->entries) {
const auto owner = propertyEntry.ownerId;
const auto otherCharacter = Database::Get()->GetCharacterInfo(owner);
if (!otherCharacter.has_value()) {
LOG("Failed to find property owner name for %u!", owner);
continue; continue;
} else {
isOwned = cloneId == character->GetPropertyCloneID();
ownerName = std::string(nameResult->getString(1).c_str());
} }
auto& entry = entries.emplace_back();
delete nameResult; entry.IsOwned = entry.CloneId == otherCharacter->cloneId;
nameResult = nullptr; entry.OwnerName = otherCharacter->name;
entry.CloneId = propertyEntry.cloneId;
delete nameLookup; entry.Name = propertyEntry.name;
nameLookup = nullptr; entry.Description = propertyEntry.description;
entry.AccessType = propertyEntry.privacyOption;
std::string propertyName = propertyNameFromDb; entry.IsModeratorApproved = propertyEntry.modApproved;
std::string propertyDescription = propertyDescriptionFromDb; entry.DateLastPublished = propertyEntry.lastUpdatedTime;
entry.Reputation = propertyEntry.reputation;
bool isBestFriend = false; entry.PerformanceCost = propertyEntry.performanceCost;
bool isFriend = false; entry.IsBestFriend = false;
entry.IsFriend = false;
// Convert owner char id to LWOOBJID
LWOOBJID ownerObjId = owner;
GeneralUtils::SetBit(ownerObjId, eObjectBits::CHARACTER);
GeneralUtils::SetBit(ownerObjId, eObjectBits::PERSISTENT);
// Query to get friend and best friend fields // Query to get friend and best friend fields
auto friendCheck = Database::Get()->CreatePreppedStmt("SELECT best_friend FROM friends WHERE (player_id = ? AND friend_id = ?) OR (player_id = ? AND friend_id = ?)"); const auto friendCheck = Database::Get()->GetBestFriendStatus(character->GetID(), owner);
friendCheck->setUInt(1, character->GetID());
friendCheck->setUInt(2, ownerObjId);
friendCheck->setUInt(3, ownerObjId);
friendCheck->setUInt(4, character->GetID());
auto friendResult = friendCheck->executeQuery();
// If we got a result than the two players are friends. // If we got a result than the two players are friends.
if (friendResult->next()) { if (friendCheck.has_value()) {
isFriend = true; entry.IsFriend = true;
if (friendResult->getInt(1) == 3) { entry.IsBestFriend = friendCheck->bestFriendStatus == 3;
isBestFriend = true;
}
} }
delete friendCheck; if (!entry.IsModeratorApproved && entity->GetGMLevel() >= eGameMasterLevel::LEAD_MODERATOR) {
friendCheck = nullptr; entry.Name = "[AWAITING APPROVAL]";
entry.Description = "[AWAITING APPROVAL]";
delete friendResult; entry.IsModeratorApproved = true;
friendResult = nullptr;
bool isModeratorApproved = propertyEntry->getBoolean(10);
if (!isModeratorApproved && entity->GetGMLevel() >= eGameMasterLevel::LEAD_MODERATOR) {
propertyName = "[AWAITING APPROVAL]";
propertyDescription = "[AWAITING APPROVAL]";
isModeratorApproved = true;
} }
bool isAlt = false;
// Query to determine whether this property is an alt character of the entity. // Query to determine whether this property is an alt character of the entity.
auto isAltQuery = Database::Get()->CreatePreppedStmt("SELECT id FROM charinfo where account_id in (SELECT account_id from charinfo WHERE id = ?) AND id = ?;"); for (const auto charid : Database::Get()->GetAccountCharacterIds(user->GetAccountID())) {
entry.IsAlt = charid == owner;
isAltQuery->setInt(1, character->GetID()); if (entry.IsAlt) break;
isAltQuery->setInt(2, owner);
auto isAltQueryResults = isAltQuery->executeQuery();
if (isAltQueryResults->next()) {
isAlt = true;
} }
delete isAltQueryResults;
isAltQueryResults = nullptr;
delete isAltQuery;
isAltQuery = nullptr;
entry = SetPropertyValues(entry, cloneId, ownerName, propertyName, propertyDescription, reputation, isBestFriend, isFriend, isModeratorApproved, isAlt, isOwned, privacyOption, dateLastUpdated, performanceCost);
entries.push_back(entry);
} }
delete propertyEntry;
propertyEntry = nullptr;
delete propertyLookup;
propertyLookup = nullptr;
propertyQueries[entity->GetObjectID()] = entries;
// Query here is to figure out whether or not to display the button to go to the next page or not. // Query here is to figure out whether or not to display the button to go to the next page or not.
int32_t numberOfProperties = 0; GameMessages::SendPropertySelectQuery(m_Parent->GetObjectID(), startIndex, lookupResult->totalEntriesMatchingQuery - (startIndex + numResults) > 0, character->GetPropertyCloneID(), false, true, entries, sysAddr);
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::Get()->CreatePreppedStmt(buttonQuery);
propertiesLeft->setUInt(1, this->m_MapID);
propertiesLeft->setString(2, searchString.c_str());
propertiesLeft->setString(3, searchString.c_str());
propertiesLeft->setString(4, searchString.c_str());
propertiesLeft->setInt(5, sortMethod == SORT_TYPE_FEATURED || sortMethod == SORT_TYPE_FRIENDS ? 1 : 2);
auto result = propertiesLeft->executeQuery();
result->next();
numberOfProperties = result->getInt(1);
delete result;
result = nullptr;
delete propertiesLeft;
propertiesLeft = nullptr;
GameMessages::SendPropertySelectQuery(m_Parent->GetObjectID(), startIndex, numberOfProperties - (startIndex + numResults) > 0, character->GetPropertyCloneID(), false, true, entries, sysAddr);
} }

View File

@ -59,10 +59,6 @@ public:
*/ */
[[nodiscard]] LWOMAPID GetMapID() const { return m_MapID; }; [[nodiscard]] LWOMAPID GetMapID() const { return m_MapID; };
PropertySelectQueryProperty SetPropertyValues(PropertySelectQueryProperty property, LWOCLONEID cloneId = LWOCLONEID_INVALID, std::string ownerName = "", std::string propertyName = "", std::string propertyDescription = "", float reputation = 0, bool isBFF = false, bool isFriend = false, bool isModeratorApproved = false, bool isAlt = false, bool isOwned = false, uint32_t privacyOption = 0, uint32_t timeLastUpdated = 0, float performanceCost = 0.0f);
std::string BuildQuery(Entity* entity, int32_t sortMethod, Character* character, std::string customQuery = "", bool wantLimits = true);
private: private:
/** /**
* Cache of property information that was queried for property launched, indexed by property ID * Cache of property information that was queried for property launched, indexed by property ID
@ -78,13 +74,4 @@ private:
* The base map ID for this property (Avant Grove, etc). * The base map ID for this property (Avant Grove, etc).
*/ */
LWOMAPID m_MapID; LWOMAPID m_MapID;
enum ePropertySortType : int32_t {
SORT_TYPE_FRIENDS = 0,
SORT_TYPE_REPUTATION = 1,
SORT_TYPE_RECENT = 3,
SORT_TYPE_FEATURED = 5
};
std::string baseQueryForProperties = "SELECT p.* 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 >= ? ";
}; };

View File

@ -29,10 +29,10 @@ void PropertySelectQueryProperty::Serialize(RakNet::BitStream& stream) const {
stream.Write(IsOwned); stream.Write(IsOwned);
stream.Write(AccessType); stream.Write(AccessType);
stream.Write(DateLastPublished); stream.Write(DateLastPublished);
stream.Write(PerformanceIndex);
stream.Write(PerformanceCost); stream.Write(PerformanceCost);
} }
void PropertySelectQueryProperty::Deserialize(RakNet::BitStream& stream) const { void PropertySelectQueryProperty::Deserialize(RakNet::BitStream& stream) const {
// Do we need this? // Do we need this?
// no
} }

View File

@ -5,8 +5,7 @@
#include "Entity.h" #include "Entity.h"
class PropertySelectQueryProperty final class PropertySelectQueryProperty final {
{
public: public:
void Serialize(RakNet::BitStream& stream) const; void Serialize(RakNet::BitStream& stream) const;
@ -23,9 +22,8 @@ public:
bool IsAlt = false; // Whether or not the property is owned by an alt of the account owner bool IsAlt = false; // Whether or not the property is owned by an alt of the account owner
bool IsOwned = false; // Whether or not the property is owned bool IsOwned = false; // Whether or not the property is owned
uint32_t AccessType = 0; // The privacy option of the property uint32_t AccessType = 0; // The privacy option of the property
uint32_t DateLastPublished = 0; // The last day the property was published uint64_t DateLastPublished = 0; // The last day the property was published
float PerformanceCost = 0; // The performance cost of the property float PerformanceCost = 0; // The performance cost of the property
uint32_t PerformanceIndex = 0; // The performance index of the property? Always 0?
}; };
#endif #endif