DarkflameServer/dGame/dComponents/PropertyEntranceComponent.cpp

344 lines
13 KiB
C++
Raw Normal View History

2022-03-31 03:33:50 +00:00
#include "PropertyEntranceComponent.h"
#include <CDPropertyEntranceComponentTable.h>
#include "Character.h"
#include "Database.h"
2022-03-31 03:33:50 +00:00
#include "GameMessages.h"
#include "PropertyManagementComponent.h"
2022-03-31 03:33:50 +00:00
#include "PropertySelectQueryProperty.h"
#include "RocketLaunchpadControlComponent.h"
2022-03-28 03:04:45 +00:00
#include "UserManager.h"
2022-03-31 03:33:50 +00:00
#include "dLogger.h"
PropertyEntranceComponent::PropertyEntranceComponent(uint32_t componentID, Entity* parent) : Component(parent)
{
this->propertyQueries = {};
auto table = CDClientManager::Instance()->GetTable<CDPropertyEntranceComponentTable>("PropertyEntranceComponent");
const auto& entry = table->GetByID(componentID);
this->m_MapID = entry.mapID;
this->m_PropertyName = entry.propertyName;
}
void PropertyEntranceComponent::OnUse(Entity* entity)
{
GameMessages::SendPropertyEntranceBegin(m_Parent->GetObjectID(), entity->GetSystemAddress());
AMFArrayValue args;
auto* state = new AMFStringValue();
state->SetStringValue("property_menu");
args.InsertValue("state", state);
GameMessages::SendUIMessageServerToSingleClient(entity, entity->GetSystemAddress(), "pushGameState", &args);
delete state;
}
void PropertyEntranceComponent::OnEnterProperty(Entity* entity, uint32_t index, bool returnToZone, const SystemAddress& sysAddr)
{
LWOCLONEID cloneId = 0;
if (index == -1 && !returnToZone)
{
cloneId = entity->GetCharacter()->GetPropertyCloneID();
}
else if (index == -1 && returnToZone)
{
cloneId = 0;
}
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());
if (pair == propertyQueries.end()) return;
const auto& query = pair->second;
if (index >= query.size()) return;
cloneId = query[index].CloneId;
}
auto* launcher = m_Parent->GetComponent<RocketLaunchpadControlComponent>();
if (launcher == nullptr)
{
return;
}
launcher->SetSelectedCloneId(entity->GetObjectID(), cloneId);
launcher->Launch(entity, LWOOBJID_EMPTY, launcher->GetTargetZone(), cloneId);
}
2022-03-31 04:18:29 +00:00
PropertySelectQueryProperty PropertyEntranceComponent::SetPropertyValues(PropertySelectQueryProperty property, LWOCLONEID cloneId, std::string ownerName, std::string propertyName, std::string propertyDescription, float reputation, bool isBFF, bool isFriend, bool isModeratorApproved, bool isAlt, bool isOwned, uint32_t privacyOption, uint32_t timeLastUpdated, float performanceCost) {
property.CloneId = cloneId;
property.OwnerName = ownerName;
property.Name = propertyName;
property.Description = propertyDescription;
property.Reputation = reputation;
property.IsBestFriend = isBFF;
property.IsFriend = isFriend;
property.IsModeratorApproved = isModeratorApproved;
property.IsAlt = isAlt;
property.IsOwned = isOwned;
property.AccessType = privacyOption;
property.DateLastPublished = timeLastUpdated;
property.PerformanceCost = performanceCost;
return property;
}
2022-03-30 23:12:42 +00:00
std::string PropertyEntranceComponent::BuildQuery(Entity* entity, int32_t sortMethod, std::string customQuery, bool wantLimits) {
std::string base;
if (customQuery == "") {
base = baseQueryForProperties;
} else {
base = customQuery;
}
2022-03-28 03:04:45 +00:00
std::string orderBy = "";
2022-03-28 10:24:49 +00:00
std::string friendsList = " AND p.owner_id IN (";
if (sortMethod == SORT_TYPE_FEATURED || sortMethod == SORT_TYPE_FRIENDS) {
2022-03-28 10:24:49 +00:00
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());
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.
2022-03-29 08:00:30 +00:00
if (friendsList.at(friendsList.size() - 1) == ',') friendsList.erase(friendsList.size() - 1, 1);
friendsList += ") ";
2022-03-29 09:33:15 +00:00
// If we have no friends then use a -1 for the query.
2022-03-30 23:12:42 +00:00
if (friendsList.find("()") != std::string::npos) friendsList = " AND p.owner_id IN (-1) ";
2022-03-29 08:00:30 +00:00
orderBy += friendsList + "ORDER BY ci.name ASC ";
delete friendsListQueryResult;
friendsListQueryResult = nullptr;
2022-03-29 09:33:15 +00:00
delete friendsListQuery;
friendsListQuery = nullptr;
2022-03-28 03:04:45 +00:00
}
else if (sortMethod == SORT_TYPE_RECENT) {
2022-03-28 10:24:49 +00:00
orderBy = "ORDER BY p.last_updated DESC ";
2022-03-28 03:04:45 +00:00
}
else if (sortMethod == SORT_TYPE_REPUTATION) {
2022-03-28 10:24:49 +00:00
orderBy = "ORDER BY p.reputation DESC, p.last_updated DESC ";
2022-03-28 03:04:45 +00:00
}
else {
2022-03-28 10:24:49 +00:00
orderBy = "ORDER BY p.last_updated DESC ";
}
2022-03-30 23:12:42 +00:00
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){
std::vector<PropertySelectQueryProperty> entries {};
PropertySelectQueryProperty playerEntry {};
2022-03-29 03:51:15 +00:00
auto character = entity->GetCharacter();
if (!character) return;
2022-03-29 03:51:15 +00:00
// 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->getUInt(14);
2022-03-30 02:48:34 +00:00
const auto performanceCost = (float)playerPropertyLookupResults->getDouble(16);
2022-03-30 02:48:34 +00:00
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);
}
delete playerPropertyLookupResults;
playerPropertyLookupResults = nullptr;
2022-03-29 03:51:15 +00:00
delete playerPropertyLookup;
playerPropertyLookup = nullptr;
entries.push_back(playerEntry);
const auto query = BuildQuery(entity, sortMethod);
2022-03-29 03:51:15 +00:00
auto propertyLookup = Database::CreatePreppedStmt(query);
2022-03-31 04:12:22 +00:00
2022-03-29 03:51:15 +00:00
const auto searchString = "%" + filterText + "%";
propertyLookup->setUInt(1, this->m_MapID);
2022-03-28 03:04:45 +00:00
propertyLookup->setString(2, searchString.c_str());
2022-03-28 10:24:49 +00:00
propertyLookup->setString(3, searchString.c_str());
propertyLookup->setString(4, searchString.c_str());
2022-03-31 04:12:22 +00:00
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);
2022-03-28 03:04:45 +00:00
2022-03-29 03:51:15 +00:00
auto propertyEntry = propertyLookup->executeQuery();
2022-03-31 03:33:50 +00:00
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();
2022-03-31 03:33:50 +00:00
const auto privacyOption = propertyEntry->getInt(9);
2022-03-28 03:04:45 +00:00
const auto modApproved = propertyEntry->getBoolean(10);
2022-03-29 03:51:15 +00:00
const auto dateLastUpdated = propertyEntry->getInt(11);
const float reputation = propertyEntry->getInt(14);
2022-03-30 02:48:34 +00:00
const auto performanceCost = (float)propertyEntry->getDouble(16);
2022-03-28 10:24:49 +00:00
2022-03-31 03:33:50 +00:00
PropertySelectQueryProperty entry{};
2022-03-29 03:51:15 +00:00
std::string ownerName = "";
bool isOwned = true;
auto nameLookup = Database::CreatePreppedStmt("SELECT name FROM charinfo WHERE prop_clone_id = ?;");
nameLookup->setUInt64(1, cloneId);
2022-03-29 03:51:15 +00:00
auto nameResult = nameLookup->executeQuery();
2022-03-29 03:51:15 +00:00
if (!nameResult->next()) {
delete nameLookup;
2022-03-29 03:51:15 +00:00
nameLookup = nullptr;
Game::logger->Log("PropertyEntranceComponent", "Failed to find property owner name for %llu!\n", cloneId);
continue;
2022-03-31 03:33:50 +00:00
} else {
2022-03-29 03:51:15 +00:00
isOwned = cloneId == character->GetPropertyCloneID();
ownerName = nameResult->getString(1).asStdString();
}
2022-03-28 06:46:43 +00:00
2022-03-29 03:51:15 +00:00
delete nameResult;
nameResult = nullptr;
2022-03-31 03:33:50 +00:00
delete nameLookup;
2022-03-29 03:51:15 +00:00
nameLookup = nullptr;
std::string propertyName = "";
std::string propertyDescription = "";
propertyName = name;
propertyDescription = description;
bool isBestFriend = false;
bool isFriend = false;
2022-03-28 03:04:45 +00:00
// Convert owner char id to LWOOBJID
LWOOBJID ownerObjId = owner;
ownerObjId = GeneralUtils::SetBit(ownerObjId, OBJECT_BIT_CHARACTER);
ownerObjId = GeneralUtils::SetBit(ownerObjId, OBJECT_BIT_PERSISTENT);
2022-03-29 03:51:15 +00:00
// Query to get friend and best friend fields
2022-03-28 06:46:43 +00:00
auto friendCheck = Database::CreatePreppedStmt("SELECT best_friend FROM friends WHERE (player_id = ? AND friend_id = ?) OR (player_id = ? AND friend_id = ?)");
2022-03-28 03:04:45 +00:00
friendCheck->setInt64(1, entity->GetObjectID());
friendCheck->setInt64(2, ownerObjId);
friendCheck->setInt64(3, ownerObjId);
friendCheck->setInt64(4, entity->GetObjectID());
auto friendResult = friendCheck->executeQuery();
2022-03-31 03:33:50 +00:00
2022-03-28 03:04:45 +00:00
// If we got a result than the two players are friends.
if (friendResult->next()) {
2022-03-29 03:51:15 +00:00
isFriend = true;
2022-03-29 08:57:23 +00:00
if (friendResult->getInt(1) == 2) {
2022-03-29 03:51:15 +00:00
isBestFriend = true;
2022-03-28 06:46:43 +00:00
}
2022-03-28 03:04:45 +00:00
}
2022-03-29 03:51:15 +00:00
delete friendCheck;
friendCheck = nullptr;
delete friendResult;
friendResult = nullptr;
bool isModeratorApproved = propertyEntry->getBoolean(10);
if (!isModeratorApproved && entity->GetGMLevel() >= GAME_MASTER_LEVEL_LEAD_MODERATOR) {
propertyName = "[AWAITING APPROVAL]";
propertyDescription = "[AWAITING APPROVAL]";
2022-03-29 03:53:09 +00:00
isModeratorApproved = true;
2022-03-28 06:46:43 +00:00
}
2022-03-29 03:51:15 +00:00
bool isAlt = false;
2022-03-31 04:12:22 +00:00
// Query to determine whether this property is an alt character of the entity.
2022-03-28 06:46:43 +00:00
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);
auto isAltQueryResults = isAltQuery->executeQuery();
if (isAltQueryResults->next()) {
2022-03-29 03:51:15 +00:00
isAlt = true;
2022-03-28 03:04:45 +00:00
}
2022-03-29 03:51:15 +00:00
delete isAltQueryResults;
isAltQueryResults = nullptr;
2022-03-28 06:46:43 +00:00
delete isAltQuery;
isAltQuery = nullptr;
2022-03-29 03:51:15 +00:00
2022-03-30 02:48:34 +00:00
entry = SetPropertyValues(entry, cloneId, ownerName, propertyName, propertyDescription, reputation, isBestFriend, isFriend, isModeratorApproved, isAlt, isOwned, privacyOption, dateLastUpdated, performanceCost);
entries.push_back(entry);
2022-03-31 03:33:50 +00:00
}
2022-03-29 03:51:15 +00:00
delete propertyEntry;
propertyEntry = nullptr;
delete propertyLookup;
2022-03-29 03:51:15 +00:00
propertyLookup = nullptr;
2022-03-28 10:24:49 +00:00
propertyQueries[entity->GetObjectID()] = entries;
2022-03-31 04:12:22 +00:00
// Query here is to figure out whether or not to display the button to go to the next page or not.
2022-03-30 23:12:42 +00:00
int32_t numberOfProperties = 0;
2022-03-29 10:50:41 +00:00
2022-03-31 04:12:22 +00:00
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);
2022-03-30 23:12:42 +00:00
auto propertiesLeft = Database::CreatePreppedStmt(buttonQuery);
2022-03-29 10:50:41 +00:00
2022-03-30 23:12:42 +00:00
propertiesLeft->setUInt(1, this->m_MapID);
propertiesLeft->setString(2, searchString.c_str());
propertiesLeft->setString(3, searchString.c_str());
propertiesLeft->setString(4, searchString.c_str());
2022-03-31 04:12:22 +00:00
propertiesLeft->setInt(5, sortMethod == SORT_TYPE_FEATURED || sortMethod == SORT_TYPE_FRIENDS ? 1 : 2);
2022-03-30 06:59:50 +00:00
2022-03-30 23:12:42 +00:00
auto result = propertiesLeft->executeQuery();
result->next();
numberOfProperties = result->getInt(1);
2022-03-29 10:50:41 +00:00
2022-03-30 23:12:42 +00:00
delete result;
result = nullptr;
2022-03-30 06:59:50 +00:00
2022-03-30 23:12:42 +00:00
delete propertiesLeft;
propertiesLeft = nullptr;
2022-03-29 10:50:41 +00:00
GameMessages::SendPropertySelectQuery(m_Parent->GetObjectID(), startIndex, numberOfProperties - (startIndex + numResults) > 0, character->GetPropertyCloneID(), false, true, entries, sysAddr);
}