2021-12-05 17:54:36 +00:00
# include "TradingManager.h"
# include "EntityManager.h"
# include "GameMessages.h"
# include "InventoryComponent.h"
# include "../dWorldServer/ObjectIDManager.h"
# include "Game.h"
# include "dLogger.h"
# include "Item.h"
# include "Character.h"
# include "CharacterComponent.h"
# include "MissionComponent.h"
TradingManager * TradingManager : : m_Address = nullptr ;
2022-07-25 02:26:51 +00:00
Trade : : Trade ( LWOOBJID tradeId , LWOOBJID participantA , LWOOBJID participantB ) {
2021-12-05 17:54:36 +00:00
m_TradeId = tradeId ;
m_ParticipantA = participantA ;
m_ParticipantB = participantB ;
}
2022-07-25 02:26:51 +00:00
Trade : : ~ Trade ( ) {
2021-12-05 17:54:36 +00:00
}
LWOOBJID Trade : : GetTradeId ( ) const {
return m_TradeId ;
}
bool Trade : : IsParticipant ( LWOOBJID playerId ) const {
return m_ParticipantA = = playerId | | m_ParticipantB = = playerId ;
}
LWOOBJID Trade : : GetParticipantA ( ) const {
return m_ParticipantA ;
}
LWOOBJID Trade : : GetParticipantB ( ) const {
return m_ParticipantB ;
}
Entity * Trade : : GetParticipantAEntity ( ) const {
return EntityManager : : Instance ( ) - > GetEntity ( m_ParticipantA ) ;
}
Entity * Trade : : GetParticipantBEntity ( ) const {
return EntityManager : : Instance ( ) - > GetEntity ( m_ParticipantB ) ;
}
2022-07-25 02:26:51 +00:00
void Trade : : SetCoins ( LWOOBJID participant , uint64_t coins ) {
2021-12-05 17:54:36 +00:00
if ( participant = = m_ParticipantA ) {
m_CoinsA = coins ;
2022-04-05 12:11:06 +00:00
} else if ( participant = = m_ParticipantB ) {
2021-12-05 17:54:36 +00:00
m_CoinsB = coins ;
}
}
2022-07-25 02:26:51 +00:00
void Trade : : SetItems ( LWOOBJID participant , std : : vector < TradeItem > items ) {
2021-12-05 17:54:36 +00:00
if ( participant = = m_ParticipantA ) {
m_ItemsA = items ;
2022-04-05 12:11:06 +00:00
} else if ( participant = = m_ParticipantB ) {
2021-12-05 17:54:36 +00:00
m_ItemsB = items ;
}
}
2022-07-25 02:26:51 +00:00
void Trade : : SetAccepted ( LWOOBJID participant , bool value ) {
2021-12-05 17:54:36 +00:00
if ( participant = = m_ParticipantA ) {
m_AcceptedA = ! value ;
2022-07-28 13:39:57 +00:00
2022-07-25 02:26:51 +00:00
Game : : logger - > Log ( " Trade " , " Accepted from A (%d), B: (%d) " , value , m_AcceptedB ) ;
2022-07-28 13:39:57 +00:00
2021-12-05 17:54:36 +00:00
auto * entityB = GetParticipantBEntity ( ) ;
2022-07-28 13:39:57 +00:00
2021-12-05 17:54:36 +00:00
if ( entityB ! = nullptr ) {
GameMessages : : SendServerTradeAccept ( m_ParticipantB , value , entityB - > GetSystemAddress ( ) ) ;
}
} else if ( participant = = m_ParticipantB ) {
m_AcceptedB = ! value ;
2022-07-28 13:39:57 +00:00
2022-07-25 02:26:51 +00:00
Game : : logger - > Log ( " Trade " , " Accepted from B (%d), A: (%d) " , value , m_AcceptedA ) ;
2022-07-28 13:39:57 +00:00
2021-12-05 17:54:36 +00:00
auto * entityA = GetParticipantAEntity ( ) ;
2022-07-28 13:39:57 +00:00
2021-12-05 17:54:36 +00:00
if ( entityA ! = nullptr ) {
GameMessages : : SendServerTradeAccept ( m_ParticipantA , value , entityA - > GetSystemAddress ( ) ) ;
}
}
2022-07-28 13:39:57 +00:00
2021-12-05 17:54:36 +00:00
if ( m_AcceptedA & & m_AcceptedB ) {
auto * entityB = GetParticipantBEntity ( ) ;
2022-07-28 13:39:57 +00:00
2021-12-05 17:54:36 +00:00
if ( entityB ! = nullptr ) {
GameMessages : : SendServerTradeAccept ( m_ParticipantB , false , entityB - > GetSystemAddress ( ) ) ;
} else {
return ;
}
2022-07-28 13:39:57 +00:00
2021-12-05 17:54:36 +00:00
auto * entityA = GetParticipantAEntity ( ) ;
2022-07-28 13:39:57 +00:00
2021-12-05 17:54:36 +00:00
if ( entityA ! = nullptr ) {
GameMessages : : SendServerTradeAccept ( m_ParticipantA , false , entityA - > GetSystemAddress ( ) ) ;
} else {
return ;
}
2022-07-28 13:39:57 +00:00
2021-12-05 17:54:36 +00:00
Complete ( ) ;
2022-12-19 20:51:44 +00:00
TradingManager : : Instance ( ) - > CancelTrade ( m_TradeId ) ;
2021-12-05 17:54:36 +00:00
}
}
2022-07-25 02:26:51 +00:00
void Trade : : Complete ( ) {
2021-12-05 17:54:36 +00:00
auto * entityA = GetParticipantAEntity ( ) ;
auto * entityB = GetParticipantBEntity ( ) ;
2022-07-25 02:26:51 +00:00
2021-12-05 17:54:36 +00:00
if ( entityA = = nullptr | | entityB = = nullptr ) return ;
auto * inventoryA = entityA - > GetComponent < InventoryComponent > ( ) ;
auto * inventoryB = entityB - > GetComponent < InventoryComponent > ( ) ;
auto * missionsA = entityA - > GetComponent < MissionComponent > ( ) ;
auto * missionsB = entityB - > GetComponent < MissionComponent > ( ) ;
auto * characterA = entityA - > GetCharacter ( ) ;
auto * characterB = entityB - > GetCharacter ( ) ;
if ( inventoryA = = nullptr | | inventoryB = = nullptr | | characterA = = nullptr | | characterB = = nullptr | | missionsA = = nullptr | | missionsB = = nullptr ) return ;
2022-12-19 20:51:44 +00:00
// First verify both players have the coins and items requested for the trade.
if ( characterA - > GetCoins ( ) < m_CoinsA | | characterB - > GetCoins ( ) < m_CoinsB ) {
Game : : logger - > Log ( " TradingManager " , " Possible coin trade cheating attempt! Aborting trade. " ) ;
return ;
}
2021-12-05 17:54:36 +00:00
for ( const auto & tradeItem : m_ItemsA ) {
2022-12-19 20:51:44 +00:00
auto * itemToRemove = inventoryA - > FindItemById ( tradeItem . itemId ) ;
if ( itemToRemove ) {
if ( itemToRemove - > GetCount ( ) < tradeItem . itemCount ) {
Game : : logger - > Log ( " TradingManager " , " Possible cheating attempt from %s in trading!!! Aborting trade " , characterA - > GetName ( ) . c_str ( ) ) ;
return ;
}
} else {
Game : : logger - > Log ( " TradingManager " , " Possible cheating attempt from %s in trading due to item not being available!!! " , characterA - > GetName ( ) . c_str ( ) ) ;
return ;
}
2021-12-05 17:54:36 +00:00
}
2022-07-25 02:26:51 +00:00
2021-12-05 17:54:36 +00:00
for ( const auto & tradeItem : m_ItemsB ) {
2022-12-19 20:51:44 +00:00
auto * itemToRemove = inventoryB - > FindItemById ( tradeItem . itemId ) ;
if ( itemToRemove ) {
if ( itemToRemove - > GetCount ( ) < tradeItem . itemCount ) {
Game : : logger - > Log ( " TradingManager " , " Possible cheating attempt from %s in trading!!! Aborting trade " , characterB - > GetName ( ) . c_str ( ) ) ;
return ;
}
} else {
Game : : logger - > Log ( " TradingManager " , " Possible cheating attempt from %s in trading due to item not being available!!! Aborting trade " , characterB - > GetName ( ) . c_str ( ) ) ;
return ;
}
2021-12-05 17:54:36 +00:00
}
2022-12-19 20:51:44 +00:00
// Now actually do the trade.
characterA - > SetCoins ( characterA - > GetCoins ( ) - m_CoinsA + m_CoinsB , eLootSourceType : : LOOT_SOURCE_TRADE ) ;
characterB - > SetCoins ( characterB - > GetCoins ( ) - m_CoinsB + m_CoinsA , eLootSourceType : : LOOT_SOURCE_TRADE ) ;
2021-12-05 17:54:36 +00:00
for ( const auto & tradeItem : m_ItemsA ) {
2022-12-19 20:51:44 +00:00
auto * itemToRemove = inventoryA - > FindItemById ( tradeItem . itemId ) ;
if ( itemToRemove ) itemToRemove - > SetCount ( itemToRemove - > GetCount ( ) - tradeItem . itemCount ) ;
missionsA - > Progress ( MissionTaskType : : MISSION_TASK_TYPE_ITEM_COLLECTION , tradeItem . itemLot , LWOOBJID_EMPTY , " " , - tradeItem . itemCount ) ;
2022-04-24 03:35:34 +00:00
inventoryB - > AddItem ( tradeItem . itemLot , tradeItem . itemCount , eLootSourceType : : LOOT_SOURCE_TRADE ) ;
2021-12-05 17:54:36 +00:00
}
for ( const auto & tradeItem : m_ItemsB ) {
2022-12-19 20:51:44 +00:00
auto * itemToRemove = inventoryB - > FindItemById ( tradeItem . itemId ) ;
if ( itemToRemove ) itemToRemove - > SetCount ( itemToRemove - > GetCount ( ) - tradeItem . itemCount ) ;
missionsB - > Progress ( MissionTaskType : : MISSION_TASK_TYPE_ITEM_COLLECTION , tradeItem . itemLot , LWOOBJID_EMPTY , " " , - tradeItem . itemCount ) ;
2022-04-24 03:35:34 +00:00
inventoryA - > AddItem ( tradeItem . itemLot , tradeItem . itemCount , eLootSourceType : : LOOT_SOURCE_TRADE ) ;
2021-12-05 17:54:36 +00:00
}
characterA - > SaveXMLToDatabase ( ) ;
characterB - > SaveXMLToDatabase ( ) ;
2022-12-19 20:51:44 +00:00
return ;
2021-12-05 17:54:36 +00:00
}
2022-07-25 02:26:51 +00:00
void Trade : : Cancel ( ) {
2021-12-05 17:54:36 +00:00
auto * entityA = GetParticipantAEntity ( ) ;
auto * entityB = GetParticipantBEntity ( ) ;
2022-07-25 02:26:51 +00:00
2021-12-05 17:54:36 +00:00
if ( entityA = = nullptr | | entityB = = nullptr ) return ;
GameMessages : : SendServerTradeCancel ( entityA - > GetObjectID ( ) , entityA - > GetSystemAddress ( ) ) ;
GameMessages : : SendServerTradeCancel ( entityB - > GetObjectID ( ) , entityB - > GetSystemAddress ( ) ) ;
}
2022-07-25 02:26:51 +00:00
void Trade : : SendUpdateToOther ( LWOOBJID participant ) {
2021-12-05 17:54:36 +00:00
Entity * other = nullptr ;
Entity * self = nullptr ;
uint64_t coins ;
std : : vector < TradeItem > itemIds ;
2022-07-25 02:26:51 +00:00
Game : : logger - > Log ( " Trade " , " Attempting to send trade update " ) ;
2021-12-05 17:54:36 +00:00
if ( participant = = m_ParticipantA ) {
other = GetParticipantBEntity ( ) ;
self = GetParticipantAEntity ( ) ;
coins = m_CoinsA ;
itemIds = m_ItemsA ;
} else if ( participant = = m_ParticipantB ) {
other = GetParticipantAEntity ( ) ;
self = GetParticipantBEntity ( ) ;
coins = m_CoinsB ;
itemIds = m_ItemsB ;
} else {
return ;
}
2022-07-25 02:26:51 +00:00
2021-12-05 17:54:36 +00:00
if ( other = = nullptr | | self = = nullptr ) return ;
std : : vector < TradeItem > items { } ;
2022-07-25 02:26:51 +00:00
2021-12-05 17:54:36 +00:00
auto * inventoryComponent = self - > GetComponent < InventoryComponent > ( ) ;
if ( inventoryComponent = = nullptr ) return ;
for ( const auto tradeItem : itemIds ) {
auto * item = inventoryComponent - > FindItemById ( tradeItem . itemId ) ;
if ( item = = nullptr ) return ;
if ( tradeItem . itemCount > item - > GetCount ( ) ) return ;
items . push_back ( tradeItem ) ;
}
2022-07-25 02:26:51 +00:00
Game : : logger - > Log ( " Trade " , " Sending trade update " ) ;
2021-12-05 17:54:36 +00:00
GameMessages : : SendServerTradeUpdate ( other - > GetObjectID ( ) , coins , items , other - > GetSystemAddress ( ) ) ;
}
TradingManager : : TradingManager ( ) {
}
TradingManager : : ~ TradingManager ( ) {
for ( const auto & pair : trades ) {
delete pair . second ;
}
2022-07-25 02:26:51 +00:00
2021-12-05 17:54:36 +00:00
trades . clear ( ) ;
}
Trade * TradingManager : : GetTrade ( LWOOBJID tradeId ) const {
const auto & pair = trades . find ( tradeId ) ;
if ( pair = = trades . end ( ) ) return nullptr ;
return pair - > second ;
}
Trade * TradingManager : : GetPlayerTrade ( LWOOBJID playerId ) const {
for ( const auto & pair : trades ) {
if ( pair . second - > IsParticipant ( playerId ) ) {
return pair . second ;
2022-07-28 13:39:57 +00:00
}
2021-12-05 17:54:36 +00:00
}
2022-07-28 13:39:57 +00:00
2021-12-05 17:54:36 +00:00
return nullptr ;
}
2022-07-25 02:26:51 +00:00
void TradingManager : : CancelTrade ( LWOOBJID tradeId ) {
2021-12-05 17:54:36 +00:00
auto * trade = GetTrade ( tradeId ) ;
if ( trade = = nullptr ) return ;
2022-07-25 02:26:51 +00:00
2021-12-05 17:54:36 +00:00
delete trade ;
trades . erase ( tradeId ) ;
}
2022-07-25 02:26:51 +00:00
Trade * TradingManager : : NewTrade ( LWOOBJID participantA , LWOOBJID participantB ) {
2021-12-05 17:54:36 +00:00
const LWOOBJID tradeId = ObjectIDManager : : Instance ( ) - > GenerateObjectID ( ) ;
auto * trade = new Trade ( tradeId , participantA , participantB ) ;
2022-07-25 02:26:51 +00:00
2021-12-05 17:54:36 +00:00
trades [ tradeId ] = trade ;
2022-07-25 02:26:51 +00:00
Game : : logger - > Log ( " TradingManager " , " Created new trade between (%llu) <-> (%llu) " , participantA , participantB ) ;
2021-12-05 17:54:36 +00:00
return trade ;
}