2018-03-06 22:22:19 +01:00
# include <Logging/Logger.h>
# include <Database/DatabaseDef.h>
# include <Exd/ExdDataGenerated.h>
2018-01-27 23:52:49 +01:00
2019-01-28 20:48:33 +11:00
# include "ServerMgr.h"
2018-02-28 10:26:03 +01:00
# include <unordered_map>
2020-02-29 22:30:10 +11:00
# include <Service.h>
2018-02-28 10:26:03 +01:00
2018-01-28 22:36:43 +01:00
# include "Actor/Player.h"
2019-07-21 22:33:33 +10:00
# include "Territory/Territory.h"
2018-12-01 00:27:16 +11:00
# include "Territory/ZonePosition.h"
# include "Territory/InstanceContent.h"
2019-03-31 23:45:03 +02:00
# include "Territory/QuestBattle.h"
2021-08-16 17:18:29 +09:00
# include "Territory/PublicContent.h"
2018-03-02 07:22:25 -03:00
# include "TerritoryMgr.h"
2018-12-01 18:18:29 +11:00
# include "HousingMgr.h"
2018-01-27 23:52:49 +01:00
2018-12-01 18:18:29 +11:00
# include "Territory/Land.h"
# include "Territory/House.h"
# include "Territory/Housing/HousingInteriorTerritory.h"
2019-01-23 19:23:49 +01:00
# include "NaviMgr.h"
2018-12-01 18:18:29 +11:00
2020-03-01 01:00:57 +11:00
Sapphire : : World : : Manager : : TerritoryMgr : : TerritoryMgr ( ) :
2018-08-29 21:40:59 +02:00
m_lastInstanceId ( 10000 )
2018-01-27 23:52:49 +01:00
{
}
2018-12-01 00:27:16 +11:00
void Sapphire : : World : : Manager : : TerritoryMgr : : loadTerritoryTypeDetailCache ( )
2018-01-27 23:52:49 +01:00
{
2020-03-01 01:00:57 +11:00
auto & exdData = Common : : Service < Data : : ExdDataGenerated > : : ref ( ) ;
auto idList = exdData . getTerritoryTypeIdList ( ) ;
2018-01-27 23:52:49 +01:00
2018-08-29 21:40:59 +02:00
for ( auto id : idList )
{
2020-03-01 01:00:57 +11:00
auto teri1 = exdData . get < Sapphire : : Data : : TerritoryType > ( id ) ;
2018-01-27 23:52:49 +01:00
2018-08-29 21:40:59 +02:00
if ( ! teri1 - > name . empty ( ) )
m_territoryTypeDetailCacheMap [ id ] = teri1 ;
}
2019-04-11 00:16:04 +02:00
2020-03-01 01:00:57 +11:00
for ( auto id : exdData . getContentFinderConditionIdList ( ) )
2019-04-11 00:16:04 +02:00
{
2020-03-01 01:00:57 +11:00
auto cfc = exdData . get < Sapphire : : Data : : ContentFinderCondition > ( id ) ;
2019-04-11 00:16:04 +02:00
if ( ! cfc | | cfc - > contentLinkType ! = 5 )
continue ;
m_questBattleToContentFinderMap [ cfc - > content ] = id ;
}
2018-01-27 23:52:49 +01:00
}
2018-12-01 00:27:16 +11:00
bool Sapphire : : World : : Manager : : TerritoryMgr : : isValidTerritory ( uint32_t territoryTypeId ) const
2018-01-27 23:52:49 +01:00
{
2018-08-29 21:40:59 +02:00
return ! ( m_territoryTypeDetailCacheMap . find ( territoryTypeId ) = = m_territoryTypeDetailCacheMap . end ( ) ) ;
2018-01-27 23:52:49 +01:00
}
2018-12-01 00:27:16 +11:00
bool Sapphire : : World : : Manager : : TerritoryMgr : : init ( )
2018-01-27 23:52:49 +01:00
{
2018-12-16 14:26:38 +01:00
try
{
loadTerritoryTypeDetailCache ( ) ;
loadTerritoryPositionMap ( ) ;
2018-01-27 23:52:49 +01:00
2018-12-16 14:26:38 +01:00
createDefaultTerritories ( ) ;
createHousingTerritories ( ) ;
}
2019-04-29 19:59:19 +10:00
catch ( const std : : runtime_error & ex )
2018-12-16 14:26:38 +01:00
{
2019-04-29 19:59:19 +10:00
Logger : : fatal ( " Caught exception during territory init: {} " , ex . what ( ) ) ;
2018-12-16 14:26:38 +01:00
return false ;
}
2018-01-27 23:52:49 +01:00
2020-02-29 22:30:10 +11:00
auto & serverMgr = Common : : Service < World : : ServerMgr > : : ref ( ) ;
auto & cfg = serverMgr . getConfig ( ) ;
2019-01-28 20:48:33 +11:00
m_inRangeDistance = cfg . network . inRangeDistance ;
2018-08-29 21:40:59 +02:00
return true ;
2018-01-27 23:52:49 +01:00
}
2018-12-01 00:27:16 +11:00
uint32_t Sapphire : : World : : Manager : : TerritoryMgr : : getNextInstanceId ( )
2018-01-27 23:52:49 +01:00
{
2018-08-29 21:40:59 +02:00
return + + m_lastInstanceId ;
2018-01-27 23:52:49 +01:00
}
2018-12-01 00:27:16 +11:00
Sapphire : : Data : : TerritoryTypePtr Sapphire : : World : : Manager : : TerritoryMgr : : getTerritoryDetail ( uint32_t territoryTypeId ) const
2018-01-27 23:52:49 +01:00
{
2018-08-29 21:40:59 +02:00
auto tIt = m_territoryTypeDetailCacheMap . find ( territoryTypeId ) ;
if ( tIt = = m_territoryTypeDetailCacheMap . end ( ) )
return nullptr ;
2018-01-27 23:52:49 +01:00
2018-08-29 21:40:59 +02:00
return tIt - > second ;
2018-01-27 23:52:49 +01:00
}
2018-12-01 00:27:16 +11:00
bool Sapphire : : World : : Manager : : TerritoryMgr : : isInstanceContentTerritory ( uint32_t territoryTypeId ) const
2018-01-27 23:52:49 +01:00
{
2018-08-29 21:40:59 +02:00
auto pTeri = getTerritoryDetail ( territoryTypeId ) ;
if ( ! pTeri )
return false ;
auto intendedUse = pTeri - > territoryIntendedUse ;
return intendedUse = = TerritoryIntendedUse : : AllianceRaid | |
intendedUse = = TerritoryIntendedUse : : BeforeTrialDung | |
intendedUse = = TerritoryIntendedUse : : Trial | |
intendedUse = = TerritoryIntendedUse : : Dungeon | |
intendedUse = = TerritoryIntendedUse : : OpenWorldInstanceBattle | |
intendedUse = = TerritoryIntendedUse : : PalaceOfTheDead | |
intendedUse = = TerritoryIntendedUse : : RaidFights | |
intendedUse = = TerritoryIntendedUse : : Raids | |
intendedUse = = TerritoryIntendedUse : : TreasureMapInstance | |
intendedUse = = TerritoryIntendedUse : : EventTrial ;
2018-01-27 23:52:49 +01:00
}
2018-12-01 00:27:16 +11:00
bool Sapphire : : World : : Manager : : TerritoryMgr : : isPrivateTerritory ( uint32_t territoryTypeId ) const
2018-01-27 23:52:49 +01:00
{
2018-08-29 21:40:59 +02:00
auto pTeri = getTerritoryDetail ( territoryTypeId ) ;
2018-01-27 23:52:49 +01:00
2018-08-29 21:40:59 +02:00
if ( ! pTeri )
return false ;
2018-01-27 23:52:49 +01:00
2018-08-29 21:40:59 +02:00
return pTeri - > territoryIntendedUse = = TerritoryIntendedUse : : OpeningArea | |
pTeri - > territoryIntendedUse = = TerritoryIntendedUse : : Inn | |
pTeri - > territoryIntendedUse = = TerritoryIntendedUse : : JailArea | |
pTeri - > territoryIntendedUse = = TerritoryIntendedUse : : MSQPrivateArea ;
2018-01-27 23:52:49 +01:00
}
2018-12-28 19:45:04 +11:00
bool Sapphire : : World : : Manager : : TerritoryMgr : : isInternalEstateTerritory ( uint32_t territoryTypeId ) const
{
auto pTeri = getTerritoryDetail ( territoryTypeId ) ;
if ( ! pTeri )
return false ;
return pTeri - > territoryIntendedUse = = TerritoryIntendedUse : : HousingPrivateArea ;
}
2018-12-01 00:27:16 +11:00
bool Sapphire : : World : : Manager : : TerritoryMgr : : isDefaultTerritory ( uint32_t territoryTypeId ) const
2018-11-06 11:11:07 +01:00
{
auto pTeri = getTerritoryDetail ( territoryTypeId ) ;
if ( ! pTeri )
return false ;
return pTeri - > territoryIntendedUse = = TerritoryIntendedUse : : Inn | |
pTeri - > territoryIntendedUse = = TerritoryIntendedUse : : Town | |
pTeri - > territoryIntendedUse = = TerritoryIntendedUse : : OpenWorld | |
pTeri - > territoryIntendedUse = = TerritoryIntendedUse : : OpeningArea ;
}
2018-12-01 00:27:16 +11:00
bool Sapphire : : World : : Manager : : TerritoryMgr : : isHousingTerritory ( uint32_t territoryTypeId ) const
2018-11-06 11:11:07 +01:00
{
auto pTeri = getTerritoryDetail ( territoryTypeId ) ;
if ( ! pTeri )
return false ;
return pTeri - > territoryIntendedUse = = TerritoryIntendedUse : : HousingArea ;
}
2018-01-27 23:52:49 +01:00
2018-12-01 00:27:16 +11:00
bool Sapphire : : World : : Manager : : TerritoryMgr : : createDefaultTerritories ( )
2018-01-27 23:52:49 +01:00
{
2020-03-01 01:00:57 +11:00
auto & exdData = Common : : Service < Data : : ExdDataGenerated > : : ref ( ) ;
2018-08-29 21:40:59 +02:00
// for each entry in territoryTypeExd, check if it is a normal and if so, add the zone object
for ( const auto & territory : m_territoryTypeDetailCacheMap )
{
2018-11-05 23:07:39 +01:00
auto territoryTypeId = territory . first ;
2018-08-29 21:40:59 +02:00
auto territoryInfo = territory . second ;
// if the zone has no name set
if ( territoryInfo - > name . empty ( ) )
continue ;
2020-03-01 01:00:57 +11:00
auto pPlaceName = exdData . get < Sapphire : : Data : : PlaceName > ( territoryInfo - > placeName ) ;
2018-08-29 21:40:59 +02:00
2018-11-05 23:07:39 +01:00
if ( ! pPlaceName | | pPlaceName - > name . empty ( ) | | ! isDefaultTerritory ( territoryTypeId ) )
2018-08-29 21:40:59 +02:00
continue ;
uint32_t guid = getNextInstanceId ( ) ;
2019-01-04 22:37:01 +11:00
2020-03-01 01:00:57 +11:00
auto pZone = make_Territory ( territoryTypeId , guid , territoryInfo - > name , pPlaceName - > name ) ;
2019-04-19 00:39:42 +02:00
pZone - > init ( ) ;
2019-01-25 08:31:20 +01:00
std : : string bgPath = territoryInfo - > bg ;
2019-04-19 00:39:42 +02:00
bool hasNaviMesh = pZone - > getNaviProvider ( ) ! = nullptr ;
2019-01-20 16:10:48 +01:00
2019-01-25 12:34:21 +11:00
Logger : : info ( " {0} \t {1} \t {2} \t {3:<10} \t {4} \t {5} \t {6} " ,
2019-01-04 22:59:09 +11:00
territoryTypeId ,
guid ,
territoryInfo - > territoryIntendedUse ,
territoryInfo - > name ,
( isPrivateTerritory ( territoryTypeId ) ? " PRIVATE " : " PUBLIC " ) ,
2019-01-25 12:23:38 +11:00
hasNaviMesh ? " NAVI " : " " ,
pPlaceName - > name ) ;
2019-01-23 19:23:49 +01:00
2019-07-21 22:33:33 +10:00
InstanceIdToTerritoryPtrMap instanceMap ;
2018-08-29 21:40:59 +02:00
instanceMap [ guid ] = pZone ;
2019-07-21 22:33:33 +10:00
m_guIdToTerritoryPtrMap [ guid ] = pZone ;
2018-11-05 23:07:39 +01:00
m_territoryTypeIdToInstanceGuidMap [ territoryTypeId ] = instanceMap ;
2019-07-24 21:58:48 +10:00
m_territorySet . insert ( { pZone } ) ;
2018-08-29 21:40:59 +02:00
}
return true ;
}
2018-01-27 23:52:49 +01:00
2018-12-01 00:27:16 +11:00
bool Sapphire : : World : : Manager : : TerritoryMgr : : createHousingTerritories ( )
2018-08-29 21:40:59 +02:00
{
//separate housing zones from default
2020-03-01 01:00:57 +11:00
auto & exdData = Common : : Service < Data : : ExdDataGenerated > : : ref ( ) ;
2018-08-29 21:40:59 +02:00
for ( const auto & territory : m_territoryTypeDetailCacheMap )
{
2018-11-05 23:07:39 +01:00
auto territoryTypeId = territory . first ;
2018-08-29 21:40:59 +02:00
auto territoryInfo = territory . second ;
uint32_t wardNum ;
2019-01-25 12:34:21 +11:00
uint32_t wardMaxNum = 18 ;
2018-08-29 21:40:59 +02:00
if ( territoryInfo - > name . empty ( ) )
continue ;
2020-03-01 01:00:57 +11:00
auto pPlaceName = exdData . get < Sapphire : : Data : : PlaceName > ( territoryInfo - > placeName ) ;
2018-08-29 21:40:59 +02:00
2018-11-05 23:07:39 +01:00
if ( ! pPlaceName | | pPlaceName - > name . empty ( ) | | ! isHousingTerritory ( territoryTypeId ) )
2018-08-29 21:40:59 +02:00
continue ;
for ( wardNum = 0 ; wardNum < wardMaxNum ; wardNum + + )
{
2018-01-27 23:52:49 +01:00
uint32_t guid = getNextInstanceId ( ) ;
2019-01-04 22:37:01 +11:00
2019-01-25 12:34:21 +11:00
Logger : : info ( " {0} \t {1} \t {2} \t {3:<10} \t HOUSING \t \t {4}#{5} " ,
2019-01-04 22:37:01 +11:00
territoryTypeId ,
guid ,
territoryInfo - > territoryIntendedUse ,
territoryInfo - > name ,
pPlaceName - > name ,
wardNum ) ;
2018-01-27 23:52:49 +01:00
2020-03-01 01:00:57 +11:00
auto pHousingZone = make_HousingZone ( wardNum , territoryTypeId , guid , territoryInfo - > name , pPlaceName - > name ) ;
2018-08-29 21:40:59 +02:00
pHousingZone - > init ( ) ;
2018-01-27 23:52:49 +01:00
2019-07-21 22:33:33 +10:00
InstanceIdToTerritoryPtrMap instanceMap ;
2018-08-29 21:40:59 +02:00
instanceMap [ guid ] = pHousingZone ;
2019-07-21 22:33:33 +10:00
m_guIdToTerritoryPtrMap [ guid ] = pHousingZone ;
2018-11-05 23:07:39 +01:00
m_territoryTypeIdToInstanceGuidMap [ territoryTypeId ] [ guid ] = pHousingZone ;
2019-07-21 22:33:33 +10:00
m_landSetIdToTerritoryPtrMap [ pHousingZone - > getLandSetId ( ) ] = pHousingZone ;
2019-07-24 21:58:48 +10:00
m_territorySet . insert ( { pHousingZone } ) ;
2018-08-29 21:40:59 +02:00
}
2018-01-27 23:52:49 +01:00
2018-08-29 21:40:59 +02:00
}
2018-01-27 23:52:49 +01:00
2018-08-29 21:40:59 +02:00
return true ;
2018-07-15 23:59:15 +02:00
}
2019-07-21 22:33:33 +10:00
Sapphire : : TerritoryPtr Sapphire : : World : : Manager : : TerritoryMgr : : createTerritoryInstance ( uint32_t territoryTypeId )
2018-01-28 23:53:58 +11:00
{
2018-08-29 21:40:59 +02:00
if ( ! isValidTerritory ( territoryTypeId ) )
return nullptr ;
2018-01-28 23:53:58 +11:00
2019-05-07 22:16:18 +10:00
// nb: disabled for now because there's not a real reason to have this constraint, makes testing some stuff easier too
// if( isInstanceContentTerritory( territoryTypeId ) )
// return nullptr;
2018-01-29 19:40:27 +11:00
2020-03-01 01:00:57 +11:00
auto & exdData = Common : : Service < Data : : ExdDataGenerated > : : ref ( ) ;
2018-08-29 21:40:59 +02:00
auto pTeri = getTerritoryDetail ( territoryTypeId ) ;
2020-03-01 01:00:57 +11:00
auto pPlaceName = exdData . get < Sapphire : : Data : : PlaceName > ( pTeri - > placeName ) ;
2018-01-28 23:53:58 +11:00
2018-08-29 21:40:59 +02:00
if ( ! pTeri | | ! pPlaceName )
return nullptr ;
2018-01-28 23:53:58 +11:00
2019-01-04 22:37:01 +11:00
Logger : : debug ( " Starting instance for territory: {0} ({1}) " , territoryTypeId , pPlaceName - > name ) ;
2018-01-28 23:53:58 +11:00
2020-03-01 01:00:57 +11:00
auto pZone = make_Territory ( territoryTypeId , getNextInstanceId ( ) , pTeri - > name , pPlaceName - > name ) ;
2018-08-29 21:40:59 +02:00
pZone - > init ( ) ;
2018-01-28 23:53:58 +11:00
2019-07-21 22:33:33 +10:00
m_guIdToTerritoryPtrMap [ pZone - > getGuId ( ) ] = pZone ;
2018-11-05 23:07:39 +01:00
m_territoryTypeIdToInstanceGuidMap [ pZone - > getTerritoryTypeId ( ) ] [ pZone - > getGuId ( ) ] = pZone ;
2019-07-24 21:58:48 +10:00
m_territorySet . insert ( { pZone } ) ;
2018-01-28 23:53:58 +11:00
2018-08-29 21:40:59 +02:00
return pZone ;
2018-01-28 23:53:58 +11:00
}
2019-07-21 22:33:33 +10:00
Sapphire : : TerritoryPtr Sapphire : : World : : Manager : : TerritoryMgr : : createQuestBattle ( uint32_t questBattleId )
2019-03-31 23:45:03 +02:00
{
2019-04-11 00:16:04 +02:00
auto it = m_questBattleToContentFinderMap . find ( questBattleId ) ;
if ( it = = m_questBattleToContentFinderMap . end ( ) )
return nullptr ;
auto contentFinderConditionId = it - > second ;
2020-03-01 01:00:57 +11:00
auto & exdData = Common : : Service < Data : : ExdDataGenerated > : : ref ( ) ;
auto pContentFinderCondition = exdData . get < Sapphire : : Data : : ContentFinderCondition > ( contentFinderConditionId ) ;
2019-03-31 23:45:03 +02:00
if ( ! pContentFinderCondition )
return nullptr ;
2020-03-01 01:00:57 +11:00
auto pQuestBattleInfo = exdData . get < Sapphire : : Data : : QuestBattle > ( questBattleId ) ;
2019-03-31 23:45:03 +02:00
if ( ! pQuestBattleInfo )
return nullptr ;
2020-03-01 01:00:57 +11:00
auto pQuestInfo = exdData . get < Sapphire : : Data : : Quest > ( pQuestBattleInfo - > quest ) ;
2019-03-31 23:45:03 +02:00
if ( ! pQuestInfo )
return nullptr ;
if ( ! isInstanceContentTerritory ( pContentFinderCondition - > territoryType ) )
return nullptr ;
auto pTeri = getTerritoryDetail ( pContentFinderCondition - > territoryType ) ;
if ( ! pTeri | | pQuestInfo - > name . empty ( ) )
return nullptr ;
2019-04-11 00:16:04 +02:00
Logger : : debug ( " Starting instance for QuestBattle id: {0} ({1}) " , questBattleId , pQuestInfo - > name ) ;
2019-03-31 23:45:03 +02:00
auto pZone = make_QuestBattle ( pQuestBattleInfo , pContentFinderCondition - > territoryType , getNextInstanceId ( ) ,
2021-08-16 17:18:29 +09:00
pTeri - > name , pQuestInfo - > name , questBattleId , contentFinderConditionId ) ;
2019-03-31 23:45:03 +02:00
pZone - > init ( ) ;
2019-04-07 16:01:53 +02:00
m_questBattleIdToInstanceMap [ questBattleId ] [ pZone - > getGuId ( ) ] = pZone ;
2019-07-21 22:33:33 +10:00
m_guIdToTerritoryPtrMap [ pZone - > getGuId ( ) ] = pZone ;
2019-03-31 23:45:03 +02:00
m_instanceZoneSet . insert ( pZone ) ;
return pZone ;
}
2019-07-21 22:33:33 +10:00
Sapphire : : TerritoryPtr Sapphire : : World : : Manager : : TerritoryMgr : : createInstanceContent ( uint32_t contentFinderConditionId )
2018-01-29 19:40:27 +11:00
{
2020-03-01 01:00:57 +11:00
auto & exdData = Common : : Service < Data : : ExdDataGenerated > : : ref ( ) ;
2018-09-19 23:04:23 +02:00
2020-03-01 01:00:57 +11:00
auto pContentFinderCondition = exdData . get < Sapphire : : Data : : ContentFinderCondition > ( contentFinderConditionId ) ;
2018-09-19 23:04:23 +02:00
if ( ! pContentFinderCondition )
return nullptr ;
2018-11-23 21:16:02 +01:00
auto instanceContentId = pContentFinderCondition - > content ;
2018-09-19 23:04:23 +02:00
2020-03-01 01:00:57 +11:00
auto pInstanceContent = exdData . get < Sapphire : : Data : : InstanceContent > ( instanceContentId ) ;
2018-08-29 21:40:59 +02:00
if ( ! pInstanceContent )
return nullptr ;
2018-01-29 19:40:27 +11:00
2018-09-19 23:04:23 +02:00
if ( ! isInstanceContentTerritory ( pContentFinderCondition - > territoryType ) )
2018-08-29 21:40:59 +02:00
return nullptr ;
2018-01-29 19:40:27 +11:00
2018-09-19 23:04:23 +02:00
auto pTeri = getTerritoryDetail ( pContentFinderCondition - > territoryType ) ;
2018-01-29 19:40:27 +11:00
2019-11-23 02:57:29 -05:00
if ( ! pTeri | | pContentFinderCondition - > name . empty ( ) )
2018-08-29 21:40:59 +02:00
return nullptr ;
2018-01-29 19:40:27 +11:00
2020-02-24 23:04:25 +11:00
Logger : : debug ( " Starting instance for InstanceContent id: {0} ({1}) " , instanceContentId , pContentFinderCondition - > name ) ;
2018-01-29 19:40:27 +11:00
2018-09-19 23:04:23 +02:00
auto pZone = make_InstanceContent ( pInstanceContent , pContentFinderCondition - > territoryType , getNextInstanceId ( ) ,
2021-08-16 17:18:29 +09:00
pTeri - > name , pContentFinderCondition - > name , instanceContentId , contentFinderConditionId ) ;
2018-08-29 21:40:59 +02:00
pZone - > init ( ) ;
2018-01-29 19:40:27 +11:00
2018-12-30 18:48:45 +11:00
m_instanceContentIdToInstanceMap [ instanceContentId ] [ pZone - > getGuId ( ) ] = pZone ;
2019-07-21 22:33:33 +10:00
m_guIdToTerritoryPtrMap [ pZone - > getGuId ( ) ] = pZone ;
2018-08-29 21:40:59 +02:00
m_instanceZoneSet . insert ( pZone ) ;
2018-01-29 19:40:27 +11:00
2018-08-29 21:40:59 +02:00
return pZone ;
2018-01-29 19:40:27 +11:00
}
2021-08-16 17:18:29 +09:00
Sapphire : : TerritoryPtr Sapphire : : World : : Manager : : TerritoryMgr : : createPublicContent ( uint32_t contentFinderConditionId )
{
auto & exdData = Common : : Service < Data : : ExdDataGenerated > : : ref ( ) ;
auto pContentFinderCondition = exdData . get < Sapphire : : Data : : ContentFinderCondition > ( contentFinderConditionId ) ;
if ( ! pContentFinderCondition )
return nullptr ;
auto contentId = pContentFinderCondition - > content ;
auto pPublicContent = exdData . get < Sapphire : : Data : : PublicContent > ( contentId ) ;
if ( ! pPublicContent )
return nullptr ;
auto pTeri = getTerritoryDetail ( pContentFinderCondition - > territoryType ) ;
if ( ! pTeri | | pContentFinderCondition - > name . empty ( ) )
return nullptr ;
Logger : : debug ( " Starting instance for PublicContent id: {0} ({1}) " , contentId , pContentFinderCondition - > name ) ;
auto pZone = make_PublicContent ( pPublicContent , pContentFinderCondition - > territoryType , getNextInstanceId ( ) ,
pTeri - > name , pContentFinderCondition - > name , contentId , contentFinderConditionId ) ;
pZone - > init ( ) ;
m_publicContentIdToInstanceMap [ contentId ] [ pZone - > getGuId ( ) ] = pZone ;
m_guIdToTerritoryPtrMap [ pZone - > getGuId ( ) ] = pZone ;
m_instanceZoneSet . insert ( pZone ) ;
return pZone ;
}
Sapphire : : TerritoryPtr Sapphire : : World : : Manager : : TerritoryMgr : : createPublicContent ( uint16_t contentId , uint16_t territoryId )
{
auto & exdData = Common : : Service < Data : : ExdDataGenerated > : : ref ( ) ;
auto pPublicContent = exdData . get < Sapphire : : Data : : PublicContent > ( contentId ) ;
if ( ! pPublicContent )
return nullptr ;
if ( pPublicContent - > contentFinderCondition > 0 )
{
Logger : : warn ( " the public content {} has a ContentFinderCondition value of {}, create the instance using it instead. " , contentId , pPublicContent - > contentFinderCondition ) ;
return nullptr ;
}
auto pTeri = getTerritoryDetail ( territoryId ) ;
if ( ! pTeri )
return nullptr ;
Logger : : debug ( " Starting instance for PublicContent id: {0} ({1}) " , contentId , pPublicContent - > name ) ;
auto pZone = make_PublicContent ( pPublicContent , territoryId , getNextInstanceId ( ) , pTeri - > name , pPublicContent - > name , contentId , 0 ) ;
pZone - > init ( ) ;
m_publicContentIdToInstanceMap [ contentId ] [ pZone - > getGuId ( ) ] = pZone ;
m_guIdToTerritoryPtrMap [ pZone - > getGuId ( ) ] = pZone ;
m_instanceZoneSet . insert ( pZone ) ;
return pZone ;
}
2019-07-21 22:33:33 +10:00
Sapphire : : TerritoryPtr Sapphire : : World : : Manager : : TerritoryMgr : : findOrCreateHousingInterior ( const Common : : LandIdent landIdent )
2018-12-01 00:27:16 +11:00
{
2018-12-01 18:18:29 +11:00
// check if zone already spawned first
auto ident = * reinterpret_cast < const uint64_t * > ( & landIdent ) ;
2019-07-21 22:33:33 +10:00
auto it = m_landIdentToTerritoryPtrMap . find ( ident ) ;
if ( it ! = m_landIdentToTerritoryPtrMap . end ( ) )
2018-12-01 18:18:29 +11:00
{
return it - > second ;
}
// otherwise, create it
2020-03-01 01:00:57 +11:00
auto & housingMgr = Common : : Service < Manager : : HousingMgr > : : ref ( ) ;
2018-12-01 18:18:29 +11:00
auto parentZone = std : : dynamic_pointer_cast < HousingZone > (
2020-03-01 01:00:57 +11:00
getZoneByLandSetId ( housingMgr . toLandSetId ( static_cast < uint16_t > ( landIdent . territoryTypeId ) ,
2018-12-02 02:01:41 +01:00
static_cast < uint8_t > ( landIdent . wardNum ) ) ) ) ;
2018-12-01 18:18:29 +11:00
if ( ! parentZone )
return nullptr ;
auto land = parentZone - > getLand ( landIdent . landId ) ;
if ( ! land )
return nullptr ;
auto house = land - > getHouse ( ) ;
if ( ! house )
return nullptr ;
// get house instance id
uint16_t territoryTypeId = 0 ;
switch ( landIdent . territoryTypeId )
{
case 339 : // mist
territoryTypeId = 282 ;
break ;
case 340 : // lavender beds
territoryTypeId = 342 ;
break ;
case 341 : // goblet
territoryTypeId = 345 ;
break ;
case 641 : // shirogane
territoryTypeId = 649 ;
break ;
default :
return nullptr ;
}
// zones are sequential in the exd for small, med, large
territoryTypeId + = land - > getSize ( ) ;
auto terriInfo = getTerritoryDetail ( territoryTypeId ) ;
if ( ! terriInfo )
return nullptr ;
2018-12-29 00:53:52 +01:00
auto zone = World : : Territory : : Housing : : make_HousingInteriorTerritory ( landIdent , territoryTypeId ,
getNextInstanceId ( ) , terriInfo - > name ,
2020-03-01 01:00:57 +11:00
house - > getHouseName ( ) ) ;
2018-12-01 18:18:29 +11:00
zone - > init ( ) ;
2019-07-21 22:33:33 +10:00
m_landIdentToTerritoryPtrMap [ ident ] = zone ;
m_guIdToTerritoryPtrMap [ zone - > getGuId ( ) ] = zone ;
2019-07-24 21:58:48 +10:00
m_territorySet . insert ( { zone } ) ;
2018-12-01 00:27:16 +11:00
2018-12-01 18:18:29 +11:00
return zone ;
2018-12-01 00:27:16 +11:00
}
2019-04-07 16:01:53 +02:00
bool Sapphire : : World : : Manager : : TerritoryMgr : : removeTerritoryInstance ( uint32_t guId )
2018-01-29 00:52:11 +11:00
{
2019-07-21 22:33:33 +10:00
TerritoryPtr pZone ;
2019-05-07 22:10:55 +10:00
if ( ( pZone = getTerritoryByGuId ( guId ) ) = = nullptr )
2018-08-29 21:40:59 +02:00
return false ;
2018-01-29 00:52:11 +11:00
2019-07-21 22:33:33 +10:00
m_guIdToTerritoryPtrMap . erase ( pZone - > getGuId ( ) ) ;
2018-01-29 20:40:32 +11:00
2018-08-29 21:40:59 +02:00
m_instanceZoneSet . erase ( pZone ) ;
2019-07-24 21:58:48 +10:00
m_territorySet . erase ( pZone ) ;
2018-02-01 23:32:59 +01:00
2021-08-16 17:18:29 +09:00
if ( pZone - > getAsInstanceContent ( ) )
2018-08-29 21:40:59 +02:00
{
2018-10-25 12:44:51 +11:00
auto instance = std : : dynamic_pointer_cast < InstanceContent > ( pZone ) ;
2018-12-30 18:48:45 +11:00
m_instanceContentIdToInstanceMap [ instance - > getInstanceContentId ( ) ] . erase ( pZone - > getGuId ( ) ) ;
2018-08-29 21:40:59 +02:00
}
2021-08-16 17:18:29 +09:00
else if ( pZone - > getAsPublicContent ( ) )
{
auto instance = std : : dynamic_pointer_cast < PublicContent > ( pZone ) ;
m_publicContentIdToInstanceMap [ instance - > getContentId ( ) ] . erase ( pZone - > getGuId ( ) ) ;
}
else if ( pZone - > getAsQuestBattle ( ) )
{
auto instance = std : : dynamic_pointer_cast < QuestBattle > ( pZone ) ;
m_questBattleIdToInstanceMap [ instance - > getQuestBattleId ( ) ] . erase ( pZone - > getGuId ( ) ) ;
}
2018-08-29 21:40:59 +02:00
else
2018-11-05 23:07:39 +01:00
m_territoryTypeIdToInstanceGuidMap [ pZone - > getTerritoryTypeId ( ) ] . erase ( pZone - > getGuId ( ) ) ;
2018-01-29 20:40:32 +11:00
2018-08-29 21:40:59 +02:00
return true ;
2018-01-29 00:52:11 +11:00
}
2019-07-21 22:33:33 +10:00
Sapphire : : TerritoryPtr Sapphire : : World : : Manager : : TerritoryMgr : : getTerritoryByGuId ( uint32_t guId ) const
2018-01-28 23:53:58 +11:00
{
2019-07-21 22:33:33 +10:00
auto it = m_guIdToTerritoryPtrMap . find ( guId ) ;
if ( it = = m_guIdToTerritoryPtrMap . end ( ) )
2018-08-29 21:40:59 +02:00
return nullptr ;
2018-01-28 23:53:58 +11:00
2018-08-29 21:40:59 +02:00
return it - > second ;
2018-01-28 23:53:58 +11:00
}
2018-12-01 00:27:16 +11:00
void Sapphire : : World : : Manager : : TerritoryMgr : : loadTerritoryPositionMap ( )
2018-01-27 23:52:49 +01:00
{
2020-03-01 01:00:57 +11:00
auto & db = Common : : Service < Db : : DbWorkerPool < Db : : ZoneDbConnection > > : : ref ( ) ;
auto pQR = db . query ( " SELECT id, target_zone_id, pos_x, pos_y, pos_z, pos_o, radius FROM zonepositions; " ) ;
2018-08-29 21:40:59 +02:00
while ( pQR - > next ( ) )
{
uint32_t id = pQR - > getUInt ( 1 ) ;
uint32_t targetZoneId = pQR - > getUInt ( 2 ) ;
Common : : FFXIVARR_POSITION3 pos { } ;
pos . x = pQR - > getFloat ( 3 ) ;
pos . y = pQR - > getFloat ( 4 ) ;
pos . z = pQR - > getFloat ( 5 ) ;
float posO = pQR - > getFloat ( 6 ) ;
uint32_t radius = pQR - > getUInt ( 7 ) ;
m_territoryPositionMap [ id ] = make_ZonePosition ( id , targetZoneId , pos , radius , posO ) ;
}
2018-01-27 23:52:49 +01:00
}
2018-12-01 00:27:16 +11:00
Sapphire : : ZonePositionPtr Sapphire : : World : : Manager : : TerritoryMgr : : getTerritoryPosition ( uint32_t territoryPositionId ) const
2018-01-27 23:52:49 +01:00
{
2018-08-29 21:40:59 +02:00
auto it = m_territoryPositionMap . find ( territoryPositionId ) ;
2018-01-27 23:52:49 +01:00
2018-08-29 21:40:59 +02:00
if ( it ! = m_territoryPositionMap . end ( ) )
return it - > second ;
2018-01-27 23:52:49 +01:00
2018-08-29 21:40:59 +02:00
return nullptr ;
2018-01-27 23:52:49 +01:00
}
2019-07-21 22:33:33 +10:00
Sapphire : : TerritoryPtr Sapphire : : World : : Manager : : TerritoryMgr : : getZoneByTerritoryTypeId ( uint32_t territoryTypeId ) const
2018-01-27 23:52:49 +01:00
{
2018-11-05 23:07:39 +01:00
auto zoneMap = m_territoryTypeIdToInstanceGuidMap . find ( territoryTypeId ) ;
if ( zoneMap = = m_territoryTypeIdToInstanceGuidMap . end ( ) )
2018-08-29 21:40:59 +02:00
return nullptr ;
2018-01-27 23:52:49 +01:00
2018-08-29 21:40:59 +02:00
// TODO: actually select the proper one
return zoneMap - > second . begin ( ) - > second ;
2018-01-27 23:52:49 +01:00
}
2019-07-21 22:33:33 +10:00
Sapphire : : TerritoryPtr Sapphire : : World : : Manager : : TerritoryMgr : : getZoneByLandSetId ( uint32_t landSetId ) const
2018-11-06 11:11:07 +01:00
{
2019-07-21 22:33:33 +10:00
auto zoneMap = m_landSetIdToTerritoryPtrMap . find ( landSetId ) ;
if ( zoneMap = = m_landSetIdToTerritoryPtrMap . end ( ) )
2018-11-06 11:11:07 +01:00
return nullptr ;
return zoneMap - > second ;
}
2019-04-04 23:29:52 +02:00
void Sapphire : : World : : Manager : : TerritoryMgr : : updateTerritoryInstances ( uint64_t tickCount )
2018-01-27 23:52:49 +01:00
{
2019-07-24 21:58:48 +10:00
for ( auto & zone : m_territorySet )
2018-08-29 21:40:59 +02:00
{
2019-04-04 23:29:52 +02:00
zone - > update ( tickCount ) ;
2018-08-29 21:40:59 +02:00
}
for ( auto & zone : m_instanceZoneSet )
{
2019-04-04 23:29:52 +02:00
zone - > update ( tickCount ) ;
2018-08-29 21:40:59 +02:00
}
2018-12-02 18:05:50 +11:00
// remove internal house zones with nobody in them
2019-07-21 22:33:33 +10:00
for ( auto it = m_landIdentToTerritoryPtrMap . begin ( ) ; it ! = m_landIdentToTerritoryPtrMap . end ( ) ; )
2018-12-02 18:05:50 +11:00
{
auto zone = std : : dynamic_pointer_cast < Territory : : Housing : : HousingInteriorTerritory > ( it - > second ) ;
assert ( zone ) ; // wtf??
2019-04-04 23:29:52 +02:00
auto diff = std : : difftime ( tickCount , zone - > getLastActivityTime ( ) ) ;
2018-12-02 18:05:50 +11:00
// todo: make this timeout configurable, though should be pretty relaxed in any case
2019-04-07 23:42:24 +02:00
if ( diff > 60000 )
2018-12-02 18:05:50 +11:00
{
2019-01-04 22:37:01 +11:00
Logger : : info ( " Removing HousingInteriorTerritory#{0} - has been inactive for 60 seconds " , zone - > getGuId ( ) ) ;
2018-12-02 18:05:50 +11:00
// remove zone from maps
2019-07-24 21:58:48 +10:00
m_territorySet . erase ( zone ) ;
2021-02-06 05:18:26 +09:00
m_guIdToTerritoryPtrMap . erase ( zone - > getGuId ( ) ) ;
2019-07-21 22:33:33 +10:00
it = m_landIdentToTerritoryPtrMap . erase ( it ) ;
2018-12-02 18:05:50 +11:00
}
else
it + + ;
}
2019-04-07 16:01:53 +02:00
// remove internal house zones with nobody in them
for ( auto it = m_questBattleIdToInstanceMap . begin ( ) ; it ! = m_questBattleIdToInstanceMap . end ( ) ; + + it )
{
for ( auto inIt = it - > second . begin ( ) ; inIt ! = it - > second . end ( ) ; )
{
auto zone = std : : dynamic_pointer_cast < QuestBattle > ( inIt - > second ) ;
if ( ! zone )
continue ;
auto diff = std : : difftime ( tickCount , zone - > getLastActivityTime ( ) ) ;
// todo: make this timeout configurable, though should be pretty relaxed in any case
2019-04-07 23:42:24 +02:00
if ( diff > 60000 )
2019-04-07 16:01:53 +02:00
{
Logger : : info ( " Removing QuestBattle#{0} - has been inactive for 60 seconds " , zone - > getGuId ( ) ) ;
// remove zone from maps
m_instanceZoneSet . erase ( zone ) ;
2019-07-21 22:33:33 +10:00
m_guIdToTerritoryPtrMap . erase ( zone - > getGuId ( ) ) ;
2019-04-07 16:01:53 +02:00
inIt = m_questBattleIdToInstanceMap [ zone - > getQuestBattleId ( ) ] . erase ( inIt ) ;
}
else
inIt + + ;
}
}
2018-01-28 13:49:51 +01:00
}
2019-04-07 16:01:53 +02:00
Sapphire : : World : : Manager : : TerritoryMgr : : InstanceIdList
Sapphire : : World : : Manager : : TerritoryMgr : : getInstanceContentIdList ( uint16_t instanceContentId ) const
2018-01-28 13:49:51 +01:00
{
2018-08-29 21:40:59 +02:00
std : : vector < uint32_t > idList ;
2018-12-30 18:48:45 +11:00
auto zoneMap = m_instanceContentIdToInstanceMap . find ( instanceContentId ) ;
if ( zoneMap = = m_instanceContentIdToInstanceMap . end ( ) )
2018-08-29 21:40:59 +02:00
return idList ;
2018-01-28 13:49:51 +01:00
2018-08-29 21:40:59 +02:00
for ( auto & entry : zoneMap - > second )
{
idList . push_back ( entry . first ) ;
}
2018-01-27 23:52:49 +01:00
2018-08-29 21:40:59 +02:00
return idList ;
2018-01-27 23:52:49 +01:00
}
2018-12-01 00:27:16 +11:00
bool Sapphire : : World : : Manager : : TerritoryMgr : : movePlayer ( uint32_t territoryTypeId , Sapphire : : Entity : : PlayerPtr pPlayer )
2018-01-28 22:36:43 +01:00
{
2018-11-05 23:07:39 +01:00
auto pZone = getZoneByTerritoryTypeId ( territoryTypeId ) ;
2018-08-29 21:40:59 +02:00
assert ( pZone ) ;
return movePlayer ( pZone , pPlayer ) ;
2018-01-28 22:36:43 +01:00
}
2019-07-21 22:33:33 +10:00
bool Sapphire : : World : : Manager : : TerritoryMgr : : movePlayer ( TerritoryPtr pZone , Sapphire : : Entity : : PlayerPtr pPlayer )
2018-01-28 22:36:43 +01:00
{
2018-08-29 21:40:59 +02:00
if ( ! pZone )
{
2019-07-21 22:33:33 +10:00
Logger : : error ( " Territory not found on this server. " ) ;
2018-08-29 21:40:59 +02:00
return false ;
}
2018-01-28 22:36:43 +01:00
2018-08-29 21:40:59 +02:00
pPlayer - > initSpawnIdQueue ( ) ;
2018-02-23 23:47:21 +01:00
2018-11-05 23:07:39 +01:00
pPlayer - > setTerritoryTypeId ( pZone - > getTerritoryTypeId ( ) ) ;
2018-01-28 22:36:43 +01:00
2018-11-06 11:11:07 +01:00
if ( isHousingTerritory ( pZone - > getTerritoryTypeId ( ) ) )
{
auto pHousing = std : : dynamic_pointer_cast < HousingZone > ( pZone ) ;
2018-11-23 16:48:32 +11:00
if ( pHousing )
2018-11-06 11:11:07 +01:00
pPlayer - > setTerritoryId ( pHousing - > getLandSetId ( ) ) ;
2018-11-23 16:48:32 +11:00
}
2021-08-16 17:18:29 +09:00
else if ( pZone - > getAsInstanceContent ( ) | | pZone - > getAsQuestBattle ( ) | | pZone - > getAsPublicContent ( ) )
2018-11-23 16:48:32 +11:00
{
pPlayer - > setTerritoryId ( pZone - > getGuId ( ) ) ;
}
2018-11-06 11:11:07 +01:00
else
{
pPlayer - > setTerritoryId ( 0 ) ;
}
2018-11-23 16:48:32 +11:00
2018-08-29 21:40:59 +02:00
// mark character as zoning in progress
pPlayer - > setLoadingComplete ( false ) ;
2018-01-28 22:36:43 +01:00
2021-02-06 05:18:26 +09:00
bool zoneChanged = true ;
2019-07-21 22:50:11 +10:00
if ( pPlayer - > getLastPing ( ) ! = 0 & & pPlayer - > getCurrentTerritory ( ) )
2021-02-06 05:18:26 +09:00
{
zoneChanged = pPlayer - > getCurrentTerritory ( ) - > getGuId ( ) ! = pZone - > getGuId ( ) ;
if ( zoneChanged )
pPlayer - > getCurrentTerritory ( ) - > removeActor ( pPlayer ) ;
}
2018-01-28 22:36:43 +01:00
2021-02-06 05:18:26 +09:00
if ( zoneChanged )
{
pPlayer - > setCurrentZone ( pZone ) ;
pZone - > pushActor ( pPlayer ) ;
2018-01-28 22:36:43 +01:00
2021-02-06 05:18:26 +09:00
// map player to instanceId so it can be tracked.
m_playerIdToInstanceMap [ pPlayer - > getId ( ) ] = pZone - > getGuId ( ) ;
}
else
{
pPlayer - > removeFromInRange ( ) ;
pPlayer - > clearInRangeSet ( ) ;
}
2018-02-04 17:46:46 +01:00
2019-01-14 22:29:52 +01:00
pPlayer - > sendZonePackets ( ) ;
2018-08-29 21:40:59 +02:00
return true ;
2018-01-28 22:36:43 +01:00
}
2019-07-21 22:33:33 +10:00
Sapphire : : TerritoryPtr Sapphire : : World : : Manager : : TerritoryMgr : : getLinkedInstance ( uint32_t playerId ) const
2018-02-04 17:46:46 +01:00
{
2018-08-29 21:40:59 +02:00
auto it = m_playerIdToInstanceMap . find ( playerId ) ;
if ( it ! = m_playerIdToInstanceMap . end ( ) )
{
2019-05-07 22:10:55 +10:00
return getTerritoryByGuId ( it - > second ) ;
2018-08-29 21:40:59 +02:00
}
return nullptr ;
2018-02-04 17:46:46 +01:00
}
2018-12-01 00:27:16 +11:00
const std : : pair < uint16_t , uint16_t > & Sapphire : : World : : Manager : : TerritoryMgr : : getCurrentFestival ( ) const
2018-03-20 20:30:05 +11:00
{
2018-08-29 21:40:59 +02:00
return m_currentFestival ;
2018-03-20 20:30:05 +11:00
}
2018-12-01 00:27:16 +11:00
void Sapphire : : World : : Manager : : TerritoryMgr : : setCurrentFestival ( uint16_t festivalId , uint16_t additionalFestival )
2018-03-20 20:30:05 +11:00
{
2018-09-01 20:55:28 +10:00
m_currentFestival = { festivalId , additionalFestival } ;
2018-03-20 20:30:05 +11:00
2019-07-24 21:58:48 +10:00
for ( const auto & zone : m_territorySet )
2018-08-29 21:40:59 +02:00
{
2018-09-01 20:55:28 +10:00
zone - > setCurrentFestival ( festivalId , additionalFestival ) ;
2018-08-29 21:40:59 +02:00
}
2018-03-20 20:30:05 +11:00
}
2018-12-01 00:27:16 +11:00
void Sapphire : : World : : Manager : : TerritoryMgr : : disableCurrentFestival ( )
2018-03-20 20:30:05 +11:00
{
2018-08-29 21:40:59 +02:00
setCurrentFestival ( 0 ) ;
2018-03-20 20:30:05 +11:00
}
2019-01-28 20:48:33 +11:00
float Sapphire : : World : : Manager : : TerritoryMgr : : getInRangeDistance ( ) const
{
return m_inRangeDistance ;
}
2018-01-27 23:52:49 +01:00
2019-04-11 00:16:04 +02:00
void Sapphire : : World : : Manager : : TerritoryMgr : : createAndJoinQuestBattle ( Entity : : Player & player , uint16_t questBattleId )
{
auto qb = createQuestBattle ( questBattleId ) ;
if ( ! qb )
return ;
player . setInstance ( qb ) ;
}
2018-01-28 13:49:51 +01:00