2022-03-31 03:33:50 +00:00
# include " PropertyEntranceComponent.h "
# include <CDPropertyEntranceComponentTable.h>
2021-12-05 17:54:36 +00:00
# include "Character.h"
# include "Database.h"
2022-03-31 03:33:50 +00:00
# include "GameMessages.h"
2021-12-05 17:54:36 +00:00
# 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"
2021-12-05 17:54:36 +00:00
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 )
{
2022-03-29 02:58:50 +00:00
// Increment index once here because the first index of other player properties is 2 in the propertyQueries cache.
2021-12-05 17:54:36 +00:00
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 ) ;
2022-03-29 02:58:50 +00:00
launcher - > Launch ( entity , LWOOBJID_EMPTY , launcher - > GetTargetZone ( ) , cloneId ) ;
2021-12-05 17:54:36 +00:00
}
2022-03-29 02:58:50 +00:00
PropertySelectQueryProperty PropertyEntranceComponent : : SetPropertyValues ( PropertySelectQueryProperty property , LWOCLONEID cloneId , std : : string ownerName , std : : string propertyName , std : : string propertyDescription ,
2022-03-30 02:48:34 +00:00
float reputation , bool isBFF , bool isFriend , bool isModeratorApproved , bool isAlt , bool isOwned , uint32_t privacyOption , uint32_t timeLastUpdated , float performanceCost ) {
2022-03-29 02:58:50 +00:00
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 ;
}
2021-12-05 17:54:36 +00:00
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 ( " ;
2022-03-29 02:58:50 +00:00
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 " ;
2022-03-29 02:58:50 +00:00
delete friendsListQueryResult ;
friendsListQueryResult = nullptr ;
2022-03-29 09:33:15 +00:00
2022-03-29 02:58:50 +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 " ;
2021-12-05 17:54:36 +00:00
}
2022-03-30 23:12:42 +00:00
return base + orderBy + ( wantLimits ? " LIMIT ? OFFSET ?; " : " ; " ) ;
2022-03-29 02:58:50 +00:00
}
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 ( ) ;
2022-03-29 02:58:50 +00:00
if ( ! character ) return ;
2022-03-29 03:51:15 +00:00
2022-03-29 02:58:50 +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 ) ;
2022-03-29 21:54:31 +00:00
const auto reputation = playerPropertyLookupResults - > getUInt ( 14 ) ;
2022-03-30 02:48:34 +00:00
const auto performanceCost = ( float ) playerPropertyLookupResults - > getDouble ( 16 ) ;
2022-03-29 02:58:50 +00:00
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 ) ;
2022-03-29 02:58:50 +00:00
} else {
playerEntry = SetPropertyValues ( playerEntry , character - > GetPropertyCloneID ( ) , character - > GetName ( ) , " " , " " , 0 , true , true ) ;
}
delete playerPropertyLookupResults ;
playerPropertyLookupResults = nullptr ;
2022-03-29 03:51:15 +00:00
2022-03-29 02:58:50 +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 + " % " ;
2022-03-29 02:58:50 +00:00
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 ) ;
2021-12-05 17:54:36 +00:00
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 ) ;
2022-03-29 21:54:31 +00:00
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 = ?; " ) ;
2021-12-05 17:54:36 +00:00
nameLookup - > setUInt64 ( 1 , cloneId ) ;
2022-03-29 03:51:15 +00:00
auto nameResult = nameLookup - > executeQuery ( ) ;
2021-12-05 17:54:36 +00:00
2022-03-29 03:51:15 +00:00
if ( ! nameResult - > next ( ) ) {
2021-12-05 17:54:36 +00:00
delete nameLookup ;
2022-03-29 03:51:15 +00:00
nameLookup = nullptr ;
2021-12-05 17:54:36 +00:00
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 ( ) ;
2021-12-05 17:54:36 +00:00
}
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 ) ;
2021-12-05 17:54:36 +00:00
entries . push_back ( entry ) ;
2022-03-31 03:33:50 +00:00
}
2021-12-05 17:54:36 +00:00
2022-03-29 03:51:15 +00:00
delete propertyEntry ;
propertyEntry = nullptr ;
2021-12-05 17:54:36 +00:00
delete propertyLookup ;
2022-03-29 03:51:15 +00:00
propertyLookup = nullptr ;
2022-03-28 10:24:49 +00:00
2021-12-05 17:54:36 +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 ) ;
2021-12-05 17:54:36 +00:00
}