From 0a7fd6f79ab57a224ae35710a8a4bbaac5e4eb98 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Sun, 27 Mar 2022 20:04:45 -0700 Subject: [PATCH 01/55] updates --- .../dComponents/PropertyEntranceComponent.cpp | 96 +++++++++++-------- dGame/dComponents/PropertyEntranceComponent.h | 7 ++ 2 files changed, 65 insertions(+), 38 deletions(-) diff --git a/dGame/dComponents/PropertyEntranceComponent.cpp b/dGame/dComponents/PropertyEntranceComponent.cpp index 9e286ffa..3736b6b8 100644 --- a/dGame/dComponents/PropertyEntranceComponent.cpp +++ b/dGame/dComponents/PropertyEntranceComponent.cpp @@ -7,6 +7,7 @@ #include "dLogger.h" #include "Database.h" #include "PropertyManagementComponent.h" +#include "UserManager.h" PropertyEntranceComponent::PropertyEntranceComponent(uint32_t componentID, Entity* parent) : Component(parent) { @@ -117,42 +118,40 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, sql::ResultSet* propertyEntry; sql::PreparedStatement* propertyLookup; + std::string orderBy = ""; + int32_t privacyType = 2; const auto moderating = entity->GetGMLevel() >= GAME_MASTER_LEVEL_LEAD_MODERATOR; - - if (!moderating) - { - propertyLookup = Database::CreatePreppedStmt( - "SELECT * FROM properties WHERE (name LIKE ? OR description LIKE ? OR " - "((SELECT name FROM charinfo WHERE prop_clone_id = clone_id) LIKE ?)) AND " - "(privacy_option = 2 AND mod_approved = true) OR (privacy_option >= 1 " - "AND (owner_id IN (SELECT friend_id FROM friends WHERE player_id = ?) OR owner_id IN (SELECT player_id FROM " - "friends WHERE friend_id = ?))) AND zone_id = ? LIMIT ? OFFSET ?;" - ); - - const std::string searchString = "%" + filterText + "%"; - Game::logger->Log("PropertyEntranceComponent", "%s\n", searchString.c_str()); - propertyLookup->setString(1, searchString.c_str()); - propertyLookup->setString(2, searchString.c_str()); - propertyLookup->setString(3, searchString.c_str()); - propertyLookup->setInt64(4, entity->GetObjectID()); - propertyLookup->setInt64(5, entity->GetObjectID()); - propertyLookup->setUInt(6, launchpadComponent->GetTargetZone()); - propertyLookup->setInt(7, numResults); - propertyLookup->setInt(8, startIndex); - - propertyEntry = propertyLookup->executeQuery(); + + // We change how we sort this query based on what the requested order is. + if (sortMethod == SORT_TYPE_FEATURED || sortMethod == SORT_TYPE_FRIENDS) { + orderBy = "ci.name"; + privacyType = 1; } - else - { - propertyLookup = Database::CreatePreppedStmt( - "SELECT * FROM properties WHERE privacy_option = 2 AND mod_approved = false AND zone_id = ?;" - ); - - propertyLookup->setUInt(1, launchpadComponent->GetTargetZone()); - - propertyEntry = propertyLookup->executeQuery(); + else if (sortMethod == SORT_TYPE_RECENT) { + orderBy = "p.last_updated"; } + else if (sortMethod == SORT_TYPE_REPUTATION) { + orderBy = "p.reputation, p.last_updated"; + } + else { + orderBy = "p.last_updated"; + } + + propertyLookup = Database::CreatePreppedStmt("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 OR p.name OR ci.name LIKE ?) AND p.mod_approved >= ? AND p.privacy_option = ? ORDER BY ? DESC LIMIT ? OFFSET ?;"); + + const std::string searchString = "%" + filterText + "%"; + Game::logger->Log("PropertyEntranceComponent", "%s\n", searchString.c_str()); + propertyLookup->setUInt(1, launchpadComponent->GetTargetZone()); + propertyLookup->setString(2, searchString.c_str()); + propertyLookup->setInt(3, entity->GetGMLevel() >= GAME_MASTER_LEVEL_LEAD_MODERATOR ? 0 : 1); + propertyLookup->setInt(4, privacyType); + propertyLookup->setString(5, orderBy); + propertyLookup->setInt(6, numResults); + propertyLookup->setInt(7, startIndex); + Game::logger->Log("PropertyEntranceComponent", "Querying target zone %i with search string %s and ordering by %s starting at index %i. Entity is %s.\n", launchpadComponent->GetTargetZone(), searchString.c_str(), orderBy.c_str(), startIndex, entity->GetGMLevel() >= GAME_MASTER_LEVEL_LEAD_MODERATOR ? "a moderator" : "not a moderator"); + + propertyEntry = propertyLookup->executeQuery(); while (propertyEntry->next()) { @@ -162,6 +161,7 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, const auto name = propertyEntry->getString(5).asStdString(); const auto description = propertyEntry->getString(6).asStdString(); const auto privacyOption = propertyEntry->getInt(9); + const auto modApproved = propertyEntry->getBoolean(10); const auto reputation = propertyEntry->getInt(15); PropertySelectQueryProperty entry {}; @@ -182,11 +182,11 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, } else { - entry.IsOwner = owner == entity->GetObjectID(); + entry.IsOwner = owner == entity->GetCharacter()->GetID(); entry.OwnerName = nameResult->getString(1).asStdString(); } - if (!moderating) + if (modApproved) { entry.Name = name; entry.Description = description; @@ -196,12 +196,32 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, entry.Name = "[Awaiting approval] " + name; entry.Description = "[Awaiting approval] " + description; } - - entry.IsFriend = privacyOption == static_cast(PropertyPrivacyOption::Friends); + // Convert owner char id to LWOOBJID + LWOOBJID ownerObjId = owner; + ownerObjId = GeneralUtils::SetBit(ownerObjId, OBJECT_BIT_CHARACTER); + ownerObjId = GeneralUtils::SetBit(ownerObjId, OBJECT_BIT_PERSISTENT); + + auto friendCheck = Database::CreatePreppedStmt("SELECT * FROM friends WHERE (player_id = ? AND friend_id = ?) OR (player_id = ? AND friend_id = ?)"); + + friendCheck->setInt64(1, entity->GetObjectID()); + friendCheck->setInt64(2, ownerObjId); + friendCheck->setInt64(3, ownerObjId); + friendCheck->setInt64(4, entity->GetObjectID()); + + auto friendResult = friendCheck->executeQuery(); + + // If we got a result than the two players are friends. + if (friendResult->next()) { + entry.IsFriend = true; + } + else { + entry.IsFriend = false; + } + entry.Reputation = reputation; entry.CloneId = cloneId; - entry.IsModeratorApproved = true; - entry.AccessType = 3; + entry.IsModeratorApproved = modApproved == true; + entry.AccessType = privacyOption; entries.push_back(entry); diff --git a/dGame/dComponents/PropertyEntranceComponent.h b/dGame/dComponents/PropertyEntranceComponent.h index 8e35fd91..0c043ed0 100644 --- a/dGame/dComponents/PropertyEntranceComponent.h +++ b/dGame/dComponents/PropertyEntranceComponent.h @@ -84,4 +84,11 @@ private: * The base map ID for this property (Avant Grove, etc). */ LWOMAPID m_MapID; + + enum ePropertySortType : int32_t { + SORT_TYPE_FRIENDS = 0, + SORT_TYPE_REPUTATION = 1, + SORT_TYPE_RECENT = 3, + SORT_TYPE_FEATURED = 5 + }; }; From 0a453e9dcae2a4d37fe4166325654d9594e08f26 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Sun, 27 Mar 2022 23:46:43 -0700 Subject: [PATCH 02/55] working state --- .../dComponents/PropertyEntranceComponent.cpp | 97 +++++++++++++++---- .../PropertySelectQueryProperty.cpp | 2 +- .../PropertySelectQueryProperty.h | 2 +- 3 files changed, 78 insertions(+), 23 deletions(-) diff --git a/dGame/dComponents/PropertyEntranceComponent.cpp b/dGame/dComponents/PropertyEntranceComponent.cpp index 3736b6b8..56317eb5 100644 --- a/dGame/dComponents/PropertyEntranceComponent.cpp +++ b/dGame/dComponents/PropertyEntranceComponent.cpp @@ -1,4 +1,5 @@ #include +#include #include "PropertyEntranceComponent.h" #include "PropertySelectQueryProperty.h" #include "RocketLaunchpadControlComponent.h" @@ -132,7 +133,7 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, orderBy = "p.last_updated"; } else if (sortMethod == SORT_TYPE_REPUTATION) { - orderBy = "p.reputation, p.last_updated"; + orderBy = "p.reputation DESC, p.last_updated"; } else { orderBy = "p.last_updated"; @@ -156,13 +157,13 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, while (propertyEntry->next()) { const auto propertyId = propertyEntry->getUInt64(1); - const auto owner = propertyEntry->getUInt64(2); + const auto owner = propertyEntry->getInt(2); const auto cloneId = propertyEntry->getUInt64(4); const auto name = propertyEntry->getString(5).asStdString(); const auto description = propertyEntry->getString(6).asStdString(); const auto privacyOption = propertyEntry->getInt(9); const auto modApproved = propertyEntry->getBoolean(10); - const auto reputation = propertyEntry->getInt(15); + const auto reputation = propertyEntry->getInt(14); PropertySelectQueryProperty entry {}; @@ -182,7 +183,7 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, } else { - entry.IsOwner = owner == entity->GetCharacter()->GetID(); + entry.IsOwned = owner == entity->GetCharacter()->GetID(); entry.OwnerName = nameResult->getString(1).asStdString(); } @@ -191,17 +192,13 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, entry.Name = name; entry.Description = description; } - else - { - entry.Name = "[Awaiting approval] " + name; - entry.Description = "[Awaiting approval] " + description; - } + // Convert owner char id to LWOOBJID LWOOBJID ownerObjId = owner; ownerObjId = GeneralUtils::SetBit(ownerObjId, OBJECT_BIT_CHARACTER); ownerObjId = GeneralUtils::SetBit(ownerObjId, OBJECT_BIT_PERSISTENT); - auto friendCheck = Database::CreatePreppedStmt("SELECT * FROM friends WHERE (player_id = ? AND friend_id = ?) OR (player_id = ? AND friend_id = ?)"); + auto friendCheck = Database::CreatePreppedStmt("SELECT best_friend FROM friends WHERE (player_id = ? AND friend_id = ?) OR (player_id = ? AND friend_id = ?)"); friendCheck->setInt64(1, entity->GetObjectID()); friendCheck->setInt64(2, ownerObjId); @@ -213,35 +210,93 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, // If we got a result than the two players are friends. if (friendResult->next()) { entry.IsFriend = true; + if (friendResult->getBoolean(1) == true) { + entry.IsBestFriend = true; + } else { + entry.IsBestFriend = false; + } } else { entry.IsFriend = false; + entry.IsBestFriend = false; } + // Game::logger->Log("FriendsQuery", "Friend OBJID %lu my OBJID %lu\n", ownerObjId, entity->GetObjectID()); + auto isAltQuery = Database::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); + + Game::logger->Log("PropertyEntranceComponent", "main character is %i with alt query being %i\n", character->GetID(), owner); + + auto isAltQueryResults = isAltQuery->executeQuery(); + + if (isAltQueryResults->next()) { + entry.IsAlt = true; + } else { + entry.IsAlt = false; + } + + delete isAltQuery; + isAltQuery = nullptr; + entry.Reputation = reputation; entry.CloneId = cloneId; entry.IsModeratorApproved = modApproved == true; entry.AccessType = privacyOption; entries.push_back(entry); - delete nameLookup; } delete propertyLookup; + Game::logger->Log("HELLO", "WE GOT TO HERE"); + // auto newpropertyLookup = Database::CreatePreppedStmt("SELECT * FROM properties WHERE owner_id = ? AND zone_id = ?"); - /* - const auto entriesSize = entries.size(); + // newpropertyLookup->setInt(1, character->GetID()); + // newpropertyLookup->setInt(2, launchpadComponent->GetTargetZone()); - if (startIndex != 0 && entriesSize > startIndex) - { - for (size_t i = 0; i < startIndex; i++) - { - entries.erase(entries.begin()); - } - } - */ + // auto results = propertyLookup->executeQuery(); + // PropertySelectQueryProperty entry {}; + + // entry.CloneId = character->GetPropertyCloneID(); + // entry.OwnerName = ""; + // entry.Name = ""; + // entry.Description = ""; + // entry.Reputation = 0; + // entry.IsBestFriend = true; + // entry.IsFriend = true; + // entry.IsModeratorApproved = false; + // entry.IsAlt = true; + // entry.IsOwned = false; + // entry.AccessType = 0; + // // entry.DatePublished = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); + // // entry.DatePublished = 0; + // // entry.PerformanceCost = entity->GetObjectID(); + + // if (results->next()) { + // const auto propertyId = results->getUInt64(1); + // const auto owner = results->getUInt64(2); + // const auto cloneId = results->getUInt64(4); + // const auto name = results->getString(5).asStdString(); + // const auto description = results->getString(6).asStdString(); + // const auto privacyOption = results->getInt(9); + // const auto modApproved = results->getBoolean(10); + // const auto reputation = results->getInt(14); + + // // entry.CloneId = cloneId; + // // entry.OwnerName = character->GetName(); + // // entry.Name = name; + // // entry.Description = description; + // // entry.Reputation = reputation; + // // entry.IsBestFriend = true; + // // entry.IsFriend = true; + // entry.IsModeratorApproved = modApproved; + // entry.IsAlt = true; + // entry.IsOwned = true; + // } + // entries.insert(entries.begin(), entry); propertyQueries[entity->GetObjectID()] = entries; GameMessages::SendPropertySelectQuery( diff --git a/dGame/dGameMessages/PropertySelectQueryProperty.cpp b/dGame/dGameMessages/PropertySelectQueryProperty.cpp index f32ce537..31a1699b 100644 --- a/dGame/dGameMessages/PropertySelectQueryProperty.cpp +++ b/dGame/dGameMessages/PropertySelectQueryProperty.cpp @@ -27,7 +27,7 @@ void PropertySelectQueryProperty::Serialize(RakNet::BitStream& stream) const stream.Write(IsFriend); stream.Write(IsModeratorApproved); stream.Write(IsAlt); - stream.Write(IsOwner); + stream.Write(IsOwned); stream.Write(AccessType); stream.Write(DatePublished); stream.Write(PerformanceCost); diff --git a/dGame/dGameMessages/PropertySelectQueryProperty.h b/dGame/dGameMessages/PropertySelectQueryProperty.h index 0aaab912..87efd4ca 100644 --- a/dGame/dGameMessages/PropertySelectQueryProperty.h +++ b/dGame/dGameMessages/PropertySelectQueryProperty.h @@ -18,7 +18,7 @@ public: bool IsFriend = false; bool IsModeratorApproved = false; bool IsAlt = false; - bool IsOwner = false; + bool IsOwned = false; uint32_t AccessType = 0; uint32_t DatePublished = 0; uint64_t PerformanceCost = 0; From 54de6c6878af501df9eb6e963486a8171b18118a Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Mon, 28 Mar 2022 03:24:49 -0700 Subject: [PATCH 03/55] FINALLY WORKING JESUS --- .../dComponents/PropertyEntranceComponent.cpp | 150 +++++++++--------- dGame/dComponents/PropertyEntranceComponent.h | 4 +- .../PropertySelectQueryProperty.cpp | 1 + .../PropertySelectQueryProperty.h | 2 +- 4 files changed, 83 insertions(+), 74 deletions(-) diff --git a/dGame/dComponents/PropertyEntranceComponent.cpp b/dGame/dComponents/PropertyEntranceComponent.cpp index 56317eb5..02bfd8c9 100644 --- a/dGame/dComponents/PropertyEntranceComponent.cpp +++ b/dGame/dComponents/PropertyEntranceComponent.cpp @@ -82,7 +82,7 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool playerOwn, bool updateUi, int32_t numResults, - int32_t reputation, + int32_t lReputationTime, int32_t sortMethod, int32_t startIndex, std::string filterText, @@ -94,7 +94,7 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, playerOwn, updateUi, numResults, - reputation, + lReputationTime, sortMethod, startIndex, filterText.c_str() @@ -106,15 +106,46 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, std::vector entries {}; PropertySelectQueryProperty playerEntry {}; - auto* character = entity->GetCharacter(); - playerEntry.OwnerName = character->GetName(); - playerEntry.Description = "No description."; - playerEntry.Name = "Your property!"; - playerEntry.IsModeratorApproved = true; - playerEntry.AccessType = 2; - playerEntry.CloneId = character->GetPropertyCloneID(); + auto newpropertyLookup = Database::CreatePreppedStmt("SELECT * FROM properties WHERE owner_id = ? AND zone_id = ?"); + + newpropertyLookup->setInt(1, character->GetID()); + newpropertyLookup->setInt(2, launchpadComponent->GetTargetZone()); + + auto results = newpropertyLookup->executeQuery(); + + playerEntry.CloneId = character->GetPropertyCloneID(); + playerEntry.OwnerName = ""; + playerEntry.Name = ""; + playerEntry.Description = ""; + playerEntry.Reputation = 0; + playerEntry.IsBestFriend = true; + playerEntry.IsFriend = true; + playerEntry.IsModeratorApproved = false; + playerEntry.IsAlt = true; + playerEntry.IsOwned = false; + playerEntry.AccessType = 0; + playerEntry.DatePublished = 0; + + if (results->next()) { + const auto propertyId = results->getUInt64(1); + const auto owner = results->getUInt64(2); + const auto cloneId = results->getUInt64(4); + const auto name = results->getString(5).asStdString(); + const auto description = results->getString(6).asStdString(); + const auto privacyOption = results->getInt(9); + const auto modApproved = results->getBoolean(10); + const auto dateUpdated = results->getInt64(11); + const auto reputation = results->getInt(14); + + playerEntry.Name = name; + playerEntry.Description = description; + playerEntry.DatePublished = dateUpdated; + playerEntry.IsModeratorApproved = modApproved; + playerEntry.IsAlt = true; + playerEntry.IsOwned = true; + } entries.push_back(playerEntry); sql::ResultSet* propertyEntry; @@ -124,32 +155,54 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, const auto moderating = entity->GetGMLevel() >= GAME_MASTER_LEVEL_LEAD_MODERATOR; + std::string baseQuery = "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.mod_approved >= ? AND p.privacy_option >= ? "; + + // In case the query is for friends. + std::string friendsList = " AND p.owner_id IN ("; // We change how we sort this query based on what the requested order is. if (sortMethod == SORT_TYPE_FEATURED || sortMethod == SORT_TYPE_FRIENDS) { - orderBy = "ci.name"; + 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 dlu.friends ) AS fr WHERE requested_player IS NOT NULL ORDER BY requested_player DESC;"); + + friendsListQuery->setInt64(1, entity->GetObjectID()); + friendsListQuery->setInt64(2, entity->GetObjectID()); + // friendsListQuery->setInt(3, numResults); + // friendsListQuery->setInt(4, startIndex); + + auto friendsListQueryResult = friendsListQuery->executeQuery(); + + while (friendsListQueryResult->next()) { + auto playerIDToConvert = friendsListQueryResult->getInt64(1); + playerIDToConvert = GeneralUtils::ClearBit(playerIDToConvert, OBJECT_BIT_CHARACTER); + playerIDToConvert = GeneralUtils::ClearBit(playerIDToConvert, OBJECT_BIT_PERSISTENT); + friendsList = friendsList + std::to_string(playerIDToConvert) + ","; + } + // Replace trailing comma with the closing parenthesis. + friendsList.replace(friendsList.size() - 1, 2, ") "); + orderBy = friendsList + "ORDER BY ci.name ASC "; privacyType = 1; } else if (sortMethod == SORT_TYPE_RECENT) { - orderBy = "p.last_updated"; + orderBy = "ORDER BY p.last_updated DESC "; } else if (sortMethod == SORT_TYPE_REPUTATION) { - orderBy = "p.reputation DESC, p.last_updated"; + orderBy = "ORDER BY p.reputation DESC, p.last_updated DESC "; } else { - orderBy = "p.last_updated"; + orderBy = "ORDER BY p.last_updated DESC "; } - - propertyLookup = Database::CreatePreppedStmt("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 OR p.name OR ci.name LIKE ?) AND p.mod_approved >= ? AND p.privacy_option = ? ORDER BY ? DESC LIMIT ? OFFSET ?;"); + auto finishedQuery = baseQuery + orderBy + "LIMIT ? OFFSET ?;"; + propertyLookup = Database::CreatePreppedStmt(finishedQuery); const std::string searchString = "%" + filterText + "%"; Game::logger->Log("PropertyEntranceComponent", "%s\n", searchString.c_str()); propertyLookup->setUInt(1, launchpadComponent->GetTargetZone()); propertyLookup->setString(2, searchString.c_str()); - propertyLookup->setInt(3, entity->GetGMLevel() >= GAME_MASTER_LEVEL_LEAD_MODERATOR ? 0 : 1); - propertyLookup->setInt(4, privacyType); - propertyLookup->setString(5, orderBy); - propertyLookup->setInt(6, numResults); - propertyLookup->setInt(7, startIndex); + propertyLookup->setString(3, searchString.c_str()); + propertyLookup->setString(4, searchString.c_str()); + propertyLookup->setInt(5, entity->GetGMLevel() >= GAME_MASTER_LEVEL_LEAD_MODERATOR || sortMethod == SORT_TYPE_FRIENDS ? 0 : 1); + propertyLookup->setInt(6, privacyType); + propertyLookup->setInt(7, numResults); + propertyLookup->setInt(8, startIndex); Game::logger->Log("PropertyEntranceComponent", "Querying target zone %i with search string %s and ordering by %s starting at index %i. Entity is %s.\n", launchpadComponent->GetTargetZone(), searchString.c_str(), orderBy.c_str(), startIndex, entity->GetGMLevel() >= GAME_MASTER_LEVEL_LEAD_MODERATOR ? "a moderator" : "not a moderator"); propertyEntry = propertyLookup->executeQuery(); @@ -163,7 +216,10 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, const auto description = propertyEntry->getString(6).asStdString(); const auto privacyOption = propertyEntry->getInt(9); const auto modApproved = propertyEntry->getBoolean(10); - const auto reputation = propertyEntry->getInt(14); + const auto dateUpdated = propertyEntry->getInt(11); + const auto reputation = propertyEntry->getUInt(14); + + Game::logger->Log("PropertyEntranceComponent", "Property being loaded is %i with reputation %lu\n", owner, reputation); PropertySelectQueryProperty entry {}; @@ -221,14 +277,11 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, entry.IsBestFriend = false; } - // Game::logger->Log("FriendsQuery", "Friend OBJID %lu my OBJID %lu\n", ownerObjId, entity->GetObjectID()); auto isAltQuery = Database::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); - Game::logger->Log("PropertyEntranceComponent", "main character is %i with alt query being %i\n", character->GetID(), owner); - auto isAltQueryResults = isAltQuery->executeQuery(); if (isAltQueryResults->next()) { @@ -239,64 +292,19 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, delete isAltQuery; isAltQuery = nullptr; - + entry.DatePublished = dateUpdated; entry.Reputation = reputation; entry.CloneId = cloneId; entry.IsModeratorApproved = modApproved == true; entry.AccessType = privacyOption; + entry.PerformanceCost = entity->GetObjectID(); entries.push_back(entry); delete nameLookup; } delete propertyLookup; - Game::logger->Log("HELLO", "WE GOT TO HERE"); - // auto newpropertyLookup = Database::CreatePreppedStmt("SELECT * FROM properties WHERE owner_id = ? AND zone_id = ?"); - // newpropertyLookup->setInt(1, character->GetID()); - // newpropertyLookup->setInt(2, launchpadComponent->GetTargetZone()); - - // auto results = propertyLookup->executeQuery(); - - // PropertySelectQueryProperty entry {}; - - // entry.CloneId = character->GetPropertyCloneID(); - // entry.OwnerName = ""; - // entry.Name = ""; - // entry.Description = ""; - // entry.Reputation = 0; - // entry.IsBestFriend = true; - // entry.IsFriend = true; - // entry.IsModeratorApproved = false; - // entry.IsAlt = true; - // entry.IsOwned = false; - // entry.AccessType = 0; - // // entry.DatePublished = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); - // // entry.DatePublished = 0; - // // entry.PerformanceCost = entity->GetObjectID(); - - // if (results->next()) { - // const auto propertyId = results->getUInt64(1); - // const auto owner = results->getUInt64(2); - // const auto cloneId = results->getUInt64(4); - // const auto name = results->getString(5).asStdString(); - // const auto description = results->getString(6).asStdString(); - // const auto privacyOption = results->getInt(9); - // const auto modApproved = results->getBoolean(10); - // const auto reputation = results->getInt(14); - - // // entry.CloneId = cloneId; - // // entry.OwnerName = character->GetName(); - // // entry.Name = name; - // // entry.Description = description; - // // entry.Reputation = reputation; - // // entry.IsBestFriend = true; - // // entry.IsFriend = true; - // entry.IsModeratorApproved = modApproved; - // entry.IsAlt = true; - // entry.IsOwned = true; - // } - // entries.insert(entries.begin(), entry); propertyQueries[entity->GetObjectID()] = entries; GameMessages::SendPropertySelectQuery( diff --git a/dGame/dComponents/PropertyEntranceComponent.h b/dGame/dComponents/PropertyEntranceComponent.h index 0c043ed0..dfc3f80a 100644 --- a/dGame/dComponents/PropertyEntranceComponent.h +++ b/dGame/dComponents/PropertyEntranceComponent.h @@ -38,7 +38,7 @@ public: * @param playerOwn only query properties owned by the entity * @param updateUi unused * @param numResults unused - * @param reputation unused + * @param lReputationTime unused * @param sortMethod unused * @param startIndex the minimum index to start the query off * @param filterText property names to search for @@ -50,7 +50,7 @@ public: bool playerOwn, bool updateUi, int32_t numResults, - int32_t reputation, + int32_t lReputationTime, int32_t sortMethod, int32_t startIndex, std::string filterText, diff --git a/dGame/dGameMessages/PropertySelectQueryProperty.cpp b/dGame/dGameMessages/PropertySelectQueryProperty.cpp index 31a1699b..135dac1f 100644 --- a/dGame/dGameMessages/PropertySelectQueryProperty.cpp +++ b/dGame/dGameMessages/PropertySelectQueryProperty.cpp @@ -1,4 +1,5 @@ #include "PropertySelectQueryProperty.h" +#include void PropertySelectQueryProperty::Serialize(RakNet::BitStream& stream) const { diff --git a/dGame/dGameMessages/PropertySelectQueryProperty.h b/dGame/dGameMessages/PropertySelectQueryProperty.h index 87efd4ca..68f95548 100644 --- a/dGame/dGameMessages/PropertySelectQueryProperty.h +++ b/dGame/dGameMessages/PropertySelectQueryProperty.h @@ -13,7 +13,7 @@ public: std::string OwnerName = ""; std::string Name = ""; std::string Description = ""; - uint32_t Reputation = 0; + uint32_t Reputation = 10; bool IsBestFriend = false; bool IsFriend = false; bool IsModeratorApproved = false; From c94f0918c9e8bd297adf9ea17bba8d7a47ca83f6 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Mon, 28 Mar 2022 03:26:01 -0700 Subject: [PATCH 04/55] testing number reverted --- dGame/dGameMessages/PropertySelectQueryProperty.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dGame/dGameMessages/PropertySelectQueryProperty.h b/dGame/dGameMessages/PropertySelectQueryProperty.h index 68f95548..87efd4ca 100644 --- a/dGame/dGameMessages/PropertySelectQueryProperty.h +++ b/dGame/dGameMessages/PropertySelectQueryProperty.h @@ -13,7 +13,7 @@ public: std::string OwnerName = ""; std::string Name = ""; std::string Description = ""; - uint32_t Reputation = 10; + uint32_t Reputation = 0; bool IsBestFriend = false; bool IsFriend = false; bool IsModeratorApproved = false; From 148c177d2721b5227a990b840589ee150e0c2b0e Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Mon, 28 Mar 2022 03:37:12 -0700 Subject: [PATCH 05/55] shortened method --- .../dComponents/PropertyEntranceComponent.cpp | 28 ++----------------- 1 file changed, 2 insertions(+), 26 deletions(-) diff --git a/dGame/dComponents/PropertyEntranceComponent.cpp b/dGame/dComponents/PropertyEntranceComponent.cpp index 02bfd8c9..28840dd0 100644 --- a/dGame/dComponents/PropertyEntranceComponent.cpp +++ b/dGame/dComponents/PropertyEntranceComponent.cpp @@ -76,33 +76,9 @@ void PropertyEntranceComponent::OnEnterProperty(Entity* entity, uint32_t index, launcher->Launch(entity, LWOOBJID_EMPTY, LWOMAPID_INVALID, cloneId); } -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) -{ - Game::logger->Log("PropertyEntranceComponent", "On Sync %d %d %d %d %i %i %i %i %s\n", - includeNullAddress, - includeNullDescription, - playerOwn, - updateUi, - numResults, - lReputationTime, - sortMethod, - startIndex, - filterText.c_str() - ); - +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){ auto* launchpadComponent = m_Parent->GetComponent(); - if (launchpadComponent == nullptr) - return; + if (launchpadComponent == nullptr) return; std::vector entries {}; PropertySelectQueryProperty playerEntry {}; From dc74b46e11f0abfc14db692f0177249b98302f05 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Mon, 28 Mar 2022 03:58:40 -0700 Subject: [PATCH 06/55] off by one moment --- dGame/dComponents/PropertyManagementComponent.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dGame/dComponents/PropertyManagementComponent.cpp b/dGame/dComponents/PropertyManagementComponent.cpp index 506c1608..cd99fd78 100644 --- a/dGame/dComponents/PropertyManagementComponent.cpp +++ b/dGame/dComponents/PropertyManagementComponent.cpp @@ -71,7 +71,7 @@ PropertyManagementComponent::PropertyManagementComponent(Entity* parent) : Compo this->propertyName = propertyEntry->getString(5).c_str(); this->propertyDescription = propertyEntry->getString(6).c_str(); this->privacyOption = static_cast(propertyEntry->getUInt(9)); - this->claimedTime = propertyEntry->getUInt64(13); + this->claimedTime = propertyEntry->getUInt64(12); Load(); } From 17f773c6cb693e79d02b8037638e5171cc7c9657 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Mon, 28 Mar 2022 04:25:44 -0700 Subject: [PATCH 07/55] comment --- dGame/dMission/Mission.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dGame/dMission/Mission.cpp b/dGame/dMission/Mission.cpp index 2719a6cf..f841f2f1 100644 --- a/dGame/dMission/Mission.cpp +++ b/dGame/dMission/Mission.cpp @@ -516,7 +516,7 @@ void Mission::YieldRewards() { } if (info->reward_reputation > 0) { - // TODO: Track reputation in the character and database. + // TODO: Track reputation in the property table and in charxml missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_EARN_REPUTATION, 0, 0L, "", info->reward_reputation); } From 895bbec277f9fd9d8e3ddf52fa8f8e81e50eb266 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Mon, 28 Mar 2022 19:58:15 -0700 Subject: [PATCH 08/55] clarified variable name --- dGame/dGameMessages/PropertySelectQueryProperty.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dGame/dGameMessages/PropertySelectQueryProperty.h b/dGame/dGameMessages/PropertySelectQueryProperty.h index 87efd4ca..b136f5cd 100644 --- a/dGame/dGameMessages/PropertySelectQueryProperty.h +++ b/dGame/dGameMessages/PropertySelectQueryProperty.h @@ -20,6 +20,6 @@ public: bool IsAlt = false; bool IsOwned = false; uint32_t AccessType = 0; - uint32_t DatePublished = 0; + uint32_t DateLastPublished = 0; uint64_t PerformanceCost = 0; }; From 17b0de80622f828dcd541d900d04b14487372c3d Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Mon, 28 Mar 2022 19:58:23 -0700 Subject: [PATCH 09/55] clarified variable name --- dGame/dGameMessages/PropertySelectQueryProperty.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dGame/dGameMessages/PropertySelectQueryProperty.cpp b/dGame/dGameMessages/PropertySelectQueryProperty.cpp index 135dac1f..78b7198d 100644 --- a/dGame/dGameMessages/PropertySelectQueryProperty.cpp +++ b/dGame/dGameMessages/PropertySelectQueryProperty.cpp @@ -30,7 +30,7 @@ void PropertySelectQueryProperty::Serialize(RakNet::BitStream& stream) const stream.Write(IsAlt); stream.Write(IsOwned); stream.Write(AccessType); - stream.Write(DatePublished); + stream.Write(DateLastPublished); stream.Write(PerformanceCost); } From 965d4c7af00568a04a684e5de4e94ed33df919ab Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Mon, 28 Mar 2022 19:58:50 -0700 Subject: [PATCH 10/55] cleaned up file and added helper functions --- .../dComponents/PropertyEntranceComponent.cpp | 165 +++++++++--------- dGame/dComponents/PropertyEntranceComponent.h | 34 ++-- 2 files changed, 98 insertions(+), 101 deletions(-) diff --git a/dGame/dComponents/PropertyEntranceComponent.cpp b/dGame/dComponents/PropertyEntranceComponent.cpp index 28840dd0..d2afd53c 100644 --- a/dGame/dComponents/PropertyEntranceComponent.cpp +++ b/dGame/dComponents/PropertyEntranceComponent.cpp @@ -1,5 +1,4 @@ #include -#include #include "PropertyEntranceComponent.h" #include "PropertySelectQueryProperty.h" #include "RocketLaunchpadControlComponent.h" @@ -51,6 +50,7 @@ void PropertyEntranceComponent::OnEnterProperty(Entity* entity, uint32_t index, } else if (index >= 0) { + // Increment index once here because the first index of other player properties is 2 in the propertyQueries cache. index++; const auto& pair = propertyQueries.find(entity->GetObjectID()); @@ -64,6 +64,8 @@ void PropertyEntranceComponent::OnEnterProperty(Entity* entity, uint32_t index, cloneId = query[index].CloneId; } + Game::logger->Log("PropertyEntranceComponent", "index is %i\n", index); + auto* launcher = m_Parent->GetComponent(); if (launcher == nullptr) @@ -73,76 +75,37 @@ void PropertyEntranceComponent::OnEnterProperty(Entity* entity, uint32_t index, launcher->SetSelectedCloneId(entity->GetObjectID(), cloneId); - launcher->Launch(entity, LWOOBJID_EMPTY, LWOMAPID_INVALID, cloneId); + launcher->Launch(entity, LWOOBJID_EMPTY, launcher->GetTargetZone(), cloneId); } -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){ - auto* launchpadComponent = m_Parent->GetComponent(); - if (launchpadComponent == nullptr) return; +PropertySelectQueryProperty PropertyEntranceComponent::SetPropertyValues(PropertySelectQueryProperty property, LWOCLONEID cloneId, std::string ownerName, std::string propertyName, std::string propertyDescription, + uint32_t reputation, bool isBFF, bool isFriend, bool isModeratorApproved, bool isAlt, bool isOwned, uint32_t privacyOption, uint32_t timeLastUpdated, uint64_t 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; - std::vector entries {}; - PropertySelectQueryProperty playerEntry {}; - auto* character = entity->GetCharacter(); + return property; +} - auto newpropertyLookup = Database::CreatePreppedStmt("SELECT * FROM properties WHERE owner_id = ? AND zone_id = ?"); - - newpropertyLookup->setInt(1, character->GetID()); - newpropertyLookup->setInt(2, launchpadComponent->GetTargetZone()); - - auto results = newpropertyLookup->executeQuery(); - - playerEntry.CloneId = character->GetPropertyCloneID(); - playerEntry.OwnerName = ""; - playerEntry.Name = ""; - playerEntry.Description = ""; - playerEntry.Reputation = 0; - playerEntry.IsBestFriend = true; - playerEntry.IsFriend = true; - playerEntry.IsModeratorApproved = false; - playerEntry.IsAlt = true; - playerEntry.IsOwned = false; - playerEntry.AccessType = 0; - playerEntry.DatePublished = 0; - - if (results->next()) { - const auto propertyId = results->getUInt64(1); - const auto owner = results->getUInt64(2); - const auto cloneId = results->getUInt64(4); - const auto name = results->getString(5).asStdString(); - const auto description = results->getString(6).asStdString(); - const auto privacyOption = results->getInt(9); - const auto modApproved = results->getBoolean(10); - const auto dateUpdated = results->getInt64(11); - const auto reputation = results->getInt(14); - - playerEntry.Name = name; - playerEntry.Description = description; - playerEntry.DatePublished = dateUpdated; - playerEntry.IsModeratorApproved = modApproved; - playerEntry.IsAlt = true; - playerEntry.IsOwned = true; - } - entries.push_back(playerEntry); - - sql::ResultSet* propertyEntry; - sql::PreparedStatement* propertyLookup; +std::string PropertyEntranceComponent::BuildQuery(Entity* entity, int32_t sortMethod) { + auto base = baseQueryForProperties; std::string orderBy = ""; - int32_t privacyType = 2; - - const auto moderating = entity->GetGMLevel() >= GAME_MASTER_LEVEL_LEAD_MODERATOR; - - std::string baseQuery = "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.mod_approved >= ? AND p.privacy_option >= ? "; - - // In case the query is for friends. std::string friendsList = " AND p.owner_id IN ("; - // We change how we sort this query based on what the requested order is. - if (sortMethod == SORT_TYPE_FEATURED || sortMethod == SORT_TYPE_FRIENDS) { + if (sortMethod == SORT_TYPE_FEATURED || sortMethod == SORT_TYPE_FRIENDS) { 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 dlu.friends ) AS fr WHERE requested_player IS NOT NULL ORDER BY requested_player DESC;"); friendsListQuery->setInt64(1, entity->GetObjectID()); friendsListQuery->setInt64(2, entity->GetObjectID()); - // friendsListQuery->setInt(3, numResults); - // friendsListQuery->setInt(4, startIndex); auto friendsListQueryResult = friendsListQuery->executeQuery(); @@ -155,7 +118,11 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl // Replace trailing comma with the closing parenthesis. friendsList.replace(friendsList.size() - 1, 2, ") "); orderBy = friendsList + "ORDER BY ci.name ASC "; - privacyType = 1; + + delete friendsListQueryResult; + friendsListQueryResult = nullptr; + delete friendsListQuery; + friendsListQuery = nullptr; } else if (sortMethod == SORT_TYPE_RECENT) { orderBy = "ORDER BY p.last_updated DESC "; @@ -166,20 +133,63 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl else { orderBy = "ORDER BY p.last_updated DESC "; } - auto finishedQuery = baseQuery + orderBy + "LIMIT ? OFFSET ?;"; - propertyLookup = Database::CreatePreppedStmt(finishedQuery); + return baseQueryForProperties + orderBy + "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){ + + std::vector entries {}; + PropertySelectQueryProperty playerEntry {}; + auto* character = entity->GetCharacter(); + 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 = ?"); + + 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 (playerPropertyLookupResults->next()) { + const auto cloneId = playerPropertyLookupResults->getUInt64(4); + const auto name = playerPropertyLookupResults->getString(5).asStdString(); + const auto description = playerPropertyLookupResults->getString(6).asStdString(); + const auto privacyOption = playerPropertyLookupResults->getInt(9); + const auto modApproved = playerPropertyLookupResults->getBoolean(10); + const auto dateLastUpdated = playerPropertyLookupResults->getInt64(11); + const auto reputation = playerPropertyLookupResults->getInt(14); + + playerEntry = SetPropertyValues(playerEntry, cloneId, character->GetName(), name, description, reputation, true, true, modApproved, true, true, privacyOption, dateLastUpdated); + } else { + playerEntry = SetPropertyValues(playerEntry, character->GetPropertyCloneID(), character->GetName(), "", "", 0, true, true); + } + + delete playerPropertyLookupResults; + playerPropertyLookupResults = nullptr; + delete playerPropertyLookup; + playerPropertyLookup = nullptr; + + entries.push_back(playerEntry); + + sql::ResultSet* propertyEntry; + sql::PreparedStatement* propertyLookup; + + const auto query = BuildQuery(entity, sortMethod); + + propertyLookup = Database::CreatePreppedStmt(query); const std::string searchString = "%" + filterText + "%"; - Game::logger->Log("PropertyEntranceComponent", "%s\n", searchString.c_str()); - propertyLookup->setUInt(1, launchpadComponent->GetTargetZone()); + 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, entity->GetGMLevel() >= GAME_MASTER_LEVEL_LEAD_MODERATOR || sortMethod == SORT_TYPE_FRIENDS ? 0 : 1); - propertyLookup->setInt(6, privacyType); + propertyLookup->setInt(6, sortMethod == SORT_TYPE_FEATURED || sortMethod == SORT_TYPE_FRIENDS ? 1 : 2); propertyLookup->setInt(7, numResults); propertyLookup->setInt(8, startIndex); - Game::logger->Log("PropertyEntranceComponent", "Querying target zone %i with search string %s and ordering by %s starting at index %i. Entity is %s.\n", launchpadComponent->GetTargetZone(), searchString.c_str(), orderBy.c_str(), startIndex, entity->GetGMLevel() >= GAME_MASTER_LEVEL_LEAD_MODERATOR ? "a moderator" : "not a moderator"); + + Game::logger->Log("PropertyEntranceComponent", "Property query is \n%s\n. Entity is %s.\n", query.c_str(), entity->GetGMLevel() >= GAME_MASTER_LEVEL_LEAD_MODERATOR ? "a moderator" : "not a moderator"); propertyEntry = propertyLookup->executeQuery(); @@ -195,8 +205,6 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl const auto dateUpdated = propertyEntry->getInt(11); const auto reputation = propertyEntry->getUInt(14); - Game::logger->Log("PropertyEntranceComponent", "Property being loaded is %i with reputation %lu\n", owner, reputation); - PropertySelectQueryProperty entry {}; auto* nameLookup = Database::CreatePreppedStmt("SELECT name FROM charinfo WHERE prop_clone_id = ?;"); @@ -268,12 +276,14 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl delete isAltQuery; isAltQuery = nullptr; - entry.DatePublished = dateUpdated; + entry.DateLastPublished = dateUpdated; + // Reputation not updated client side for listing? entry.Reputation = reputation; entry.CloneId = cloneId; entry.IsModeratorApproved = modApproved == true; entry.AccessType = privacyOption; - entry.PerformanceCost = entity->GetObjectID(); + // Client still reads performance cost as zero? + entry.PerformanceCost = 0; entries.push_back(entry); delete nameLookup; @@ -283,14 +293,5 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl propertyQueries[entity->GetObjectID()] = entries; - GameMessages::SendPropertySelectQuery( - m_Parent->GetObjectID(), - startIndex, - entries.size() >= numResults, - character->GetPropertyCloneID(), - false, - true, - entries, - sysAddr - ); + GameMessages::SendPropertySelectQuery(m_Parent->GetObjectID(), startIndex, entries.size() >= numResults, character->GetPropertyCloneID(), false, true, entries, sysAddr); } \ No newline at end of file diff --git a/dGame/dComponents/PropertyEntranceComponent.h b/dGame/dComponents/PropertyEntranceComponent.h index dfc3f80a..1cfb98dc 100644 --- a/dGame/dComponents/PropertyEntranceComponent.h +++ b/dGame/dComponents/PropertyEntranceComponent.h @@ -1,17 +1,17 @@ #pragma once +#include + +#include "Component.h" #include "Entity.h" #include "EntityManager.h" #include "GameMessages.h" -#include "Component.h" -#include /** * Represents the launch pad that's used to select and browse properties */ -class PropertyEntranceComponent : public Component -{ -public: +class PropertyEntranceComponent : public Component { + public: static const uint32_t ComponentType = COMPONENT_TYPE_PROPERTY_ENTRANCE; explicit PropertyEntranceComponent(uint32_t componentID, Entity* parent); @@ -24,11 +24,11 @@ public: /** * Handles the event triggered when the entity selects a property to visit and makes the entity to there * @param entity the entity that triggered the event - * @param index the clone ID of the property to visit + * @param index the index of the property property * @param returnToZone whether or not the entity wishes to go back to the launch zone * @param sysAddr the address to send gamemessage responses to */ - void OnEnterProperty(Entity* entity, uint32_t index, bool returnToZone, const SystemAddress &sysAddr); + void OnEnterProperty(Entity* entity, uint32_t index, bool returnToZone, const SystemAddress& sysAddr); /** * Handles a request for information on available properties when an entity lands on the property @@ -44,17 +44,7 @@ public: * @param filterText property names to search for * @param sysAddr the address to send gamemessage responses to */ - void 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 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); /** * Returns the name of this property @@ -68,8 +58,12 @@ public: */ [[nodiscard]] LWOMAPID GetMapID() const { return m_MapID; }; -private: + PropertySelectQueryProperty SetPropertyValues(PropertySelectQueryProperty property, LWOCLONEID cloneId = LWOCLONEID_INVALID, std::string ownerName = "", std::string propertyName = "", std::string propertyDescription = "", + uint32_t 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, uint64_t performanceCost = 0); + std::string BuildQuery(Entity* entity, int32_t sortMethod); + + private: /** * Cache of property information that was queried for property launched, indexed by property ID */ @@ -91,4 +85,6 @@ private: SORT_TYPE_RECENT = 3, SORT_TYPE_FEATURED = 5 }; + + const 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.mod_approved >= ? AND p.privacy_option >= ? "; }; From 19e82a5150ed57ece1fca0d1778af5064e28a3ca Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Mon, 28 Mar 2022 20:51:15 -0700 Subject: [PATCH 11/55] more cleanup --- .../dComponents/PropertyEntranceComponent.cpp | 106 +++++++++++------- 1 file changed, 63 insertions(+), 43 deletions(-) diff --git a/dGame/dComponents/PropertyEntranceComponent.cpp b/dGame/dComponents/PropertyEntranceComponent.cpp index d2afd53c..fb13d622 100644 --- a/dGame/dComponents/PropertyEntranceComponent.cpp +++ b/dGame/dComponents/PropertyEntranceComponent.cpp @@ -84,6 +84,7 @@ PropertySelectQueryProperty PropertyEntranceComponent::SetPropertyValues(Propert property.OwnerName = ownerName; property.Name = propertyName; property.Description = propertyDescription; + // Reputation not updated for client side listing? property.Reputation = reputation; property.IsBestFriend = isBFF; property.IsFriend = isFriend; @@ -140,8 +141,10 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl std::vector entries {}; PropertySelectQueryProperty playerEntry {}; - auto* character = entity->GetCharacter(); + + auto character = entity->GetCharacter(); 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 = ?"); @@ -167,19 +170,17 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl delete playerPropertyLookupResults; playerPropertyLookupResults = nullptr; + delete playerPropertyLookup; playerPropertyLookup = nullptr; entries.push_back(playerEntry); - sql::ResultSet* propertyEntry; - sql::PreparedStatement* propertyLookup; - const auto query = BuildQuery(entity, sortMethod); - propertyLookup = Database::CreatePreppedStmt(query); + auto propertyLookup = Database::CreatePreppedStmt(query); - const std::string searchString = "%" + filterText + "%"; + const auto searchString = "%" + filterText + "%"; propertyLookup->setUInt(1, this->m_MapID); propertyLookup->setString(2, searchString.c_str()); propertyLookup->setString(3, searchString.c_str()); @@ -191,7 +192,7 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl Game::logger->Log("PropertyEntranceComponent", "Property query is \n%s\n. Entity is %s.\n", query.c_str(), entity->GetGMLevel() >= GAME_MASTER_LEVEL_LEAD_MODERATOR ? "a moderator" : "not a moderator"); - propertyEntry = propertyLookup->executeQuery(); + auto propertyEntry = propertyLookup->executeQuery(); while (propertyEntry->next()) { @@ -202,42 +203,52 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl const auto description = propertyEntry->getString(6).asStdString(); const auto privacyOption = propertyEntry->getInt(9); const auto modApproved = propertyEntry->getBoolean(10); - const auto dateUpdated = propertyEntry->getInt(11); - const auto reputation = propertyEntry->getUInt(14); + const auto dateLastUpdated = propertyEntry->getInt(11); + const auto reputation = propertyEntry->getUInt(14); PropertySelectQueryProperty entry {}; - - auto* nameLookup = Database::CreatePreppedStmt("SELECT name FROM charinfo WHERE prop_clone_id = ?;"); + + std::string ownerName = ""; + bool isOwned = true; + auto nameLookup = Database::CreatePreppedStmt("SELECT name FROM charinfo WHERE prop_clone_id = ?;"); nameLookup->setUInt64(1, cloneId); - auto* nameResult = nameLookup->executeQuery(); + auto nameResult = nameLookup->executeQuery(); - if (!nameResult->next()) - { + if (!nameResult->next()) { delete nameLookup; + nameLookup = nullptr; Game::logger->Log("PropertyEntranceComponent", "Failed to find property owner name for %llu!\n", cloneId); continue; } - else - { - entry.IsOwned = owner == entity->GetCharacter()->GetID(); - entry.OwnerName = nameResult->getString(1).asStdString(); - } - - if (modApproved) - { - entry.Name = name; - entry.Description = description; + else { + isOwned = cloneId == character->GetPropertyCloneID(); + ownerName = nameResult->getString(1).asStdString(); } + delete nameResult; + nameResult = nullptr; + + delete nameLookup; + nameLookup = nullptr; + + std::string propertyName = ""; + std::string propertyDescription = ""; + propertyName = name; + propertyDescription = description; + + bool isBestFriend = false; + bool isFriend = false; + // Convert owner char id to LWOOBJID LWOOBJID ownerObjId = owner; ownerObjId = GeneralUtils::SetBit(ownerObjId, OBJECT_BIT_CHARACTER); ownerObjId = GeneralUtils::SetBit(ownerObjId, OBJECT_BIT_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 = ?)"); friendCheck->setInt64(1, entity->GetObjectID()); @@ -249,18 +260,29 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl // If we got a result than the two players are friends. if (friendResult->next()) { - entry.IsFriend = true; + isFriend = true; if (friendResult->getBoolean(1) == true) { - entry.IsBestFriend = true; - } else { - entry.IsBestFriend = false; + isBestFriend = true; } } - else { - entry.IsFriend = false; - entry.IsBestFriend = false; + + delete friendCheck; + friendCheck = nullptr; + + delete friendResult; + friendResult = nullptr; + + bool isModeratorApproved = propertyEntry->getBoolean(10); + + if (!isModeratorApproved && entity->GetGMLevel() >= GAME_MASTER_LEVEL_LEAD_MODERATOR) { + ownerName = "[AWAITING APPROVAL]"; + propertyName = "[AWAITING APPROVAL]"; + propertyDescription = "[AWAITING APPROVAL]"; + entry.IsModeratorApproved = true; } + bool isAlt = false; + // Query to determine whether this property is an alt of the entity. auto isAltQuery = Database::CreatePreppedStmt("SELECT id FROM charinfo where account_id in (SELECT account_id from charinfo WHERE id = ?) AND id = ?;"); isAltQuery->setInt(1, character->GetID()); @@ -269,27 +291,25 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl auto isAltQueryResults = isAltQuery->executeQuery(); if (isAltQueryResults->next()) { - entry.IsAlt = true; - } else { - entry.IsAlt = false; + isAlt = true; } + delete isAltQueryResults; + isAltQueryResults = nullptr; + delete isAltQuery; isAltQuery = nullptr; - entry.DateLastPublished = dateUpdated; - // Reputation not updated client side for listing? - entry.Reputation = reputation; - entry.CloneId = cloneId; - entry.IsModeratorApproved = modApproved == true; - entry.AccessType = privacyOption; - // Client still reads performance cost as zero? - entry.PerformanceCost = 0; + + entry = SetPropertyValues(entry, cloneId, ownerName, propertyName, propertyDescription, reputation, isBestFriend, isFriend, isModeratorApproved, isAlt, isOwned, privacyOption, dateLastUpdated); entries.push_back(entry); - delete nameLookup; } + delete propertyEntry; + propertyEntry = nullptr; + delete propertyLookup; + propertyLookup = nullptr; propertyQueries[entity->GetObjectID()] = entries; From 69ec1216dc999564df7bbc027eb8186cf64b1dd8 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Mon, 28 Mar 2022 20:51:19 -0700 Subject: [PATCH 12/55] added comments --- .../PropertySelectQueryProperty.h | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/dGame/dGameMessages/PropertySelectQueryProperty.h b/dGame/dGameMessages/PropertySelectQueryProperty.h index b136f5cd..f8042bbf 100644 --- a/dGame/dGameMessages/PropertySelectQueryProperty.h +++ b/dGame/dGameMessages/PropertySelectQueryProperty.h @@ -9,17 +9,17 @@ public: void Deserialize(RakNet::BitStream& stream) const; - LWOCLONEID CloneId = LWOCLONEID_INVALID; - std::string OwnerName = ""; - std::string Name = ""; - std::string Description = ""; - uint32_t Reputation = 0; - bool IsBestFriend = false; - bool IsFriend = false; - bool IsModeratorApproved = false; - bool IsAlt = false; - bool IsOwned = false; - uint32_t AccessType = 0; - uint32_t DateLastPublished = 0; - uint64_t PerformanceCost = 0; + LWOCLONEID CloneId = LWOCLONEID_INVALID; // The cloneID of the property + std::string OwnerName = ""; // The property owners name + std::string Name = ""; // The property name + std::string Description = ""; // The property description + uint32_t Reputation = 0; // The reputation of the property + bool IsBestFriend = false; // Whether or not the property belongs to a best friend + bool IsFriend = false; // Whether or not the property belongs to a friend + bool IsModeratorApproved = false; // Whether or not a moderator has approved this property + 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 + uint32_t AccessType = 0; // The privacy option of the property + uint32_t DateLastPublished = 0; // The last day the property was published + uint64_t PerformanceCost = 0; // The performance cost of the property }; From 35e576a8398e110f7de86d99d55ab0a524bceff8 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Mon, 28 Mar 2022 20:53:09 -0700 Subject: [PATCH 13/55] fixed moderator issue --- dGame/dComponents/PropertyEntranceComponent.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dGame/dComponents/PropertyEntranceComponent.cpp b/dGame/dComponents/PropertyEntranceComponent.cpp index fb13d622..80c31d4a 100644 --- a/dGame/dComponents/PropertyEntranceComponent.cpp +++ b/dGame/dComponents/PropertyEntranceComponent.cpp @@ -278,7 +278,7 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl ownerName = "[AWAITING APPROVAL]"; propertyName = "[AWAITING APPROVAL]"; propertyDescription = "[AWAITING APPROVAL]"; - entry.IsModeratorApproved = true; + isModeratorApproved = true; } bool isAlt = false; From b0d499334428e88871b5ace22442069ba8bb993c Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Mon, 28 Mar 2022 21:02:46 -0700 Subject: [PATCH 14/55] owner name change --- dGame/dComponents/PropertyEntranceComponent.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/dGame/dComponents/PropertyEntranceComponent.cpp b/dGame/dComponents/PropertyEntranceComponent.cpp index 80c31d4a..504f2dc3 100644 --- a/dGame/dComponents/PropertyEntranceComponent.cpp +++ b/dGame/dComponents/PropertyEntranceComponent.cpp @@ -275,7 +275,6 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl bool isModeratorApproved = propertyEntry->getBoolean(10); if (!isModeratorApproved && entity->GetGMLevel() >= GAME_MASTER_LEVEL_LEAD_MODERATOR) { - ownerName = "[AWAITING APPROVAL]"; propertyName = "[AWAITING APPROVAL]"; propertyDescription = "[AWAITING APPROVAL]"; isModeratorApproved = true; From 0c41026df020d3065bcb96d01a64f564fab78da0 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Tue, 29 Mar 2022 01:00:30 -0700 Subject: [PATCH 15/55] Fixed friendless crash --- dGame/dComponents/PropertyEntranceComponent.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/dGame/dComponents/PropertyEntranceComponent.cpp b/dGame/dComponents/PropertyEntranceComponent.cpp index 504f2dc3..fbbdb896 100644 --- a/dGame/dComponents/PropertyEntranceComponent.cpp +++ b/dGame/dComponents/PropertyEntranceComponent.cpp @@ -117,8 +117,14 @@ std::string PropertyEntranceComponent::BuildQuery(Entity* entity, int32_t sortMe friendsList = friendsList + std::to_string(playerIDToConvert) + ","; } // Replace trailing comma with the closing parenthesis. - friendsList.replace(friendsList.size() - 1, 2, ") "); - orderBy = friendsList + "ORDER BY ci.name ASC "; + if (friendsList.at(friendsList.size() - 1) == ',') friendsList.erase(friendsList.size() - 1, 1); + friendsList += ") "; + if (friendsList.find("()") == std::string::npos) { + orderBy = friendsList; + } else { + friendsList = " AND p.owner_id IN (-1) "; + } + orderBy += friendsList + "ORDER BY ci.name ASC "; delete friendsListQueryResult; friendsListQueryResult = nullptr; From 7b536ee079185ebf02b708ccf76c0340770e922e Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Tue, 29 Mar 2022 01:57:23 -0700 Subject: [PATCH 16/55] Best friends is 2 not 1 --- dGame/dComponents/PropertyEntranceComponent.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dGame/dComponents/PropertyEntranceComponent.cpp b/dGame/dComponents/PropertyEntranceComponent.cpp index fbbdb896..5ee832fd 100644 --- a/dGame/dComponents/PropertyEntranceComponent.cpp +++ b/dGame/dComponents/PropertyEntranceComponent.cpp @@ -267,7 +267,7 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl // If we got a result than the two players are friends. if (friendResult->next()) { isFriend = true; - if (friendResult->getBoolean(1) == true) { + if (friendResult->getInt(1) == 2) { isBestFriend = true; } } From 9385c337299731a87764473010e40468b2d52718 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Tue, 29 Mar 2022 02:33:15 -0700 Subject: [PATCH 17/55] grammar and new line --- dGame/dComponents/PropertyEntranceComponent.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dGame/dComponents/PropertyEntranceComponent.cpp b/dGame/dComponents/PropertyEntranceComponent.cpp index 5ee832fd..4065c3fc 100644 --- a/dGame/dComponents/PropertyEntranceComponent.cpp +++ b/dGame/dComponents/PropertyEntranceComponent.cpp @@ -119,6 +119,8 @@ std::string PropertyEntranceComponent::BuildQuery(Entity* entity, int32_t sortMe // 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) { orderBy = friendsList; } else { @@ -128,6 +130,7 @@ std::string PropertyEntranceComponent::BuildQuery(Entity* entity, int32_t sortMe delete friendsListQueryResult; friendsListQueryResult = nullptr; + delete friendsListQuery; friendsListQuery = nullptr; } From ec9749ab852f1a7f24e7c946c184be0cd83249a8 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Tue, 29 Mar 2022 03:50:41 -0700 Subject: [PATCH 18/55] flag for are more being worked on --- .../dComponents/PropertyEntranceComponent.cpp | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/dGame/dComponents/PropertyEntranceComponent.cpp b/dGame/dComponents/PropertyEntranceComponent.cpp index 4065c3fc..b3b78754 100644 --- a/dGame/dComponents/PropertyEntranceComponent.cpp +++ b/dGame/dComponents/PropertyEntranceComponent.cpp @@ -321,5 +321,24 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl propertyQueries[entity->GetObjectID()] = entries; - GameMessages::SendPropertySelectQuery(m_Parent->GetObjectID(), startIndex, entries.size() >= numResults, character->GetPropertyCloneID(), false, true, entries, sysAddr); + auto propertiesLeft = Database::CreatePreppedStmt("SELECT COUNT(*) FROM properties WHERE zone_id = ?;"); + + propertiesLeft->setInt(1, this->m_MapID); + + auto result = propertiesLeft->executeQuery(); + result->next(); + auto numberOfProperties = result->getInt(1); + + delete result; + result = nullptr; + + delete propertiesLeft; + propertiesLeft = nullptr; + + auto forFriends = query; + forFriends.replace(7, 3, "COUNT(*)"); + // if sort method is friends or featured do above query. + // do same maths below with resulting query + // else use default count. + GameMessages::SendPropertySelectQuery(m_Parent->GetObjectID(), startIndex, numberOfProperties - (startIndex + numResults) > 0, character->GetPropertyCloneID(), false, true, entries, sysAddr); } \ No newline at end of file From 82ebdccdb2f0019dbfc6955125d21be0ccea4bec Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Tue, 29 Mar 2022 14:54:31 -0700 Subject: [PATCH 19/55] Reputation is sent as a float not an int --- dGame/dComponents/PropertyEntranceComponent.cpp | 6 +++--- dGame/dComponents/PropertyEntranceComponent.h | 2 +- dGame/dGameMessages/PropertySelectQueryProperty.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/dGame/dComponents/PropertyEntranceComponent.cpp b/dGame/dComponents/PropertyEntranceComponent.cpp index b3b78754..4296dee4 100644 --- a/dGame/dComponents/PropertyEntranceComponent.cpp +++ b/dGame/dComponents/PropertyEntranceComponent.cpp @@ -79,7 +79,7 @@ void PropertyEntranceComponent::OnEnterProperty(Entity* entity, uint32_t index, } PropertySelectQueryProperty PropertyEntranceComponent::SetPropertyValues(PropertySelectQueryProperty property, LWOCLONEID cloneId, std::string ownerName, std::string propertyName, std::string propertyDescription, - uint32_t reputation, bool isBFF, bool isFriend, bool isModeratorApproved, bool isAlt, bool isOwned, uint32_t privacyOption, uint32_t timeLastUpdated, uint64_t performanceCost) { + float reputation, bool isBFF, bool isFriend, bool isModeratorApproved, bool isAlt, bool isOwned, uint32_t privacyOption, uint32_t timeLastUpdated, uint64_t performanceCost) { property.CloneId = cloneId; property.OwnerName = ownerName; property.Name = propertyName; @@ -170,7 +170,7 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl const auto privacyOption = playerPropertyLookupResults->getInt(9); const auto modApproved = playerPropertyLookupResults->getBoolean(10); const auto dateLastUpdated = playerPropertyLookupResults->getInt64(11); - const auto reputation = playerPropertyLookupResults->getInt(14); + const auto reputation = playerPropertyLookupResults->getUInt(14); playerEntry = SetPropertyValues(playerEntry, cloneId, character->GetName(), name, description, reputation, true, true, modApproved, true, true, privacyOption, dateLastUpdated); } else { @@ -213,7 +213,7 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl const auto privacyOption = propertyEntry->getInt(9); const auto modApproved = propertyEntry->getBoolean(10); const auto dateLastUpdated = propertyEntry->getInt(11); - const auto reputation = propertyEntry->getUInt(14); + const float reputation = propertyEntry->getInt(14); PropertySelectQueryProperty entry {}; diff --git a/dGame/dComponents/PropertyEntranceComponent.h b/dGame/dComponents/PropertyEntranceComponent.h index 1cfb98dc..4ba7a74f 100644 --- a/dGame/dComponents/PropertyEntranceComponent.h +++ b/dGame/dComponents/PropertyEntranceComponent.h @@ -59,7 +59,7 @@ class PropertyEntranceComponent : public Component { [[nodiscard]] LWOMAPID GetMapID() const { return m_MapID; }; PropertySelectQueryProperty SetPropertyValues(PropertySelectQueryProperty property, LWOCLONEID cloneId = LWOCLONEID_INVALID, std::string ownerName = "", std::string propertyName = "", std::string propertyDescription = "", - uint32_t 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, uint64_t performanceCost = 0); + 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, uint64_t performanceCost = 0); std::string BuildQuery(Entity* entity, int32_t sortMethod); diff --git a/dGame/dGameMessages/PropertySelectQueryProperty.h b/dGame/dGameMessages/PropertySelectQueryProperty.h index f8042bbf..f451ae31 100644 --- a/dGame/dGameMessages/PropertySelectQueryProperty.h +++ b/dGame/dGameMessages/PropertySelectQueryProperty.h @@ -13,7 +13,7 @@ public: std::string OwnerName = ""; // The property owners name std::string Name = ""; // The property name std::string Description = ""; // The property description - uint32_t Reputation = 0; // The reputation of the property + float Reputation = 0; // The reputation of the property bool IsBestFriend = false; // Whether or not the property belongs to a best friend bool IsFriend = false; // Whether or not the property belongs to a friend bool IsModeratorApproved = false; // Whether or not a moderator has approved this property From e79d4e66f385f84ff02accc28f6f1a5927ceae31 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Tue, 29 Mar 2022 19:46:38 -0700 Subject: [PATCH 20/55] add performance cost column --- migrations/dlu/3_add_performance_cost.sql | 1 + 1 file changed, 1 insertion(+) create mode 100644 migrations/dlu/3_add_performance_cost.sql diff --git a/migrations/dlu/3_add_performance_cost.sql b/migrations/dlu/3_add_performance_cost.sql new file mode 100644 index 00000000..8d9bc6e9 --- /dev/null +++ b/migrations/dlu/3_add_performance_cost.sql @@ -0,0 +1 @@ +ALTER TABLE properties ADD COLUMN performance_cost DOUBLE(20, 15); \ No newline at end of file From af15cc60ebfa74529ca543bc839038f29901fff9 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Tue, 29 Mar 2022 19:46:47 -0700 Subject: [PATCH 21/55] Add GM for performance cost --- dNet/dMessageIdentifiers.h | 1 + 1 file changed, 1 insertion(+) diff --git a/dNet/dMessageIdentifiers.h b/dNet/dMessageIdentifiers.h index 36e85df2..d2080248 100644 --- a/dNet/dMessageIdentifiers.h +++ b/dNet/dMessageIdentifiers.h @@ -527,6 +527,7 @@ enum GAME_MSG : unsigned short { GAME_MSG_VEHICLE_NOTIFY_HIT_IMAGINATION_SERVER = 1606, GAME_MSG_ADD_RUN_SPEED_MODIFIER = 1505, GAME_MSG_REMOVE_RUN_SPEED_MODIFIER = 1506, + GAME_MSG_UPDATE_PROPERTY_PERFORMANCE_COST = 1547, GAME_MSG_PROPERTY_ENTRANCE_BEGIN = 1553, GAME_MSG_REQUEST_MOVE_ITEM_BETWEEN_INVENTORY_TYPES = 1666, GAME_MSG_RESPONSE_MOVE_ITEM_BETWEEN_INVENTORY_TYPES = 1667, From 9f162845953451272f71126dcd659b50b0cc1c52 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Tue, 29 Mar 2022 19:47:15 -0700 Subject: [PATCH 22/55] tab spacing --- .../PropertySelectQueryProperty.cpp | 19 ++++++++++--------- .../PropertySelectQueryProperty.h | 3 ++- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/dGame/dGameMessages/PropertySelectQueryProperty.cpp b/dGame/dGameMessages/PropertySelectQueryProperty.cpp index 78b7198d..6a66554d 100644 --- a/dGame/dGameMessages/PropertySelectQueryProperty.cpp +++ b/dGame/dGameMessages/PropertySelectQueryProperty.cpp @@ -23,15 +23,16 @@ void PropertySelectQueryProperty::Serialize(RakNet::BitStream& stream) const stream.Write(static_cast(description[i])); } - stream.Write(Reputation); - stream.Write(IsBestFriend); - stream.Write(IsFriend); - stream.Write(IsModeratorApproved); - stream.Write(IsAlt); - stream.Write(IsOwned); - stream.Write(AccessType); - stream.Write(DateLastPublished); - stream.Write(PerformanceCost); + stream.Write(Reputation); + stream.Write(IsBestFriend); + stream.Write(IsFriend); + stream.Write(IsModeratorApproved); + stream.Write(IsAlt); + stream.Write(IsOwned); + stream.Write(AccessType); + stream.Write(DateLastPublished); + stream.Write(PerformanceIndex); + stream.Write(PerformanceCost); } void PropertySelectQueryProperty::Deserialize(RakNet::BitStream& stream) const diff --git a/dGame/dGameMessages/PropertySelectQueryProperty.h b/dGame/dGameMessages/PropertySelectQueryProperty.h index f451ae31..61fa7b86 100644 --- a/dGame/dGameMessages/PropertySelectQueryProperty.h +++ b/dGame/dGameMessages/PropertySelectQueryProperty.h @@ -21,5 +21,6 @@ public: bool IsOwned = false; // Whether or not the property is owned uint32_t AccessType = 0; // The privacy option of the property uint32_t DateLastPublished = 0; // The last day the property was published - uint64_t 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? }; From 1783904cb63ce791030d38d3f7e90fe97864268c Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Tue, 29 Mar 2022 19:47:27 -0700 Subject: [PATCH 23/55] fixed __int64 in missions table --- dDatabase/Tables/CDMissionsTable.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/dDatabase/Tables/CDMissionsTable.h b/dDatabase/Tables/CDMissionsTable.h index c083bd31..c961bb80 100644 --- a/dDatabase/Tables/CDMissionsTable.h +++ b/dDatabase/Tables/CDMissionsTable.h @@ -3,6 +3,7 @@ // Custom Classes #include "CDTable.h" #include +#include /*! \file CDMissionsTable.hpp @@ -17,9 +18,9 @@ struct CDMissions { int UISortOrder; //!< The UI Sort Order for the mission int offer_objectID; //!< The LOT of the mission giver int target_objectID; //!< The LOT of the mission's target - __int64 reward_currency; //!< The amount of currency to reward the player + int64_t reward_currency; //!< The amount of currency to reward the player int LegoScore; //!< The amount of LEGO Score to reward the player - __int64 reward_reputation; //!< The reputation to award the player + int64_t reward_reputation; //!< The reputation to award the player bool isChoiceReward; //!< Whether or not the user has the option to choose their loot int reward_item1; //!< The first rewarded item int reward_item1_count; //!< The count of the first item to be rewarded @@ -40,7 +41,7 @@ struct CDMissions { int reward_maxwidget; //!< ??? int reward_maxwallet; //!< ??? bool repeatable; //!< Whether or not this mission can be repeated (for instance, is it a daily mission) - __int64 reward_currency_repeatable; //!< The repeatable reward + int64_t reward_currency_repeatable; //!< The repeatable reward int reward_item1_repeatable; //!< The first rewarded item int reward_item1_repeat_count; //!< The count of the first item to be rewarded int reward_item2_repeatable; //!< The second rewarded item @@ -55,7 +56,7 @@ struct CDMissions { std::string prereqMissionID; //!< A '|' seperated list of prerequisite missions bool localize; //!< Whether or not to localize the mission bool inMOTD; //!< In Match of the Day(?) - __int64 cooldownTime; //!< The mission cooldown time + int64_t cooldownTime; //!< The mission cooldown time bool isRandom; //!< ??? std::string randomPool; //!< ??? int UIPrereqID; //!< ??? From 06671b8d66ceeea4957ef5758ed8e049e103d855 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Tue, 29 Mar 2022 19:48:34 -0700 Subject: [PATCH 24/55] performance cost is a float --- dGame/dComponents/PropertyEntranceComponent.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/dGame/dComponents/PropertyEntranceComponent.cpp b/dGame/dComponents/PropertyEntranceComponent.cpp index 4296dee4..3e3c3cc1 100644 --- a/dGame/dComponents/PropertyEntranceComponent.cpp +++ b/dGame/dComponents/PropertyEntranceComponent.cpp @@ -79,12 +79,11 @@ void PropertyEntranceComponent::OnEnterProperty(Entity* entity, uint32_t index, } 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, uint64_t performanceCost) { + 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; - // Reputation not updated for client side listing? property.Reputation = reputation; property.IsBestFriend = isBFF; property.IsFriend = isFriend; @@ -171,8 +170,9 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl const auto modApproved = playerPropertyLookupResults->getBoolean(10); const auto dateLastUpdated = playerPropertyLookupResults->getInt64(11); const auto reputation = playerPropertyLookupResults->getUInt(14); + const auto performanceCost = (float)playerPropertyLookupResults->getDouble(16); - playerEntry = SetPropertyValues(playerEntry, cloneId, character->GetName(), name, description, reputation, true, true, modApproved, true, true, privacyOption, dateLastUpdated); + playerEntry = SetPropertyValues(playerEntry, cloneId, character->GetName(), name, description, reputation, true, true, modApproved, true, true, privacyOption, dateLastUpdated, performanceCost); } else { playerEntry = SetPropertyValues(playerEntry, character->GetPropertyCloneID(), character->GetName(), "", "", 0, true, true); } @@ -214,6 +214,7 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl const auto modApproved = propertyEntry->getBoolean(10); const auto dateLastUpdated = propertyEntry->getInt(11); const float reputation = propertyEntry->getInt(14); + const auto performanceCost = (float)propertyEntry->getDouble(16); PropertySelectQueryProperty entry {}; @@ -308,7 +309,7 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl delete isAltQuery; isAltQuery = nullptr; - entry = SetPropertyValues(entry, cloneId, ownerName, propertyName, propertyDescription, reputation, isBestFriend, isFriend, isModeratorApproved, isAlt, isOwned, privacyOption, dateLastUpdated); + entry = SetPropertyValues(entry, cloneId, ownerName, propertyName, propertyDescription, reputation, isBestFriend, isFriend, isModeratorApproved, isAlt, isOwned, privacyOption, dateLastUpdated, performanceCost); entries.push_back(entry); } From 94e0ef77a963d4075112f2de12a9a38449191adc Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Tue, 29 Mar 2022 19:49:54 -0700 Subject: [PATCH 25/55] performance cost is still a float --- dGame/dComponents/PropertyEntranceComponent.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dGame/dComponents/PropertyEntranceComponent.h b/dGame/dComponents/PropertyEntranceComponent.h index 4ba7a74f..fdb9240d 100644 --- a/dGame/dComponents/PropertyEntranceComponent.h +++ b/dGame/dComponents/PropertyEntranceComponent.h @@ -59,7 +59,7 @@ class PropertyEntranceComponent : public Component { [[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, uint64_t performanceCost = 0); + 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); From fdd3e15b2f51e4ebfaf28c7201f0e12686c830f7 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Tue, 29 Mar 2022 19:52:07 -0700 Subject: [PATCH 26/55] Added GM for reputation update --- dGame/dGameMessages/GameMessageHandler.cpp | 4 +++- dGame/dGameMessages/GameMessages.cpp | 25 ++++++++++++++++++++++ dGame/dGameMessages/GameMessages.h | 2 ++ 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/dGame/dGameMessages/GameMessageHandler.cpp b/dGame/dGameMessages/GameMessageHandler.cpp index 83187e2f..45760cc9 100644 --- a/dGame/dGameMessages/GameMessageHandler.cpp +++ b/dGame/dGameMessages/GameMessageHandler.cpp @@ -595,7 +595,9 @@ void GameMessageHandler::HandleMessage(RakNet::BitStream* inStream, const System case GAME_MSG_VEHICLE_NOTIFY_HIT_IMAGINATION_SERVER: GameMessages::HandleVehicleNotifyHitImaginationServer(inStream, entity, sysAddr); break; - + case GAME_MSG_UPDATE_PROPERTY_PERFORMANCE_COST: + GameMessages::HandleUpdatePropertyPerformanceCost(inStream, entity, sysAddr); + break; // SG case GAME_MSG_UPDATE_SHOOTING_GALLERY_ROTATION: GameMessages::HandleUpdateShootingGalleryRotation(inStream, entity, sysAddr); diff --git a/dGame/dGameMessages/GameMessages.cpp b/dGame/dGameMessages/GameMessages.cpp index 53699f4e..6d70e105 100644 --- a/dGame/dGameMessages/GameMessages.cpp +++ b/dGame/dGameMessages/GameMessages.cpp @@ -4137,6 +4137,31 @@ void GameMessages::HandleRacingPlayerInfoResetFinished(RakNet::BitStream* inStre } } +void GameMessages::HandleUpdatePropertyPerformanceCost(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) { + float performanceCost = 0.0f; + + if (inStream->ReadBit()) inStream->Read(performanceCost); + + Game::logger->Log("GameMessages", "new value is %f\n", performanceCost); + + if (performanceCost == 0.0f) return; + + auto zone = dZoneManager::Instance()->GetZone(); + const auto& worldId = zone->GetZoneID(); + const auto cloneId = worldId.GetCloneID(); + const auto zoneId = worldId.GetMapID(); + + auto updatePerformanceCostQuery = Database::CreatePreppedStmt("UPDATE properties SET performance_cost = ? WHERE clone_id = ? AND zone_id = ?"); + + updatePerformanceCostQuery->setDouble(1, performanceCost); + updatePerformanceCostQuery->setInt(2, cloneId); + updatePerformanceCostQuery->setInt(3, zoneId); + + updatePerformanceCostQuery->execute(); + + delete updatePerformanceCostQuery; + updatePerformanceCostQuery = nullptr; +} void GameMessages::HandleVehicleNotifyHitImaginationServer(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) { diff --git a/dGame/dGameMessages/GameMessages.h b/dGame/dGameMessages/GameMessages.h index 671c3b3a..b2d9a6c9 100644 --- a/dGame/dGameMessages/GameMessages.h +++ b/dGame/dGameMessages/GameMessages.h @@ -386,6 +386,8 @@ namespace GameMessages { bool bUseLeaderboards ); + void HandleUpdatePropertyPerformanceCost(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr); + void SendNotifyClientShootingGalleryScore(LWOOBJID objectId, const SystemAddress& sysAddr, float addTime, int32_t score, From 258174d4e1290b1beda049fa39832828ebe78a2a Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Tue, 29 Mar 2022 23:46:23 -0700 Subject: [PATCH 27/55] Added GameMessage for UpdateReputation --- dGame/dGameMessages/GameMessages.cpp | 14 ++++++++++++-- dGame/dGameMessages/GameMessages.h | 2 ++ dNet/dMessageIdentifiers.h | 1 + 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/dGame/dGameMessages/GameMessages.cpp b/dGame/dGameMessages/GameMessages.cpp index 6d70e105..e8973283 100644 --- a/dGame/dGameMessages/GameMessages.cpp +++ b/dGame/dGameMessages/GameMessages.cpp @@ -4137,13 +4137,23 @@ void GameMessages::HandleRacingPlayerInfoResetFinished(RakNet::BitStream* inStre } } +void GameMessages::SendUpdateReputation(const LWOOBJID objectId, const int64_t reputation, const SystemAddress& sysAddr) { + CBITSTREAM; + CMSGHEADER; + + bitStream.Write(objectId); + bitStream.Write(GAME_MSG::GAME_MSG_UPDATE_REPUTATION); + + bitStream.Write(reputation); + + SEND_PACKET; +} + void GameMessages::HandleUpdatePropertyPerformanceCost(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) { float performanceCost = 0.0f; if (inStream->ReadBit()) inStream->Read(performanceCost); - Game::logger->Log("GameMessages", "new value is %f\n", performanceCost); - if (performanceCost == 0.0f) return; auto zone = dZoneManager::Instance()->GetZone(); diff --git a/dGame/dGameMessages/GameMessages.h b/dGame/dGameMessages/GameMessages.h index b2d9a6c9..ababed5f 100644 --- a/dGame/dGameMessages/GameMessages.h +++ b/dGame/dGameMessages/GameMessages.h @@ -397,6 +397,8 @@ namespace GameMessages { void HandleUpdateShootingGalleryRotation(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr); + void SendUpdateReputation(const LWOOBJID objectId, const int64_t reputation, const SystemAddress& sysAddr); + // Leaderboards void SendActivitySummaryLeaderboardData(const LWOOBJID& objectID, const Leaderboard* leaderboard, const SystemAddress& sysAddr = UNASSIGNED_SYSTEM_ADDRESS); diff --git a/dNet/dMessageIdentifiers.h b/dNet/dMessageIdentifiers.h index d2080248..eae3f88a 100644 --- a/dNet/dMessageIdentifiers.h +++ b/dNet/dMessageIdentifiers.h @@ -382,6 +382,7 @@ enum GAME_MSG : unsigned short { GAME_MSG_PROPERTY_EDITOR_END = 725, GAME_MSG_START_PATHING = 735, GAME_MSG_NOTIFY_CLIENT_ZONE_OBJECT = 737, + GAME_MSG_UPDATE_REPUTATION = 746, GAME_MSG_PROPERTY_RENTAL_RESPONSE = 750, GAME_MSG_REQUEST_PLATFORM_RESYNC = 760, GAME_MSG_PLATFORM_RESYNC = 761, From 36edbf393b4e68a3db969e73cd2e224726929993 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Tue, 29 Mar 2022 23:46:56 -0700 Subject: [PATCH 28/55] Added support to update reputation --- dGame/dMission/Mission.cpp | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/dGame/dMission/Mission.cpp b/dGame/dMission/Mission.cpp index f841f2f1..c0fe60c0 100644 --- a/dGame/dMission/Mission.cpp +++ b/dGame/dMission/Mission.cpp @@ -16,6 +16,7 @@ #include "dLogger.h" #include "dServer.h" #include "dZoneManager.h" +#include "Database.h" Mission::Mission(MissionComponent* missionComponent, const uint32_t missionId) { m_MissionComponent = missionComponent; @@ -516,8 +517,41 @@ void Mission::YieldRewards() { } if (info->reward_reputation > 0) { - // TODO: Track reputation in the property table and in charxml missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_EARN_REPUTATION, 0, 0L, "", info->reward_reputation); + auto character = entity->GetCharacter(); + if (!character) return; + + auto charId = character->GetID(); + auto propertyCloneId = character->GetPropertyCloneID(); + + auto properties = Database::CreatePreppedStmt("SELECT reputation FROM properties WHERE owner_id = ? AND clone_id = ?"); + + properties->setInt(1, charId); + properties->setInt64(2, propertyCloneId); + + auto results = properties->executeQuery(); + + while (results->next()) { + const auto oldReputation = results->getInt(1); + + auto reputationUpdate = Database::CreatePreppedStmt("UPDATE properties SET reputation = ? where owner_id = ? AND clone_id = ?"); + + reputationUpdate->setInt64(1, oldReputation + info->reward_reputation); + reputationUpdate->setInt(2, charId); + reputationUpdate->setInt64(3, propertyCloneId); + + reputationUpdate->execute(); + + delete reputationUpdate; + reputationUpdate = nullptr; + } + delete results; + results = nullptr; + + delete properties; + properties = nullptr; + + GameMessages::SendUpdateReputation(entity->GetObjectID(), info->reward_reputation, entity->GetSystemAddress()); } if (info->reward_maxhealth > 0) { From e244fbccc2ac2ffe8ad077bab02bf369bb9d9ed6 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Tue, 29 Mar 2022 23:49:04 -0700 Subject: [PATCH 29/55] General updates to the property manager clone id is correctly assigned, reputation now shows up, rejection verdict is sent correctly (not sure about where the reason goes if it even goes here). --- .../PropertyManagementComponent.cpp | 13 ++++++++-- .../dComponents/PropertyManagementComponent.h | 25 +++++++++++++++++++ dGame/dGameMessages/PropertyDataMessage.cpp | 18 +++++++++---- dGame/dGameMessages/PropertyDataMessage.h | 5 ++++ 4 files changed, 54 insertions(+), 7 deletions(-) diff --git a/dGame/dComponents/PropertyManagementComponent.cpp b/dGame/dComponents/PropertyManagementComponent.cpp index cd99fd78..a433aa56 100644 --- a/dGame/dComponents/PropertyManagementComponent.cpp +++ b/dGame/dComponents/PropertyManagementComponent.cpp @@ -68,10 +68,15 @@ PropertyManagementComponent::PropertyManagementComponent(Entity* parent) : Compo this->owner = propertyEntry->getUInt64(2); this->owner = GeneralUtils::SetBit(this->owner, OBJECT_BIT_CHARACTER); this->owner = GeneralUtils::SetBit(this->owner, OBJECT_BIT_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(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 = propertyEntry->getString(13); + this->reputation = propertyEntry->getUInt(14); Load(); } @@ -822,17 +827,21 @@ void PropertyManagementComponent::OnQueryPropertyData(Entity* originator, const claimed = claimedTime; privacy = static_cast(this->privacyOption); } - + message.moderatorRequested = moderatorRequested; + message.reputation = reputation; + message.LastUpdatedTime = LastUpdatedTime; message.OwnerId = ownerId; message.OwnerName = ownerName; message.Name = name; message.Description = description; message.ClaimedTime = claimed; message.PrivacyOption = privacy; - + message.cloneId = clone_Id; + message.rejectionReason = rejectionReason; message.Paths = GetPaths(); SendDownloadPropertyData(author, message, UNASSIGNED_SYSTEM_ADDRESS); + // send rejction here? } void PropertyManagementComponent::OnUse(Entity* originator) diff --git a/dGame/dComponents/PropertyManagementComponent.h b/dGame/dComponents/PropertyManagementComponent.h index bf577760..6aee8ed3 100644 --- a/dGame/dComponents/PropertyManagementComponent.h +++ b/dGame/dComponents/PropertyManagementComponent.h @@ -194,11 +194,36 @@ private: */ std::string propertyName = ""; + /** + * The clone ID of this property + */ + LWOCLONEID clone_Id = 0; + + /** + * Whether a moderator was requested + */ + bool moderatorRequested = false; + + /** + * The rejection reason for the property + */ + std::string rejectionReason = ""; + /** * The description of this property */ std::string propertyDescription = ""; + /** + * The reputation of this property + */ + uint32_t reputation = 0; + + /** + * The last time this property was updated + */ + uint32_t LastUpdatedTime = 0; + /** * Determines which players may visit this property */ diff --git a/dGame/dGameMessages/PropertyDataMessage.cpp b/dGame/dGameMessages/PropertyDataMessage.cpp index 9c3b6d3f..cbe3e67b 100644 --- a/dGame/dGameMessages/PropertyDataMessage.cpp +++ b/dGame/dGameMessages/PropertyDataMessage.cpp @@ -13,7 +13,7 @@ void GameMessages::PropertyDataMessage::Serialize(RakNet::BitStream& stream) con stream.Write(TemplateID); // - template id stream.Write(ZoneId); // - map id stream.Write(VendorMapId); // - vendor map id - stream.Write(1); + stream.Write(cloneId); // clone id const auto& name = GeneralUtils::ASCIIToUTF16(Name); stream.Write(uint32_t(name.size())); @@ -40,11 +40,12 @@ void GameMessages::PropertyDataMessage::Serialize(RakNet::BitStream& stream) con stream.Write(0); // - minimum price stream.Write(1); // - rent duration - stream.Write(ClaimedTime); // - timestamp + stream.Write(LastUpdatedTime); // - timestamp stream.Write(1); - stream.Write(0); + stream.Write(reputation); // Reputation + stream.Write(0); const auto& spawn = GeneralUtils::ASCIIToUTF16(SpawnName); stream.Write(uint32_t(spawn.size())); @@ -63,9 +64,16 @@ void GameMessages::PropertyDataMessage::Serialize(RakNet::BitStream& stream) con stream.Write(0); - stream.Write(1); + if (rejectionReason != "") stream.Write(2); + else if (moderatorRequested == true && rejectionReason == "") stream.Write(0); + else stream.Write(1); - stream.Write(0); // String length + const auto& rejectionReasonConverted = GeneralUtils::ASCIIToUTF16(rejectionReason); + stream.Write(uint32_t(rejectionReasonConverted.size())); + for (uint32_t i = 0; i < rejectionReasonConverted.size(); ++i) { + stream.Write(uint16_t(rejectionReasonConverted[i])); + std::cout << rejectionReason[i] << std::endl; + } stream.Write(0); diff --git a/dGame/dGameMessages/PropertyDataMessage.h b/dGame/dGameMessages/PropertyDataMessage.h index 219ac08d..a85702c4 100644 --- a/dGame/dGameMessages/PropertyDataMessage.h +++ b/dGame/dGameMessages/PropertyDataMessage.h @@ -28,8 +28,13 @@ namespace GameMessages std::string Name = ""; std::string Description = ""; + std::string rejectionReason = ""; + bool moderatorRequested = 0; + LWOCLONEID cloneId = 0; + uint32_t reputation = 0; uint64_t ClaimedTime = 0; + uint64_t LastUpdatedTime = 0; NiPoint3 ZonePosition = { 548.0f, 406.0f, 178.0f }; char PrivacyOption = 0; From c838f4f422a84350e5ac2e4523623528d7dc612d Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Tue, 29 Mar 2022 23:59:50 -0700 Subject: [PATCH 30/55] Added query for friends list next page --- .../dComponents/PropertyEntranceComponent.cpp | 47 ++++++++++++++----- 1 file changed, 36 insertions(+), 11 deletions(-) diff --git a/dGame/dComponents/PropertyEntranceComponent.cpp b/dGame/dComponents/PropertyEntranceComponent.cpp index 3e3c3cc1..72ee2a70 100644 --- a/dGame/dComponents/PropertyEntranceComponent.cpp +++ b/dGame/dComponents/PropertyEntranceComponent.cpp @@ -322,22 +322,47 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl propertyQueries[entity->GetObjectID()] = entries; - auto propertiesLeft = Database::CreatePreppedStmt("SELECT COUNT(*) FROM properties WHERE zone_id = ?;"); + uint32_t numberOfProperties = 0; + if (sortMethod != SORT_TYPE_FRIENDS || sortMethod != SORT_TYPE_FEATURED) { + auto propertiesLeft = Database::CreatePreppedStmt("SELECT COUNT(*) FROM properties WHERE zone_id = ?;"); - propertiesLeft->setInt(1, this->m_MapID); + propertiesLeft->setInt(1, this->m_MapID); - auto result = propertiesLeft->executeQuery(); - result->next(); - auto numberOfProperties = result->getInt(1); + auto result = propertiesLeft->executeQuery(); + result->next(); + numberOfProperties = result->getInt(1); - delete result; - result = nullptr; + delete result; + result = nullptr; - delete propertiesLeft; - propertiesLeft = nullptr; + delete propertiesLeft; + propertiesLeft = nullptr; + } else { + auto forFriends = query; + forFriends.replace(7, 3, "COUNT(*)"); - auto forFriends = query; - forFriends.replace(7, 3, "COUNT(*)"); + auto friendsQuery = Database::CreatePreppedStmt(query); + + 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, entity->GetGMLevel() >= GAME_MASTER_LEVEL_LEAD_MODERATOR || sortMethod == SORT_TYPE_FRIENDS ? 0 : 1); + propertyLookup->setInt(6, sortMethod == SORT_TYPE_FEATURED || sortMethod == SORT_TYPE_FRIENDS ? 1 : 2); + propertyLookup->setInt(7, numResults); + propertyLookup->setInt(8, startIndex); + + auto result = friendsQuery->executeQuery(); + result->next(); + numberOfProperties = result->getInt(1); + + delete friendsQuery; + friendsQuery = nullptr; + + delete result; + result = nullptr; + } + // if sort method is friends or featured do above query. // do same maths below with resulting query // else use default count. From b676343b0215a51973a9582984739b93aad4f383 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Wed, 30 Mar 2022 00:02:18 -0700 Subject: [PATCH 31/55] removed print and rejection send --- dGame/dGameMessages/PropertyDataMessage.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/dGame/dGameMessages/PropertyDataMessage.cpp b/dGame/dGameMessages/PropertyDataMessage.cpp index cbe3e67b..9a261a65 100644 --- a/dGame/dGameMessages/PropertyDataMessage.cpp +++ b/dGame/dGameMessages/PropertyDataMessage.cpp @@ -68,12 +68,13 @@ void GameMessages::PropertyDataMessage::Serialize(RakNet::BitStream& stream) con else if (moderatorRequested == true && rejectionReason == "") stream.Write(0); else stream.Write(1); - const auto& rejectionReasonConverted = GeneralUtils::ASCIIToUTF16(rejectionReason); - stream.Write(uint32_t(rejectionReasonConverted.size())); - for (uint32_t i = 0; i < rejectionReasonConverted.size(); ++i) { - stream.Write(uint16_t(rejectionReasonConverted[i])); - std::cout << rejectionReason[i] << std::endl; - } + // Does this go here??? + // const auto& rejectionReasonConverted = GeneralUtils::ASCIIToUTF16(rejectionReason); + // stream.Write(uint32_t(rejectionReasonConverted.size())); + // for (uint32_t i = 0; i < rejectionReasonConverted.size(); ++i) { + // stream.Write(uint16_t(rejectionReasonConverted[i])); + // } + stream.Write(0); stream.Write(0); From 17e9fb0d3c0c5cce9ecf7208428bb5d94ffc7e8a Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Wed, 30 Mar 2022 00:20:04 -0700 Subject: [PATCH 32/55] Default time is now the current time rather than 0 --- dGame/dComponents/PropertyManagementComponent.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/dGame/dComponents/PropertyManagementComponent.h b/dGame/dComponents/PropertyManagementComponent.h index 6aee8ed3..2184eed3 100644 --- a/dGame/dComponents/PropertyManagementComponent.h +++ b/dGame/dComponents/PropertyManagementComponent.h @@ -1,5 +1,6 @@ #pragma once +#include #include "Entity.h" #include "Component.h" @@ -182,7 +183,7 @@ private: /** * The time since this property was claimed */ - uint64_t claimedTime = 0; + uint64_t claimedTime = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); /** * The models that are placed on this property @@ -222,7 +223,7 @@ private: /** * The last time this property was updated */ - uint32_t LastUpdatedTime = 0; + uint32_t LastUpdatedTime = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); /** * Determines which players may visit this property From 69cc265fea45ec20186b0bf39cf7102651c696ab Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Wed, 30 Mar 2022 00:20:15 -0700 Subject: [PATCH 33/55] added performance cost initializer --- dGame/dComponents/PropertyManagementComponent.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dGame/dComponents/PropertyManagementComponent.cpp b/dGame/dComponents/PropertyManagementComponent.cpp index a433aa56..f2f6e0eb 100644 --- a/dGame/dComponents/PropertyManagementComponent.cpp +++ b/dGame/dComponents/PropertyManagementComponent.cpp @@ -79,7 +79,7 @@ PropertyManagementComponent::PropertyManagementComponent(Entity* parent) : Compo this->reputation = propertyEntry->getUInt(14); Load(); - } + } delete propertyLookup; } @@ -209,8 +209,8 @@ void PropertyManagementComponent::Claim(const LWOOBJID playerId) 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)" - "VALUES (?, ?, ?, ?, ?, '', 0, 0, 0, UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), '', 0, ?)" + "(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); From fe334d87391f6c2cafbb8ad2cd854a6d30e1434e Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Wed, 30 Mar 2022 00:20:26 -0700 Subject: [PATCH 34/55] clarified magic nums --- dGame/dComponents/PropertyEntranceComponent.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dGame/dComponents/PropertyEntranceComponent.cpp b/dGame/dComponents/PropertyEntranceComponent.cpp index 72ee2a70..bf63028b 100644 --- a/dGame/dComponents/PropertyEntranceComponent.cpp +++ b/dGame/dComponents/PropertyEntranceComponent.cpp @@ -195,7 +195,7 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl propertyLookup->setString(3, searchString.c_str()); propertyLookup->setString(4, searchString.c_str()); propertyLookup->setInt(5, entity->GetGMLevel() >= GAME_MASTER_LEVEL_LEAD_MODERATOR || sortMethod == SORT_TYPE_FRIENDS ? 0 : 1); - propertyLookup->setInt(6, sortMethod == SORT_TYPE_FEATURED || sortMethod == SORT_TYPE_FRIENDS ? 1 : 2); + propertyLookup->setInt(6, sortMethod == SORT_TYPE_FEATURED || sortMethod == SORT_TYPE_FRIENDS ? (uint32_t)PropertyPrivacyOption::Friends : (uint32_t)PropertyPrivacyOption::Public); propertyLookup->setInt(7, numResults); propertyLookup->setInt(8, startIndex); From bd6bdddcdeb188f8e471a2cce2b717bcc2c3686b Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Wed, 30 Mar 2022 00:33:31 -0700 Subject: [PATCH 35/55] clone ID now based on character data --- dGame/dComponents/PropertyManagementComponent.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/dGame/dComponents/PropertyManagementComponent.cpp b/dGame/dComponents/PropertyManagementComponent.cpp index f2f6e0eb..a5e33667 100644 --- a/dGame/dComponents/PropertyManagementComponent.cpp +++ b/dGame/dComponents/PropertyManagementComponent.cpp @@ -199,12 +199,16 @@ void PropertyManagementComponent::Claim(const LWOOBJID playerId) const auto& worldId = zone->GetZoneID(); const auto zoneId = worldId.GetMapID(); - const auto cloneId = worldId.GetCloneID(); auto* entity = EntityManager::Instance()->GetEntity(playerId); auto* user = entity->GetParentUser(); + auto character = entity->GetCharacter(); + if (!character) return; + + const auto cloneId = character->GetPropertyCloneID(); + propertyId = ObjectIDManager::GenerateRandomObjectID(); auto* insertion = Database::CreatePreppedStmt( From 5c16dd11f4bdefa6d80f88fbe71540186f022462 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Wed, 30 Mar 2022 00:37:36 -0700 Subject: [PATCH 36/55] altered table now has a default for performance cost --- migrations/dlu/3_add_performance_cost.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/migrations/dlu/3_add_performance_cost.sql b/migrations/dlu/3_add_performance_cost.sql index 8d9bc6e9..15da4470 100644 --- a/migrations/dlu/3_add_performance_cost.sql +++ b/migrations/dlu/3_add_performance_cost.sql @@ -1 +1 @@ -ALTER TABLE properties ADD COLUMN performance_cost DOUBLE(20, 15); \ No newline at end of file +ALTER TABLE properties ADD COLUMN performance_cost DOUBLE(20, 15) DEFAULT 0.0; \ No newline at end of file From 4edb4289544a6d5abda994a0adccf608ea1b92b1 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Wed, 30 Mar 2022 16:12:42 -0700 Subject: [PATCH 37/55] next page query now works --- .../dComponents/PropertyEntranceComponent.cpp | 74 +++++++------------ 1 file changed, 27 insertions(+), 47 deletions(-) diff --git a/dGame/dComponents/PropertyEntranceComponent.cpp b/dGame/dComponents/PropertyEntranceComponent.cpp index bf63028b..cfe39bed 100644 --- a/dGame/dComponents/PropertyEntranceComponent.cpp +++ b/dGame/dComponents/PropertyEntranceComponent.cpp @@ -97,8 +97,13 @@ PropertySelectQueryProperty PropertyEntranceComponent::SetPropertyValues(Propert return property; } -std::string PropertyEntranceComponent::BuildQuery(Entity* entity, int32_t sortMethod) { - auto base = baseQueryForProperties; +std::string PropertyEntranceComponent::BuildQuery(Entity* entity, int32_t sortMethod, std::string customQuery, bool wantLimits) { + std::string base; + if (customQuery == "") { + base = baseQueryForProperties; + } else { + base = customQuery; + } std::string orderBy = ""; std::string friendsList = " AND p.owner_id IN ("; if (sortMethod == SORT_TYPE_FEATURED || sortMethod == SORT_TYPE_FRIENDS) { @@ -120,11 +125,8 @@ std::string PropertyEntranceComponent::BuildQuery(Entity* entity, int32_t sortMe friendsList += ") "; // If we have no friends then use a -1 for the query. - if (friendsList.find("()") == std::string::npos) { - orderBy = friendsList; - } else { - friendsList = " AND p.owner_id IN (-1) "; - } + if (friendsList.find("()") != std::string::npos) friendsList = " AND p.owner_id IN (-1) "; + orderBy += friendsList + "ORDER BY ci.name ASC "; delete friendsListQueryResult; @@ -142,7 +144,7 @@ std::string PropertyEntranceComponent::BuildQuery(Entity* entity, int32_t sortMe else { orderBy = "ORDER BY p.last_updated DESC "; } - return baseQueryForProperties + orderBy + "LIMIT ? OFFSET ?;"; + 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){ @@ -322,49 +324,27 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl propertyQueries[entity->GetObjectID()] = entries; - uint32_t numberOfProperties = 0; - if (sortMethod != SORT_TYPE_FRIENDS || sortMethod != SORT_TYPE_FEATURED) { - auto propertiesLeft = Database::CreatePreppedStmt("SELECT COUNT(*) FROM properties WHERE zone_id = ?;"); + int32_t numberOfProperties = 0; - propertiesLeft->setInt(1, this->m_MapID); + auto buttonQuery = BuildQuery(entity, sortMethod, "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.mod_approved >= ? AND p.privacy_option >= ? ", false); + auto propertiesLeft = Database::CreatePreppedStmt(buttonQuery); - auto result = propertiesLeft->executeQuery(); - result->next(); - numberOfProperties = result->getInt(1); + 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, entity->GetGMLevel() >= GAME_MASTER_LEVEL_LEAD_MODERATOR || sortMethod == SORT_TYPE_FRIENDS ? 0 : 1); + propertiesLeft->setInt(6, sortMethod == SORT_TYPE_FEATURED || sortMethod == SORT_TYPE_FRIENDS ? 1 : 2); - delete result; - result = nullptr; + auto result = propertiesLeft->executeQuery(); + result->next(); + numberOfProperties = result->getInt(1); - delete propertiesLeft; - propertiesLeft = nullptr; - } else { - auto forFriends = query; - forFriends.replace(7, 3, "COUNT(*)"); - - auto friendsQuery = Database::CreatePreppedStmt(query); - - 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, entity->GetGMLevel() >= GAME_MASTER_LEVEL_LEAD_MODERATOR || sortMethod == SORT_TYPE_FRIENDS ? 0 : 1); - propertyLookup->setInt(6, sortMethod == SORT_TYPE_FEATURED || sortMethod == SORT_TYPE_FRIENDS ? 1 : 2); - propertyLookup->setInt(7, numResults); - propertyLookup->setInt(8, startIndex); - - auto result = friendsQuery->executeQuery(); - result->next(); - numberOfProperties = result->getInt(1); - - delete friendsQuery; - friendsQuery = nullptr; - - delete result; - result = nullptr; - } + delete result; + result = nullptr; - // if sort method is friends or featured do above query. - // do same maths below with resulting query - // else use default count. + delete propertiesLeft; + propertiesLeft = nullptr; + GameMessages::SendPropertySelectQuery(m_Parent->GetObjectID(), startIndex, numberOfProperties - (startIndex + numResults) > 0, character->GetPropertyCloneID(), false, true, entries, sysAddr); } \ No newline at end of file From 5fa0a16302554446b9a1f58dee02c51ae5442485 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Wed, 30 Mar 2022 16:13:01 -0700 Subject: [PATCH 38/55] more options in BuildQuery method --- dGame/dComponents/PropertyEntranceComponent.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dGame/dComponents/PropertyEntranceComponent.h b/dGame/dComponents/PropertyEntranceComponent.h index fdb9240d..67b97ef2 100644 --- a/dGame/dComponents/PropertyEntranceComponent.h +++ b/dGame/dComponents/PropertyEntranceComponent.h @@ -61,7 +61,7 @@ class PropertyEntranceComponent : public Component { 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); + std::string BuildQuery(Entity* entity, int32_t sortMethod, std::string customQuery = "", bool wantLimits = true); private: /** @@ -86,5 +86,5 @@ class PropertyEntranceComponent : public Component { SORT_TYPE_FEATURED = 5 }; - const 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.mod_approved >= ? AND p.privacy_option >= ? "; + 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.mod_approved >= ? AND p.privacy_option >= ? "; }; From 04852ac1d93c08f112038656636cafffa35ae726 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Wed, 30 Mar 2022 16:13:21 -0700 Subject: [PATCH 39/55] Removed const --- dGame/dComponents/PropertyManagementComponent.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dGame/dComponents/PropertyManagementComponent.h b/dGame/dComponents/PropertyManagementComponent.h index 2184eed3..fd208b63 100644 --- a/dGame/dComponents/PropertyManagementComponent.h +++ b/dGame/dComponents/PropertyManagementComponent.h @@ -41,7 +41,7 @@ public: * @param sysAddr the address to send game message responses to * @param author optional explicit ID for the property, if not set defaults to the originator */ - void OnQueryPropertyData(Entity* originator, const SystemAddress& sysAddr, LWOOBJID author = LWOOBJID_EMPTY) const; + void OnQueryPropertyData(Entity* originator, const SystemAddress& sysAddr, LWOOBJID author = LWOOBJID_EMPTY); /** * Handles an OnUse event, telling the client who owns this property, etc. From 0bf2f0e92abffe661992bb634c4a491b4db5b303 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Wed, 30 Mar 2022 16:14:24 -0700 Subject: [PATCH 40/55] Added enum for rejection statuses --- dGame/dGameMessages/PropertyDataMessage.cpp | 19 ++++++++++--------- dGame/dGameMessages/PropertyDataMessage.h | 6 ++++++ 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/dGame/dGameMessages/PropertyDataMessage.cpp b/dGame/dGameMessages/PropertyDataMessage.cpp index 9a261a65..d763399d 100644 --- a/dGame/dGameMessages/PropertyDataMessage.cpp +++ b/dGame/dGameMessages/PropertyDataMessage.cpp @@ -64,17 +64,18 @@ void GameMessages::PropertyDataMessage::Serialize(RakNet::BitStream& stream) con stream.Write(0); - if (rejectionReason != "") stream.Write(2); - else if (moderatorRequested == true && rejectionReason == "") stream.Write(0); - else stream.Write(1); + if (rejectionReason != "") stream.Write(REJECTION_STATUS_REJECTED); + else if (moderatorRequested == true && rejectionReason == "") stream.Write(REJECTION_STATUS_PENDING); + else stream.Write(REJECTION_STATUS_APPROVED); // Does this go here??? - // const auto& rejectionReasonConverted = GeneralUtils::ASCIIToUTF16(rejectionReason); - // stream.Write(uint32_t(rejectionReasonConverted.size())); - // for (uint32_t i = 0; i < rejectionReasonConverted.size(); ++i) { - // stream.Write(uint16_t(rejectionReasonConverted[i])); - // } - stream.Write(0); + const auto& rejectionReasonConverted = GeneralUtils::ASCIIToUTF16(rejectionReason); + stream.Write(uint32_t(rejectionReasonConverted.size())); + for (uint32_t i = 0; i < rejectionReasonConverted.size(); ++i) { + stream.Write(uint16_t(rejectionReasonConverted[i])); + } + + // stream.Write(0); stream.Write(0); diff --git a/dGame/dGameMessages/PropertyDataMessage.h b/dGame/dGameMessages/PropertyDataMessage.h index a85702c4..5b5d7d0f 100644 --- a/dGame/dGameMessages/PropertyDataMessage.h +++ b/dGame/dGameMessages/PropertyDataMessage.h @@ -40,5 +40,11 @@ namespace GameMessages char PrivacyOption = 0; float MaxBuildHeight = 128.0f; std::vector Paths = {}; + private: + enum RejectionStatus : uint32_t { + REJECTION_STATUS_APPROVED = 0, + REJECTION_STATUS_PENDING = 1, + REJECTION_STATUS_REJECTED = 2 + }; }; } \ No newline at end of file From b903c81a0add07dc1dff95843601c879564191f2 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Wed, 30 Mar 2022 20:31:23 -0700 Subject: [PATCH 41/55] Shortened reputation update --- dGame/dMission/Mission.cpp | 30 +++++++----------------------- 1 file changed, 7 insertions(+), 23 deletions(-) diff --git a/dGame/dMission/Mission.cpp b/dGame/dMission/Mission.cpp index c0fe60c0..748bebd4 100644 --- a/dGame/dMission/Mission.cpp +++ b/dGame/dMission/Mission.cpp @@ -524,32 +524,16 @@ void Mission::YieldRewards() { auto charId = character->GetID(); auto propertyCloneId = character->GetPropertyCloneID(); - auto properties = Database::CreatePreppedStmt("SELECT reputation FROM properties WHERE owner_id = ? AND clone_id = ?"); + auto reputationUpdate = Database::CreatePreppedStmt("UPDATE properties SET reputation = reputation + ? where owner_id = ? AND clone_id = ?"); - properties->setInt(1, charId); - properties->setInt64(2, propertyCloneId); + reputationUpdate->setInt64(1, info->reward_reputation); + reputationUpdate->setInt(2, charId); + reputationUpdate->setInt64(3, propertyCloneId); - auto results = properties->executeQuery(); + reputationUpdate->executeUpdate(); - while (results->next()) { - const auto oldReputation = results->getInt(1); - - auto reputationUpdate = Database::CreatePreppedStmt("UPDATE properties SET reputation = ? where owner_id = ? AND clone_id = ?"); - - reputationUpdate->setInt64(1, oldReputation + info->reward_reputation); - reputationUpdate->setInt(2, charId); - reputationUpdate->setInt64(3, propertyCloneId); - - reputationUpdate->execute(); - - delete reputationUpdate; - reputationUpdate = nullptr; - } - delete results; - results = nullptr; - - delete properties; - properties = nullptr; + delete reputationUpdate; + reputationUpdate = nullptr; GameMessages::SendUpdateReputation(entity->GetObjectID(), info->reward_reputation, entity->GetSystemAddress()); } From c80a90e81e1385bec3e01f32021cb67b07538a0b Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Wed, 30 Mar 2022 20:31:51 -0700 Subject: [PATCH 42/55] rejection statuses were backwards --- dGame/dGameMessages/PropertyDataMessage.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dGame/dGameMessages/PropertyDataMessage.cpp b/dGame/dGameMessages/PropertyDataMessage.cpp index d763399d..0831ac26 100644 --- a/dGame/dGameMessages/PropertyDataMessage.cpp +++ b/dGame/dGameMessages/PropertyDataMessage.cpp @@ -65,8 +65,8 @@ void GameMessages::PropertyDataMessage::Serialize(RakNet::BitStream& stream) con stream.Write(0); if (rejectionReason != "") stream.Write(REJECTION_STATUS_REJECTED); - else if (moderatorRequested == true && rejectionReason == "") stream.Write(REJECTION_STATUS_PENDING); - else stream.Write(REJECTION_STATUS_APPROVED); + else if (moderatorRequested == true && rejectionReason == "") stream.Write(REJECTION_STATUS_APPROVED); + else stream.Write(REJECTION_STATUS_PENDING); // Does this go here??? const auto& rejectionReasonConverted = GeneralUtils::ASCIIToUTF16(rejectionReason); From d3f954bdacdc0b02251a64af31632165f1bc2ffa Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Wed, 30 Mar 2022 20:32:59 -0700 Subject: [PATCH 43/55] changed serialized value to old I am unsure if this is what gets serialized here so I am reverting this back to a zero. --- dGame/dGameMessages/PropertyDataMessage.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/dGame/dGameMessages/PropertyDataMessage.cpp b/dGame/dGameMessages/PropertyDataMessage.cpp index 0831ac26..85eb54cb 100644 --- a/dGame/dGameMessages/PropertyDataMessage.cpp +++ b/dGame/dGameMessages/PropertyDataMessage.cpp @@ -69,13 +69,13 @@ void GameMessages::PropertyDataMessage::Serialize(RakNet::BitStream& stream) con else stream.Write(REJECTION_STATUS_PENDING); // Does this go here??? - const auto& rejectionReasonConverted = GeneralUtils::ASCIIToUTF16(rejectionReason); - stream.Write(uint32_t(rejectionReasonConverted.size())); - for (uint32_t i = 0; i < rejectionReasonConverted.size(); ++i) { - stream.Write(uint16_t(rejectionReasonConverted[i])); - } + // const auto& rejectionReasonConverted = GeneralUtils::ASCIIToUTF16(rejectionReason); + // stream.Write(uint32_t(rejectionReasonConverted.size())); + // for (uint32_t i = 0; i < rejectionReasonConverted.size(); ++i) { + // stream.Write(uint16_t(rejectionReasonConverted[i])); + // } - // stream.Write(0); + stream.Write(0); stream.Write(0); From 061d2b394c5cc1381784a4010d45cf5132f3bb76 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Wed, 30 Mar 2022 20:33:37 -0700 Subject: [PATCH 44/55] on the fly property moderating notifications --- .../PropertyManagementComponent.cpp | 38 ++++++++++++++++--- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/dGame/dComponents/PropertyManagementComponent.cpp b/dGame/dComponents/PropertyManagementComponent.cpp index a5e33667..431cb800 100644 --- a/dGame/dComponents/PropertyManagementComponent.cpp +++ b/dGame/dComponents/PropertyManagementComponent.cpp @@ -75,7 +75,7 @@ PropertyManagementComponent::PropertyManagementComponent(Entity* parent) : Compo this->moderatorRequested = propertyEntry->getInt(10) == 0 && rejectionReason == "" && privacyOption == PropertyPrivacyOption::Public; this->LastUpdatedTime = propertyEntry->getUInt64(11); this->claimedTime = propertyEntry->getUInt64(12); - this->rejectionReason = propertyEntry->getString(13); + this->rejectionReason = propertyEntry->getString(13).asStdString(); this->reputation = propertyEntry->getUInt(14); Load(); @@ -157,12 +157,18 @@ void PropertyManagementComponent::SetPrivacyOption(PropertyPrivacyOption value) value = PropertyPrivacyOption::Private; } + if (value == PropertyPrivacyOption::Public && privacyOption != PropertyPrivacyOption::Public) { + rejectionReason = ""; + moderatorRequested = true; + } privacyOption = value; - auto* propertyUpdate = Database::CreatePreppedStmt("UPDATE properties SET privacy_option = ? WHERE id = ?;"); + auto* propertyUpdate = Database::CreatePreppedStmt("UPDATE properties SET privacy_option = ?, rejection_reason = ?, mod_approved = ? WHERE id = ?;"); propertyUpdate->setInt(1, static_cast(value)); - propertyUpdate->setInt64(2, propertyId); + propertyUpdate->setString(2, ""); + propertyUpdate->setInt(3, 0); + propertyUpdate->setInt64(4, propertyId); propertyUpdate->executeUpdate(); } @@ -791,7 +797,7 @@ PropertyManagementComponent* PropertyManagementComponent::Instance() return instance; } -void PropertyManagementComponent::OnQueryPropertyData(Entity* originator, const SystemAddress& sysAddr, LWOOBJID author) const +void PropertyManagementComponent::OnQueryPropertyData(Entity* originator, const SystemAddress& sysAddr, LWOOBJID author) { if (author == LWOOBJID_EMPTY) { author = m_Parent->GetObjectID(); @@ -830,6 +836,28 @@ void PropertyManagementComponent::OnQueryPropertyData(Entity* originator, const description = propertyDescription; claimed = claimedTime; privacy = static_cast(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 = result->getString(1).asStdString();; + const auto modApproved = result->getInt(2); + if (reason != "") { + moderatorRequested = false; + rejectionReason = reason; + } else if (reason == "" && modApproved == 1) { + moderatorRequested = false; + rejectionReason = ""; + } else { + moderatorRequested = true; + rejectionReason = ""; + } + } } message.moderatorRequested = moderatorRequested; message.reputation = reputation; @@ -845,7 +873,7 @@ void PropertyManagementComponent::OnQueryPropertyData(Entity* originator, const message.Paths = GetPaths(); SendDownloadPropertyData(author, message, UNASSIGNED_SYSTEM_ADDRESS); - // send rejction here? + // send rejection here? } void PropertyManagementComponent::OnUse(Entity* originator) From 002025231e920229f4517044b7f79c62821f7825 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Wed, 30 Mar 2022 20:33:50 -0700 Subject: [PATCH 45/55] Semantics --- .../dComponents/PropertyEntranceComponent.cpp | 40 +++++++++---------- 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/dGame/dComponents/PropertyEntranceComponent.cpp b/dGame/dComponents/PropertyEntranceComponent.cpp index cfe39bed..c1e29b95 100644 --- a/dGame/dComponents/PropertyEntranceComponent.cpp +++ b/dGame/dComponents/PropertyEntranceComponent.cpp @@ -1,13 +1,15 @@ -#include -#include "PropertyEntranceComponent.h" +#include "PropertyEntranceComponent.h" + +#include + +#include "Character.h" +#include "Database.h" +#include "GameMessages.h" +#include "PropertyManagementComponent.h" #include "PropertySelectQueryProperty.h" #include "RocketLaunchpadControlComponent.h" -#include "Character.h" -#include "GameMessages.h" -#include "dLogger.h" -#include "Database.h" -#include "PropertyManagementComponent.h" #include "UserManager.h" +#include "dLogger.h" PropertyEntranceComponent::PropertyEntranceComponent(uint32_t componentID, Entity* parent) : Component(parent) { @@ -200,25 +202,22 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl propertyLookup->setInt(6, sortMethod == SORT_TYPE_FEATURED || sortMethod == SORT_TYPE_FRIENDS ? (uint32_t)PropertyPrivacyOption::Friends : (uint32_t)PropertyPrivacyOption::Public); propertyLookup->setInt(7, numResults); propertyLookup->setInt(8, startIndex); - - Game::logger->Log("PropertyEntranceComponent", "Property query is \n%s\n. Entity is %s.\n", query.c_str(), entity->GetGMLevel() >= GAME_MASTER_LEVEL_LEAD_MODERATOR ? "a moderator" : "not a moderator"); auto propertyEntry = propertyLookup->executeQuery(); - - while (propertyEntry->next()) - { - const auto propertyId = propertyEntry->getUInt64(1); - const auto owner = propertyEntry->getInt(2); + + while (propertyEntry->next()) { + const auto propertyId = propertyEntry->getUInt64(1); + const auto owner = propertyEntry->getInt(2); const auto cloneId = propertyEntry->getUInt64(4); const auto name = propertyEntry->getString(5).asStdString(); const auto description = propertyEntry->getString(6).asStdString(); - const auto privacyOption = propertyEntry->getInt(9); + 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 = (float)propertyEntry->getDouble(16); - PropertySelectQueryProperty entry {}; + PropertySelectQueryProperty entry{}; std::string ownerName = ""; bool isOwned = true; @@ -235,8 +234,7 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl Game::logger->Log("PropertyEntranceComponent", "Failed to find property owner name for %llu!\n", cloneId); continue; - } - else { + } else { isOwned = cloneId == character->GetPropertyCloneID(); ownerName = nameResult->getString(1).asStdString(); } @@ -244,7 +242,7 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl delete nameResult; nameResult = nullptr; - delete nameLookup; + delete nameLookup; nameLookup = nullptr; std::string propertyName = ""; @@ -269,7 +267,7 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl friendCheck->setInt64(4, entity->GetObjectID()); auto friendResult = friendCheck->executeQuery(); - + // If we got a result than the two players are friends. if (friendResult->next()) { isFriend = true; @@ -314,7 +312,7 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl entry = SetPropertyValues(entry, cloneId, ownerName, propertyName, propertyDescription, reputation, isBestFriend, isFriend, isModeratorApproved, isAlt, isOwned, privacyOption, dateLastUpdated, performanceCost); entries.push_back(entry); - } + } delete propertyEntry; propertyEntry = nullptr; From f22dab0f72ac94f6a1f0a86be34d0b4720566f62 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Wed, 30 Mar 2022 21:12:22 -0700 Subject: [PATCH 46/55] unapproved properties render correctly --- .../dComponents/PropertyEntranceComponent.cpp | 19 +++++++++---------- dGame/dComponents/PropertyEntranceComponent.h | 2 +- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/dGame/dComponents/PropertyEntranceComponent.cpp b/dGame/dComponents/PropertyEntranceComponent.cpp index c1e29b95..eaee9077 100644 --- a/dGame/dComponents/PropertyEntranceComponent.cpp +++ b/dGame/dComponents/PropertyEntranceComponent.cpp @@ -192,16 +192,15 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl const auto query = BuildQuery(entity, sortMethod); auto propertyLookup = Database::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, entity->GetGMLevel() >= GAME_MASTER_LEVEL_LEAD_MODERATOR || sortMethod == SORT_TYPE_FRIENDS ? 0 : 1); - propertyLookup->setInt(6, sortMethod == SORT_TYPE_FEATURED || sortMethod == SORT_TYPE_FRIENDS ? (uint32_t)PropertyPrivacyOption::Friends : (uint32_t)PropertyPrivacyOption::Public); - propertyLookup->setInt(7, numResults); - propertyLookup->setInt(8, startIndex); + propertyLookup->setInt(5, sortMethod == SORT_TYPE_FEATURED || sortMethod == SORT_TYPE_FRIENDS ? (uint32_t)PropertyPrivacyOption::Friends : (uint32_t)PropertyPrivacyOption::Public); + propertyLookup->setInt(6, numResults); + propertyLookup->setInt(7, startIndex); auto propertyEntry = propertyLookup->executeQuery(); @@ -291,7 +290,7 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl } bool isAlt = false; - // Query to determine whether this property is an alt of the entity. + // 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 = ?;"); isAltQuery->setInt(1, character->GetID()); @@ -321,18 +320,18 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl 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. int32_t numberOfProperties = 0; - auto buttonQuery = BuildQuery(entity, sortMethod, "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.mod_approved >= ? AND p.privacy_option >= ? ", false); + auto buttonQuery = BuildQuery(entity, sortMethod, "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); 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, entity->GetGMLevel() >= GAME_MASTER_LEVEL_LEAD_MODERATOR || sortMethod == SORT_TYPE_FRIENDS ? 0 : 1); - propertiesLeft->setInt(6, sortMethod == SORT_TYPE_FEATURED || sortMethod == SORT_TYPE_FRIENDS ? 1 : 2); + propertiesLeft->setInt(5, sortMethod == SORT_TYPE_FEATURED || sortMethod == SORT_TYPE_FRIENDS ? 1 : 2); auto result = propertiesLeft->executeQuery(); result->next(); diff --git a/dGame/dComponents/PropertyEntranceComponent.h b/dGame/dComponents/PropertyEntranceComponent.h index 67b97ef2..0e948068 100644 --- a/dGame/dComponents/PropertyEntranceComponent.h +++ b/dGame/dComponents/PropertyEntranceComponent.h @@ -86,5 +86,5 @@ class PropertyEntranceComponent : public Component { 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.mod_approved >= ? AND p.privacy_option >= ? "; + 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 >= ? "; }; From bc7c54353062d0286f8a78c10c5866eab247b4a4 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Wed, 30 Mar 2022 21:15:50 -0700 Subject: [PATCH 47/55] removed debug log --- dGame/dComponents/PropertyEntranceComponent.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/dGame/dComponents/PropertyEntranceComponent.cpp b/dGame/dComponents/PropertyEntranceComponent.cpp index eaee9077..8ee20466 100644 --- a/dGame/dComponents/PropertyEntranceComponent.cpp +++ b/dGame/dComponents/PropertyEntranceComponent.cpp @@ -66,8 +66,6 @@ void PropertyEntranceComponent::OnEnterProperty(Entity* entity, uint32_t index, cloneId = query[index].CloneId; } - Game::logger->Log("PropertyEntranceComponent", "index is %i\n", index); - auto* launcher = m_Parent->GetComponent(); if (launcher == nullptr) From 8a8b5b4f442c8849dced180557e910b72b9e833b Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Wed, 30 Mar 2022 21:18:29 -0700 Subject: [PATCH 48/55] removed new line --- dGame/dComponents/PropertyEntranceComponent.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/dGame/dComponents/PropertyEntranceComponent.cpp b/dGame/dComponents/PropertyEntranceComponent.cpp index 8ee20466..06886a0a 100644 --- a/dGame/dComponents/PropertyEntranceComponent.cpp +++ b/dGame/dComponents/PropertyEntranceComponent.cpp @@ -78,8 +78,7 @@ void PropertyEntranceComponent::OnEnterProperty(Entity* entity, uint32_t index, launcher->Launch(entity, LWOOBJID_EMPTY, 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) { +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; From 8462068a05c98ae8cd63c9c84f394fd884137fe4 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Wed, 30 Mar 2022 21:33:25 -0700 Subject: [PATCH 49/55] clarified variable names, used encapsulation --- dGame/dComponents/PropertyEntranceComponent.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/dGame/dComponents/PropertyEntranceComponent.cpp b/dGame/dComponents/PropertyEntranceComponent.cpp index 06886a0a..f125f326 100644 --- a/dGame/dComponents/PropertyEntranceComponent.cpp +++ b/dGame/dComponents/PropertyEntranceComponent.cpp @@ -104,8 +104,9 @@ std::string PropertyEntranceComponent::BuildQuery(Entity* entity, int32_t sortMe base = customQuery; } std::string orderBy = ""; - std::string friendsList = " AND p.owner_id IN ("; 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 dlu.friends ) AS fr WHERE requested_player IS NOT NULL ORDER BY requested_player DESC;"); friendsListQuery->setInt64(1, entity->GetObjectID()); @@ -165,15 +166,15 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl // If the player has a property this query will have a single result. if (playerPropertyLookupResults->next()) { const auto cloneId = playerPropertyLookupResults->getUInt64(4); - const auto name = playerPropertyLookupResults->getString(5).asStdString(); - const auto description = playerPropertyLookupResults->getString(6).asStdString(); + const auto propertyName = playerPropertyLookupResults->getString(5).asStdString(); + const auto propertyDescription = playerPropertyLookupResults->getString(6).asStdString(); const auto privacyOption = playerPropertyLookupResults->getInt(9); const auto modApproved = playerPropertyLookupResults->getBoolean(10); const auto dateLastUpdated = playerPropertyLookupResults->getInt64(11); const auto reputation = playerPropertyLookupResults->getUInt(14); const auto performanceCost = (float)playerPropertyLookupResults->getDouble(16); - playerEntry = SetPropertyValues(playerEntry, cloneId, character->GetName(), name, description, reputation, true, true, modApproved, true, true, privacyOption, dateLastUpdated, performanceCost); + playerEntry = SetPropertyValues(playerEntry, cloneId, character->GetName(), propertyName, propertyDescription, reputation, true, true, modApproved, true, true, privacyOption, dateLastUpdated, performanceCost); } else { playerEntry = SetPropertyValues(playerEntry, character->GetPropertyCloneID(), character->GetName(), "", "", 0, true, true); } From e66421d34f3868b7bb9ef9849cc80dcacd99a8c8 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Wed, 30 Mar 2022 21:58:43 -0700 Subject: [PATCH 50/55] clarified variable name --- dGame/dComponents/PropertyEntranceComponent.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/dGame/dComponents/PropertyEntranceComponent.cpp b/dGame/dComponents/PropertyEntranceComponent.cpp index f125f326..4dd2eed0 100644 --- a/dGame/dComponents/PropertyEntranceComponent.cpp +++ b/dGame/dComponents/PropertyEntranceComponent.cpp @@ -206,8 +206,8 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl const auto propertyId = propertyEntry->getUInt64(1); const auto owner = propertyEntry->getInt(2); const auto cloneId = propertyEntry->getUInt64(4); - const auto name = propertyEntry->getString(5).asStdString(); - const auto description = propertyEntry->getString(6).asStdString(); + const auto propertyNameFromDb = propertyEntry->getString(5).asStdString(); + const auto propertyDescriptionFromDb = propertyEntry->getString(6).asStdString(); const auto privacyOption = propertyEntry->getInt(9); const auto modApproved = propertyEntry->getBoolean(10); const auto dateLastUpdated = propertyEntry->getInt(11); @@ -242,10 +242,8 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl delete nameLookup; nameLookup = nullptr; - std::string propertyName = ""; - std::string propertyDescription = ""; - propertyName = name; - propertyDescription = description; + std::string propertyName = propertyNameFromDb; + std::string propertyDescription = propertyDescriptionFromDb; bool isBestFriend = false; bool isFriend = false; From 0561f600316c1d48dd57e93f94b3e0ae10c1d762 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Wed, 30 Mar 2022 21:58:59 -0700 Subject: [PATCH 51/55] Added negative checks --- .../PropertyManagementComponent.cpp | 34 +++++++++++-------- .../dComponents/PropertyManagementComponent.h | 4 ++- dGame/dComponents/PropertyVendorComponent.cpp | 7 ++-- 3 files changed, 28 insertions(+), 17 deletions(-) diff --git a/dGame/dComponents/PropertyManagementComponent.cpp b/dGame/dComponents/PropertyManagementComponent.cpp index 431cb800..550d15fe 100644 --- a/dGame/dComponents/PropertyManagementComponent.cpp +++ b/dGame/dComponents/PropertyManagementComponent.cpp @@ -192,31 +192,35 @@ void PropertyManagementComponent::UpdatePropertyDetails(std::string name, std::s OnQueryPropertyData(GetOwner(), UNASSIGNED_SYSTEM_ADDRESS); } -void PropertyManagementComponent::Claim(const LWOOBJID playerId) +bool PropertyManagementComponent::Claim(const LWOOBJID playerId) { if (owner != LWOOBJID_EMPTY) { - return; + return false; } - - SetOwnerId(playerId); - - auto* zone = dZoneManager::Instance()->GetZone(); - - const auto& worldId = zone->GetZoneID(); - const auto zoneId = worldId.GetMapID(); auto* entity = EntityManager::Instance()->GetEntity(playerId); auto* user = entity->GetParentUser(); auto character = entity->GetCharacter(); - if (!character) return; + if (!character) return false; - const auto cloneId = character->GetPropertyCloneID(); + auto* zone = dZoneManager::Instance()->GetZone(); + + const auto& worldId = zone->GetZoneID(); + const auto propertyZoneId = worldId.GetMapID(); + const auto propertyCloneId = worldId.GetCloneID(); + + const auto playerCloneId = character->GetPropertyCloneID(); + + // If we are not on our clone do not allow us to claim the property + if (propertyCloneId != playerCloneId) return false; + + SetOwnerId(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)" @@ -225,9 +229,9 @@ void PropertyManagementComponent::Claim(const LWOOBJID playerId) insertion->setUInt64(1, propertyId); insertion->setUInt64(2, (uint32_t) playerId); insertion->setUInt(3, templateId); - insertion->setUInt64(4, cloneId); + insertion->setUInt64(4, playerCloneId); insertion->setString(5, zone->GetZoneName().c_str()); - insertion->setInt(6, zoneId); + insertion->setInt(6, propertyZoneId); // Try and execute the query, print an error if it fails. try @@ -239,12 +243,14 @@ void PropertyManagementComponent::Claim(const LWOOBJID playerId) Game::logger->Log("PropertyManagementComponent", "Failed to execute query: (%s)!\n", exception.what()); throw exception; + return false; } auto* zoneControlObject = dZoneManager::Instance()->GetZoneControlObject(); for (CppScripts::Script* script : CppScripts::GetEntityScripts(zoneControlObject)) { script->OnZonePropertyRented(zoneControlObject, entity); } + return true; } void PropertyManagementComponent::OnStartBuilding() diff --git a/dGame/dComponents/PropertyManagementComponent.h b/dGame/dComponents/PropertyManagementComponent.h index fd208b63..c37282e9 100644 --- a/dGame/dComponents/PropertyManagementComponent.h +++ b/dGame/dComponents/PropertyManagementComponent.h @@ -101,8 +101,10 @@ public: /** * Makes this property owned by the passed player ID, storing it in the database * @param playerId the ID of the entity that claimed the property + * + * @return If the claim is successful return true. */ - void Claim(LWOOBJID playerId); + bool Claim(LWOOBJID playerId); /** * Event triggered when the owner of the property starts building, will kick other entities out diff --git a/dGame/dComponents/PropertyVendorComponent.cpp b/dGame/dComponents/PropertyVendorComponent.cpp index e6b8fe97..72e8ad64 100644 --- a/dGame/dComponents/PropertyVendorComponent.cpp +++ b/dGame/dComponents/PropertyVendorComponent.cpp @@ -41,13 +41,16 @@ void PropertyVendorComponent::OnBuyFromVendor(Entity* originator, const bool con { if (PropertyManagementComponent::Instance() == nullptr) return; + if (PropertyManagementComponent::Instance()->Claim(originator->GetObjectID()) == false) { + Game::logger->Log("PropertyVendorComponent", "FAILED TO CLAIM PROPERTY. PLAYER ID IS %llu\n", originator->GetObjectID()); + return; + } + GameMessages::SendPropertyRentalResponse(m_Parent->GetObjectID(), 0, 0, 0, 0, originator->GetSystemAddress()); auto* controller = dZoneManager::Instance()->GetZoneControlObject(); controller->OnFireEventServerSide(m_Parent, "propertyRented"); - - PropertyManagementComponent::Instance()->Claim(originator->GetObjectID()); PropertyManagementComponent::Instance()->SetOwner(originator); From aed0ecc9fc3aea0677093ecae99ae857e1bc96f4 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Wed, 30 Mar 2022 22:05:09 -0700 Subject: [PATCH 52/55] removed newline --- dGame/dComponents/PropertyEntranceComponent.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/dGame/dComponents/PropertyEntranceComponent.h b/dGame/dComponents/PropertyEntranceComponent.h index 0e948068..a3be38a6 100644 --- a/dGame/dComponents/PropertyEntranceComponent.h +++ b/dGame/dComponents/PropertyEntranceComponent.h @@ -58,8 +58,7 @@ class PropertyEntranceComponent : public Component { */ [[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); + 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, std::string customQuery = "", bool wantLimits = true); From 9169acad476d0f5f5e5427fbe247910419da28fa Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Wed, 30 Mar 2022 22:14:51 -0700 Subject: [PATCH 53/55] changed to update --- dGame/dGameMessages/GameMessages.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dGame/dGameMessages/GameMessages.cpp b/dGame/dGameMessages/GameMessages.cpp index e8973283..1a1795f2 100644 --- a/dGame/dGameMessages/GameMessages.cpp +++ b/dGame/dGameMessages/GameMessages.cpp @@ -4167,7 +4167,7 @@ void GameMessages::HandleUpdatePropertyPerformanceCost(RakNet::BitStream* inStre updatePerformanceCostQuery->setInt(2, cloneId); updatePerformanceCostQuery->setInt(3, zoneId); - updatePerformanceCostQuery->execute(); + updatePerformanceCostQuery->executeUpdate(); delete updatePerformanceCostQuery; updatePerformanceCostQuery = nullptr; From cc9b6c05f60ebef1b545eec36c57239ecef934b2 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Wed, 30 Mar 2022 22:35:41 -0700 Subject: [PATCH 54/55] removed include --- dGame/dGameMessages/PropertySelectQueryProperty.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/dGame/dGameMessages/PropertySelectQueryProperty.cpp b/dGame/dGameMessages/PropertySelectQueryProperty.cpp index 6a66554d..38e7cea2 100644 --- a/dGame/dGameMessages/PropertySelectQueryProperty.cpp +++ b/dGame/dGameMessages/PropertySelectQueryProperty.cpp @@ -1,5 +1,4 @@ #include "PropertySelectQueryProperty.h" -#include void PropertySelectQueryProperty::Serialize(RakNet::BitStream& stream) const { From 33b16a56e32beda7ffe55a3f4d9c401aa6bba241 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Wed, 30 Mar 2022 22:51:09 -0700 Subject: [PATCH 55/55] Added a save and fixed a crash If am item were to be added to properties_contents and an item with that Primary Key already existed, the world would crash. This addresses this. --- .../PropertyManagementComponent.cpp | 32 +++++++++++++------ 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/dGame/dComponents/PropertyManagementComponent.cpp b/dGame/dComponents/PropertyManagementComponent.cpp index 550d15fe..f982326c 100644 --- a/dGame/dComponents/PropertyManagementComponent.cpp +++ b/dGame/dComponents/PropertyManagementComponent.cpp @@ -296,6 +296,8 @@ void PropertyManagementComponent::OnFinishBuilding() SetPrivacyOption(originalPrivacyOption); UpdateApprovedStatus(false); + + Save(); } void PropertyManagementComponent::UpdateModelPosition(const LWOOBJID id, const NiPoint3 position, NiQuaternion rotation) @@ -706,9 +708,12 @@ void PropertyManagementComponent::Save() auto* remove = Database::CreatePreppedStmt("DELETE FROM properties_contents WHERE id = ?;"); lookup->setUInt64(1, propertyId); - - auto* lookupResult = lookup->executeQuery(); - + sql::ResultSet* lookupResult = nullptr; + try { + lookupResult = lookup->executeQuery(); + } catch (sql::SQLException& ex) { + Game::logger->Log("PropertyManagementComponent", "lookup error %s\n", ex.what()); + } std::vector present; while (lookupResult->next()) @@ -751,8 +756,11 @@ void PropertyManagementComponent::Save() insertion->setDouble(9, rotation.y); insertion->setDouble(10, rotation.z); insertion->setDouble(11, rotation.w); - - insertion->execute(); + try { + insertion->execute(); + } catch (sql::SQLException& ex) { + Game::logger->Log("PropertyManagementComponent", "Error inserting into properties_contents. Error %s\n", ex.what()); + } } else { @@ -765,8 +773,11 @@ void PropertyManagementComponent::Save() update->setDouble(7, rotation.w); update->setInt64(8, id); - - update->executeUpdate(); + try { + update->executeUpdate(); + } catch (sql::SQLException& ex) { + Game::logger->Log("PropertyManagementComponent", "Error updating properties_contents. Error: %s\n", ex.what()); + } } } @@ -778,8 +789,11 @@ void PropertyManagementComponent::Save() } remove->setInt64(1, id); - - remove->execute(); + try { + remove->execute(); + } catch (sql::SQLException& ex) { + Game::logger->Log("PropertyManagementComponent", "Error removing from properties_contents. Error %s\n", ex.what()); + } } auto* removeUGC = Database::CreatePreppedStmt("DELETE FROM ugc WHERE id NOT IN (SELECT ugc_id FROM properties_contents);");